# LendCore Business Adaptation & Integration Plan

## Document Purpose
This document outlines the complete core business logic, workflow, and technical implementation roadmap for the LendCore loan management system with tier-based loan access, M-Pesa integration, and comprehensive repayment tracking.

---

## 1. Core Business Rules

### 1.1 User Registration & Approval Workflow

**Registration Process:**
- User registers through web form or mobile API with name, email, password, and M-Pesa phone
- Account status set to `pending` upon registration
- User receives confirmation that registration is pending admin approval

**Admin Approval Process:**
- Admin reviews pending registrations in admin user management interface
- Admin can approve or reject pending users
- Upon approval: user status changes to `approved` and automatically assigned BIASHARA 1 tier
- Upon rejection: user status changes to `rejected` and cannot access the system
- All approval/rejection actions are logged in audit trail

**Post-Approval Access:**
- Approved users can login and access loan features
- Default tier assignment ensures immediate loan eligibility
- Tier progression follows existing automatic rules

**Automatic Tier Progression:**
- User unlocks next tier automatically after completing a configurable number of loans in their current tier
- Default threshold: 3 completed loans per tier
- This progression is automatic and requires no admin intervention
- **Tier progression rule:** If user has ≥3 completed loans in current tier → unlock next tier

**Manual Admin Override:**
- Admin can manually set a user's accessible tier at any time
- This allows admin to promote or demote users based on business decisions
- Manual assignments override automatic progression

**Tier Request Limitation:**
- Users can only request loans in tiers at or below their unlocked tier
- Attempting to request a tier above their unlocked level is blocked
- Loan request form shows only accessible tiers

---

### 1.2 Loan Request & Approval Workflow

**Step 1: User Requests Loan**
- User selects an accessible tier (≤ unlocked tier)
- User enters requested amount (within tier min/max)
- Request submitted with status: `pending`
- Admin is notified of pending request

**Step 2: Admin Reviews & Approves**
- Admin views pending loan requests dashboard
- Admin can view requested amount
- Admin can adjust the approved amount (≤ requested amount or tier max)
- Admin enters separate PIN (not the login password) to confirm approval
- Request status changes to: `approved`

**Step 3: M-Pesa B2C Disbursement**
- System initiates B2C payment to user's registered M-Pesa number
- M-Pesa transaction code is stored
- Upon successful callback, loan status becomes: `disbursed`
- Repayment schedule is automatically generated

**Step 4: User Notification**
- User receives SMS/notification with:
  - Loan amount disbursed
  - M-Pesa transaction code/reference
  - Link to view loan details and repayment schedule

---

### 1.3 Repayment Algorithm (Weekly Installments)

**Installment Generation:**
- Upon loan disbursement, repayment schedule is auto-generated
- Number of installments = tier duration (in weeks)
- Each installment amount = total_payable / duration_weeks
- Due dates calculated from disbursement date, same day of week

**Installment Independence:**
- Each installment is treated as a separate entity
- Status tracking per installment: `pending`, `partial`, `paid`, `overdue`
- An installment can be paid early (before due date)

**Payment Logic:**
- User can pay full installment amount or partial amount
- Full payment: installment marked `paid`, move to next installment
- Partial payment: balance remains, installment stays active or moves to `partial`
- User can make multiple partial payments on same installment
- Partial payment does NOT extend due date (due date remains fixed)

**Active Installment Display:**
- Currently due installment is always visible to user
- Shows: amount due, amount paid, balance, due date
- Overdue installments also remain active and visible
- Next due installment becomes visible when it transitions to due status

**Parallel Active Installments:**
- If installment becomes overdue (week passes without full payment), it remains active
- When the next installment's due date arrives, it also becomes active
- Both overdue and currently-due installments are visible
- User can pay either or both in any order

---

### 1.4 Late Payment Fine System

**Fine Trigger:**
- Fine is applied when an installment remains unpaid after due date

**Fine Calculation:**
- Fine accrues **every 24 hours** after the due date passes
- Fine amount (default): 100 KSH per 24-hour period
- Fine is cumulative: each full 24 hours adds another 100 KSH
- Example: 3 days overdue = 300 KSH fine

**Fine Application:**
- Fine is calculated and displayed separately from installment amount
- Fine appears on both user and admin views
- User can pay fine together with installment or separately
- Admin can waive/reduce fine manually (with audit trail)

**Fine Configuration:**
- Configurable via Settings model
- Setting key: `late_payment_fine_amount` (default: 100 KSH)
- Setting key: `fine_calculation_period` (default: 1 day in hours = 24)

---

### 1.5 M-Pesa Integration Points

**M-Pesa Disbursement (Admin → User):**
- B2C API call after admin approval with PIN
- Send funds to registered M-Pesa number
- Store transaction code in `loan_requests.mpesa_code`
- Store transaction ID in `transactions.mpesa_transaction_id`
- Update loan status to `disbursed` on success
- Retry logic for failed transactions

**M-Pesa Repayment (User → System):**
- STK Push initiated when user clicks "Pay" button
- User enters M-Pesa PIN on phone
- Success callback received and processed
- Transaction recorded with M-Pesa code and reference
- Repayment balance updated automatically
- Partial payments supported (user can enter custom amount ≤ due)

**Transaction Storage:**
- All M-Pesa transactions stored in `transactions` table
- Fields: `mpesa_code`, `mpesa_transaction_id`, `callback_data`, `processed_at`
- Audit trail maintained for all disbursements and payments

---

### 1.6 Admin PIN System

