Skip to content

Instantly share code, notes, and snippets.

@Konyuka
Last active November 25, 2025 12:41
Show Gist options
  • Select an option

  • Save Konyuka/f4e6b9b933c6fafcca3b4e52f2b1b8ff to your computer and use it in GitHub Desktop.

Select an option

Save Konyuka/f4e6b9b933c6fafcca3b4e52f2b1b8ff to your computer and use it in GitHub Desktop.
Change of Agent - Technical Documentation

Change of Agent - Technical Documentation

Overview

The Change of Agent feature allows system administrators to transfer member accounts from one agent to another. This documentation covers both single and batch (multiple) member agent changes, including the maker-checker workflow.


Table of Contents

  1. Architecture Overview
  2. Database Schema
  3. User Interface Flow
  4. Backend Logic
  5. Helper Methods
  6. Maker-Checker Workflow
  7. Error Handling
  8. API Endpoints

Architecture Overview

┌─────────────────────────────────────────────────────────────────────┐
│                        Frontend (Vue/Blade)                         │
│   index.blade.php (Change Agent UI)                                 │
│   confirm_change_of_agent.blade.php (Confirmation UI)               │
└─────────────────────────────────────────────────────────────────────┘
                                    │
                                    ▼
┌─────────────────────────────────────────────────────────────────────┐
│                           Routes (web.php)                          │
│  POST /handle/multiple/member/agent/change/members_multiple         │
│  POST /multiple/member/agent/change/members_multiple                │
│  POST /batch/confirm/agent_change  ⭐ NEW                           │
│  POST /single/member/agent/change                                   │
└─────────────────────────────────────────────────────────────────────┘
                                    │
                                    ▼
┌─────────────────────────────────────────────────────────────────────┐
│                      AgentController.php                            │
│  ├── handleMultipleMemberAgentChange() [Entry point for batch]      │
│  ├── multipleMemberAgentChange()       [Execution logic]            │
│  ├── batchConfirmAgentChange()         [⭐ Batch confirm from queue]│
│  ├── handlesingleAgentChange()         [Entry for single]           │
│  └── singleMemberAgentChange()         [Single execution]           │
└─────────────────────────────────────────────────────────────────────┘
                                    │
                                    ▼
┌─────────────────────────────────────────────────────────────────────┐
│                        Database Tables                              │
│  ├── accounts                (Main account table)                   │
│  ├── change_of_agents        (Pending changes - maker/checker)      │
│  ├── account_agent_log       (Audit trail)                          │
│  ├── um_trans                (Transactions)                         │
│  ├── um_transactions         (Transaction records)                  │
│  ├── um_trans_interests      (Interest transactions)                │
│  └── um_trans_agent_commissions (Agent commissions)                 │
└─────────────────────────────────────────────────────────────────────┘

Database Schema

1. change_of_agents Table (AgentChange Model)

Stores pending agent change requests for maker-checker workflow.

Column Type Description
id int Primary key
member_no_and_account_no_to_change string Format: member_no;account_no
agent_from_name string Source agent name
agent_from_agent_no string Source agent number
agent_to_name string Destination agent name
agent_to_agent_no string Destination agent number
change_reason string Reason for the change
created_by string Username who initiated
created_on datetime Creation timestamp
confirmed boolean Whether change is confirmed
confirmed_on datetime Confirmation timestamp
confirmed_by string Username who confirmed
deleted boolean Soft delete flag
deleted_on datetime Deletion timestamp
deleted_by string Username who deleted

2. account_agent_log Table (AccountAgentLog Model)

Audit trail for all executed agent changes.

Column Type Description
old_agent string Previous agent number
new_agent string New agent number
old_account_no string Previous account number
new_account_no string New account number (may change)
staff_name string Username who executed
reason string Reason for the change

User Interface Flow

1. Change Agent Page (index.blade.php)

Location: resources/views/agents/change_agent/index.blade.php

Step-by-Step User Flow

