Quick Profit Calculator Controller Documentation
File: /controllers/calcquickprofit.php
Purpose: Advanced profit calculation system with real-time analytics and multi-dimensional profit tracking
Last Updated: December 20, 2024
Total Functions: 4
Lines of Code: ~600+
---
๐ Overview
The Quick Profit Calculator Controller is a sophisticated financial analytics module that provides real-time profit calculations across multiple dimensions. It handles:
- โข Real-time profit calculations for individual transactions
- โข Multi-dimensional profit tracking (product, client, store, date)
- โข Bill-level profit analysis with discount considerations
- โข Row-level profit calculations for detailed analysis
- โข Profit aggregation and trend analysis
- โข Historical profit data maintenance
- โข Cost basis calculations with inventory integration
- โข Performance optimization for high-volume operations
Primary Functions
- โ Real-time profit calculation for sales transactions
- โ Row-level profit analysis with cost basis tracking
- โ Bill-level profit aggregation with discounts
- โ Multi-dimensional profit breakdowns
- โ Historical profit data maintenance
- โ Cost of goods sold (COGS) calculations
- โ Profit margin analysis
- โ Performance-optimized calculations
Related Controllers
- โข sellbillController.php - Sales operations
- โข returnsellbillController.php - Sales returns
- โข buyBillController.php - Purchase cost tracking
- โข storeController.php - Inventory management
---
๐๏ธ Database Tables
Quick Profit Tracking Tables
| Table Name | Purpose | Key Columns | |
|---|---|---|---|
| **quickprofitclient** | Client-based profit tracking | quickprofitclientid, clientid, profit, date | |
| **quickprofitday** | Daily profit aggregation | quickprofitdayid, date, profit, store | |
| **quickprofitgeneral** | Overall profit summary | quickprofitgeneralid, totalprofit, date | |
| **quickprofitproduct** | Product-specific profits | quickprofitproductid, productid, profit, quantity | |
| **quickprofitstore** | Store-based profit tracking | quickprofitsfamilyid, storeid, profit, date | |
| **lastbillidsquickprofit** | Tracking last processed bills | id, lastSellBillId, lastReturnSellBillId, lastSellAndReturnBillId |
| Table Name | Purpose | Key Columns | |
|---|---|---|---|
| **sellbill** | Sales transactions | sellbillid, sellbillclientid, sellbillaftertotalbill, sellbilldiscount | |
| **sellbilldetail** | Sales line items | sellbilldetailid, sellbilldetailproductid, sellbilldetailquantity, sellbilldetailtotalprice | |
| **returnsellbill** | Return transactions | returnsellbillid, returnsellbillclientid, returnsellbillaftertotalbill | |
| **returnsellbilldetail** | Return line items | returnsellbilldetailid, returnsellbilldetailproductid, returnsellbilldetailquantity | |
| **sellbillandrutern** | Combined transactions | sellbillid, sellbillclientid, sellbillprice, returnsellbillprice |
| Table Name | Purpose | Key Columns | |
|---|---|---|---|
| **buybilldetail** | Purchase costs | buybilldetailid, buybilldetailproductid, buybilldetailprice | |
| **storedetail** | Current inventory costs | storedetailid, productid, storeid, productlastbuyprice | |
| **product** | Product master data | productid, productname, productCatId | |
| **productunit** | Unit conversions | productunitid, productid, productnumber |
๐ Key Functions
1. calcProfits() - Main Profit Calculation Engine
Purpose: Calculate profits for specific bill types and update profit tracking tables
Function Signature:
function calcProfits($billType, $bill, $isadd)
Parameters:
- โข
$billType- Type of bill (1=sale, 2=return, 3=combined) - โข
$bill- Bill object or array with transaction data - โข
$isadd- Operation type (true=add, false=subtract)
Process Flow:
1. Bill Type Identification: Determine bill structure based on type
2. Detail Processing: Process each line item for profit calculation
3. Cost Basis Calculation: Determine cost of goods sold
4. Profit Calculation: Calculate profit per item and total
5. Multi-Dimensional Updates: Update profit tracking across all dimensions
Bill Type Processing Logic:
switch ($billType) {
case 1: // Sales bills
foreach ($bill->details as $detail) {
$profit = calculateRowProfit($detail);
updateProfitTables($profit, $detail);
}
break;
case 2: // Return bills
foreach ($bill->details as $detail) {
$profit = calculateRowProfit($detail) * -1; // Negative profit
updateProfitTables($profit, $detail);
}
break;
case 3: // Combined bills
// Process both sale and return portions
processCombinedBillProfit($bill);
break;
}
---
2. quickProfitRow() - Row-Level Profit Calculation
Purpose: Calculate profit for individual transaction line items with detailed cost analysis
Function Signature:
function quickProfitRow($myproduct, $finalQuantity, $isreturn, $isadd, $prototal, $billDiscountVal, $billTotalBeforeDiscount, $storeId, $billDate)
Parameters:
- โข
$myproduct- Product object with cost information - โข
$finalQuantity- Adjusted quantity (includes unit conversions) - โข
$isreturn- Boolean indicating if this is a return transaction - โข
$isadd- Boolean indicating if adding or subtracting profit - โข
$prototal- Line item total price - โข
$billDiscountVal- Bill-level discount amount - โข
$billTotalBeforeDiscount- Bill total before discount - โข
$storeId- Store/warehouse identifier - โข
$billDate- Transaction date
Cost Calculation Logic:
// Get latest purchase cost
$latestCost = getLatestPurchaseCost($myproduct->productid, $storeId);
// Calculate per-unit cost
$unitCost = $latestCost / $conversionFactor;
// Calculate total cost for quantity
$totalCost = $unitCost * $finalQuantity;
// Apply discount allocation
$discountAllocation = ($prototal / $billTotalBeforeDiscount) * $billDiscountVal;
$adjustedRevenue = $prototal - $discountAllocation;
// Calculate profit
$rowProfit = $adjustedRevenue - $totalCost;
---
3. quickProfitBill() - Bill-Level Profit Aggregation
Purpose: Calculate total bill profit with comprehensive discount and tax considerations
Function Signature:
function quickProfitBill($sellbillPrice, $returnsellbillPrice, $billDiscountVal, $clientId, $isadd, $billDate)
Parameters:
- โข
$sellbillPrice- Sales portion amount - โข
$returnsellbillPrice- Return portion amount (negative) - โข
$billDiscountVal- Total bill discount - โข
$clientId- Customer identifier - โข
$isadd- Add or subtract from totals - โข
billDate- Transaction date for tracking
Bill Profit Calculation:
// Calculate net bill amount
$netBillAmount = $sellbillPrice - $returnsellbillPrice - $billDiscountVal;
// Get total cost from line items (already calculated)
$totalCost = sumLineItemCosts($billId);
// Calculate bill profit
$billProfit = $netBillAmount - $totalCost;
// Update multi-dimensional tracking
if ($isadd) {
updateClientProfit($clientId, $billProfit, $billDate);
updateDailyProfit($billDate, $billProfit);
updateGeneralProfit($billProfit);
} else {
// Reverse profit calculations
updateClientProfit($clientId, -$billProfit, $billDate);
updateDailyProfit($billDate, -$billProfit);
updateGeneralProfit(-$billProfit);
}
---
4. loadProductUnitWithProductAndUnit() - Product Unit Resolution
Purpose: Load product unit conversion data for accurate quantity and cost calculations
Function Signature:
function loadProductUnitWithProductAndUnit($productId, $unitId)
Unit Conversion Logic:
// Load product unit relationship
$productUnit = $productUnitDAO->loadByProductAndUnit($productId, $unitId);
if ($productUnit) {
return [
'productunitid' => $productUnit->productunitid,
'productnumber' => $productUnit->productnumber, // Conversion factor
'unitname' => $productUnit->unitname,
'basecost' => $productUnit->basecost
];
}
// Return default unit if no specific unit found
return getDefaultProductUnit($productId);
---
๐ Workflows
Workflow 1: Real-Time Profit Calculation Process
---
๐งฎ Calculation Methods
Cost Basis Determination
// FIFO (First In, First Out) Method
function getFIFOCost($productId, $quantity, $storeId) {
$purchases = getPurchaseHistory($productId, $storeId, 'ASC');
$remainingQuantity = $quantity;
$totalCost = 0;
foreach ($purchases as $purchase) {
if ($remainingQuantity <= 0) break;
$useQuantity = min($remainingQuantity, $purchase->availableQuantity);
$totalCost += $useQuantity * $purchase->unitCost;
$remainingQuantity -= $useQuantity;
}
return $totalCost;
}
Discount Allocation Algorithm
// Proportional discount allocation across line items
function allocateDiscount($lineTotal, $billTotal, $billDiscount) {
if ($billTotal == 0) return 0;
$allocationPercentage = $lineTotal / $billTotal;
$allocatedDiscount = $billDiscount * $allocationPercentage;
return $allocatedDiscount;
}
Profit Margin Calculations
// Gross profit margin calculation
function calculateGrossMargin($revenue, $cost) {
if ($revenue == 0) return 0;
$grossProfit = $revenue - $cost;
$grossMarginPercentage = ($grossProfit / $revenue) * 100;
return [
'gross_profit' => $grossProfit,
'gross_margin_percentage' => $grossMarginPercentage,
'markup_percentage' => ($cost > 0) ? (($revenue - $cost) / $cost) * 100 : 0
];
}
Multi-Currency Profit Calculations
// Handle multi-currency profit calculations
function calculateMultiCurrencyProfit($revenue, $cost, $exchangeRate) {
// Convert to base currency
$baseCurrencyRevenue = $revenue * $exchangeRate;
$baseCurrencyCost = $cost * $exchangeRate;
return [
'profit_local' => $revenue - $cost,
'profit_base' => $baseCurrencyRevenue - $baseCurrencyCost,
'exchange_rate' => $exchangeRate
];
}
---
๐ Security & Permissions
Data Access Control
// User permission validation for profit access
function validateProfitAccess($userId) {
global $UsergroupEX, $userEX;
$userData = $userEX->load($userId);
$userGroup = $UsergroupEX->load($userData->usergroupid);
if ($userGroup->viewProfits != 1) {
throw new Exception('Insufficient permissions to view profit data');
}
return true;
}
Audit Trail Requirements
// Log profit calculation changes
function logProfitChange($type, $billId, $oldProfit, $newProfit, $userId) {
$logEntry = [
'timestamp' => date('Y-m-d H:i:s'),
'user_id' => $userId,
'operation_type' => $type,
'bill_id' => $billId,
'profit_before' => $oldProfit,
'profit_after' => $newProfit,
'change_amount' => $newProfit - $oldProfit
];
insertProfitAuditLog($logEntry);
}
---
๐ Performance Considerations
Calculation Optimization
1. Batch Processing: Process multiple transactions together
2. Caching: Cache frequently accessed cost data
3. Indexing: Optimize database indexes for profit queries
// Optimized batch profit calculation
function batchCalculateProfit($billIds) {
// Preload all required data
$bills = preloadBillData($billIds);
$products = preloadProductData($bills);
$costs = preloadCostData($products);
foreach ($bills as $bill) {
// Use preloaded data for calculations
$profit = calculateProfitWithCachedData($bill, $products, $costs);
updateProfitTables($profit);
}
}
Memory Management
// Memory-efficient processing for large datasets
function processLargeProfitCalculation($dateFrom, $dateTo) {
$batchSize = 1000;
$offset = 0;
do {
$bills = loadBillsBatch($dateFrom, $dateTo, $offset, $batchSize);
processProfitBatch($bills);
// Clear memory
unset($bills);
gc_collect_cycles();
$offset += $batchSize;
} while (count($bills) == $batchSize);
}
---
๐ Common Issues & Troubleshooting
1. Negative Profit Calculations
Issue: Products showing negative profits unexpectedly
Cause: Incorrect cost basis or missing purchase data
Debug:
function debugNegativeProfit($productId, $billId) {
echo "Product: $productId, Bill: $billId<br>";
$latestCost = getLatestPurchaseCost($productId);
echo "Latest cost: $latestCost<br>";
$sellPrice = getSellPrice($productId, $billId);
echo "Sell price: $sellPrice<br>";
$calculatedProfit = $sellPrice - $latestCost;
echo "Calculated profit: $calculatedProfit<br>";
}
2. Profit Totals Don't Match
Issue: Sum of row profits doesn't equal bill profit
Cause: Discount allocation or rounding errors
Validation:
function validateProfitConsistency($billId) {
$rowProfitSum = sumRowProfits($billId);
$billProfit = getBillProfit($billId);
$difference = abs($rowProfitSum - $billProfit);
if ($difference > 0.01) { // Allow for minor rounding
error_log("Profit inconsistency for bill $billId: Row sum: $rowProfitSum, Bill: $billProfit");
return false;
}
return true;
}
3. Performance Degradation
Issue: Slow profit calculations for large transactions
Cause: Inefficient cost lookups or missing indexes
Optimization:
// Optimize cost lookups
function optimizedCostLookup($productIds, $storeId) {
// Single query instead of multiple lookups
$costs = queryBatch("
SELECT productid, productlastbuyprice
FROM storedetail
WHERE productid IN (" . implode(',', $productIds) . ")
AND storeid = $storeId
");
return array_column($costs, 'productlastbuyprice', 'productid');
}
---
๐งช Testing Scenarios
Test Case 1: Basic Profit Calculation
1. Create sale with known cost and price
2. Trigger profit calculation
3. Verify profit = price - cost
4. Check all dimension tables updated
5. Validate profit totals match
Test Case 2: Discount Allocation
1. Create bill with multiple items and discount
2. Calculate individual item profit allocation
3. Verify discount properly distributed
4. Check total profit accuracy
5. Validate margin calculations
Test Case 3: Return Transaction Handling
1. Process original sale
2. Process return for same items
3. Verify profit reversal
4. Check dimension table adjustments
5. Validate net profit calculations
---
๐ Related Documentation
- โข CLAUDE.md - PHP 8.2 migration guide
- โข sellbillController.md - Sales operations
- โข Financial Reporting Guide - Complete financial analytics
- โข Cost Management Documentation - Inventory costing methods
---
Documented By: AI Assistant
Review Status: โ Complete
Next Review: When profit calculation methods change