**Purpose:**
- Separate authentication for sensitive approval actions
- Prevent accidental loan approvals
- Maintain audit trail of who approved what

**Implementation:**
- Admin model has dedicated `admin_pin_hash` field
- PIN stored as hash (not password)
- PIN is 4-6 digits (configurable, default 4)
- Admin sets PIN during first login or admin setup

**Approval Process:**
- Admin views pending loan request with requested amount
- Admin enters adjustment amount (if needed)
- Admin clicks "Approve"
- Admin is prompted to enter PIN
- PIN is validated; if correct, approval proceeds
- If PIN incorrect, approval is rejected with error message
- All approval attempts (success/failure) are logged

**Security:**
- PIN never displayed in logs
- Only hash stored
- Failed PIN attempts logged for audit
- Admin can reset PIN (requires admin access)

---

## 1.7 Admin Backend (Phase 3)

**Implemented so far:**
- Admin dashboard with loan analytics, filters, and loan/fine summaries
- Tier CRUD interfaces including create, edit, show, and delete protections
- Manual admin loan creation and edit workflows for back-office loan management
- Loan approval and disbursement controls from the admin dashboard
- Repayment review with overdue tracking, status filtering, and payment recording
- Fine review page for overdue charges and borrower-specific filtering
- Fine waiver workflow available from the admin fine detail view
- M-Pesa callback endpoint for asynchronous disbursement updates
- Responsive admin UI using current Tailwind-based layout and mobile-first tables
- User application form now filters available tiers by the borrower's accessible tier
- Audit logging for admin fine waivers, loan approvals, and transaction callbacks (including index and show views for audit logs)

**Officer Management (Phase 3B):**
- Officer role with dedicated login interface (`/officer/login`)
- Officer middleware for route protection
- Officer dashboard with system-wide statistics
- View all approved users and their detailed loan/repayment data
- View all loans across the system with status tracking
- Cannot access admin reporting or perform admin-only CRUD operations
- Admin can create, edit, and delete officer accounts
- Officer seeder with 3 pre-configured test officers
- Full audit trail for officer account management

**Next target work:**
- Improve M-Pesa callback security and request validation

---

## 2. Database Schema Updates

### 2.1 Users Table Additions

```sql
ALTER TABLE users ADD COLUMN accessible_tier_id BIGINT UNSIGNED AFTER role;
ALTER TABLE users ADD COLUMN mpesa_phone VARCHAR(20) NULLABLE AFTER accessible_tier_id;
ALTER TABLE users ADD COLUMN admin_pin_hash VARCHAR(255) NULLABLE AFTER mpesa_phone;
ALTER TABLE users ADD FOREIGN KEY (accessible_tier_id) REFERENCES tiers(id);
```

**Fields:**
- `accessible_tier_id`: ID of the highest tier user can access (FK to tiers table)
- `mpesa_phone`: Registered M-Pesa phone number for disbursements
- `admin_pin_hash`: Hashed admin PIN (if user is admin)

---

### 2.2 Loan Requests Table (New)

```sql
CREATE TABLE loan_requests (
    id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
    user_id BIGINT UNSIGNED NOT NULL,
    tier_id BIGINT UNSIGNED NOT NULL,
    requested_amount DECIMAL(12, 2) NOT NULL,
    approved_amount DECIMAL(12, 2) NULLABLE,
    status ENUM('pending', 'approved', 'rejected', 'disbursed') DEFAULT 'pending',
    admin_notes TEXT NULLABLE,
    approved_by BIGINT UNSIGNED NULLABLE,
    approved_at TIMESTAMP NULLABLE,
    mpesa_code VARCHAR(255) NULLABLE,
    mpesa_transaction_id VARCHAR(255) NULLABLE,
    callback_data JSON NULLABLE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
    FOREIGN KEY (tier_id) REFERENCES tiers(id),
    FOREIGN KEY (approved_by) REFERENCES users(id) ON DELETE SET NULL
);
```

**Purpose:** Track all loan requests from request to disbursement
**Status Flow:** pending → approved → disbursed (or rejected)

---

### 2.3 Repayments Table Additions

```sql
ALTER TABLE repayments ADD COLUMN installment_number INT AFTER loan_id;
ALTER TABLE repayments ADD COLUMN is_active BOOLEAN DEFAULT TRUE AFTER installment_number;
ALTER TABLE repayments ADD COLUMN paid_at TIMESTAMP NULLABLE;
```

**Fields:**
- `installment_number`: Sequential number (1, 2, 3, ...) for tracking
- `is_active`: Whether this installment is currently visible/actionable to user
- `paid_at`: Timestamp when fully paid

---

### 2.4 Transactions Table Enhancements

```sql
ALTER TABLE transactions ADD COLUMN mpesa_code VARCHAR(255) NULLABLE;
ALTER TABLE transactions ADD COLUMN mpesa_transaction_id VARCHAR(255) NULLABLE;
ALTER TABLE transactions ADD COLUMN callback_data JSON NULLABLE;
ALTER TABLE transactions ADD COLUMN processed_at TIMESTAMP NULLABLE;
ALTER TABLE transactions ADD COLUMN repayment_id BIGINT UNSIGNED NULLABLE;
ALTER TABLE transactions ADD FOREIGN KEY (repayment_id) REFERENCES repayments(id) ON DELETE SET NULL;
```

**Purpose:** Store M-Pesa transaction details and maintain full audit trail
**Supports:** Disbursements and repayments with external reference tracking

---

### 2.5 Settings Table Additions