1. SELECT SOURCE AGENT ("Agent From")
   ├── User types agent number in search input
   ├── Debounced AJAX call to /agent/search_agent_details
   ├── Dropdown populated with matching agents
   └── On selection: DataTable loads with members belonging to this agent

2. SELECT DESTINATION AGENT ("Agent To")
   ├── User types agent number in search input
   ├── Debounced AJAX call to /agent/search_agent_details
   └── Dropdown populated with matching agents

3. SELECT MEMBER ACCOUNTS
   ├── Individual selection via checkboxes
   ├── "Select All" checkbox for bulk selection
   └── Visual feedback shows selected count

4. INITIATE TRANSFER
   ├── "Batch Transfer" button appears when 2+ accounts selected
   ├── Modal appears requesting "Change Reason"
   └── Confirmation dialog with count and agent details

5. PROCESSING
   ├── POST to /handle/multiple/member/agent/change/members_multiple
   ├── If maker-checker enabled → Creates pending records
   └── If maker-checker disabled → Direct execution

2. Confirmation Page (confirm_change_of_agent.blade.php)

Location: resources/views/agents/change_agent/confirm_change_of_agent.blade.php

Step-by-Step Confirmation Flow

1. VIEW PENDING CHANGES
   ├── DataTable shows all pending agent changes
   ├── Each row shows: Member, Account, Agent From, Agent To, Reason, Initiator

2. SELECT CHANGES TO CONFIRM
   ├── Individual selection via checkboxes
   ├── "Select All" for bulk selection
   ├── Can select changes with DIFFERENT source/destination agents

3. BATCH CONFIRM
   ├── Click "Batch Confirm" button
   ├── Summary dialog shows grouped transfers:
   │   • IFA0033 → IFA0032: 10 accounts
   │   • IFA0130 → IFA0131: 10 accounts
   └── Confirm to proceed

4. PROCESSING
   ├── POST to /batch/confirm/agent_change
   ├── Each record processed with its OWN agent mapping
   └── No mix-up between different batches

Backend Logic

handleMultipleMemberAgentChange

Purpose: Entry point for batch agent changes from the Change Agent page. Determines whether to use maker-checker workflow or execute directly.

Route: POST /handle/multiple/member/agent/change/members_multiple

Controller: AgentController@handleMultipleMemberAgentChange

Request Payload Structure

{
  "_token": "csrf_token_here",
  "data": [
    ["member_no1;account_no1", "member_no2;account_no2"],
    ["OLD_AGENT_CODE", "NEW_AGENT_CODE"]
  ],
  "change_reason": "Reason for the agent change"
}

Logic Flow

START
  │
  ▼
┌─────────────────────────────────────────────┐
│ 1. Check system_controls for                │
│    'agent_maker_checker_true' setting       │
└─────────────────────────────────────────────┘
  │
  ▼
┌─────────────────────────────────────────────┐
│ 2. Is maker-checker enabled?                │
└─────────────────────────────────────────────┘
  │                         │
  │ YES                     │ NO
  ▼                         ▼
┌─────────────────┐   ┌─────────────────┐
│ Check for       │   │ Call            │
│ pending changes │   │ multipleMember  │
│ (duplicate)     │   │ AgentChange()   │
└─────────────────┘   │ directly        │
  │                   └─────────────────┘
  ▼
┌─────────────────────────────────────────────┐
│ 3. Create AgentChange records for each      │
│    member/account pair                      │
│    - Store agent_from and agent_to          │
│    - confirmed = false                      │
│    - Record reason and creator              │
└─────────────────────────────────────────────┘
  │
  ▼
┌─────────────────────────────────────────────┐
│ 4. Return success:                          │
│    "Pending Confirmation"                   │
└─────────────────────────────────────────────┘

batchConfirmAgentChange ⭐ NEW

Purpose: Confirms multiple pending agent change records from the confirmation page. Each record is processed using its own stored source/destination agent mapping, allowing mixed batches to be confirmed correctly without any mix-up.

Route: POST /batch/confirm/agent_change

Controller: AgentController@batchConfirmAgentChange

Request Payload Structure

