๐Ÿ“š ERP Documentation Viewer

Beautiful, colorful documentation for your ERP system

Sell Bill Controller Documentation

File: /controllers/sellbillController.php

Purpose: Manages sales orders, sell bills, sales returns, and customer transactions

Last Updated: December 19, 2024

Total Functions: 95+

Lines of Code: ~14,765

---

๐Ÿ“‹ Overview

The Sell Bill Controller is the core component for managing all sales-related operations in the ERP system. It handles:

Primary Functions

Related Controllers

---

๐Ÿ—„๏ธ Database Tables

Primary Tables (Direct Operations)

Table NamePurposeKey Columns
**sellbill**Main sales billssellbillid, sellbillserial, sellbilldate, sellbilltotalbill, sellbillclientid, sellbillstoreid, sellbillsaveid
**sellbilldetail**Sales bill line itemssellbilldetailid, sellbilldetailproductid, sellbilldetailproductquantity, sellbilldetailproductprice, sellbillid
**returnsellbill**Sales return billsreturnsellbillid, returnsellbillserial, returnsellbilldate, returnsellbilltotalbill, returnsellbillclientid
**returnsellbilldetail**Return bill line itemsreturnsellbilldetailid, returnsellbilldetailproductid, returnsellbilldetailproductquantity, returnsellbillid
**sellbillandrutern**Combined sell & return billssellbillandruternid, sellbillandruternserial, sellbillandruterndate, sellbillandruternclientid
**sellandruternbilldetail**Combined bill detailssellandruternbilldetailid, sellandruternbilldetailproductid, sellandruternbilldetailproductquantity
### Inventory Tables (Stock Management)

Table NamePurposeKey Columns
**storedetail**Current stock levelsstoredetailid, storeid, productid, productquantity
**storereport**Stock movement historystorereportid, productid, storeid, storereporttype, storereportmodelid
**sizecolorstoredetail**Stock by size/colorsizecolorstoredetailid, storeid, productid, sizeid, colorid, quantity
**productserial**Serial number masterproductserailid, serialnumber, productid, don (sold flag)
**soldserialproduct**Sold serial trackingsoldserialproductid, productserailid, soldquantity, sellbillid, clientid
**buypricesh istorybook**FIFO/LIFO cost trackingbuypricesh istorybookid, productid, storeid, quantity, buyprice
### Financial Tables

Table NamePurposeKey Columns
**client**Customer accountsclientid, clientname, clientdebt (running balance)
**clientdebtchange**Customer payment historyclientdebtchangeid, clientid, clientdebtchangeamount, clientdebtchangetype
**save**Cash registers/safessaveid, savename, savevalue (current balance)
**savedaily**Cash register movementssavedailyid, saveid, savedailychangeamount, savedailychangetype
**dailyentry**Journal entriesdailyentryid, dailyentrymodelid, tablename, sysdate
**dailyentrydebtor**Debit entriesdailyentrydebtorid, dailyentryid, accountid, value
**dailyentrycreditor**Credit entriesdailyentrycreditorid, dailyentryid, accountid, value
**bankaccountmovement**Bank transactionsbankaccountmovementid, accountid, bankid, amount, type
### Reference Tables

Table NamePurposeKey Columns
**product**Product masterproductid, productname, productcatid
**billname**Bill templatesbillnameid, billname, billtype
**billsettings**Bill configurationbillsettingsid, billnameid, settings (JSON)
**user**System usersuserid, username
**programsettings**System settingsprogramsettingsid, key, value
---

๐Ÿ”‘ Key Functions

1. add() - Create New Sales Bill

Location: Line 2579

Purpose: Main function to create a new sales bill (regular/restaurant/quotation)

Function Signature:

function add()

Process Flow:

1. Begin transaction

2. Retrieve bill settings (billnameid, billtype)

3. Generate bill serial number

4. Create sellbill record

5. Loop through products:

- Validate stock availability

- Create sellbilldetail records

- Decrease stock via decreaseProductQuantity()

- Track serial numbers if applicable

- Calculate profit via quickProfitRow()

6. Handle multi-payment (cash, visa, bank)

7. Update customer debt via updateClientDebt()

8. Update cash register via getSaveValueAndPlus()

9. Generate accounting entries via doBillDailyEntry()

10. Handle collective products (recipes) if applicable

11. Commit transaction

12. Redirect to success page

Key Variables:

Dependencies:

---

2. decreaseProductQuantity() - Stock Decrease Logic

Location: Line 10161

Purpose: Decrease product quantity in stock when selling

Function Signature:

function decreaseProductQuantity(
    $storedetailId,           // Stock record ID
    $productquantityBefore,   // Quantity before sale
    $productChangeAmount,     // Quantity to decrease
    $colName,                 // Detail table column name
    $detailId,                // Bill detail ID
    $productId,               // Product ID
    $tableName,               // Bill table name
    $prototal,                // Line total
    $billDiscountVal,         // Bill discount
    $billTotalBeforeDiscount, // Bill total before discount
    $isreturn,                // Is return operation
    $isadd,                   // Is add operation
    $sizeColorStoreDetailId,  // Size/color variant ID
    $sizeId,                  // Size ID
    $colorId                  // Color ID
)

Process Flow:

1. Calculate new quantity: $productquantityAfter = $productquantityBefore - $productChangeAmount

2. Update storedetail record with new quantity

3. Insert storereport movement record

4. Handle FIFO/LIFO cost tracking via getBuyPriceFromAndHandleBuyPricesHistoryBook()

5. Calculate profit via lastAndMeanBuyPrice_Sell()

6. Handle size/color variants if applicable

Critical Bug Fixed (Dec 19, 2024):

---

3. doBillDailyEntry() - Generate Accounting Entries

Location: Line 13612

Purpose: Auto-generate journal entries for sales bills

Function Signature:

function doBillDailyEntry(
    $billtype,                // Bill type (sell/return/combined)
    $sellbillId,              // Sell bill ID
    $returnsellbillId,        // Return bill ID
    $sellbilltotalPayed,      // Amount paid
    $saveid,                  // Cash register ID
    $visa,                    // Visa amount
    $visaAccount,             // Visa account ID
    $gen4totalinput,          // Additional inputs
    $clientTreeId,            // Customer account ID
    $taxOfDiscountVal,        // Tax on discount
    $billDiscountVal,         // Discount amount
    $sellbilltotalbill,       // Total before discount
    $sellbillAftertotalBill,  // Total after discount
    $taxVal,                  // Tax amount
    $sellCostsArray,          // Additional costs
    $sellbillstoreId,         // Store ID
    $firstProductId,          // First product ID
    $billoperationid          // Operation ID
)

Accounting Logic:

For Regular Sale (Cash):

Debit:  Cash Register          (sellbilltotalPayed)
Credit: Sales Revenue          (sellbillAftertotalBill - taxVal)
Credit: Tax Payable            (taxVal)
Debit:  Customer Receivable    (sellbillAftertotalBill - sellbilltotalPayed)

For Sale with Visa:

Debit:  Cash Register          (cash amount)
Debit:  Bank Account           (visa amount)
Credit: Sales Revenue          (total)

Process Flow:

1. Get account tree IDs via getsellTreeIdAccontId()

2. Create dailyentry master record

3. Create debit entries (dailyentrydebtor):

- Cash register (if cash payment)

- Bank account (if visa payment)

- Customer receivable (if credit)

4. Create credit entries (dailyentrycreditor):

- Sales revenue account

- Tax payable account

5. Handle additional costs/expenses

6. Link entry to bill via dailyentrymodelid

---

4. quickProfitRow() - Calculate Profit per Line

Location: Line 10551

Purpose: Calculate gross profit for each product sold

Function Signature:

function quickProfitRow(
    $myproduct,               // Product object
    $finalQuantity,           // Quantity sold
    $isreturn,                // Is return
    $isadd,                   // Is add
    $prototal,                // Line total
    $billDiscountVal,         // Bill discount
    $billTotalBeforeDiscount, // Bill total
    $storeId                  // Store ID
)

Calculation Logic:

// Get cost from FIFO/LIFO tracking
$costData = getBuyPriceFromAndHandleBuyPricesHistoryBook(
    $storeId, $productId, $sizeId, $colorId, $productBuyPrice, $finalQuantity, 1
);

// Calculate profit
$profit = ($sellPrice * $quantity) - $costData['totalCost'];

// Store in faida (profit) table
INSERT INTO faida (
    productid, storeid, quantity, sellprice, buyprice, profit, billid, billtype
)

---

5. editsellBill() - Edit Existing Sales Bill

Location: Line 2041

Purpose: Modify an existing sales bill

Process Flow:

1. Begin transaction

2. Load existing bill data

3. Reverse previous operations:

- Restore stock quantities

- Reverse customer debt changes

- Reverse cash register changes

- Delete old accounting entries

- Delete old profit records

4. Delete old sellbilldetail records

5. Apply new operations (same as add()):

- Decrease stock with new quantities

- Update customer debt

- Update cash register

- Generate new accounting entries

6. Update sellbill master record

7. Commit transaction

Critical Notes:

---

6. delete() - Delete Sales Bill

Location: Line 9530

Purpose: Soft delete or hard delete a sales bill

Function Signature:

function delete($sellbillid, $savePaymentDateWithBillDate = 0)

Process Flow:

1. Begin transaction

2. Load bill data

3. Reverse all operations:

- Restore stock: call increaseProductQuantity()

- Reverse customer debt: subtract bill total

- Reverse cash register: subtract payment

- Reverse bank movements

- Delete accounting entries

- Delete profit records

- Restore serial numbers (mark as unsold)

4. Soft delete: Set sellbill.conditions = 1

5. Commit transaction

Soft Delete:

---

7. showDetail() - View Bill Details

Location: Line 4610

Purpose: Display full details of a sales bill for viewing/printing

Process Flow:

1. Load sellbill master record

2. Load customer data

3. Load bill details (sellbilldetail records)

4. Load product names, prices

5. Calculate totals, discounts, tax

6. Check for serial numbers

7. Prepare Smarty template data

8. Display via selldetail.html template

Template Variables:

---

8. showAll() - List All Sales Bills

Location: Line 6933

Purpose: Display paginated list of all sales bills

Features:

SQL Query:

SELECT 
    sellbill.*,
    client.clientname,
    user.username,
    billname.billname
FROM sellbill
LEFT JOIN client ON sellbill.sellbillclientid = client.clientid
LEFT JOIN user ON sellbill.sellbilluserid = user.userid
LEFT JOIN billname ON sellbill.sellbillbillnameid = billname.billnameid
WHERE sellbill.conditions = 0
ORDER BY sellbill.sellbilldate DESC
LIMIT 50 OFFSET 0

---

9. getBuyPriceFromAndHandleBuyPricesHistoryBook() - FIFO/LIFO Costing

Location: Line 13073

Purpose: Track product costs using FIFO/LIFO method

Function Signature:

function getBuyPriceFromAndHandleBuyPricesHistoryBook(
    $storeId,         // Store ID
    $productid,       // Product ID
    $sizeid,          // Size ID
    $colorid,         // Color ID
    $productBuyPrice, // Fallback buy price
    $soldQuantity,    // Quantity sold
    $type = 0         // 0=get cost, 1=decrease stock
)

FIFO Logic:

1. Query buypricesh istorybook for oldest stock:

SELECT * FROM buypricesh istorybook
WHERE storeid = ? AND productid = ?
  AND quantity > 0
ORDER BY buybilldate ASC, buypricesh istorybookid ASC

2. Allocate sold quantity from oldest batches first

3. Decrease batch quantities

4. Return weighted average cost

Example:

Stock batches:
- Batch 1: 10 units @ $5 (oldest)
- Batch 2: 20 units @ $6
- Batch 3: 15 units @ $7

Sell 25 units:
- Take 10 from Batch 1 โ†’ Cost: $50
- Take 15 from Batch 2 โ†’ Cost: $90
- Total cost: $140
- Average cost per unit: $5.60

---

10. addRestaurantBill() - Restaurant/POS Orders

Location: Line 10807

Purpose: Create sales bill from restaurant table order

Function Signature:

function addRestaurantBill($restaurantOrder, $restaurantOrderDetails)

Process Flow:

1. Load restaurant order data

2. Convert order details to sell bill format

3. Call add() with restaurant-specific parameters

4. Mark restaurant order as completed

5. Print kitchen receipt

6. Print customer receipt

Integration:

---

11. addOnlineOrderAsSellBill() - Online Store Integration

Location: Line 11247

Purpose: Convert online store order to ERP sales bill

Function Signature:

function addOnlineOrderAsSellBill(
    $onlineOrderId,         // Online order ID
    $onlineStoreId,         // Online store ID
    $clientChoosen,         // Customer selection
    $onlineStoreSetting     // Store settings
)

Process Flow:

1. Fetch order data from online store API

2. Match/create customer in ERP

3. Map online products to ERP products

4. Create sell bill

5. Update online order status

6. Send confirmation email

Supported Platforms:

---

12. getStoreDetails() - Get Stock Record

Location: Line 10709

Purpose: Retrieve stock detail record for product

Function Signature:

function getStoreDetails(
    $storeId,                 // Store ID
    $productId,               // Product ID
    $unittype,                // Unit type
    $sizeColorStoreDetailId,  // Size/color variant ID
    $sizeId,                  // Size ID
    $colorId                  // Color ID
)

Returns: storedetail object or null

Logic:

Used By:

---

๐Ÿ”„ Workflows

Workflow 1: Create Sales Bill (Cash Sale)

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
START: User clicks "Add Bill"
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
1Display Bill Form (do=add)
- Select customer
- Select products
- Enter quantities, prices
- Apply discount, tax
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
2Submit Form (do=addsellBill)
- Validate inputs
- Check stock availability
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
3Begin Database Transaction
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
4Create sellbill Master Record
- Generate serial number
- Store date, customer, totals
- INSERT INTO sellbill
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
5Loop Through Products
FOR EACH product line item:
โ”‚
โ†’ Create sellbilldetail record
โ”‚
โ†’ Call decreaseProductQuantity()
โ”‚ โ”œโ”€ Update storedetail.productquantity
โ”‚ โ”œโ”€ Insert storereport record
โ”‚ โ”‚ โ””โ”€ Handle FIFO cost tracking โ”‚
โ”‚
โ†’ Call quickProfitRow()
โ”‚ โ”‚ โ””โ”€ Insert profit record โ”‚
โ”‚
โ”‚ โ””โ”€โ†’ Handle serial numbers (if applicable) โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
6Update Customer Debt
- Calculate debt increase
- Call updateClientDebt()
- Update client.clientdebt
- Insert clientdebtchange record
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
7Update Cash Register
- Call getSaveValueAndPlus()
- Update save.savevalue
- Insert savedaily record
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
8Generate Accounting Entries
- Call doBillDailyEntry()
- Insert dailyentry
- Insert dailyentrydebtor (Cash Register)
- Insert dailyentrycreditor (Sales Revenue)
- Insert dailyentrycreditor (Tax Payable)
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
9Commit Transaction
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
10Redirect to Success / Print Bill
- Show success message
- Option to print bill
- Redirect to new bill form
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

---

Workflow 2: Sales Return Process

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
START: Customer Returns Product
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
1Find Original Bill (do=showDetail)
- Search by serial number or customer
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
2Create Return Bill (do=add with return flag)
- Select products to return
- Enter return quantities
- Apply return discount if any
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
3Begin Transaction
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
4Create returnsellbill Record
- Link to original sellbill
- Store return date, amounts
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
5Process Returned Products
FOR EACH returned item:
โ”‚
โ†’ Create returnsellbilldetail
โ”‚
โ†’ Call increaseProductQuantity()
โ”‚ โ”œโ”€ Restore stock quantity
โ”‚ โ”œโ”€ Insert storereport (type=return)
โ”‚ โ”‚ โ””โ”€ Update FIFO tracking โ”‚
โ”‚
โ”‚ โ””โ”€โ†’ Reverse profit calculation โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
6Update Customer Debt (Decrease)
- Subtract return amount from debt
- Insert clientdebtchange (negative)
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
7Refund Payment
- Decrease cash register balance
- Insert savedaily (negative amount)
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
8Generate Reverse Accounting Entries
- Debit: Sales Returns account
- Credit: Cash Register
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
9Commit Transaction
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
10Print Return Receipt
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

---

๐ŸŒ URL Routes & Actions

URL ParameterFunction CalledDescription
`do=add``add()`Display new bill form
`do=addsellBill``add()`Process new sales bill
`do=editsellBill``editsellBill()`Edit existing sales bill
`do=editreturnsellBill``editreturnsellBill()`Edit return bill
`do=editsellandrutrnBill``editsellandrutrnBill()`Edit combined bill
`do=delete``delete()`Delete/cancel bill
`do=showDetail``showDetail()`View bill details
`do=show` or `do=all``showAll()`List all bills
`do=showoffers``showAllOffers()`List sales quotations
`do=saveOfferAsBill``saveOfferAsBill()`Convert quotation to bill
`do=addresBill`Restaurant billAdd restaurant order
`do=endKitchenBill`Kitchen flowComplete kitchen order
`do=onlineOrderConfirm``addOnlineOrderAsSellBill()`Process online order
`do=billToExcel`Excel exportExport bill to Excel
`do=billToPDF`PDF exportExport bill to PDF
`do=serializeProducts`Serial trackingAssign serial numbers
`do=showallajax``showallajax()`Ajax bill list
`do=addObgyVisit``addObgyVisit()`OBGY visit billing
`do=addProductToOrder``addProductToOrder()`Add product to quotation
`do=removeProductFromOrder``removeProductFromOrder()`Remove from quotation
---

๐Ÿ› Known Issues & Fixes

1. Stock Quantity Goes to Zero Bug (CRITICAL - FIXED)

Location: Line 10161 (decreaseProductQuantity)

Date Fixed: December 19, 2024

Problem:

When selling products, stock quantity became 0 instead of decreasing by sold amount.

Root Cause:

if ((!empty($allStoredetailData) && is_array($allStoredetailData) ? count($allStoredetailData) : 0) > 0) {
    decreaseProductQuantity(...);
}

Fix Applied:

if (!empty($allStoredetailData)) {
    decreaseProductQuantity(...);
}

Files Modified:

---

2. Attempt to Assign Property on Null

Location: Multiple functions

Error: Fatal error: Uncaught Error: Attempt to assign property on null

Fix Pattern:

$dailyEntry = new stdClass();
$dailyEntry->entryComment = $billComment;

Affected Functions:

---

3. implode() TypeError

Error: TypeError: implode(): Argument must be array

Fix:

$tagids = isset($_POST['tagids']) && is_array($_POST['tagids']) ? $_POST['tagids'] : [];
$mySellbill->tagids = is_array($tagids) ? implode(',', $tagids) : '';

---

4. Collective Product Cost Calculation

Location: Lines 12691-12887

Issue: Collective products (recipes/bundles) need special handling

Logic:

Functions:

---

5. FIFO Cost Tracking with Returns

Location: Line 13121 (decreaseSellQuantityHandleBuyPricesHistoryBook)

Problem: Returns must restore original FIFO batches

Solution:

---

๐Ÿ”’ Security & Permissions

Authentication

Authorization

Input Validation

Audit Trail

---

๐Ÿงช Testing & Debugging

Enable Debug Mode

// In sellbillController.php
error_reporting(E_ALL);
ini_set('display_errors', 1);

Debug Stock Issues

-- Check current stock
SELECT * FROM storedetail WHERE productid = [ID];

-- Check stock movements
SELECT * FROM storereport 
WHERE storereportproductid = [ID] 
ORDER BY storereportdate DESC 
LIMIT 20;

-- Check FIFO batches
SELECT * FROM buypricesh istorybook 
WHERE productid = [ID] AND quantity > 0;

Debug Customer Debt

-- Check customer balance
SELECT clientdebt FROM client WHERE clientid = [ID];

-- Check debt history
SELECT * FROM clientdebtchange 
WHERE clientid = [ID] 
ORDER BY clientdebtchangedate DESC;

Debug Accounting Entries

-- Check journal entries for bill
SELECT * FROM dailyentry 
WHERE dailyentrymodelid = [BILL_ID] 
AND tablename = 'sellbill';

-- Check debit/credit balance
SELECT 
    (SELECT SUM(value) FROM dailyentrydebtor WHERE dailyentryid = de.dailyentryid) as debits,
    (SELECT SUM(value) FROM dailyentrycreditor WHERE dailyentryid = de.dailyentryid) as credits
FROM dailyentry de
WHERE dailyentrymodelid = [BILL_ID];

Common Debug Points

// After stock decrease
file_put_contents('/tmp/stock_debug.log', 
    "Product: $productId, Before: $qtyBefore, After: $qtyAfter\n", FILE_APPEND);

// After FIFO allocation
var_dump($costData);
exit;

// Check transaction state
if (R::testConnection()) {
    echo "DB connected\n";
}

---

๐Ÿ“Š Performance Considerations

Optimization Tips

1. OPcache: Critical for loading 500+ DAO files

2. Indexes: Ensure indexes on:

- sellbill.sellbillclientid

- sellbill.sellbilldate

- sellbilldetail.sellbillid

- storedetail.productid, storeid

3. Batch Operations: Use transactions for multi-line bills

4. Avoid N+1 Queries: Load products in single query

5. Session Caching: Cache frequently used data (bill settings, etc.)

Known Slow Queries

-- This query is slow on large datasets (add index)
SELECT * FROM sellbill 
WHERE sellbilldate BETWEEN ? AND ? 
AND conditions = 0
ORDER BY sellbilldate DESC;

-- Fix: Add composite index
CREATE INDEX idx_date_conditions ON sellbill(sellbilldate, conditions);

---

๐Ÿ“š Related Documentation

---

Documented By: AI Assistant

Review Status: โœ… Complete

Next Review: When major changes occur

โ†‘