```sql
INSERT INTO settings (key, value) VALUES
('tier_progression_threshold', '3'),
('late_payment_fine_amount', '100'),
('fine_calculation_period_hours', '24'),
('default_tier_id', '1'),
('laf_fee_percentage', '2.00'),
('registration_fee_amount', '500.00'),
('default_interest_rate', '25.00');
```

---

## 3. Business Logic Services

### 3.1 Tier Access Service

```php
class TierAccessService {
    public function getAccessibleTiers(User $user): Collection {
        // Return all tiers where tier_id <= user.accessible_tier_id
    }
    
    public function canRequestTier(User $user, Tier $tier): bool {
        // Check if tier <= user's unlocked tier
    }
    
    public function checkAndPromoteUser(User $user): void {
        // Auto-promote if user has 3+ completed loans in current tier
    }
    
    public function manuallySetTier(User $user, Tier $tier, Admin $admin): void {
        // Admin override; log the action
    }
}
```

---

### 3.2 Loan Request Service

```php
class LoanRequestService {
    public function submitRequest(User $user, Tier $tier, decimal $amount): LoanRequest {
        // Validate tier access and amount range
        // Create request with status 'pending'
        // Notify admin
    }
    
    public function approveLoan(LoanRequest $request, decimal $approvedAmount, Admin $admin, string $pin): bool {
        // Verify admin PIN
        // Update request status to 'approved'
        // Initiate M-Pesa B2C disbursement
        // Log approval
    }
    
    public function rejectRequest(LoanRequest $request, string $reason): void {
        // Update status to 'rejected'
        // Notify user
    }
}
```

---

### 3.3 Repayment Service (Enhanced)

```php
class RepaymentService {
    public function getActiveInstallments(Loan $loan): Collection {
        // Return all unpaid installments (status != 'paid')
        // Order by due_date
    }
    
    public function recordPayment(Repayment $repayment, decimal $amount, string $mpesaCode): Transaction {
        // Validate amount
        // Deduct from balance
        // Update amount_paid
        // Create transaction with M-Pesa code
        // If fully paid, mark as 'paid'
        // Activate next installment if applicable
    }
    
    public function processPartialPayment(Repayment $repayment, decimal $amount): void {
        // Update amount_paid, balance
        // Keep status as 'pending' or 'partial'
        // Do NOT extend due date
    }
    
    public function calculateFine(Repayment $repayment): decimal {
        // If today > due_date:
        //   hours_late = (now - due_date) in hours
        //   full_days_late = floor(hours_late / 24)
        //   fine = full_days_late * setting('late_payment_fine_amount')
        // Return fine amount
    }
    
    public function getOverdueInstallments(Loan $loan): Collection {
        // Return all unpaid installments where due_date < today
    }
}
```

---

### 3.4 M-Pesa Service

```php
class MpesaService {
    public function initiateDisbursement(LoanRequest $request, Admin $admin): bool {
        // Call M-Pesa B2C API
        // Send funds to user.mpesa_phone
        // Store transaction code
        // Handle success/failure callback
    }
    
    public function initiateStk(User $user, Repayment $repayment, decimal $amount): string {
        // Call M-Pesa STK Push API
        // Return checkout request ID for polling
    }
    
    public function processCallback(array $callbackData): void {
        // Verify callback signature
        // Extract transaction code, result, reference
        // Update corresponding transaction/loan status
        // Update repayment balance
    }
    
    public function verifyTransaction(string $transactionCode): array {
        // Query M-Pesa API for transaction status
        // Return status and details
    }
}
```

---

### 3.5 Admin Service

```php
class AdminService {
    public function validatePin(Admin $admin, string $pin): bool {
        // Hash pin and compare with admin_pin_hash
        // Log attempt (success/failure)
    }
    
    public function getUserDetail(User $user): array {
        // Return user profile, accessible tier, loans, repayments, transactions
    }
    
    public function getPendingRequests(): Collection {
        // Return all loan_requests with status 'pending'
        // Order by created_at DESC
    }
    
    public function weaveFine(Repayment $repayment, decimal $newAmount, Admin $admin, string $reason): void {
        // Update fine amount
        // Log action with reason
    }
}
```

---

## 4. M-Pesa Real-World Integration Implementation

### 4.1 Why this is needed

Safaricom STK callback payloads do not include internal loan IDs. The system must map M-Pesa callbacks to transactions by `CheckoutRequestID` and then link that transaction to the related loan or repayment.

### 4.2 What was implemented

- Added `checkout_request_id` to `transactions` and made it searchable with an index.
- Updated `TransactionService` to:
  - store `checkout_request_id` when creating disbursement or payment transactions
  - locate transactions using `findByCheckoutRequestId()`
  - preserve `checkout_request_id` during callback updates
- Updated `MpesaCallbackController::handle()` to detect Safaricom Daraja STK callback payloads and translate them into the internal callback format.
- Added payment callback handling in `RepaymentService` so `payment` transactions can be updated from STK callbacks and then applied to the repayment balance.
- Preserved the existing manual callback format for local testing and API-driven calls.

### 4.3 Callback workflow

The app exposes the following M-Pesa callback endpoints in `routes/api.php` and handles them in `app/Http/Controllers/Api/MpesaCallbackController.php`:

- `POST /api/payment/callback` — STK Push callback and manual payment callback handler
- `POST /api/payment/c2b/validation` — C2B validation handler
- `POST /api/payment/c2b/confirmation` — C2B confirmation handler
- `POST /api/payment/b2c/result` — B2C result callback handler
- `POST /api/payment/b2c/timeout` — B2C timeout callback handler
- `POST /api/payment/register-callbacks` — Admin route to register C2B callback URLs with Safaricom

