Files
usher-manage-stack/docs/SYSTEM_SPECIFICATION.md
2025-11-20 23:21:05 +08:00

42 KiB
Raw Permalink Blame History

Taiwan NPO Membership Management System

Complete System Specification

Version: 1.0 Last Updated: 2025-11-20 Technology Stack: Laravel 11, PHP 8.x, MySQL, Spatie Permission


Table of Contents

  1. Executive Summary
  2. System Architecture
  3. Database Schema
  4. Core Features
  5. Workflows
  6. Security & Authorization
  7. Email Notifications
  8. File Structure
  9. Configuration

1. Executive Summary

This system is a comprehensive membership management platform designed specifically for Taiwan NPOs (Non-Profit Organizations). It implements a complete lifecycle for member registration, payment verification, financial management, issue tracking, and budget management.

Key Capabilities

  • Member Lifecycle Management: Registration → Payment → 3-Tier Verification → Activation
  • Financial Management: Budget planning, transaction tracking, finance document approval
  • Issue Tracking: Complete work item management with time logging and collaboration
  • Multi-Tier Approval Workflows: 3-tier verification for payments and finance documents
  • Audit Logging: Complete audit trail for compliance and accountability
  • Role-Based Access Control: Granular permissions using Spatie Permission package

User Roles

  1. Public Users: Can self-register as members
  2. Members: Can submit payments, view membership status, request issues
  3. Cashier: First-tier verification for payments and documents
  4. Accountant: Second-tier verification
  5. Chair: Third-tier final approval
  6. Membership Manager: Activates memberships after approval
  7. Staff: General administrative access
  8. Admin: Full system access

2. System Architecture

2.1 Technology Stack

Backend:

  • Framework: Laravel 11
  • PHP Version: 8.x
  • Database: MySQL 8.0+
  • Authentication: Laravel Breeze
  • Authorization: Spatie Laravel Permission
  • Queue System: Database/Redis queue driver

Frontend:

  • Template Engine: Blade
  • CSS Framework: Tailwind CSS
  • JavaScript: Alpine.js (via Breeze)
  • Dark Mode: Supported

Infrastructure:

  • File Storage: Laravel Storage (private disk)
  • Email: Laravel Mail with queue support
  • Encryption: AES-256 for sensitive data

2.2 Application Layers

┌─────────────────────────────────────────┐
│         Web Interface (Blade)           │
│  - Public Registration                   │
│  - Member Dashboard                      │
│  - Admin Panel                           │
└─────────────────────────────────────────┘
                    ↓
┌─────────────────────────────────────────┐
│      HTTP Layer (Controllers)           │
│  - Request Validation                    │
│  - Business Logic Coordination           │
│  - Response Formatting                   │
└─────────────────────────────────────────┘
                    ↓
┌─────────────────────────────────────────┐
│       Application Layer (Models)         │
│  - Business Logic                        │
│  - Eloquent Relationships                │
│  - Accessors & Mutators                  │
└─────────────────────────────────────────┘
                    ↓
┌─────────────────────────────────────────┐
│         Data Layer (Database)            │
│  - MySQL Database                        │
│  - Migrations & Schema                   │
│  - Indexes & Constraints                 │
└─────────────────────────────────────────┘
                    ↓
┌─────────────────────────────────────────┐
│      Support Services (Cross-cutting)    │
│  - AuditLogger                           │
│  - Email Notifications                   │
│  - File Storage                          │
│  - Encryption Services                   │
└─────────────────────────────────────────┘

3. Database Schema

3.1 Core Tables

users

Primary authentication table.

Column Type Constraints Description
id bigint unsigned PK, AUTO_INCREMENT Primary key
name varchar(255) NOT NULL User's full name
email varchar(255) NOT NULL, UNIQUE Email address
email_verified_at timestamp NULL Email verification time
password varchar(255) NOT NULL Bcrypt hashed password
is_admin boolean DEFAULT false Legacy admin flag
profile_photo_path varchar(2048) NULL Profile photo path
remember_token varchar(100) NULL Remember me token
created_at timestamp NULL Creation timestamp
updated_at timestamp NULL Last update timestamp

Relationships:

  • HasOne: Member
  • BelongsToMany: Role (via model_has_roles)
  • BelongsToMany: Permission (via model_has_permissions)

members

Member profile information.

Column Type Constraints Description
id bigint unsigned PK, AUTO_INCREMENT Primary key
user_id bigint unsigned FK(users), NULL, UNIQUE Associated user account
full_name varchar(255) NOT NULL, INDEXED Full name
email varchar(255) NOT NULL, INDEXED Email (indexed for search)
phone varchar(20) NULL Phone number
national_id_encrypted text NULL AES-256 encrypted national ID
national_id_hash varchar(64) NULL, INDEXED SHA256 hash for search
address_line_1 varchar(255) NULL Address line 1
address_line_2 varchar(255) NULL Address line 2
city varchar(100) NULL City
postal_code varchar(10) NULL Postal code
emergency_contact_name varchar(255) NULL Emergency contact name
emergency_contact_phone varchar(20) NULL Emergency contact phone
membership_started_at date NULL Membership start date
membership_expires_at date NULL Membership expiry date
membership_status enum DEFAULT 'pending' Status: pending, active, expired, suspended
membership_type enum DEFAULT 'regular' Type: regular, honorary, lifetime, student
created_at timestamp NULL Creation timestamp
updated_at timestamp NULL Last update timestamp

Relationships:

  • BelongsTo: User
  • HasMany: MembershipPayment
  • HasMany: FinanceDocument
  • HasMany: Issue (for member requests)

Key Methods:

  • hasPaidMembership() - Returns true if active with future expiry
  • canSubmitPayment() - Returns true if pending and no pending payment
  • getPendingPayment() - Gets payment awaiting verification
  • getMembershipStatusBadgeAttribute() - CSS badge class
  • getMembershipStatusLabelAttribute() - Chinese label
  • getMembershipTypeLabelAttribute() - Chinese type label

membership_payments

Payment records with 3-tier verification workflow.

Column Type Constraints Description
id bigint unsigned PK, AUTO_INCREMENT Primary key
member_id bigint unsigned FK(members), NOT NULL Member who paid
paid_at date NOT NULL Payment date
amount decimal(10,2) NOT NULL Payment amount (TWD)
method varchar(255) NULL Legacy payment method
reference varchar(255) NULL Legacy reference
status enum DEFAULT 'pending' Workflow status
payment_method enum NULL Method: bank_transfer, convenience_store, cash, credit_card
receipt_path varchar(255) NULL Receipt file path (private storage)
submitted_by_user_id bigint unsigned FK(users), NULL User who submitted
verified_by_cashier_id bigint unsigned FK(users), NULL Tier 1 verifier
cashier_verified_at timestamp NULL Tier 1 timestamp
verified_by_accountant_id bigint unsigned FK(users), NULL Tier 2 verifier
accountant_verified_at timestamp NULL Tier 2 timestamp
verified_by_chair_id bigint unsigned FK(users), NULL Tier 3 verifier
chair_verified_at timestamp NULL Tier 3 timestamp
rejected_by_user_id bigint unsigned FK(users), NULL Rejector
rejected_at timestamp NULL Rejection timestamp
rejection_reason text NULL Reason for rejection
notes text NULL Admin notes
created_at timestamp NULL Creation timestamp
updated_at timestamp NULL Last update timestamp

Workflow States:

  1. pending - Awaiting Tier 1 verification
  2. approved_cashier - Tier 1 approved, awaiting Tier 2
  3. approved_accountant - Tier 2 approved, awaiting Tier 3
  4. approved_chair - Fully approved (triggers activation)
  5. rejected - Rejected at any tier

Key Methods:

  • canBeApprovedByCashier() - Validates Tier 1 eligibility
  • canBeApprovedByAccountant() - Validates Tier 2 eligibility
  • canBeApprovedByChair() - Validates Tier 3 eligibility
  • getStatusLabelAttribute() - Chinese status label
  • getPaymentMethodLabelAttribute() - Chinese method label

finance_documents

Finance document approval workflow (3-tier).

Column Type Constraints Description
id bigint unsigned PK, AUTO_INCREMENT Primary key
member_id bigint unsigned FK(members), NULL Related member
submitted_by_user_id bigint unsigned FK(users), NOT NULL Submitter
title varchar(255) NOT NULL Document title
amount decimal(10,2) NULL Amount (if applicable)
status varchar(255) DEFAULT 'pending' Workflow status
description text NULL Description
attachment_path varchar(255) NULL Attachment file path
approved_by_cashier_id bigint unsigned FK(users), NULL Tier 1 approver
cashier_approved_at timestamp NULL Tier 1 timestamp
approved_by_accountant_id bigint unsigned FK(users), NULL Tier 2 approver
accountant_approved_at timestamp NULL Tier 2 timestamp
approved_by_chair_id bigint unsigned FK(users), NULL Tier 3 approver
chair_approved_at timestamp NULL Tier 3 timestamp
rejected_by_user_id bigint unsigned FK(users), NULL Rejector
rejected_at timestamp NULL Rejection timestamp
rejection_reason text NULL Reason for rejection
submitted_at timestamp NULL Submission timestamp
created_at timestamp NULL Creation timestamp
updated_at timestamp NULL Last update timestamp

