SaveClose Documentation
Save Close Controller Documentation
File: /controllers/saveCloseController.php
Purpose: Manages cash register/safe closing operations with fund transfers and daily accounting
Last Updated: December 20, 2024
Total Functions: 16
Lines of Code: ~1,033
---
๐ Overview
The Save Close Controller manages the critical end-of-day operations for cash registers and safes. It handles the transfer of funds between different cash storage locations, maintains daily transaction logs, and ensures proper accounting entries for all cash movements. This system is essential for businesses that need to consolidate cash from multiple registers into secure storage locations.
Primary Functions
- โ Transfer funds between cash registers/safes
- โ Daily cash register closing operations
- โ Multi-currency support with conversion factors
- โ Comprehensive audit trail with daily entries
- โ Fund transfer validation and balance checking
- โ Reversal and correction capabilities
- โ Date range reporting and filtering
- โ Print-friendly transfer receipts
- โ User permission-based save access
Related Controllers
- โข saveController.php - Cash register management
- โข savedailyController.php - Daily transaction reporting
- โข cashTransferController.php - Regular cash transfers
- โข dailyentry.php - Accounting system integration
---
๐๏ธ Database Tables
Primary Tables (Direct Operations)
| Table Name | Purpose | Key Columns | |
|---|---|---|---|
| **saveclose** | Cash closing transactions | savecloseid, saveidfrom, saveidto, saveclosevalue, saveclosedate, conditions, dailyentryid, currencyId, conversionFactorFrom, conversionFactorTo | |
| **save** | Cash registers/safes | saveid, savename, savecurrentvalue, treeId, currencyId, conversionFactor | |
| **savedaily** | Daily transaction log | savedailyid, saveid, savedailychangeamount, savedailychangetype, processname, savedailymodelid, tablename |
| Table Name | Purpose | Key Columns | |
|---|---|---|---|
| **dailyentry** | Journal entries | dailyentryid, entryComment, reverseofid | |
| **dailyentrycreditor** | Credit entries | dailyentrycreditorid, dailyentryid, accountstreeid, value | |
| **dailyentrydebtor** | Debit entries | dailyentrydebtorId, dailyentryid, accountstreeid, value | |
| **accountstree** | Chart of accounts | accountstreeid, accountname |
| Table Name | Purpose | Key Columns | |
|---|---|---|---|
| **currency** | Currency definitions | currencyid, currencyname, conversionfactor | |
| **usergroup** | User groups | usergroupid, groupname | |
| **user** | System users | userid, username, usergroupid, closeSavid, saveids, searchinonesave | |
| **youtubelink** | Tutorial videos | youtubelinkid, title, url | |
| **programsettings** | System configuration | programsettingsid, settingkey, settingvalue |
๐ Key Functions
1. Default Action - Display Close Form
Location: Lines 144-180
Purpose: Display form for creating new cash closing transfers
Process Flow:
1. Save Access Control: Check user's save permissions
- If searchinonesave = 0: Show multiple saves based on saveids
- If searchinonesave = 1: Show only user's assigned save
2. Load Available Saves: Get accessible cash registers
3. Load Currency Options: Get active currencies for conversion
4. Display Form: Show transfer form with breadcrumbs
User Permission Logic:
if ($_SESSION['searchinonesave'] == 0) {
if ($_SESSION['saveids'] == 0) {
$saves = $mySaveEx->queryAllEX2(); // All saves
} else {
$queryString = ' and saveid in (' . $_SESSION['saveids'] . ')';
$saves = $mySaveEx->queryAllEX2($queryString); // Allowed saves
}
} else {
$queryString = ' and saveid = ' . $_SESSION['saveid'] . ' ';
$save = $mySaveEx->queryAllEXOne2($queryString); // Single save
}
Template: savecloseview/add.html
---
2. add() - Process Cash Closing
Location: Lines 333-466
Purpose: Execute cash transfer from source to destination safe with full accounting
Function Signature:
// POST Parameters
$saveidFrom = $_POST['saveidfrom']; // Source cash register
$saveidTo = (int) $userData->closeSavid; // Destination (user's close save)
$savecloseValue = $_POST['saveclosevalue']; // Amount to transfer
$comment = $_POST['comment']; // Transfer notes
Process Flow:
1. Validation: Get save data and validate transfer amount
2. Create Transfer Record: Insert saveclose table entry
3. Source Save Processing:
- Calculate new balance (current - transfer amount)
- Update save table
- Insert savedaily transaction record
4. Destination Save Processing:
- Calculate new balance (current + transfer amount)
- Update save table
- Insert savedaily transaction record
5. Accounting Entry: Create balanced journal entry
6. Currency Handling: Apply conversion factors for multi-currency
Currency Conversion:
// Convert transfer amount to save's currency
$savevaluechanged = round(($savevaluechanged * $saveConversionFactor), 4);
Accounting Entries:
// Debit: Destination Save Account
// Credit: Source Save Account
$dailyEntry->entryComment = 'ุชูููู ุฎุฒูุฉ ' . $saveDataFrom->savename;
$dailyEntryDebtor->accountstreeid = $toTreeId;
$dailyEntryDebtor->value = $savecloseValue;
$dailyEntryCreditor->accountstreeid = $fromTreeId;
$dailyEntryCreditor->value = $savecloseValue;
---
3. show() - Display Transfer History
Location: Lines 209-260
Purpose: Show filtered list of cash closing transactions
Process Flow:
1. Build Query Filters: Construct WHERE clause based on parameters
- ID filter: Specific transfer
- Date range: From/to dates
- Save permissions: User-based filtering
2. Execute Query: Get transfer history with save names
3. Display Results: Show transfers with breadcrumbs and YouTube links
Filter Examples:
// ID filter
if ($id > 0) {
$queryString .= " AND saveclose.savecloseid = $id ";
}
// Date filters
if ($startDate) {
$queryString .= ' AND saveclosedate >= "' . $startDate . '" ';
}
// Permission-based filtering
if ($_SESSION['searchinonesave'] == 0) {
if ($_SESSION['saveids'] != 0) {
$queryString .= ' and ( saveclose.saveidfrom in (' . $_SESSION['saveids'] .
') or saveclose.saveidto in (' . $_SESSION['saveids'] . ') ) ';
}
}
Template: savecloseview/show.html
---
4. editprint() - Print Transfer Receipt
Location: Lines 769-778
Purpose: Generate print-friendly transfer receipt
Template: savecloseview/editprint.html
---
5. tempdelete() - Temporarily Delete Transfer
Location: Lines 511-608
Purpose: Soft delete transfer and reverse financial impact
Process Flow:
1. Validation: Check destination save has sufficient funds for reversal
2. Mark as Deleted: Set conditions = 1
3. Reverse Destination: Subtract transfer amount from destination save
4. Restore Source: Add transfer amount back to source save
5. Update Transaction Logs: Record reversal in savedaily
6. Reverse Accounting: Cancel journal entry
Balance Validation:
$saveToValueafterValid = $saveToValueBefore - $savecloseValueInSaveCurr;
if ($saveToValueafterValid >= 0) {
$saveValuebeforeValid = 1; // OK to proceed
} else {
$saveValuebeforeValid = 0; // Insufficient funds
}
---
6. returndelete() - Restore Deleted Transfer
Location: Lines 610-766
Purpose: Restore previously deleted transfer
Process Flow:
1. Validation: Check source save has sufficient funds
2. Restore Transfer: Set conditions = 0
3. Re-execute Transfer: Move funds from source to destination
4. Update Logs: Record restoration in savedaily
5. Create Accounting: Generate new journal entry
---
7. delete() - Permanently Delete Transfer
Location: Lines 923-1032
Purpose: Completely cancel transfer with full reversal
Process Flow:
1. Load Original: Get transfer details
2. Reverse Transfer: Move funds back (destination โ source)
3. Mark Permanent: Set conditions = 2
4. Update Logs: Record cancellation
5. Reverse Accounting: Cancel original journal entry
---
8. getSaveValueAndPlus() - Calculate Addition Impact
Location: Lines 845-863
Purpose: Calculate save balance after adding funds
Function Signature:
function getSaveValueAndPlus($saveid, $savevaluechanged, $saveConversionFactor = 0)
Returns: Array with save ID, balance before, balance after, converted amount, conversion factor
---
9. getSaveValueAndMins() - Calculate Subtraction Impact
Location: Lines 866-884
Purpose: Calculate save balance after removing funds
Function Signature:
function getSaveValueAndMins($saveid, $savevaluechanged, $saveConversionFactor = 0)
Returns: Array with save ID, balance before, balance after, converted amount, conversion factor
---
10. updateSave() - Update Save Balance
Location: Lines 887-899
Purpose: Update cash register balance
Function Signature:
function updateSave($saveid, $savevalueafter)
---
11. insertSavedaily() - Log Transaction
Location: Lines 902-921
Purpose: Insert transaction into daily log
Function Signature:
function insertSavedaily($savedailysavebefore, $savedailychangeamount, $savedailychangetype,
$saveid, $processname, $savedailymodelid, $savedailysaveafter, $tablename)
---
๐ Workflows
Workflow 1: End-of-Day Cash Closing
---
Workflow 2: Transfer Reversal Process
---
๐ URL Routes & Actions
| URL Parameter | Function Called | Description | |
|---|---|---|---|
| (empty) | Default action | Display cash closing form | |
| `do=add` | `add()` | Process new cash transfer | |
| `do=show` | `show()` | Display transfer history | |
| `do=editprint` | `editprint()` | Print transfer receipt | |
| `do=sucess` | Success | Show success page | |
| `do=error` | Error | Show error page |
Add Transfer (do=add):
- โข
saveidfrom- Source cash register ID - โข
saveclosevalue- Transfer amount - โข
comment- Transfer description - โข
printTxt- Print option (1=print receipt)
Show History (do=show):
- โข
from- Start date (YYYY-MM-DD) [optional] - โข
to- End date (YYYY-MM-DD) [optional] - โข
id- Specific transfer ID [optional]
Print Receipt (do=editprint):
- โข
id- Transfer ID
AJAX Operations (via POST)
- โข
operation=1- Temporary delete - โข
operation=2- Restore delete - โข
choosedItem[]- Array of transfer IDs
---
๐งฎ Calculation Methods
Currency Conversion
// Convert from main currency to save currency
$savevaluechanged = round(($savevaluechanged * $saveConversionFactor), 4);
// Convert from save currency to main currency
$mainCurrencyAmount = round(($saveCurrencyAmount / $saveConversionFactor), 4);
Balance Calculations
// Addition to save
$saveValueafter = $saveValuebefore + $savevaluechanged;
// Subtraction from save
$saveValueafter = $saveValuebefore - $savevaluechanged;
// Validation check
if ($saveValueafter < 0) {
// Insufficient funds error
}
Transfer Impact Assessment
// Check if reversal is possible
$saveToValueafterValid = $saveToValueBefore - $savecloseValueInSaveCurr;
if ($saveToValueafterValid >= 0) {
$canReverse = true;
} else {
$canReverse = false;
$errorMessage = "Insufficient funds for reversal";
}
---
๐ Security & Permissions
User-Based Save Access
// Multiple save access
if ($_SESSION['searchinonesave'] == 0) {
if ($_SESSION['saveids'] == 0) {
// User can access all saves
} else {
// User limited to specific saves in saveids
$queryString = ' and saveid in (' . $_SESSION['saveids'] . ')';
}
} else {
// User limited to single assigned save
$queryString = ' and saveid = ' . $_SESSION['saveid'] . ' ';
}
Authentication
include_once("../public/authentication.php");
- โข All actions require valid user session
- โข User group permissions checked
- โข Branch-based data isolation
Input Validation
$saveidFrom = $_POST['saveidfrom'];
$saveidTo = (int) $userData->closeSavid; // Cast to integer
$savecloseValue = $_POST['saveclosevalue'];
Validation Rules:
- โข Transfer amount must be positive
- โข Source save must have sufficient funds
- โข Destination save must be valid
- โข User must have access to source save
Transaction Safety
- โข Database transactions with commit/rollback
- โข Balance validation before operations
- โข Atomic operations for fund movements
- โข Audit trail preservation
---
๐ Performance Considerations
Database Optimization
1. Indexes Recommended:
- saveclose(saveidfrom, saveidto, saveclosedate)
- saveclose(conditions, saveclosedate)
- save(saveid, conditions)
- savedaily(saveid, savedailydate)
2. Query Efficiency:
- Proper JOIN usage in reports
- Date range indexing
- Permission-based filtering
Memory Management
- โข Minimal data loading for dropdowns
- โข Efficient array operations
- โข Clean object instantiation
Currency Processing
- โข Rounding to 4 decimal places for precision
- โข Conversion factor caching
- โข Efficient calculation methods
Known Performance Issues
// Potential issue: Multiple save loads in complex operations
$saveDataFrom = $mySaveRecord->load($saveidFrom);
$saveDataTo = $mySaveRecord->load($saveidTo);
// Consider caching save data for repeated operations
---
๐ Common Issues & Troubleshooting
1. Insufficient Funds for Transfer
Issue: Transfer fails due to insufficient source funds
Cause: No balance validation before transfer
Debug:
SELECT savecurrentvalue FROM save WHERE saveid = [SOURCE_ID];
Prevention: Add balance check in validation
2. Currency Conversion Errors
Issue: Incorrect amounts after currency conversion
Cause: Missing or wrong conversion factors
Debug:
echo "Original Amount: $savecloseValue<br>";
echo "Conversion Factor: $saveConversionFactor<br>";
echo "Converted Amount: " . round(($savecloseValue * $saveConversionFactor), 4) . "<br>";
3. Accounting Entry Imbalance
Issue: Debits don't equal credits in journal entries
Cause: Currency conversion applied inconsistently
Fix:
// Ensure same amount used for both debit and credit
$dailyEntryDebtor->value = $savecloseValue;
$dailyEntryCreditor->value = $savecloseValue; // Same amount
4. Permission Errors
Issue: Users can't see their transfers
Cause: Incorrect save permission filtering
Debug:
echo "User Save IDs: " . $_SESSION['saveids'] . "<br>";
echo "Search in One Save: " . $_SESSION['searchinonesave'] . "<br>";
echo "User Save ID: " . $_SESSION['saveid'] . "<br>";
5. Reversal Validation Failures
Issue: Cannot reverse transfer due to validation errors
Cause: Destination save doesn't have enough funds
Solution: Check if other transactions occurred after the original transfer
---
๐งช Testing Scenarios
Test Case 1: Basic Cash Transfer
1. Login with user having multiple save access
2. Select source register with sufficient funds
3. Enter transfer amount less than current balance
4. Submit transfer
5. Verify: Source decreased, destination increased, accounting entry created
Test Case 2: Multi-Currency Transfer
1. Setup saves with different currencies
2. Create transfer between different currency saves
3. Verify conversion factors applied correctly
4. Check saved amounts in respective currencies
Test Case 3: Transfer Reversal
1. Create successful transfer
2. Attempt to reverse transfer
3. Verify destination has sufficient funds
4. Execute reversal
5. Check: Balances restored, accounting entries reversed
Test Case 4: Insufficient Funds Prevention
1. Select source with low balance
2. Enter transfer amount greater than balance
3. Verify appropriate error handling
4. Ensure no partial transactions
Test Case 5: Permission-Based Access
1. Login with restricted user
2. Verify only authorized saves visible
3. Attempt transfer from unauthorized save
4. Check access control enforcement
Debug Mode Enable
// Add at top for debugging
error_reporting(E_ALL);
ini_set('display_errors', 1);
// Debug fund movements
echo "Source Before: $saveFromValuebefore<br>";
echo "Source After: $saveFromValueafter<br>";
echo "Destination Before: $saveToValuebefore<br>";
echo "Destination After: $saveToValueafter<br>";
echo "Transfer Amount: $savecloseValue<br>";
---
๐ Related Documentation
- โข CLAUDE.md - PHP 8.2 migration guide
- โข saveController.php - Cash register management
- โข savedailyController.php - Daily transaction reports
- โข cashTransferController.php - Regular transfers
- โข dailyentry.php - Accounting system
- โข Database Schema Documentation - Table relationships
---
Documented By: AI Assistant
Review Status: โ Complete
Next Review: When major changes occur