#### STK Push callback flow

1. The user submits a repayment payment form and the app initiates STK Push via `MpesaService::sendStkPush()`.
2. A pending `payment` transaction record is created and the returned `CheckoutRequestID` is stored on the transaction.
3. Daraja sends the STK callback to the configured confirmation URL, which in this app resolves to `/api/payment/callback`.
4. `MpesaCallbackController::handle()` detects the callback payload by looking for `Body.stkCallback`.
5. It extracts:
   - `CheckoutRequestID`
   - `MerchantRequestID`
   - `ResultCode`
   - `Amount`
   - `MpesaReceiptNumber`
   - `CallbackMetadata`
6. The controller looks up the pending transaction by `checkout_request_id` using `TransactionService::findByCheckoutRequestId()`.
7. If the transaction is a `payment`, `RepaymentService::processMpesaPaymentCallback()` applies the payment to the linked repayment and updates the transaction.
8. The transaction is updated with:
   - `status` = `completed` or `failed`
   - `mpesa_transaction_id`
   - `mpesa_code`
   - `processed_at`
   - full callback payload in `callback_data`
9. The action is audited with loan and transaction context.

### 4.4 Database migration

A new migration file was created:

- `database/migrations/2026_04_30_120000_add_checkout_request_id_to_transactions_table.php`

It adds:
- `checkout_request_id VARCHAR(255) NULLABLE`
- index on `checkout_request_id`

### 4.5 Test coverage and verification

- Added feature tests in `tests/Feature/MpesaCallbackTest.php`
- Covered:
  - STK payment callback mapping via `checkout_request_id`
  - M-Pesa disbursement callback driving loan activation
- Recommended test commands:
  - `php artisan migrate`
  - `vendor/bin/phpunit --filter MpesaCallbackTest`

### 4.6 Sandbox readiness

To test with Safaricom Daraja sandbox:
- Run `ngrok http 8000`
- Set `MPESA_ENV=sandbox` for sandbox testing. When moving to production, set `MPESA_ENV=production` and update all callback URLs to the live domain.
- Set the callback URL to `https://<ngrok-id>.ngrok.io/api/payment/callback`
- Set validation and confirmation URLs in `.env` as:
  - `MPESA_C2B_VALIDATION_URL=https://<ngrok-id>.ngrok.io/api/payment/c2b/validation`
  - `MPESA_C2B_CONFIRMATION_URL=https://<ngrok-id>.ngrok.io/api/payment/callback`
- If using Non-STK Paybill, also set:
  - `MPESA_C2B_NONSTK_VALIDATION_URL=https://<ngrok-id>.ngrok.io/api/payment/c2b/nonstk/validation`
  - `MPESA_C2B_NONSTK_CONFIRMATION_URL=https://<ngrok-id>.ngrok.io/api/payment/c2b/nonstk/confirmation`
  - `MPESA_C2B_NONSTK_SHORT_CODE=<nonstk-short-code>`
- Ensure the app also has `MPESA_B2C_RESULT_URL` and `MPESA_B2C_TIMEOUT_URL` pointing at:
  - `https://<ngrok-id>.ngrok.io/api/payment/b2c/result`
  - `https://<ngrok-id>.ngrok.io/api/payment/b2c/timeout`
- Register the C2B callback URLs with Safaricom using the admin endpoint:
  - `POST /api/payment/register-callbacks`
- Trigger STK push from the application and use sandbox test numbers
- Confirm:
  - callback hits `/api/payment/callback`
  - transaction status changes to `completed`
  - repayment balance and loan state update correctly

---

## 5. User Interface Workflows

### 4.1 User Loan Request Flow

**User Dashboard:**
1. View accessible tiers with description and amounts
2. Click "Request Loan" on desired tier
3. Enter requested amount (validated against tier min/max)
4. Submit request
5. See status: "Request Submitted - Pending Admin Approval"

**After Approval:**
1. Receive notification: "Your loan request has been approved"
2. M-Pesa popup for confirmation
3. After disbursement: "Loan Amount KSh X received - Ref: XXXXX"
4. View loan details with repayment schedule

---

### 4.2 User Repayment Flow

**Active Installment View:**
- Display only currently due and overdue installments
- Show per installment:
  - Installment #1, #2, etc.
  - Amount Due: KSh XXX
  - Amount Paid: KSh YYY
  - Balance: KSh ZZZ
  - Due Date: YYYY-MM-DD
  - Fine (if any): KSh FFF
  - Status badge: pending/partial/overdue

**Payment Action:**
1. User clicks "Pay" on installment
2. Enter amount (default = balance, can reduce for partial)
3. Confirm M-Pesa payment
4. STK Push sent to M-Pesa
5. After success: balance updated, transaction recorded

---

### 4.3 Admin Loan Request Approval Flow

**Pending Requests Dashboard:**
1. View list of pending requests: User Name, Tier, Requested Amount, Request Date
2. Click request to view details
3. See requested amount in edit field (pre-filled)
4. Adjust approved amount if needed
5. Click "Approve"
6. Prompted for admin PIN
7. Enter PIN
8. Upon success: confirmation, B2C initiated
9. Track M-Pesa transaction status
10. Once confirmed: loan marked disbursed

---

### 4.5 View Updates for M-Pesa Transaction Display

**Admin Views Updated:**
- **Admin Loan Show:** Added "M-Pesa Transaction" column to repayment schedule table showing `mpesa_transaction_id` and `processed_at` timestamp for completed transactions
- **Admin Repayment Show:** Added "M-Pesa Transactions" section in payment history displaying all completed transactions with ID, timestamp, amount, and type

**User Views Updated:**
- **User Loan Show:** Added "M-Pesa Transaction" column to repayment schedule table showing transaction details for each repayment
- **User Repayments Index:** Added "M-Pesa Transaction" column displaying transaction ID and processed timestamp for completed payments

**Officer Views Updated:**
- **Officer Loan Show:** Added "M-Pesa Transaction" column to repayment schedule table showing transaction details

**Controller Updates:**
- **Admin/LoanController:** Added `repayments.transactions` eager loading
- **Web/LoanController:** Added `repayments.transactions` eager loading  
- **Web/RepaymentController:** Added `transactions` eager loading
- **Officer/OfficerDashboardController:** Added `repayments.transactions` eager loading

### 4.6 M-Pesa Transaction Seeder

**Purpose:** Add realistic M-Pesa transaction IDs to existing seeded payment transactions that were created without M-Pesa details.

**Seeder Created:** `MpesaTransactionSeeder.php`
- Finds all completed payment transactions without `mpesa_transaction_id`
- Generates realistic M-Pesa transaction codes (e.g., "RBK7128087", "RBJ5021932")
- Updates transactions with `mpesa_transaction_id`, `mpesa_code`, and `processed_at`

**Transaction ID Format:**
- Prefixes: RBJ, RCK, RBK, Q (realistic M-Pesa prefixes)
- Followed by 7 random digits
- Example: "RBJ5021932", "RBK7128087", "RCK9475447"

**Execution:**
- Added to `DatabaseSeeder.php` after `TestDataSeeder`
- Run with: `php artisan db:seed --class=MpesaTransactionSeeder`
- Updated 62 transactions in the seeded data

**Result:** All seeded payment transactions now display realistic M-Pesa transaction IDs in the admin, user, and officer views.

---

---

## 5. Implementation Roadmap

### Phase 1: Database Foundation (Week 1)
**Migrations:**
- Add fields to users table
- Create loan_requests table
- Add fields to repayments table
- Enhance transactions table
- Seed settings

**Models:**
- Update User model with relationships
- Create LoanRequest model
- Update Repayment model
- Update Transaction model

**Status:** Database schema ready

---

### Phase 2: Core Logic Services (Week 2)
**Services:**
- TierAccessService
- LoanRequestService
- Enhanced RepaymentService (with installment logic)
- AdminService

**Logic:**
- Tier access validation
- Automatic tier progression
- Loan request workflow
- Installment independence
- Fine calculation

**Status:** Business logic layer complete

---

### Phase 3: M-Pesa Integration (Week 3)
**Services:**
- MpesaService with B2C and STK Push
- Callback processing

**Controllers:**
- MpesaController for webhooks
- Endpoints for callback handling

**Features:**
- B2C disbursement
- STK Push for payments
- Callback processing and status updates
- Error handling and retries

**Status:** M-Pesa flow operational

---

### Phase 4: Admin Backend (Week 4)
**Controllers & Views:**
- LoanRequestController (index, show, approve)
- UserController (list, show, edit tier, detail)
- AdminDashboard enhancements
- AdminPin management UI

**Features:**
- Pending loan request dashboard
- Admin PIN entry on approval
- User detail pages with all data
- Tier management interface

**Status:** Admin workflows fully functional

---

### Phase 5: User Frontend (Week 5)
**Controllers & Views:**
- Enhanced LoanController (request, show)
- Enhanced RepaymentController (show, pay)
- User dashboard updates
- Loan list with repayment progress

**Features:**
- Accessible tier filtering in request
- Active installment display
- Partial payment UI
- M-Pesa payment flow
- Transaction history view

**Status:** User workflows complete

---

### Phase 6: Reporting & Analytics (Week 6)
**Reports:**
- Monthly/quarterly/annual disbursements
- Repayment collection rates
- Tier progression metrics
- User acquisition trends
- Overdue installment reports

**Features:**
- Charts and visualizations
- Date range filters
- Exportable reports
- Admin dashboard analytics

**Status:** Reporting & analytics complete

### Phase 7: Mobile API (Week 7)
**Endpoints:**
- Authentication (login/register/logout with Sanctum)
- User profile and accessible tiers
- Loan management (list/request/view)
- Repayment management (active installments/payment)
- Transaction history
- Notifications

**Features:**
- REST API with proper resources
- Sanctum token authentication
- Mobile-optimized responses
- Rate limiting and validation

**Status:** API integration complete

---

## 6. Key Configuration Settings

```php
// app/Models/Setting.php suggestions
return [
    'tier_progression_threshold' => 3,                    // Completed loans to unlock next tier
    'late_payment_fine_amount' => 100,                    // KSH per 24 hours
    'fine_calculation_period_hours' => 24,               // Hours between fine increments
    'default_tier_id' => 1,                              // First tier for new users
    'laf_fee_percentage' => 2.00,                        // LAF fee as % of loan amount
    'registration_fee_amount' => 500.00,                 // Fixed registration fee
    'default_interest_rate' => 25.00,                    // Default interest % per annum
    'admin_pin_length' => 4,                             // Admin PIN digit count
    'mpesa_b2c_timeout_seconds' => 30,                   // B2C call timeout
    'mpesa_retry_attempts' => 3,                         // Retry failed B2C attempts
];
```

---

## 7. Data Flow Diagram

```
┌─────────────────────────────────────────────────────────────────┐
│                    USER TIER ACCESS                               │
├─────────────────────────────────────────────────────────────────┤
│ New User → Default Tier (BIASHARA 1)                             │
│ Complete 3 Loans → Unlock Tier 2 (Auto)                          │
│ Admin Override → Set Tier Manually (Any Tier)                    │
│ Request Loan → Can only request Tier <= Accessible Tier          │
└─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│                 LOAN REQUEST → DISBURSEMENT                       │
├─────────────────────────────────────────────────────────────────┤
│ User: Request Loan (Tier, Amount)                                │
│       ↓                                                            │
│ Admin: View Pending Request                                      │
│       ↓                                                            │
│ Admin: Enter PIN + Approve Amount                                │
│       ↓                                                            │
│ System: Validate PIN                                             │
│       ↓                                                            │
│ System: Initiate M-Pesa B2C Disbursement                         │
│       ↓                                                            │
│ M-Pesa: Send funds to user's phone                               │
│       ↓                                                            │
│ Callback: Store transaction code, mark loan disbursed            │
│       ↓                                                            │
│ System: Generate repayment schedule (weekly installments)        │
│       ↓                                                            │
│ User: Notified with M-Pesa reference + Loan details              │
└─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│              REPAYMENT (WEEKLY INSTALLMENTS)                      │
├─────────────────────────────────────────────────────────────────┤
│ Installment 1: Due Date YYYY-MM-DD                               │
│   ├─ Amount Due: KSh 2,000                                       │
│   ├─ Amount Paid: KSh 0 (initially)                              │
│   ├─ Balance: KSh 2,000                                          │
│   ├─ Status: pending                                             │
│   └─ User Can: Pay full, pay partial, or pay late (with fine)   │
│                                                                   │
│ When Due Date Passes:                                            │
│   ├─ Fine: 100 KSH per 24 hours (cumulative)                    │
│   ├─ Status: pending → overdue                                   │
│   ├─ Installment remains ACTIVE                                  │
│   └─ Next installment ALSO becomes active when it's due          │
│                                                                   │
│ User Payment:                                                    │
│   ├─ Enter amount (≤ balance)                                    │
│   ├─ STK Push to M-Pesa                                          │
│   ├─ On success: balance decremented                             │
│   ├─ If balance = 0: mark as paid                                │
│   ├─ If balance > 0: keep as partial/pending                     │
│   └─ Store M-Pesa transaction code                               │
│                                                                   │
│ Next Installment: Similar flow, independent status               │
└─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│           ADMIN & USER DATA VISIBILITY                            │
├─────────────────────────────────────────────────────────────────┤
│ ADMIN SEES:                                                      │
│   ├─ User: Name, Email, Phone, Accessible Tier                  │
│   ├─ Loans: Amount, Status, Tier, Disbursement Date             │
│   ├─ Repayments: All installments with status, fine              │
│   ├─ Transactions: M-Pesa codes, amounts, dates                  │
│   ├─ Pending Requests: With approval interface                   │
│   └─ Reports: Disbursements, Collections, Defaults               │
│                                                                   │
│ USER SEES:                                                       │
│   ├─ Accessible Tiers: Only tiers <= unlocked tier               │
│   ├─ Loans: Current and past loans with status                   │
│   ├─ Active Installments: Currently due + overdue (unpaid)       │
│   ├─ Payment Details: Amount due, paid, balance, fine             │
│   ├─ Payment History: M-Pesa references                          │
│   └─ Notifications: Request status, disbursements, payments      │
└─────────────────────────────────────────────────────────────────┘
```

---

## 8. Summary of Business Rules

| Rule | Description |
|------|-------------|
| **Tier Access** | User starts at default tier, unlocks next after 3 completed loans, or admin can override |
| **Loan Request** | Users can only request tiers ≤ their unlocked tier |
| **Admin Approval** | Requires separate PIN; admin can adjust approved amount |
| **Disbursement** | B2C to M-Pesa phone upon approval; store transaction code |
| **Installments** | Weekly, independent, each with separate tracking |
| **Early Payment** | Allowed anytime before due date |
| **Partial Payment** | Allowed; balance remains, due date stays fixed |
| **Overdue Handling** | Installment stays active after due date passes; next installment also becomes active when due |
| **Fine** | Cumulative 100 KSH per 24 hours (configurable) |
| **Visibility** | All data accessible to both admin and user in respective contexts |

---

## 9. Testing Scenarios

### Scenario 1: New User Journey
1. User registers via web or mobile app with name, email, password, M-Pesa phone
2. Account status set to `pending`; user sees "Registration submitted. Please wait for admin approval."
3. Admin reviews pending users and approves registration
4. User status changes to `approved` and automatically assigned BIASHARA 1 tier
5. User can now login and request loans up to BIASHARA 1 limits
6. User completes 3 loans and unlocks BIASHARA 2 automatically

### Scenario 2: Partial Payments
1. Installment 1 due: 2,000 KSh
2. User pays 1,200 KSh on day 3 (before due date)
3. Balance: 800 KSh, status: partial
4. User pays remaining 800 KSh on day 5
5. Balance: 0, status: paid, move to Installment 2

### Scenario 3: Overdue & Fine
1. Installment 1 due: 2,000 KSh on Mon
2. User doesn't pay by Mon end of day
3. Fine: 100 KSH (Tue)
4. Total due: 2,100 KSH (Tue)
5. User pays 2,100 KSH on Wed
6. Balance: 0, status: paid

### Scenario 4: Concurrent Installments
1. Installment 1 due Mon, unpaid by Fri
2. Installment 2 due next Mon, now also due
3. Both visible to user: Installment 1 (overdue, 2,100 due) + Installment 2 (due, 2,000 due)
4. User can pay either or both

### Scenario 5: Admin Manual Tier Adjustment
1. User at BIASHARA 2, only completed 1 loan
2. Admin promotes to BIASHARA 3 (for special case)
3. User can now request BIASHARA 3 loans immediately
4. Progression still based on 3 completed loans per tier

---

## 10. Deployment Checklist

- [ ] Database migrations applied
- [ ] Settings table populated
- [ ] Models updated with new relationships
- [ ] Services implemented and tested
- [ ] M-Pesa credentials configured
- [ ] Admin PIN setup UI implemented
- [ ] Tier access validation in place
- [ ] Loan request workflow tested
- [ ] Repayment algorithm tested with scenarios
- [ ] Fine calculation verified
- [ ] Admin dashboard updated
- [ ] User dashboard updated
- [ ] M-Pesa callback handlers tested
- [ ] Transaction logging verified
- [ ] Admin reports generated
- [ ] Production M-Pesa credentials set
- [ ] Staging environment tested end-to-end

---

## 11. Conclusion

This integration plan establishes a tier-based, PIN-verified, M-Pesa-enabled loan management system with granular installment tracking, automatic tier progression, and comprehensive audit trails. The system is built on modular services that preserve existing functionality while adding sophisticated business rules around user access, loan approval, repayment flexibility, and late payment penalties.

All data flows are bidirectional: users have visibility into their loans and payments, admins have oversight of all requests, disbursements, repayments, and can intervene where necessary. The roadmap prioritizes database schema, business logic, M-Pesa integration, and UI in logical phases for efficient implementation.

---

## BUSINESS ADAPTATION INTEGRATION IMPLEMENTED

This document and the LendCore application implementation are complete. The admin backend, user workflows, reporting, and mobile API are all implemented according to the business adaptation plan.

✅ Completed Phases
- Phase 1-2: Database foundation and core business logic services (already done)
- Phase 3: Admin backend with audit logging (completed with show.blade.php)
- Phase 4: M-Pesa integration (operational)
- Phase 5: User frontend (loan requests, repayments, transaction history)
- Phase 6: Reporting & analytics (charts, exports, admin dashboard)
- Phase 7: Mobile API for Flutter (Sanctum auth, REST endpoints)

---

## FLUTTER MOBILE APP INTEGRATION ROADMAP

### API Base Configuration
- **Base URL:** `http://your-domain.com/api` (replace with production URL)
- **Authentication:** Laravel Sanctum token-based
- **Content-Type:** `application/json`
- **Rate Limiting:** 60 requests per minute per user

### User Registration Flow (Critical for Onboarding)
1. **Registration Screen:**
   - Fields: name, email, password, mpesa_phone (format: 254XXXXXXXXX)
   - Validation: Email unique, password min 8 chars, phone regex validation
   - API Call: `POST /api/register`
   - Response: Success message + token (user status = 'pending')
   - UI Feedback: "Registration submitted. Please wait for admin approval."

2. **Post-Registration State:**
   - User cannot login until admin approves
   - Show pending approval screen with retry option
   - Poll status or notify when approved

### Authentication Flow
1. **Login Screen:**
   - Fields: email, password
   - API Call: `POST /api/login`
   - Response: User data + access token
   - Store token securely (flutter_secure_storage)
   - Redirect to dashboard if status = 'approved'

2. **Token Management:**
   - Include `Authorization: Bearer {token}` in all authenticated requests
   - Handle 401 responses (token expired)
   - Auto-refresh or re-login on auth failure

### Core API Endpoints & Flutter Implementation

#### 1. User Profile Management
- **GET /api/user** - Get current user profile
- **PUT /api/user** - Update profile (name, mpesa_phone)
- **GET /api/user/accessible-tiers** - Get user's available tiers
- **Flutter:** Profile screen with editable fields, tier display

#### 2. Tier Management
- **GET /api/tiers** - List all tiers
- **GET /api/tiers/{id}** - Get specific tier details
- **Flutter:** Tier selection dropdown in loan request

#### 3. Loan Management
- **GET /api/loans** - User's loan history
- **GET /api/loans/{id}** - Loan details with repayment schedule
- **POST /api/loans** - Request new loan
  - Body: {tier_id, amount}
  - Validation: Amount within tier limits, tier accessible
- **Flutter:** Loan list, request form, detail view

#### 4. Repayment Management
- **GET /api/repayments** - Active installments (pending + overdue only)
- **GET /api/repayments/{id}** - Individual installment details
- **POST /api/repayments/{id}/pay** - Initiate payment
  - Body: {amount, phone} (STK Push simulation)
- **Flutter:** Active repayments list, payment screen

#### 5. Transaction History
- **GET /api/transactions** - User's M-Pesa transaction history
- **GET /api/transactions/{id}** - Transaction details
- **Flutter:** Transaction history screen with filtering

#### 6. Notifications
- **GET /api/notifications** - User notifications
- **Flutter:** Notification center with read/unread status

### Flutter Data Models (DTO Classes)
```dart
class User {
  int id;
  String name;
  String email;
  String status; // 'pending', 'approved', 'rejected'
  String? mpesaPhone;
  int? accessibleTierId;
  Tier? accessibleTier;
  DateTime createdAt;
}

class Tier {
  int id;
  String name;
  String description;
  double minAmount;
  double maxAmount;
  int durationWeeks;
}

class Loan {
  int id;
  int userId;
  int tierId;
  Tier tier;
  double requestedAmount;
  double? approvedAmount;
  String status; // 'pending', 'approved', 'disbursed'
  String? mpesaCode;
  DateTime createdAt;
  List<Repayment> repayments;
}

class Repayment {
  int id;
  int loanId;
  int installmentNumber;
  double amountDue;
  double amountPaid;
  double balance;
  double fine;
  DateTime dueDate;
  String status; // 'pending', 'partial', 'paid', 'overdue'
  bool isActive;
}

class Transaction {
  int id;
  String type; // 'disbursement', 'payment'
  double amount;
  String? mpesaCode;
  String? mpesaTransactionId;
  DateTime createdAt;
  String status;
}
```

### Flutter App Architecture Roadmap

#### Phase 1: Authentication & Onboarding (Week 1-2)
- Implement registration screen with validation
- Login/logout functionality with token storage
- Handle pending approval state
- Basic navigation structure

#### Phase 2: Core User Dashboard (Week 3)
- Dashboard with accessible tiers display
- User profile management
- Basic loan history view
- Navigation drawer/sidebar

#### Phase 3: Loan Request Flow (Week 4)
- Tier selection interface
- Loan request form with amount validation
- Request submission and status tracking
- Integration with accessible tiers API

#### Phase 4: Repayment System (Week 5)
- Active installments list (pending + overdue)
- Payment initiation with M-Pesa phone input
- Payment confirmation and status updates
- Fine display and calculation

#### Phase 5: Transaction History & Notifications (Week 6)
- Complete transaction history with search/filter
- Notification system integration
- Offline data caching (optional)
- Push notifications setup

#### Phase 6: Polish & Testing (Week 7)
- Error handling and retry logic
- Loading states and progress indicators
- Offline mode considerations
- End-to-end testing with API

### Business Logic Considerations for Flutter Dev

#### 1. User Status Handling
- Always check `user.status` before allowing access
- Show appropriate messages for 'pending'/'rejected' users
- Implement status polling or push notifications for approval

#### 2. Tier Access Control
- Filter loan request tiers based on `user.accessibleTierId`
- Display only accessible tiers in dropdowns
- Handle tier progression after loan completions

#### 3. Repayment Logic
- Display only `isActive = true` installments
- Allow partial payments (any amount ≤ balance + fine)
- Show fines separately from installment amounts
- Handle multiple active installments simultaneously

#### 4. M-Pesa Integration
- Use STK Push simulation for payments
- Validate phone format (254XXXXXXXXX)
- Handle payment callbacks and status updates
- Store transaction references for history

#### 5. Data Synchronization
- Implement pull-to-refresh for real-time data
- Cache essential data locally for offline access
- Handle API rate limits gracefully
- Sync user status changes

### API Error Handling
- **400:** Validation errors - show field-specific messages
- **401:** Unauthorized - redirect to login
- **403:** Forbidden (pending/rejected) - show status message
- **404:** Not found - handle gracefully
- **429:** Rate limited - implement backoff retry
- **500:** Server error - show generic error with retry option

### Testing Checklist for Flutter Dev
- [ ] User registration with pending status
- [ ] Admin approval flow (test with approved user)
- [ ] Login with approved/rejected/pending users
- [ ] Loan request with tier validation
- [ ] Repayment with partial payments
- [ ] Transaction history display
- [ ] Offline data handling
- [ ] Error states and recovery

This roadmap ensures the Flutter app properly interfaces with all LendCore APIs while maintaining the business rules and user experience defined in the adaptation plan.

# ✅ Completed Phases

- **Phase 1–2:** Database foundation and core business logic services *(already done)*
- **Phase 3:** Admin backend with audit logging *(completed with `show.blade.php`)*
- **Phase 3B:** Officer role with dedicated portal and data access *(newly implemented)*
- **Phase 4:** M-Pesa integration *(operational)*
- **Phase 5:** User frontend *(loan requests, repayments, transaction history)*
- **Phase 6:** Reporting & analytics *(charts, exports, admin dashboard)*
- **Phase 7:** Mobile API for Flutter *(Sanctum auth, REST endpoints)*

---

# 🔧 Key Features Implemented

- **Dual-Role Authentication:** Admin/User/Officer middleware with PIN verification  
- **Officer Portal:** Dedicated login, dashboard, user data access, loan viewing (read-only)
- **Tier-Based Access:** Automatic progression with manual overrides  
- **Loan Workflow:**  
  `Request → Admin approval → M-Pesa disbursement → Repayment schedule`  
- **Installment System:** Weekly payments, partial payments allowed, fines for late payments  
- **M-Pesa Integration:** B2C disbursements and STK Push repayments  
- **Audit Logging:** Admin actions tracked with detailed view (`show`)  
- **Officer Management:** Admin can create/edit/delete officer accounts  
- **User Portal:** Tier-based access filtering and active installment display  
- **Admin Dashboard:** CRUD operations, fine waivers, reporting with charts  
- **API Endpoints:** Full REST API for mobile app integration  

---

# 📊 Technical Stack

- **Backend:** Laravel 11 (Eloquent models, service layer)
- **Frontend:** Blade Templates + Tailwind CSS v4 + Vite
- **Database:** MySQL (migrations & seeders)
- **Authentication:** Laravel Sanctum (API auth)
- **Charts & Visualization:** Chart.js
- **Reporting:** DomPDF (PDF exports)

---

# 🚀 Ready to Test

The application is running at:

