Buy Bill Controller Documentation
File: /controllers/buyBillController.php
Purpose: Manages purchase orders, buy bills, purchase returns, and supplier transactions
Last Updated: December 19, 2024
Total Functions: 57
Lines of Code: ~7000+
---
๐ Overview
The Buy Bill Controller is the core component for managing all purchase-related operations in the ERP system. It handles:
- โข Creating and editing purchase bills (buy bills)
- โข Managing purchase returns (return buy bills)
- โข Combined buy & return operations
- โข Purchase offers/quotations
- โข Inventory stock increases
- โข Supplier debt tracking
- โข Daily accounting entries for purchases
- โข Serial number tracking for purchased items
- โข Excel import for bulk purchases
Primary Functions
- โ Create new purchase bills
- โ Edit existing purchase bills
- โ Delete purchase bills
- โ View purchase bill details
- โ Print purchase bills
- โ Manage purchase returns
- โ Track serial numbers
- โ Generate accounting entries
- โ Update inventory quantities
- โ Excel import/export
Related Controllers
- โข sellbillController.php - Sales operations
- โข supplierController.php - Supplier management
- โข productController.php - Product management
- โข storeController.php - Warehouse/store management
- โข returnBuyBillController.php - Dedicated purchase returns
- โข storedetailController.php - Inventory management
- โข dailyentryController.php - Accounting entries
---
๐๏ธ Database Tables
Primary Tables (Direct Operations)
| Table Name | Purpose | Key Columns | |
|---|---|---|---|
| **buybill** | Main purchase bills | buybillid, buybillserial, buybilldate, buybilltotalbill, buybillsupplierid, buybillstoreid, buybillsaveid | |
| **buybilldetail** | Purchase bill line items | buybilldetailid, buybillid, buybilldetailproductid, buybilldetailquantity, buybilldetailprice | |
| **returnbuybill** | Purchase return bills | returnbuybillid, returnbuybillserial, returnbuybilltotalbill | |
| **returnbuybilldetail** | Return bill line items | returnbuybilldetailid, returnbuybillid, returnbuybilldetailproductid | |
| **buyandruternbill** | Combined buy & return | buybillid (combined operations) | |
| **buyandruternbilldetail** | Combined details | Details for mixed operations | |
| **buybilloffer** | Purchase quotations/offers | Same structure as buybill, conditions=1 | |
| **buybilldetailoffer** | Offer line items | Details for offers |
| Table Name | Purpose | Relationship | |
|---|---|---|---|
| **storedetail** | Stock quantities by store | Updated on buy/return | |
| **sizecolorstoredetail** | Stock by size/color | For variant products | |
| **storereport** | Stock movement history | Audit trail | |
| **buypriceshistorybook** | Purchase price history | Price tracking | |
| **productserial** | Serial number tracking | For serialized items |
| Table Name | Purpose | Relationship | |
|---|---|---|---|
| **supplier** | Supplier master data | buybill.buybillsupplierid | |
| **save** | Cash registers/safes | buybill.buybillsaveid | |
| **savedaily** | Daily cash movements | Financial reconciliation | |
| **dailyentry** | Accounting journal entries | Auto-generated from bills | |
| **buybillcurr** | Multi-currency support | Currency conversion |
| Table Name | Purpose | Relationship | |
|---|---|---|---|
| **product** | Product master data | Foreign key in details | |
| **productcat** | Product categories | product.productCatId | |
| **productunit** | Units of measurement | buybilldetail.productunitid | |
| **store** | Warehouses/stores | buybill.buybillstoreid | |
| **billname** | Bill templates/types | buybill.billnameid | |
| **billsettings** | Bill configuration | Per bill type settings | |
| **currency** | Currency definitions | For multi-currency | |
| **costcenter** | Cost centers | For cost allocation |
๐ง Key Functions
1. add()
Purpose: Create a new purchase bill (main entry point)
Called By: Form submission with ?do=add
Line: 3952
Parameters (via $_POST):
- โข
billnameid(int) - Bill template ID - โข
saveid(int) - Cash register/safe ID - โข
supplier(int) - Supplier ID - โข
storeid(int) - Store/warehouse ID - โข
ordertype(int) - 0=Bill, 1=Offer - โข
buyItr(int) - Number of line items - โข
product{n}- Product IDs (n=1 to buyItr) - โข
pronum{n}- Quantities - โข
proprice{n}- Unit prices - โข
totalbill(float) - Total before discount - โข
gendis(float) - General discount - โข
totalafterdiscount(float) - Total after discount - โข
genpay(float) - Payment amount
Returns: Array [billType, returnBuyBill_Id, buyBill_Id, buyAndReturnBill_Id, ordertype, billnameId]
Database Operations:
1. BEGIN TRANSACTION
2. INSERT into buybill - Main bill record
3. INSERT into buybilldetail - For each product line
4. UPDATE storedetail SET productquantity = productquantity + quantity - Increase stock
5. INSERT into storereport - Stock movement record
6. INSERT into buypriceshistorybook - Price history
7. UPDATE supplier SET supplierdebt = supplierdebt + totalBill - Update supplier debt
8. INSERT into savedaily - Cash movement (if payment made)
9. INSERT into dailyentry - Accounting journal entry
10. COMMIT TRANSACTION
Business Logic Flow:
1. Validate form data
2. Determine bill type (Buy, Return, or Both)
3. Create bill header record
4. Loop through products:
a. Insert detail record
b. Update stock quantity (call increaseProductQuantity)
c. Record price history
d. Handle serial numbers if applicable
5. Update supplier debt
6. Record cash payment
7. Create accounting entries (call doBillDailyEntry)
8. Commit or rollback on error
9. Redirect to success page with bill ID
Example Flow:
---
2. increaseProductQuantity()
Purpose: Increase stock quantity when purchasing products
Line: 6144
CRITICAL: This function was fixed for PHP 8.2 compatibility
Parameters:
- โข
$storedetailId(int) - Store detail record ID - โข
$productquantityBefore(float) - Current quantity - โข
$productChangeAmount(float) - Quantity to add - โข
$lastBuyPrice(float) - Purchase price - โข
$productnumber(float) - Unit conversion factor - โข
$colName(string) - Detail table column name - โข
$detailId(int) - Detail record ID - โข
$productId(int) - Product ID - โข
$tableName(string) - Detail table name - โข
$sizeColorStoreDetailId(int) - Size/color variant ID - โข
$sizeId(int) - Size ID - โข
$colorId(int) - Color ID - โข ... (additional parameters for accounting)
Returns: $productquantityAfter (float) - New quantity
Database Operations:
- โข UPDATE
storedetailSETproductquantity = Before + Change - โข UPDATE
sizecolorstoredetail(if product has size/color) - โข INSERT/UPDATE
buypriceshistorybook- Price tracking
Logic:
if (has size/color) {
UPDATE sizecolorstoredetail.quantity
UPDATE storedetail (sum all size/color quantities)
} else {
UPDATE storedetail.productquantity directly
}
PHP 8.2 Fix Applied:
- โข Changed from
updateQuantityWithSumChild()for all products - โข Now uses
updateQuantityPlusEqualORMinusEqual()for non-size/color products - โข Prevents setting quantity to 0 when sizecolorstoredetail is empty
---
3. doBillDailyEntry()
Purpose: Create accounting journal entries for purchase bills
Line: 6948
Parameters:
- โข
$billType(int) - 1=Return, 2=Buy, 3=Both - โข
$buyBill_Id(int) - Buy bill ID - โข
$returnBuyBill_Id(int) - Return bill ID - โข
$buyAndReturnBill_Id(int) - Combined bill ID - โข
$billTotalBeforeDiscount(float) - Subtotal - โข
$storeId(int) - Warehouse ID - โข
$taxVal(float) - Tax amount - โข
$totalpayed(float) - Payment amount - โข
$saveId(int) - Cash register ID - โข
$remin(float) - Remaining balance - โข
$supdata(object) - Supplier data - โข
$billDiscountVal(float) - Discount amount - โข
$taxOfDiscountVal(float) - Tax on discount - โข
$billAdditionVal(float) - Additional charges
Returns: void
Database Operations:
- โข INSERT into
dailyentry- Journal entry header - โข INSERT into
dailyentrydetail- Debit/credit lines
Accounting Entries Created:
For Buy Bill (Type 2):
Debit: Inventory (Store Account) XXX
Debit: VAT Receivable XXX
Credit: Supplier Payable XXX
Credit: Withholding Tax XXX
For Return Bill (Type 1):
Debit: Supplier Payable XXX
Credit: Inventory (Store Account) XXX
Credit: VAT Receivable XXX
---
4. insertStoredetail()
Purpose: Create new stock record or update existing
Line: 6295
CRITICAL: Fixed for PHP 8.2 - now properly handles non-size/color products
Parameters:
- โข
$storeid(int) - โข
$productid(int) - โข
$productChangeAmount(float) - โข
$sizeColorStoreDetailId(int) - โข
$sizeId(int) - โข
$colorId(int)
Logic:
if (size/color product) {
// Update sizecolorstoredetail
// Update main storedetail with SUM
} else {
if (storedetail exists) {
// PHP 8.2 FIX: Use updateQuantityPlusEqualORMinusEqual
// NOT updateQuantityWithSumChild (which returns 0)
} else {
// Insert new storedetail record
}
}
---
5. delete()
Purpose: Soft delete purchase bill (sets conditions=1)
Line: 5537
Parameters (via $_GET):
- โข
id(int) - Bill ID to delete - โข
ordertype(int) - 0=Bill, 1=Offer
Database Operations:
- โข UPDATE
buybillSETconditions = 1WHEREbuybillid = ? - โข Does NOT physically delete - preserves audit trail
---
6. showAll()
Purpose: Display list of all purchase bills
Line: 5347
Returns: Assigns to Smarty template
Database Operations:
- โข SELECT from
buybillJOINsupplierWHEREconditions = 0 - โข Calculates total bill amounts
---
7. showBillDetails()
Purpose: Load bill header and details for viewing/editing
Line: 5298
Parameters:
- โข
$buyBill_Id(int) - โข
$ordertype(int) - 0=Bill, 1=Offer
Returns: Array [billData, billDetails, currencyData]
Database Operations:
- โข SELECT from
buybillJOIN related tables - โข SELECT from
buybilldetailWHEREbuybillid = ? - โข SELECT currency conversion data if multi-currency
---
๐ Main Workflows
Workflow 1: Create Purchase Bill
User visits: ?do=bill&billnameid=X
โ
Display Form (bill.html)
โ
User fills:
- Supplier
- Store
- Products (barcode scan or select)
- Quantities
- Prices
โ
Submit POST ?do=add
โ
add() Function:
โโโ Validate data
โโโ BEGIN TRANSACTION
โโโ INSERT buybill
โโโ INSERT buybilldetail (foreach product)
โโโ increaseProductQuantity() (foreach product)
โโโ UPDATE supplier debt
โโโ INSERT savedaily (if payment)
โโโ doBillDailyEntry() (accounting)
โโโ COMMIT
โโโ Redirect to success page
โ
Display: notes2.html ("Success")
โ
Auto-redirect (1 sec): ?do=bill (new bill)
Files Involved:
- โข View:
/views/default/buyBillview/bill.html - โข Controller:
buyBillController.php::add() - โข Models: Buybill, Buybilldetail, Storedetail, Supplier, Save
- โข JavaScript:
/views/default/assets/js/buyBill.js
---
Workflow 2: Edit Existing Bill
?do=editbill&id=123
โ
Load bill data: showBillDetails(123)
โ
Display form pre-filled
โ
Submit POST ?do=update
โ
update() Function:
โโโ Load old bill data
โโโ Reverse old stock changes
โโโ Reverse old accounting entries
โโโ Apply new changes (like add())
โโโ Redirect
---
Workflow 3: Purchase Return
User scans "return" products
โ
Submit with negative quantities
โ
add() detects returns
โ
Creates returnbuybill record
โ
decreaseProductQuantity() (opposite of buy)
โ
Reverse accounting entries
---
๐ฏ URL Routes & Actions
| Action (`?do=`) | Method | Description | View Template | Line | |
|---|---|---|---|---|---|
| **bill** | GET | Display new bill form | bill.html | 492 | |
| **editbill** | GET | Edit existing bill form | edit.html | 756 | |
| **add** | POST | Create new bill | - | 1245 | |
| **update** | POST | Update existing bill | - | 1308 | |
| **details** | GET | View bill details (read-only) | details.html | 1412 | |
| **editprint** | GET | View/print bill | editprint.html | 1485 | |
| **delete** | POST | Soft delete bill | - | 1846 | |
| **show** | GET | List all bills | show.html | 1744 | |
| **showoffers** | GET | List quotations/offers | showoffers.html | 2209 | |
| **excelToBill** | GET/POST | Import from Excel | excelToBill.html | 1877 | |
| **sucess** | GET | Success message | notes2.html | 1869 |
โ ๏ธ Known Issues & Fixes
Issue 1: Stock Quantity Set to 0 on Second Buy (FIXED)
Problem: When buying a product for the second time, stock quantity becomes 0 instead of increasing
Cause: updateQuantityWithSumChild() was called for all products, which does SUM(quantity) FROM sizecolorstoredetail. For products without size/color, this table is empty, so SUM returns NULL โ 0
Fix: In insertStoredetail() line 6330-6340, added conditional:
if (has size/color) {
$storeDetailExt->updateQuantityWithSumChild(...);
} else {
$storeDetailExt->updateQuantityPlusEqualORMinusEqual(...);
}
Date Fixed: December 19, 2024
File: buyBillController.php lines 6330-6340
---
Issue 2: Property Assignment on Null (FIXED)
Problem: Fatal error: Attempt to assign property "entryComment" on null
Cause: PHP 8.2 doesn't allow assigning properties to uninitialized objects
Fix: Added $dailyEntry = new stdClass(); before property assignments
Line: 6993
Date Fixed: December 19, 2024
---
Issue 3: abs() TypeError (FIXED)
Problem: TypeError: abs(): Argument #1 must be of type int|float, string given
Cause: Empty string $billAdditionVal = '' passed to abs()
Fix: Cast to float before abs(): abs((float)$billAdditionVal)
Line: 7001
Date Fixed: December 19, 2024
---
๐ Permissions & Security
Required Permissions
- โข User must be authenticated (
include_once("../public/authentication.php")) - โข Permission to access buy bills module
- โข Store access permissions (users can be restricted to specific stores)
Security Checks
// Line 1246
include_once("../public/authentication.php");
// Store restrictions
if ($userdata->viewbills == 0) {
// Show only user's own bills
} elseif ($userdata->viewbills == 2) {
// Show group's bills
}
Input Validation
- โข Supplier ID must exist
- โข Store ID must exist
- โข Product IDs must be valid
- โข Quantities must be > 0
- โข Prices must be numeric
- โข Transaction used for atomicity
---
๐ Notes
Important Considerations
1. Transactions: All bill operations use database transactions for data integrity
2. Stock Updates: Stock is updated immediately upon bill creation
3. Accounting: Daily entries are auto-generated and linked to bills
4. Multi-Currency: System supports multiple currencies with conversion factors
5. Serial Numbers: Products can have serial number tracking
6. Cost Centers: Bills can be allocated to cost centers
7. Taxes: Multiple tax types supported (VAT, withholding tax)
8. Bill Templates: Different bill types via billname table
Performance Optimizations
- โข OPcache enabled (see CLAUDE.md)
- โข Session caching for MAC address
- โข Lazy loading of product data
- โข Index on foreign keys
Data Integrity
- โข Foreign key constraints ensure referential integrity
- โข Soft deletes preserve audit trail (
conditions=1) - โข Stock movements tracked in
storereport - โข Price history maintained in
buypriceshistorybook
---
๐ง Configuration & Settings
Bill Settings (via billsettings table)
- โข Enable/disable buy functionality
- โข Enable/disable return functionality
- โข Auto-numbering sequences
- โข Default accounts for accounting entries
- โข Tax calculation methods
Program Settings (via programsettings table)
- โข Decimal places for quantities
- โข Decimal places for prices
- โข Default store
- โข Default currency
- โข Inventory valuation method (FIFO, LIFO, Average)
---
๐ Related Documentation
- โข CLAUDE.md - PHP 8.2 Migration Guide
- โข sellbillController.md - Sales Operations
- โข Database Schema - Full database structure
- โข API Documentation - Web API endpoints
---
๐ Debugging Tips
Enable Debug Mode
// In buyBillController.php
error_reporting(E_ALL);
ini_set('display_errors', 1);
Check Stock Updates
SELECT * FROM storereport
WHERE storereportproductid = [PRODUCT_ID]
ORDER BY storereportdate DESC
LIMIT 10;
Verify Accounting Entries
SELECT * FROM dailyentry
WHERE dailyentrymodelid = [BILL_ID]
AND tablename = 'buybill';
Test Transaction Rollback
- โข Introduce intentional error in add() function
- โข Verify all changes are rolled back
- โข Check stock quantities remain unchanged
---
Documented By: AI Assistant
Review Status: โ Complete
Next Review: When major changes occur