{
  "_token": "csrf_token_here",
  "change_ids": [1, 2, 3, 4, 5, 11, 12, 13, 14, 15]
}

Why This Method Exists

The previous approach had a critical flaw:

  • Users could select pending changes from different batches (e.g., Agent A → B and Agent C → D)
  • The old code took agent info from only the first selected item
  • This caused "Cannot process batch: Accounts belong to different agents" error

The new batchConfirmAgentChange method:

  • Fetches each pending change record by ID
  • Uses the stored agent_from_agent_no and agent_to_agent_no from each record
  • Processes each account with its correct source and destination agent
  • No mix-up possible

Logic Flow

START
  │
  ▼
┌─────────────────────────────────────────────┐
│ 1. Receive array of change_ids              │
└─────────────────────────────────────────────┘
  │
  ▼
┌─────────────────────────────────────────────┐
│ 2. Fetch pending AgentChange records        │
│    WHERE id IN (change_ids)                 │
│    AND confirmed = false                    │
│    AND deleted = false                      │
└─────────────────────────────────────────────┘
  │
  ▼
┌─────────────────────────────────────────────┐
│ 3. BEGIN DATABASE TRANSACTION               │
└─────────────────────────────────────────────┘
  │
  ▼
┌─────────────────────────────────────────────┐
│ 4. FOR EACH pending change record:          │
│    ├── Get agent_from from record           │
│    ├── Get agent_to from record             │
│    ├── Get member_no;account_no from record │
│    ├── Validate account exists              │
│    ├── Validate current agent = agent_from  │
│    ├── Generate new account number          │
│    ├── Update account table                 │
│    ├── Update related tables                │
│    ├── Create audit log                     │
│    └── Mark change as confirmed             │
└─────────────────────────────────────────────┘
  │
  ▼
┌─────────────────────────────────────────────┐
│ 5. COMMIT TRANSACTION                       │
│    Return success with counts               │
└─────────────────────────────────────────────┘

Key Safety Features

  1. Per-Record Agent Mapping: Each change uses its stored agent_from_agent_no and agent_to_agent_no
  2. Current Agent Validation: Verifies account's current agent matches expected source agent
  3. Graceful Skipping: If agent already changed, marks as confirmed and skips
  4. Atomic Transaction: All changes commit together or rollback together
  5. Comprehensive Logging: Every step logged for debugging

Response Format

{
  "status": "success",
  "message": "Batch confirmation completed. Processed: 20 account(s)",
  "processed_count": 20,
  "skipped_count": 0,
  "error_count": 0,
  "errors": [],
  "skipped": []
}

multipleMemberAgentChange

Purpose: Executes agent changes when all accounts should go to the SAME destination agent. Used for direct execution (non-maker-checker) or when called from handleMultipleMemberAgentChange.

Route: POST /multiple/member/agent/change/members_multiple

Note: This method has strict mode enabled - it rejects batches where accounts belong to different source agents. Use batchConfirmAgentChange for confirming mixed batches from the confirmation page.


Single Member Agent Change

For individual account transfers.

handlesingleAgentChange

Entry point for single member changes. Checks maker-checker setting.

singleMemberAgentChange

Executes single account transfer with same table updates as batch.


Helper Methods

getAccountInfoRows

Location: app/Http/Traits/AccountsSubTrait.php

public function getAccountInfoRows($account_number)
{
    return Account::join('securities', ...)
        ->where('account_no', $account_number)
        ->select('agent_no', 'security_code', 'category',
                 'member_no', 'mode', 'company_id')
        ->first();
}

modifyAgentonAccountNo

Location: app/Http/Traits/AccountsSubTrait.php

Generates new account number with updated agent code:

AGENT_CODE-SECURITY-MEMBER-[SUFFIX]
Example: AG001-SEC001-MEM001 → AG002-SEC001-MEM001

Maker-Checker Workflow

System Control Setting

SELECT value FROM system_controls WHERE setting = 'agent_maker_checker_true';
-- 1 = enabled, 0 = disabled

Workflow Diagram

