Checkwithdrawal Documentation

Check Withdrawal Controller Documentation

File: /controllers/checkwithdrawalController.php

Purpose: Manages check withdrawals for supplier payments with comprehensive financial tracking

Last Updated: December 20, 2024

Total Functions: 10

Lines of Code: ~1,027

---

๐Ÿ“‹ Overview

The Check Withdrawal Controller is a sophisticated financial management module that handles check payments to suppliers with comprehensive account tracking and debt management. It handles:

Primary Functions

Financial Impact

When Check Withdrawn:

1. Bank Account: Decreased by check amount

2. Supplier Debt: Decreased by check amount

3. Account Movement: Withdrawal transaction recorded

4. Daily Entry: Debit supplier account, credit bank account

When Check Cancelled:

1. Bank Account: Increased by check amount (reversed)

2. Supplier Debt: Increased by check amount (reversed)

3. Account Movement: Deposit transaction recorded

4. Daily Entry: Reversed automatically

Related Controllers

---

๐Ÿ—„๏ธ Database Tables

Primary Tables (Direct Operations)

Table NamePurposeKey Columns
**checkwithdrawal**Check withdrawal recordscheckwithdrawalid, bankaccountid, supplierid, checkwithdrawalamount, checkwithdrawalnumber, conditions, dailyentryid
**accountmovement**Bank account movementsaccountmovementid, accountid, accountmovementamount, accountmovementtype, tablename, accountmovementmodelid
**supplierdebtchange**Supplier debt trackingsupplierdebtchangeid, supplierid, supplierdebtchangeamount, supplierdebtchangetype, tablename, supplierdebtchangemodelid
### Reference Tables

Table NamePurposeKey Columns
**bankaccount**Bank account masteraccountid, accountname, accountbeginingbalance, bankid, treeId
**bank**Bank informationbankid, bankname
**supplier**Supplier master datasupplierid, suppliername, suppliercurrentDebt, treeId, inUse
**user**System usersuserid, username
### Accounting Tables

Table NamePurposeKey Columns
**dailyentry**Journal entry headerdailyentryid, entryComment, userid
**dailyentrycreditor**Credit side entriesdailyentrycreditorid, dailyentryid, accountstreeid, value
**dailyentrydebtor**Debit side entriesdailyentrydebttorid, dailyentryid, accountstreeid, value
**accountstree**Chart of accountsaccountstreeid, accountname
---

๐Ÿ”‘ Key Functions

1. Default Action - Add Check Form

Location: Lines 141-164

Purpose: Display form to create new check withdrawal

Process Flow:

1. Load all banks with extended information

2. Load all suppliers for selection

3. Display add form template

4. Set custom validation flag

Template Variables:

---

2. add - Create Check Withdrawal

Location: Lines 401-624

Purpose: Process new check withdrawal with full financial impact

Function Signature:

function add()

Process Flow:

Phase 1: Input Validation and Setup

$supplierid = $_POST["supplierid"];
$accountid = (int) $_POST["accountid"];
$checkwithdrawalamount = $_POST["txtAmount"];
$checkwithdrawalnumber = $_POST["txtcheckNum"];
$checkwithdrawaluser = $_POST["txtUser"];
$checkwithdrawalnote = $_POST["textNote"];

Phase 2: Check Withdrawal Record Creation

$checkWithdrawal->bankaccountid = $accountid;
$checkWithdrawal->supplierid = $supplierid;
$checkWithdrawal->accountbeforevalue = $accountbeginingbalance;
$checkWithdrawal->checkwithdrawalamount = $checkwithdrawalamount;
$checkWithdrawal->checkwithdrawaldate = date("Y-m-d H:i:s");
$checkWithdrawal->conditions = 0; // Active
$checkWithdrawal->userid = $_SESSION['userid'];

$checkWithdrawalId = $checkWithdrawalDAO->insert($checkWithdrawal, $checkwithdrawalnote);

Phase 3: Supplier Debt Management

// Load supplier with concurrency control
$supplierdata = getSupplierDataFromSupplierInUseSP($supplierid);
$debtBefore = $supplierdata->suppliercurrentDebt;

// Update supplier debt (decrease by check amount)
$Supplier->suppliercurrentDebt = ($debtBefore - $checkwithdrawalamount);
$SupplierEX->updatedept($Supplier);

// Record debt change
$supDebtChange->supplierdebtchangebefore = $debtBefore;
$supDebtChange->supplierid = $supplierid;
$supDebtChange->supplierdebtchangeamount = $checkwithdrawalamount;
$supDebtChange->supplierdebtchangetype = 1; // Decrease
$supDebtChange->tablename = "checkwithdrawalController.php";
$supDebtChange->supplierdebtchangemodelid = $checkWithdrawalId;
$supDebtChange->supplierdebtchangeafter = $debtBefore - $checkwithdrawalamount;
$supDebtChange->processname = "ุฏูุน ุดูŠูƒ"; // "Check payment"

$supDebtChangeDAO->insert($supDebtChange);

Phase 4: Bank Account Update

$accoundatat = $accountDAO->load($accountid);
$accountBefore = $accoundatat->accountbeginingbalance;

// Update account balance (decrease by check amount)
$account->accountbeginingbalance = $accountBefore - $checkwithdrawalamount;
$accountExtDAO->updateacount($account);

// Record account movement
$accountMove->accountmovementbefore = $accountBefore;
$accountMove->accountid = $accountid;
$accountMove->accountmovementamount = $checkwithdrawalamount;
$accountMove->accountmovementafter = $accountBefore - $checkwithdrawalamount;
$accountMove->accountmovementtype = 1; // Withdrawal
$accountMove->processname = "ุณุญุจ ุดูŠูƒ"; // "Check withdrawal"
$accountMove->tablename = "checkwithdrawalController.php";
$accountMove->accountmovementmodelid = $checkWithdrawalId;

$accountMoveDAO->insert($accountMove);

Phase 5: Daily Entry Generation

$dailyEntry->entryComment = 'ุชู… ุนู…ู„ ุณุญุจ ุดูŠูƒ ู„ู„ู…ูˆุฑุฏ (  ' . $supplierdata->suppliername . ' )';

// Debit: Supplier account (debt reduction)
$dailyEntryDebtor->value = $checkwithdrawalamount;
$dailyEntryDebtor->accountstreeid = $supplierdata->treeId;

// Credit: Bank account
$dailyEntryCreditor->value = $checkwithdrawalamount;
$accountData = $accountDAO->load($accountid);
$dailyEntryCreditor->accountstreeid = $accountData->treeId;

$returnedData = insertEntery($dailyEntry, $dailyEntryDebtorArray, $dailyEntryCreditorArray, 1, $checkWithdrawalId, "checkwithdrawalController.php?do=show&id=$checkWithdrawalId");

Error Handling:

Return Values:

---

3. show - Display Check List

Location: Lines 627-690

Purpose: Search and display check withdrawals based on criteria

Function Signature:

function show()

Search Criteria:

Date Range Search:

$from = $_REQUEST["from"];
$to = $_REQUEST["to"];

if (isset($to) && $to != "" && isset($from) && $from != "") {
    $message = "ุนุฑุถ ุงู„ู…ุณุญูˆุจุงุช  ู…ู† ุชุงุฑูŠุฎ : " . $from . "  ุงู„ู‰ ุชุงุฑูŠุฎ  " . $to;
    $shownData = $checkWithdrawalExtDAO->queryBydateExt($from, $to);
}

Supplier Filter:

$supplierid = $_REQUEST["supplierid"];

if (isset($supplierid) && $supplierid != "-1") {
    $mysupplierdata = $SupplierDAO->load($supplierid);
    $message = "ุนุฑุถ ุงู„ู…ุณุญูˆุจุงุช ู„ู„ู…ูˆุฑุฏ : " . $mysupplierdata->suppliername;
    $shownData = $checkWithdrawalExtDAO->queryWithSupplieridExt($supplierid);
}

Specific Check ID:

$id = (int) $_REQUEST["id"];

if (isset($id) && $id > 0) {
    $message = "ุนุฑุถ ุงู„ู…ุณุญูˆุจุงุช  ุฑู‚ู…: " . $id;
    $temp = $checkWithdrawalExtDAO->loadExt($id);
    $shownData = array($temp);
}

Default (Today's Checks):

else {
    $message = "ุนุฑุถ ุงู„ู…ุณุญูˆุจุงุช  ู…ู† ุชุงุฑูŠุฎ : " . date("Y-m-d") . "  ุงู„ู‰ ุชุงุฑูŠุฎ :   " . date("Y-m-d");
    $shownData = $checkWithdrawalExtDAO->queryBydateExt(date("Y-m-d"), date("Y-m-d"));
}

---

4. delete - Cancel Check Withdrawal

Location: Lines 694-850

Purpose: Reverse check withdrawal with complete financial reversal

Function Signature:

function delete($id)

Process Flow:

Phase 1: Load Check Data

$checkdata = $checkWithdrawalDAO->load($checkid);
$accountid = $checkdata->bankaccountid;
$checkwithdrawalamount = $checkdata->checkwithdrawalamount;
$supplierid = $checkdata->supplierid;

Phase 2: Reverse Supplier Debt

$supplierdata = getSupplierDataFromSupplierInUseSP($supplierid);
$debtBefore = $supplierdata->suppliercurrentDebt;

// Increase supplier debt (reverse the payment)
$Supplier->suppliercurrentDebt = ($debtBefore + $checkwithdrawalamount);
$SupplierEX->updatedept($Supplier);

// Record reversal in debt change
$supDebtChange->supplierdebtchangebefore = $debtBefore;
$supDebtChange->supplierdebtchangeamount = $checkwithdrawalamount;
$supDebtChange->supplierdebtchangetype = 0; // Increase
$supDebtChange->tablename = "checkwithdrawalController.php";
$supDebtChange->supplierdebtchangeafter = $debtBefore + $checkwithdrawalamount;
$supDebtChange->processname = "ุญุฐู ุฏูุน ุดูŠูƒ"; // "Delete check payment"

$supDebtChangeDAO->insert($supDebtChange);

Phase 3: Mark Check as Deleted

$checkWithdrawal->conditions = 1; // Deleted
$checkWithdrawal->checkwithdrawalid = $checkid;
$checkWithdrawalExtDAO->updatedel($checkWithdrawal);

Phase 4: Reverse Bank Account

$accountdata = $accountDAO->load($accountid);
$accountBefore = $accountdata->accountbeginingbalance;

// Increase account balance (reverse the withdrawal)
$account->accountbeginingbalance = $accountBefore + $checkwithdrawalamount;
$accountExtDAO->updateacount($account);

// Record reversal movement
$accountMove->accountmovementbefore = $accountBefore;
$accountMove->accountmovementamount = $checkwithdrawalamount;
$accountMove->accountmovementafter = $accountBefore + $checkwithdrawalamount;
$accountMove->accountmovementtype = 0; // Deposit
$accountMove->processname = "ุงู„ุบุงุก ุณุญุจ ุดูŠูƒ"; // "Cancel check withdrawal"
$accountMove->tablename = "wirhdrawalCheckController.php";

$accountMoveDAO->insert($accountMove);

Phase 5: Reverse Daily Entry

// Reverse the original daily entry
if (isset($dailyentry) && $dailyentryid2 == '') {
    reverseEntryWithItsID($dailyentry, 1);
} else {
    reverseEntryWithItsID($dailyentryid2, 1);
}

Return Values:

---

5. edit - Load Check for Editing

Location: Lines 853-879

Purpose: Load check data with debt information for editing

Function Signature:

function edit()

Process Flow:

1. Load check withdrawal with supplier information

2. Load related debt change information

3. Calculate debt before/after values

4. Return data object for form population

Debt Information Loading:

$showData = $checkWithdrawalExtDAO->queryByIdExtwithsuplier($id);

if ($showData->suppliername) {
    $debtRow = R::getRow('select supplierdebtchangebefore,supplierdebtchangeafter from supplierdebtchange where tablename="checkwithdrawalController.php" and supplierdebtchangemodelid=' . $id);
    $debtBefore = $debtRow['supplierdebtchangebefore'];
    $debtAfter = $debtRow['supplierdebtchangeafter'];
}

---

6. update - Update Check Details

Location: Lines 882-902

Purpose: Update only user and note fields (amount cannot be changed)

Function Signature:

function update()

Updateable Fields:

Restriction: Check amount, supplier, and bank account cannot be changed after creation.

---

7. execute - Bulk Operations

Location: Lines 927-984

Purpose: Perform bulk operations on multiple selected checks

Function Signature:

function execute()

Process Flow:

1. Get operation type and selected check IDs

2. For each selected check:

- Validate operation (only active checks can be deleted)

- Execute delete operation

- Record success/failure messages

3. Display results summary

Operation Types:

Validation:

if ($operationType == '1' && $conditions == 0) { // Can delete only active checks
    $note = delete($checkId);
    if ($note != "sucess") {
        $outputString .= $checkwithdrawalnumber . ": " . $note . "<br/>";
    } else {
        $outputString .= $checkwithdrawalnumber . ": ุชู…ุช ุงู„ุนู…ู„ูŠุฉ ุจู†ุฌุงุญ <br/>";
    }
} else {
    $outputString .= $checkwithdrawalnumber . ": ู„ุง ูŠู…ูƒู† ุงู„ุบุงุก ู‡ุฐุง ุงู„ุดูŠูƒ ู„ุงู†ู‡ ู…ู„ุบู‰ ุณุงุจู‚ุง<br/>";
}

---

8. getSupplierDataFromSupplierInUseSP - Concurrency Management

Location: Lines 986-1007

Purpose: Load supplier data with concurrency control to prevent debt conflicts

Function Signature:

function getSupplierDataFromSupplierInUseSP($supplier)

Concurrency Logic:

$supplier_data = $SupplierEX->callSupplierInUseSP($supplier);

while ($supplier_data->suppliercurrentDebt == 'in_use') {
    sleep(1); // Wait 1 second
    $noOfTries++;
    if ($noOfTries > 15) { // Max 15 seconds wait
        // Force unlock supplier
        R::exec('UPDATE supplier SET inUse = 0 where supplierid = ' . $supplier);
    }
    $supplier_data = $SupplierEX->callSupplierInUseSP($supplier);
}

Purpose: Prevents multiple users from simultaneously modifying the same supplier's debt, which could lead to data corruption.

---

๐Ÿ”„ Workflows

Workflow 1: Check Withdrawal Creation

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
START: User Creates Check
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
1Form Input Validation
- Supplier ID and name
- Bank account selection
- Check amount and number
- Check recipient and notes
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
2Create Check Withdrawal Record
- Insert into checkwithdrawal table
- Record check details and timestamp
- Set conditions = 0 (active)
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
3Update Supplier Debt
- Load supplier with concurrency control
- Calculate new debt (current - check amount)
- Update supplier record
- Record debt change transaction
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
4Update Bank Account
- Load current account balance
- Calculate new balance (current - check amount)
- Update account record
- Record account movement transaction
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
5Generate Accounting Entry
- Create daily entry header
- Debit: Supplier account (debt reduction)
- Credit: Bank account (cash outflow)
- Link entry ID to check withdrawal
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
6Finalize Transaction
- Commit database transaction
- Release supplier concurrency lock
- Return success status
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

---

Workflow 2: Check Withdrawal Cancellation

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
START: User Cancels Check
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
1Load Check Data
- Retrieve original check withdrawal record
- Get check amount, supplier ID, account ID
- Verify check is active (conditions = 0)
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
2Reverse Supplier Debt
- Load supplier with concurrency control
- Increase debt by check amount (reverse payment)
- Update supplier record
- Record debt change as increase
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
3Mark Check as Deleted
- Set conditions = 1 (deleted)
- Update check withdrawal record
- Preserve original data for audit
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
4Reverse Bank Account
- Load current account balance
- Increase balance by check amount (reverse withdrawal)
- Update account record
- Record account movement as deposit
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
5Reverse Accounting Entry
- Locate original daily entry
- Create reversing entry
- Update daily entry status
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
6Complete Reversal
- Commit transaction
- Release supplier concurrency lock
- Return success status
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

---

๐ŸŒ URL Routes & Actions

URL ParameterFunction CalledDescription
(no parameters)Default actionDisplay add check form
`do=add``add()`Process new check withdrawal
`do=show``show()`Display check list with filters
`do=delete``delete()`Cancel/delete check withdrawal
`do=edit``edit()`Load check data for editing
`do=update``update()`Update check user/notes only
`do=details``edit()`Display check details (read-only)
`do=editprint``edit()`Display check in print format
`do=executeOperation``execute()`Bulk operations on selected checks
`do=sucess`Success pageDisplay success message
`do=error`Error pageDisplay error message
### Required Parameters by Action

Create Check (do=add):

Show Checks (do=show):

Delete Check (do=delete):

Edit Check (do=edit):

Update Check (do=update):

Bulk Operations (do=executeOperation):

---

๐Ÿงฎ Financial Calculations

Check Withdrawal Impact

// Bank Account Balance
$newAccountBalance = $currentAccountBalance - $checkAmount;

// Supplier Debt  
$newSupplierDebt = $currentSupplierDebt - $checkAmount;

// Account Movement
$accountMovement = [
    'before' => $currentAccountBalance,
    'amount' => $checkAmount,
    'after' => $newAccountBalance,
    'type' => 1  // Withdrawal
];

// Supplier Debt Change
$supplierDebtChange = [
    'before' => $currentSupplierDebt,
    'amount' => $checkAmount,
    'after' => $newSupplierDebt,
    'type' => 1  // Decrease
];

Check Cancellation Impact

// Bank Account Balance (Reversal)
$newAccountBalance = $currentAccountBalance + $checkAmount;

// Supplier Debt (Reversal)
$newSupplierDebt = $currentSupplierDebt + $checkAmount;

// Account Movement (Reversal)
$accountMovement = [
    'before' => $currentAccountBalance,
    'amount' => $checkAmount,
    'after' => $newAccountBalance,
    'type' => 0  // Deposit
];

// Supplier Debt Change (Reversal)
$supplierDebtChange = [
    'before' => $currentSupplierDebt,
    'amount' => $checkAmount,
    'after' => $newSupplierDebt,
    'type' => 0  // Increase
];

Daily Entry Structure

// Debit Side: Supplier Account (Accounts Payable decrease)
$debitEntry = [
    'accountstreeid' => $supplier->treeId,
    'value' => $checkAmount,
    'description' => 'Check payment to supplier'
];

// Credit Side: Bank Account (Cash decrease)
$creditEntry = [
    'accountstreeid' => $bankAccount->treeId,
    'value' => $checkAmount,
    'description' => 'Check withdrawal from bank'
];

---

๐Ÿ”’ Security & Permissions

Access Control

// All actions require authentication
include_once("../public/authentication.php");

// User session tracking
$checkWithdrawal->userid = $_SESSION['userid'];

Input Validation

// Type casting for critical fields
$accountid = (int) $_POST["accountid"];
$id = (int) $_REQUEST["id"];

// SQL injection prevention through DAO layer
// All database operations use parameterized queries

Concurrency Control

// Supplier locking mechanism
function getSupplierDataFromSupplierInUseSP($supplier) {
    $supplier_data = $SupplierEX->callSupplierInUseSP($supplier);
    
    while ($supplier_data->suppliercurrentDebt == 'in_use') {
        sleep(1); // Wait for lock release
        $noOfTries++;
        
        if ($noOfTries > 15) {
            // Force unlock after 15 seconds
            R::exec('UPDATE supplier SET inUse = 0 where supplierid = ' . $supplier);
        }
        
        $supplier_data = $SupplierEX->callSupplierInUseSP($supplier);
    }
    
    return $supplier_data;
}

Transaction Integrity

// Database transactions ensure consistency
$mytransactions = new Transaction();
try {
    // All operations
    $mytransactions->commit();
} catch (Exception $ex) {
    $mytransactions->rollback();
    markSupplierAsNOTInUse($supplierid);
}

---

๐Ÿ“Š Performance Considerations

Database Optimization Tips

1. Critical Indexes:

- checkwithdrawal(bankaccountid, supplierid) - For account/supplier searches

- checkwithdrawal(checkwithdrawaldate) - For date range queries

- supplierdebtchange(tablename, supplierdebtchangemodelid) - For linking

2. Query Optimization:

- Date range queries could benefit from partitioning

- Supplier concurrency could use database-level locking

- Extended DAO queries load multiple related tables

3. Concurrency Issues:

- Sleep-based waiting is inefficient

- Could implement proper database locking

- Supplier "inUse" flag needs timeout mechanism

Performance Bottlenecks

// This pattern appears frequently and could be optimized:
while ($supplier_data->suppliercurrentDebt == 'in_use') {
    sleep(1); // Inefficient - blocks thread
    $noOfTries++;
    if ($noOfTries > 15) {
        // Force unlock - could cause data inconsistency
        R::exec('UPDATE supplier SET inUse = 0 where supplierid = ' . $supplier);
    }
}

Better Approach:

-- Use database-level locking instead
SELECT ... FROM supplier WHERE supplierid = ? FOR UPDATE;

---

๐Ÿ› Common Issues & Troubleshooting

1. Check Creation Fails with Insufficient Balance

Issue: Check withdrawal fails even when account has sufficient funds

Cause: Concurrency issues or stale balance data

Debug:

-- Check current account balance
SELECT accountbeginingbalance FROM bankaccount WHERE accountid = [ACCOUNT_ID];

-- Check recent movements
SELECT * FROM accountmovement 
WHERE accountid = [ACCOUNT_ID] 
ORDER BY accountmovementdate DESC 
LIMIT 10;

2. Supplier Debt Not Updating

Issue: Supplier debt doesn't decrease after check withdrawal

Cause: Concurrency lock issues or transaction rollback

Debug:

-- Check supplier lock status
SELECT supplierid, suppliercurrentDebt, inUse FROM supplier WHERE supplierid = [SUPPLIER_ID];

-- Check recent debt changes
SELECT * FROM supplierdebtchange 
WHERE supplierid = [SUPPLIER_ID] 
ORDER BY supplierdebtchangedate DESC 
LIMIT 5;

3. Daily Entry Not Generated

Issue: Accounting entry missing for check withdrawal

Cause: Missing tree IDs or daily entry function failure

Debug:

-- Check tree ID assignments
SELECT s.supplierid, s.suppliername, s.treeId as supplier_tree,
       ba.accountid, ba.accountname, ba.treeId as account_tree
FROM supplier s, bankaccount ba 
WHERE s.supplierid = [SUPPLIER_ID] AND ba.accountid = [ACCOUNT_ID];

-- Check if daily entry was created
SELECT * FROM dailyentry WHERE tablename = 'checkwithdrawalController.php' 
ORDER BY dailyentrydate DESC LIMIT 5;

4. Concurrency Timeout Issues

Issue: Multiple users cannot work with same supplier simultaneously

Cause: Supplier locking mechanism too aggressive

Solutions:

---

๐Ÿงช Testing Scenarios

Test Case 1: Normal Check Withdrawal

1. Select supplier with sufficient debt
2. Select bank account with sufficient funds
3. Create check withdrawal
4. Verify all tables updated correctly:
   - checkwithdrawal record created
   - bankaccount balance decreased
   - supplier debt decreased
   - accountmovement recorded
   - supplierdebtchange recorded
   - dailyentry generated

Test Case 2: Check Cancellation

1. Create check withdrawal
2. Cancel the check
3. Verify all reversals work:
   - Check marked as deleted (conditions = 1)
   - Bank account balance restored
   - Supplier debt restored
   - Reversal movements recorded
   - Daily entry reversed

Test Case 3: Concurrent Access

1. Two users try to create checks for same supplier
2. Verify concurrency control works
3. Check that only one succeeds initially
4. Verify second user can proceed after first completes

Test Case 4: Bulk Operations

1. Create multiple check withdrawals
2. Select subset for bulk cancellation
3. Verify all selected checks are cancelled
4. Verify unselected checks remain active
5. Check output messages for success/failure

---

๐Ÿ“š Related Documentation

---

Documented By: AI Assistant

Review Status: โœ… Complete

Next Review: When major changes occur