Same 3-tier workflow as membership_payments


issues

Issue tracking system with comprehensive features.

Column Type Constraints Description
id bigint unsigned PK, AUTO_INCREMENT Primary key
issue_number varchar(50) NOT NULL, UNIQUE Auto: ISS-2025-001
title varchar(255) NOT NULL Issue title
description text NULL Issue description
issue_type enum NOT NULL Type: work_item, project_task, maintenance, member_request
status enum DEFAULT 'new', INDEXED Status: new, assigned, in_progress, review, closed
priority enum DEFAULT 'medium', INDEXED Priority: low, medium, high, urgent
created_by_user_id bigint unsigned FK(users), INDEXED Creator
assigned_to_user_id bigint unsigned FK(users), NULL, INDEXED Assignee
reviewer_id bigint unsigned FK(users), NULL Reviewer
member_id bigint unsigned FK(members), NULL Related member
parent_issue_id bigint unsigned FK(issues), NULL Parent issue (for sub-tasks)
due_date date NULL, INDEXED Due date
closed_at timestamp NULL Closure timestamp
estimated_hours decimal(8,2) NULL Estimated hours
actual_hours decimal(8,2) DEFAULT 0 Actual hours (from time logs)
created_at timestamp NULL Creation timestamp
updated_at timestamp NULL Last update timestamp
deleted_at timestamp NULL Soft delete timestamp

Relationships:

  • HasMany: IssueComment, IssueAttachment, IssueTimeLog
  • BelongsToMany: IssueLabel, User (watchers)
  • BelongsTo: User (creator, assignee, reviewer)
  • BelongsTo: Issue (parent)

Key Methods:

  • Status checks: isNew(), isAssigned(), isInProgress(), inReview(), isClosed()
  • Workflow validation: canBeAssigned(), canMoveToInProgress(), canMoveToReview(), canBeClosed()
  • Calculations: getProgressPercentageAttribute(), getIsOverdueAttribute(), getTotalTimeLoggedAttribute()

budgets

Budget management with lifecycle workflow.

Column Type Constraints Description
id bigint unsigned PK, AUTO_INCREMENT Primary key
fiscal_year integer NOT NULL, INDEXED Fiscal year (2000-2100)
name varchar(255) NOT NULL Budget name
period_type enum NOT NULL Type: annual, quarterly, monthly
period_start date NOT NULL Period start date
period_end date NOT NULL Period end date
status enum DEFAULT 'draft', INDEXED Status: draft, submitted, approved, active, closed
created_by_user_id bigint unsigned FK(users), NOT NULL Creator
approved_by_user_id bigint unsigned FK(users), NULL Approver
approved_at timestamp NULL Approval timestamp
notes text NULL Notes
created_at timestamp NULL Creation timestamp
updated_at timestamp NULL Last update timestamp

Workflow: draft → submitted → approved → active → closed

Key Methods:

  • Status checks: isDraft(), isApproved(), isActive(), isClosed()
  • Validation: canBeEdited(), canBeApproved()
  • Calculations: getTotalBudgetedIncomeAttribute(), getTotalActualExpenseAttribute(), etc.

budget_items

Line items within budgets.

Column Type Constraints Description
id bigint unsigned PK, AUTO_INCREMENT Primary key
budget_id bigint unsigned FK(budgets), NOT NULL, INDEXED Parent budget
chart_of_account_id bigint unsigned FK(chart_of_accounts), NOT NULL Account code
budgeted_amount decimal(15,2) NOT NULL Planned amount
actual_amount decimal(15,2) NOT NULL, DEFAULT 0 Actual amount spent
notes text NULL Notes
created_at timestamp NULL Creation timestamp
updated_at timestamp NULL Last update timestamp

Composite Index: (budget_id, chart_of_account_id)

Key Methods:

  • getVarianceAttribute() - actual - budgeted
  • getVariancePercentageAttribute() - (variance / budgeted) × 100
  • getRemainingBudgetAttribute() - budgeted - actual
  • isOverBudget() - Returns true if actual > budgeted

transactions

Financial transaction records.

Column Type Constraints Description
id bigint unsigned PK, AUTO_INCREMENT Primary key
budget_item_id bigint unsigned FK(budget_items), NULL Linked budget item
chart_of_account_id bigint unsigned FK(chart_of_accounts), NOT NULL Account code
transaction_date date NOT NULL, INDEXED Transaction date
amount decimal(15,2) NOT NULL Amount
transaction_type enum NOT NULL, INDEXED Type: income, expense
description varchar(255) NOT NULL Description
reference_number varchar(255) NULL Reference number
finance_document_id bigint unsigned FK(finance_documents), NULL Linked document
membership_payment_id bigint unsigned FK(membership_payments), NULL Linked payment
created_by_user_id bigint unsigned FK(users), NOT NULL Creator
notes text NULL Notes
created_at timestamp NULL Creation timestamp
updated_at timestamp NULL Last update timestamp

Indexes: transaction_date, transaction_type, (budget_item_id, transaction_date)


chart_of_accounts

Hierarchical chart of accounts for financial tracking.

Column Type Constraints Description
id bigint unsigned PK, AUTO_INCREMENT Primary key
account_code varchar(50) NOT NULL, UNIQUE Account code (e.g., 4000)
account_name_zh varchar(255) NOT NULL Chinese name
account_name_en varchar(255) NOT NULL English name
account_type enum NOT NULL Type: income, expense, asset, liability, net_asset
category varchar(100) NULL Category grouping
parent_account_id bigint unsigned FK(chart_of_accounts), NULL Parent account (hierarchy)
is_active boolean DEFAULT true Active flag
display_order integer DEFAULT 0 Sort order
description text NULL Description
created_at timestamp NULL Creation timestamp
updated_at timestamp NULL Last update timestamp

Hierarchical Structure: Supports parent-child relationships for account grouping


audit_logs

Complete audit trail for compliance.

Column Type Constraints Description
id bigint unsigned PK, AUTO_INCREMENT Primary key
user_id bigint unsigned FK(users), NULL User who performed action
action varchar(255) NOT NULL, INDEXED Action name (e.g., member.created)
auditable_type varchar(255) NULL Model class name
auditable_id bigint unsigned NULL Model ID
metadata json NULL Additional context
created_at timestamp NULL Action timestamp
updated_at timestamp NULL Last update timestamp

Common Actions:

  • member.self_registered, member.created, member.updated, member.activated
  • payment.submitted, payment.approved_by_*, payment.rejected
  • finance_document., issue., budget., transaction.

3.2 Supporting Tables

roles (Spatie Permission)

  • id, name, guard_name, description, timestamps

permissions (Spatie Permission)

  • id, name, guard_name, timestamps

model_has_roles (Spatie Permission)

  • role_id, model_type, model_id

model_has_permissions (Spatie Permission)

  • permission_id, model_type, model_id

role_has_permissions (Spatie Permission)

  • permission_id, role_id

issue_comments

  • id, issue_id, user_id, comment_text, is_internal, timestamps

issue_attachments

  • id, issue_id, user_id, file_path, file_name, file_size, mime_type, timestamps

issue_labels

  • id, name (unique), color, description, timestamps

issue_label_pivot

  • issue_id, issue_label_id

issue_time_logs

  • id, issue_id, user_id, hours, work_date, description, timestamps

issue_watchers

  • id, issue_id, user_id

issue_relationships

  • id, issue_id, related_issue_id, relationship_type, timestamps

custom_fields

  • id, name, field_type, options (JSON), is_required, timestamps

custom_field_values

  • id, custom_field_id, customizable_type, customizable_id, value (JSON), timestamps

financial_reports

  • id, budget_id, report_type, report_data (JSON), generated_by_user_id, generated_at, timestamps

4. Core Features

4.1 Member Registration & Lifecycle

Public Self-Registration:

  • Route: GET/POST /register/member
  • Controller: PublicMemberRegistrationController
  • Creates User + Member records
  • Sets initial status to 'pending'
  • Sends welcome email with payment instructions
  • Auto-login after registration

Admin-Created Members:

  • Route: POST /admin/members
  • Controller: AdminMemberController
  • Can create member with or without user account
  • Sets initial status to 'pending'

Member States:

  1. Pending: Registered but not yet paid/verified
  2. Active: Payment approved and membership activated
  3. Expired: Membership expiry date has passed
  4. Suspended: Admin-suspended

Key Features:

  • National ID encryption (AES-256)
  • National ID hash (SHA256) for searching without decryption
  • Emergency contact information
  • Address management
  • Membership type management (regular, student, honorary, lifetime)

4.2 Payment Verification Workflow (3-Tier)

Member Payment Submission:

  • Route: POST /member/payments
  • Controller: MemberPaymentController
  • Upload receipt (JPG, PNG, PDF, max 10MB)
  • Specify payment method, amount, date, reference
  • Creates payment with status='pending'
  • Stored in private storage
  • Emails sent to member (confirmation) and cashiers (notification)

Tier 1: Cashier Verification

  • Route: POST /admin/payment-verifications/{payment}/approve-cashier
  • Permission: verify_payments_cashier
  • Verifies receipt legitimacy
  • Updates: status=approved_cashier, cashier_verified_at, verified_by_cashier_id
  • Sends email to member and accountants

Tier 2: Accountant Verification

  • Route: POST /admin/payment-verifications/{payment}/approve-accountant
  • Permission: verify_payments_accountant
  • Reviews financial details
  • Updates: status=approved_accountant, accountant_verified_at, verified_by_accountant_id
  • Sends email to member and chairs

Tier 3: Chair Approval

  • Route: POST /admin/payment-verifications/{payment}/approve-chair
  • Permission: verify_payments_chair
  • Final approval
  • Updates: status=approved_chair, chair_verified_at, verified_by_chair_id
  • Automatically activates membership:
    • member.membership_status = 'active'
    • member.membership_started_at = today
    • member.membership_expires_at = today + 1 year (or lifetime)
  • Sends activation email to member

Rejection:

  • Route: POST /admin/payment-verifications/{payment}/reject
  • Can be done at any tier
  • Requires rejection reason
  • Updates: status=rejected, rejected_by_user_id, rejected_at, rejection_reason
  • Sends rejection email with reason
  • Member can resubmit

Dashboard:

  • Route: GET /admin/payment-verifications
  • Tabbed interface: All, Cashier Queue, Accountant Queue, Chair Queue, Approved, Rejected
  • Shows counts for each queue
  • Search by member name, email, reference
  • Permission-based filtering

4.3 Finance Document Approval

Document Submission:

  • Route: POST /admin/finance-documents
  • Controller: FinanceDocumentController
  • Title, optional amount, optional attachment
  • Status starts as 'pending'

3-Tier Approval: Same workflow structure as payment verification:

  1. Cashier approval (Tier 1)
  2. Accountant approval (Tier 2)
  3. Chair approval (Tier 3)

Features:

  • File attachment support
  • Amount tracking
  • Rejection with reason
  • Email notifications at each stage

4.4 Issue Tracking System

Issue Creation:

  • Route: POST /admin/issues
  • Controller: IssueController
  • Auto-generates issue number: ISS-{YYYY}-{incrementing}
  • Required: title, type, priority
  • Optional: description, assignee, labels, due date, estimated hours

Issue Types:

  • work_item: General work tasks
  • project_task: Project-related tasks
  • maintenance: System maintenance
  • member_request: Member support requests

Status Workflow:

new → assigned → in_progress → review → closed

Can reopen: closed → assigned

Priority Levels:

  • low (default background color: gray)
  • medium (default background color: blue)
  • high (default background color: orange)
  • urgent (default background color: red)

Collaboration Features:

  1. Comments:

    • Add comments to issues
    • is_internal flag hides comments from members
    • Notifies watchers
  2. Attachments:

    • Upload files to issues
    • Download attachments
    • Delete attachments
  3. Time Logging:

    • Log hours worked on issues
    • Specify work date
    • Automatic summation
  4. Watchers:

    • Add users to watch issue updates
    • Receive email notifications
  5. Labels:

    • Color-coded labels
    • Filterable
    • Multiple labels per issue
  6. Sub-tasks:

    • Create child issues via parent_issue_id
    • Hierarchical structure
  7. Issue Relationships:

    • blocks, is_blocked_by
    • relates_to
    • duplicates, is_duplicated_by

Automation:

  • Auto-calculation of progress percentage (0-100% based on status)
  • Overdue detection (due_date < today and not closed)
  • Days until due calculation

Reports:

  • Route: GET /admin/issue-reports
  • Status distribution
  • Priority distribution
  • Workload analysis

4.5 Budget Management

Budget Creation:

  • Route: POST /admin/budgets
  • Controller: BudgetController
  • Fiscal year, period type, date range
  • Status starts as 'draft'

Budget Items:

  • Link to chart of accounts
  • Set budgeted amounts
  • Track actual amounts (updated via transactions)
  • Calculate variances

Workflow:

draft → submitted → approved → active → closed

Features:

  • Total budgeted income/expense calculation
  • Total actual income/expense calculation
  • Variance analysis (budgeted vs actual)
  • Utilization percentage
  • Over-budget detection

Reporting:

  • Generate financial reports
  • Store report snapshots (JSON)
  • Historical tracking

4.6 Transaction Management

Transaction Recording:

  • Route: POST /admin/transactions
  • Controller: TransactionController
  • Type: income or expense
  • Link to budget item (optional)
  • Link to chart of account (required)
  • Link to finance document or membership payment (optional)
  • Date, amount, description

Features:

  • Search by date range, type, description
  • Automatic budget item actual amount update
  • Reference number tracking
  • Notes support

5. Workflows

5.1 Complete Member Journey

┌─────────────────────────────────────────────────────────────┐
│ STEP 1: REGISTRATION                                        │
│ User fills public registration form                          │
│ → Creates User account (with password)                       │
│ → Creates Member record (status='pending')                   │
│ → Sends welcome email                                        │
│ → Auto-login                                                 │
└─────────────────────────────────────────────────────────────┘
                          ↓
┌─────────────────────────────────────────────────────────────┐
│ STEP 2: PAYMENT SUBMISSION                                  │
│ Member uploads receipt + payment details                     │
│ → Payment created (status='pending')                         │
│ → Receipt stored in private storage                          │
│ → Email to member (confirmation)                             │
│ → Email to cashiers (notification)                           │
└─────────────────────────────────────────────────────────────┘
                          ↓
┌─────────────────────────────────────────────────────────────┐
│ STEP 3: TIER 1 VERIFICATION (Cashier)                       │
│ Cashier reviews receipt and basic info                       │
│ → Approves or rejects                                        │
│ IF APPROVED:                                                 │
│   → status='approved_cashier'                                │
│   → Email to member + accountants                            │
│ IF REJECTED:                                                 │
│   → status='rejected'                                        │
│   → Email to member with reason                              │
│   → Member must resubmit                                     │
└─────────────────────────────────────────────────────────────┘
                          ↓ (if approved)
┌─────────────────────────────────────────────────────────────┐
│ STEP 4: TIER 2 VERIFICATION (Accountant)                    │
│ Accountant verifies financial details                        │
│ → Approves or rejects                                        │
│ IF APPROVED:                                                 │
│   → status='approved_accountant'                             │
│   → Email to member + chairs                                 │
│ IF REJECTED: (same as Tier 1)                                │
└─────────────────────────────────────────────────────────────┘
                          ↓ (if approved)
┌─────────────────────────────────────────────────────────────┐
│ STEP 5: TIER 3 APPROVAL (Chair)                             │
│ Chair gives final approval                                   │
│ → Approves or rejects                                        │
│ IF APPROVED:                                                 │
│   → status='approved_chair'                                  │
│   → AUTOMATIC ACTIVATION:                                    │
│       ◦ member.membership_status = 'active'                  │
│       ◦ member.membership_started_at = today                 │
│       ◦ member.membership_expires_at = today + 1 year        │
│   → Email to member (activation confirmation)                │
│   → Email to membership managers (FYI)                       │
│ IF REJECTED: (same as Tier 1 & 2)                            │
└─────────────────────────────────────────────────────────────┘
                          ↓ (if approved)
┌─────────────────────────────────────────────────────────────┐
│ STEP 6: ACTIVE MEMBERSHIP                                   │
│ Member now has:                                              │
│ → Access to member-only resources                            │
│ → Active membership badge                                    │
│ → Membership expiry date                                     │
│ → Full dashboard access                                      │
└─────────────────────────────────────────────────────────────┘

5.2 Issue Lifecycle

┌──────────┐
│   NEW    │  ← Issue created
└────┬─────┘
     │ assign user
     ↓
┌──────────┐
│ ASSIGNED │  ← User assigned
└────┬─────┘
     │ start work
     ↓
┌──────────────┐
│ IN_PROGRESS  │  ← Work started
└────┬─────────┘
     │ ready for review
     ↓
┌──────────┐
│  REVIEW  │  ← Reviewing
└────┬─────┘
     │ approve
     ↓
┌──────────┐
│  CLOSED  │  ← Done
└──────────┘
     ↑
     │ can reopen
     └──────────

5.3 Budget Lifecycle

┌────────┐
│ DRAFT  │  ← Create budget, add items
└───┬────┘
    │ submit for approval
    ↓
┌───────────┐
│ SUBMITTED │  ← Pending approval
└─────┬─────┘
      │ approve
      ↓
┌───────────┐
│ APPROVED  │  ← Approved but not yet active
└─────┬─────┘
      │ activate
      ↓
┌────────┐
│ ACTIVE │  ← Currently in use, transactions linked
└───┬────┘
    │ period ends
    ↓
┌────────┐
│ CLOSED │  ← Period ended, archived
└────────┘

6. Security & Authorization

6.1 Authentication

Method: Session-based authentication via Laravel Breeze Features:

  • Password hashing (Bcrypt)
  • Email verification (optional)
  • Remember me functionality
  • Password reset via email

6.2 Authorization (Spatie Permission)

Roles:

  1. admin - Full system access
  2. staff - Internal tools access
  3. cashier - Payment Tier 1 verification
  4. accountant - Payment Tier 2 verification
  5. chair - Payment Tier 3 approval
  6. payment_cashier - Dedicated cashier role
  7. payment_accountant - Dedicated accountant role
  8. payment_chair - Dedicated chair role
  9. membership_manager - Membership activation

Permissions:

  • verify_payments_cashier - Tier 1 approval
  • verify_payments_accountant - Tier 2 approval
  • verify_payments_chair - Tier 3 approval
  • activate_memberships - Activate memberships
  • view_payment_verifications - View dashboard

Middleware:

  • EnsureUserIsAdmin - Protects /admin routes
  • CheckPaidMembership - Verifies active paid membership

6.3 Data Security

National ID Protection:

  • Stored encrypted (AES-256)
  • Hashed with SHA256 for searching
  • Never displayed in plain text

Password Security:

  • Bcrypt hashing
  • Minimum password requirements
  • Password confirmation on sensitive actions

CSRF Protection:

  • All POST/PATCH/DELETE requests protected
  • Automatic token generation

File Security:

  • Payment receipts stored in private disk
  • Served only via authenticated controller methods
  • File type validation on upload

SQL Injection Prevention:

  • Eloquent ORM with parameter binding
  • Never use raw queries without bindings

7. Email Notifications

7.1 Membership Emails

Email Trigger Recipients
MemberRegistrationWelcomeMail After self-registration New member
PaymentSubmittedMail Payment submitted Member + Cashiers
PaymentApprovedByCashierMail Tier 1 approval Member + Accountants
PaymentApprovedByAccountantMail Tier 2 approval Member + Chairs
PaymentFullyApprovedMail Tier 3 approval Member + Membership Managers
PaymentRejectedMail Payment rejected Member
MembershipActivatedMail Membership activated Member
MembershipExpiryReminderMail X days before expiry Member

7.2 Finance Emails

Email Trigger Recipients
FinanceDocumentSubmitted Document submitted Cashiers
FinanceDocumentApprovedByCashier Tier 1 approval Submitter + Accountants
FinanceDocumentApprovedByAccountant Tier 2 approval Submitter + Chairs
FinanceDocumentFullyApproved Tier 3 approval Submitter
FinanceDocumentRejected Document rejected Submitter

7.3 Issue Emails

Email Trigger Recipients
IssueAssignedMail Issue assigned Assignee
IssueStatusChangedMail Status changed Creator + Assignee + Watchers
IssueCommentedMail New comment Creator + Assignee + Watchers
IssueDueSoonMail Due within X days Assignee
IssueOverdueMail Past due date Assignee
IssueClosedMail Issue closed Creator + Watchers

7.4 Queue Configuration

All emails implement ShouldQueue for async delivery:

  • Queue driver: database/redis
  • Failed jobs table for retry
  • Queue workers handle delivery

8. File Structure

usher-manage-stack/
├── app/
│   ├── Http/
│   │   ├── Controllers/
│   │   │   ├── AdminMemberController.php
│   │   │   ├── AdminPaymentController.php
│   │   │   ├── PaymentVerificationController.php
│   │   │   ├── PublicMemberRegistrationController.php
│   │   │   ├── MemberPaymentController.php
│   │   │   ├── MemberDashboardController.php
│   │   │   ├── FinanceDocumentController.php
│   │   │   ├── IssueController.php
│   │   │   ├── IssueLabelController.php
│   │   │   ├── IssueReportsController.php
│   │   │   ├── BudgetController.php
│   │   │   ├── TransactionController.php
│   │   │   ├── AdminRoleController.php
│   │   │   ├── AdminAuditLogController.php
│   │   │   └── AdminDashboardController.php
│   │   └── Middleware/
│   │       ├── EnsureUserIsAdmin.php
│   │       └── CheckPaidMembership.php
│   ├── Mail/
│   │   ├── MemberRegistrationWelcomeMail.php
│   │   ├── PaymentSubmittedMail.php
│   │   ├── PaymentApprovedByCashierMail.php
│   │   ├── PaymentApprovedByAccountantMail.php
│   │   ├── PaymentFullyApprovedMail.php
│   │   ├── PaymentRejectedMail.php
│   │   ├── MembershipActivatedMail.php
│   │   ├── FinanceDocument*.php (5 files)
│   │   └── Issue*.php (6 files)
│   ├── Models/
│   │   ├── Member.php
│   │   ├── MembershipPayment.php
│   │   ├── User.php
│   │   ├── Role.php
│   │   ├── Permission.php
│   │   ├── Issue.php
│   │   ├── IssueComment.php
│   │   ├── IssueAttachment.php
│   │   ├── IssueLabel.php
│   │   ├── IssueTimeLog.php
│   │   ├── Budget.php
│   │   ├── BudgetItem.php
│   │   ├── Transaction.php
│   │   ├── ChartOfAccount.php
│   │   ├── FinanceDocument.php
│   │   └── AuditLog.php
│   └── Support/
│       └── AuditLogger.php
├── database/
│   ├── migrations/
│   │   ├── 2025_11_18_092000_create_audit_logs_table.php
│   │   ├── 2025_11_18_093000_create_finance_documents_table.php
│   │   ├── 2025_11_19_133732_create_budgets_table.php
│   │   ├── 2025_11_19_133802_create_transactions_table.php
│   │   ├── 2025_11_19_144027_create_issues_table.php
│   │   ├── 2025_11_19_155725_enhance_membership_payments_table_for_verification.php
│   │   └── 2025_11_19_155807_add_membership_status_to_members_table.php
│   └── seeders/
│       ├── RoleSeeder.php
│       ├── PaymentVerificationRolesSeeder.php
│       ├── ChartOfAccountSeeder.php
│       └── IssueLabelSeeder.php
├── resources/
│   └── views/
│       ├── admin/
│       │   ├── members/
│       │   │   ├── index.blade.php
│       │   │   ├── show.blade.php
│       │   │   ├── create.blade.php
│       │   │   ├── edit.blade.php
│       │   │   └── activate.blade.php
│       │   ├── payment-verifications/
│       │   │   ├── index.blade.php
│       │   │   └── show.blade.php
│       │   ├── issues/
│       │   ├── budgets/
│       │   └── finance-documents/
│       ├── member/
│       │   ├── dashboard.blade.php
│       │   └── submit-payment.blade.php
│       ├── register/
│       │   └── member.blade.php
│       └── emails/
│           ├── members/
│           ├── payments/
│           ├── finance-documents/
│           └── issues/
└── routes/
    └── web.php

9. Configuration

9.1 Environment Variables

APP_NAME="Taiwan NPO Membership System"
APP_ENV=production
APP_KEY=base64:...
APP_DEBUG=false
APP_URL=https://your-domain.com

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=usher_manage
DB_USERNAME=root
DB_PASSWORD=

MAIL_MAILER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=
MAIL_PASSWORD=
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=noreply@your-domain.com
MAIL_FROM_NAME="${APP_NAME}"

QUEUE_CONNECTION=database

FILESYSTEM_DISK=local

9.2 Permissions Required

Cashier:

  • verify_payments_cashier
  • view_payment_verifications

Accountant:

  • verify_payments_accountant
  • view_payment_verifications

Chair:

  • verify_payments_chair
  • view_payment_verifications

Membership Manager:

  • activate_memberships
  • view_payment_verifications

Admin:

  • All permissions (automatic grant)

10. Deployment Checklist

  • Run migrations: php artisan migrate
  • Seed roles & permissions: php artisan db:seed --class=RoleSeeder
  • Seed payment roles: php artisan db:seed --class=PaymentVerificationRolesSeeder
  • Seed chart of accounts: php artisan db:seed --class=ChartOfAccountSeeder
  • Seed issue labels: php artisan db:seed --class=IssueLabelSeeder
  • Configure mail settings
  • Configure queue worker
  • Set up file storage (private disk)
  • Create admin user
  • Assign admin role
  • Test payment workflow end-to-end
  • Test email delivery
  • Set up SSL certificate
  • Configure backup strategy

Appendix A: Glossary

Member: A registered person in the NPO system Payment Verification: 3-tier approval process for membership payments Tier 1/2/3: Sequential approval levels (Cashier/Accountant/Chair) Issue: Work item, task, or support request in the tracking system Budget: Financial plan for a fiscal period Chart of Account: Standardized account codes for financial tracking Audit Log: Record of all significant system actions


End of Specification Document