┌─────────────────────────────────────────────────────────────────────┐
│                        MAKER (Creator)                              │
│             Uses: index.blade.php                                   │
└─────────────────────────────────────────────────────────────────────┘
                                │
                                ▼
┌─────────────────────────────────────────────────────────────────────┐
│ Creates pending change request in change_of_agents table           │
│ Stores: agent_from_agent_no, agent_to_agent_no per record          │
│ Status: confirmed = false                                           │
└─────────────────────────────────────────────────────────────────────┘
                                │
                                ▼
┌─────────────────────────────────────────────────────────────────────┐
│                      Pending Queue                                  │
│ View: confirm_change_of_agent.blade.php                             │
│ Route: /confirm/agent_change                                        │
└─────────────────────────────────────────────────────────────────────┘
                                │
                ┌───────────────┴───────────────┐
                ▼                               ▼
┌─────────────────────────┐       ┌─────────────────────────┐
│    APPROVE (Checker)    │       │    REJECT (Checker)     │
│                         │       │                         │
│  Single: Confirm button │       │    Cancel button        │
│  Batch: Batch Confirm   │       │    cancelAgentChange()  │
│                         │       │                         │
│  Uses stored agent      │       │                         │
│  from/to per record     │       │                         │
└─────────────────────────┘       └─────────────────────────┘
                │                               │
                ▼                               ▼
┌─────────────────────────┐       ┌─────────────────────────┐
│ batchConfirmAgentChange │       │ Sets deleted = true     │
│ or singleMemberAgent    │       │ Records deleted_by/on   │
│ Change()                │       │                         │
└─────────────────────────┘       └─────────────────────────┘

API Endpoints

Method Endpoint Controller Method Purpose
GET /change/agent viewChangeAgent Display change agent UI
GET /show/members_belonging_to_agent/details/{agent_code} showMemberAgentDetails DataTable for member accounts
POST /handle/multiple/member/agent/change/members_multiple handleMultipleMemberAgentChange Entry point for batch change
POST /multiple/member/agent/change/members_multiple multipleMemberAgentChange Execute batch change (same agent)
POST /batch/confirm/agent_change batchConfirmAgentChange ⭐ Batch confirm from queue
POST /single/member/agent/change handlesingleAgentChange Entry point for single change
POST /single/member/agent_change singleMemberAgentChange Execute single change
GET /confirm/agent_change pendingAgentChange View pending changes
POST /single/member/agent_change/cancel cancelAgentChange Cancel pending change

Frontend Changes Summary

confirm_change_of_agent.blade.php

The batch confirm button now:

  1. Collects change IDs (not member;account pairs)

  2. Groups and summarizes the selected changes by transfer direction

  3. Shows confirmation dialog with transfer summary:

    You are about to confirm 20 agent change(s):
    
    • IFA0033 → IFA0032: 10 account(s)
    • IFA0130 → IFA0131: 10 account(s)
    
    Are you sure you want to proceed?
    
  4. Calls new endpoint /batch/confirm/agent_change

  5. Sends change_ids array instead of member/account pairs + agent codes


Security Considerations

  1. Authentication: All routes protected by auth middleware
  2. Permission Check: create-Change-Of-Agent and confirm-agent-change permissions
  3. CSRF Protection: All POST requests require valid CSRF token
  4. Maker ≠ Checker: Same user cannot confirm their own changes
  5. Audit Trail: All changes logged to account_agent_log table
  6. Transaction Safety: Database transactions ensure data integrity

Logging

Check Laravel logs at storage/logs/laravel.log:

Log::info('=== STARTING BATCH CONFIRM AGENT CHANGE ===');
Log::info("Processing: {$memberAccountPair} | From: {$old_agent_code} | To: {$new_agent_code}");
Log::info("=== Successfully processed Change ID: {$pendingChange->id} ===");
Log::info("=== BATCH CONFIRM COMPLETED ===");
Log::info("Processed: {$processedCount}, Errors: X, Skipped: Y");

Document Version: 2.0
Last Updated: November 25, 2025
Major Update: Added batchConfirmAgentChange method for mixed batch confirmation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment