Quickprofitreports Documentation
Quick Profit Reports Controller Documentation
File: /controllers/quickprofitreports.php
Purpose: Generates comprehensive quick profit analysis reports for sales performance tracking
Last Updated: December 20, 2024
Total Functions: 2+
Lines of Code: ~406
---
๐ Overview
The Quick Profit Reports Controller is a specialized reporting module that provides detailed profit analysis capabilities across multiple dimensions. It handles:
- โข General profit analysis (overall system)
- โข Daily profit breakdowns with date range filtering
- โข Store-specific profit tracking
- โข Product-level profit analysis
- โข Client-specific profit reporting
- โข Category-based profit summaries with hierarchical support
- โข Multi-format cost calculation methods (first, last, mean, with/without discounts)
- โข Date range filtering and comparison
- โข Profit margin calculations with various pricing methods
Primary Functions
- โ Generate system-wide general profit reports
- โ Track daily profit by date ranges
- โ Store-specific profit analysis
- โ Product-level profit tracking
- โ Client profit performance reports
- โ Category profit analysis with sub-category rollup
- โ Multiple buy price calculation methods
- โ Sales vs returns profit analysis
- โ Date range filtering and comparison
- โ Hierarchical category reporting
Related Controllers
- โข sellbillController.php - Sales operations that generate profit data
- โข buyBillController.php - Purchase operations for cost tracking
- โข calcquickprofit.php - Profit calculation engine
- โข productController.php - Product management
- โข clientController.php - Customer management
- โข storeController.php - Store management
---
๐๏ธ Database Tables
Primary Profit Tables (Direct Operations)
| Table Name | Purpose | Key Columns | |
|---|---|---|---|
| **quickprofitgeneral** | System-wide profit totals | id, netSellVal, netSellCostBuyPrice, netSellCostLastBuyPrice, netSellCostMeanBuyPrice, netSellCostLastBuyPricewithDiscount, netSellCostMeanBuyPricewithDiscount, netSellCostOverAllAveragePrice | |
| **quickprofitday** | Daily profit breakdown | id, theDate, sellVal, sellCostBuyPrice, sellCostLastBuyPrice, sellCostMeanBuyPrice, returnSellVal, returnSellCostBuyPrice, returnSellCostLastBuyPrice, returnSellCostMeanBuyPrice | |
| **quickprofitclient** | Client-specific profits | id, clientId, theDate, sellVal, sellCostBuyPrice, sellCostLastBuyPrice, sellCostMeanBuyPrice, returnSellVal, clientname, areaName | |
| **quickprofitproduct** | Product-level profits | id, productId, theDate, sellVal, sellCostBuyPrice, sellCostLastBuyPrice, sellCostMeanBuyPrice, returnSellVal, returnSellCostBuyPrice, returnSellCostLastBuyPrice | |
| **quickprofitstore** | Store-specific profits | id, storeId, theDate, sellVal, sellCostBuyPrice, sellCostLastBuyPrice, sellCostMeanBuyPrice, returnSellVal, returnSellCostBuyPrice, returnSellCostLastBuyPrice |
| Table Name | Purpose | Key Columns | |
|---|---|---|---|
| **store** | Store master data | storeid, storename, storedesc | |
| **client** | Customer information | clientid, clientname, clientarea | |
| **product** | Product master data | productid, productname, productCatId | |
| **productcat** | Product categories | productCatId, productCatName, productCatParent | |
| **youtubelink** | Tutorial/help links | youtubelinkid, title, url | |
| **programsettings** | System configuration | programsettingsid, settingkey, settingvalue |
| Table Name | Purpose | Key Columns | |
|---|---|---|---|
| **sellbill** | Sales transactions | sellbillid, sellbillclientid, sellbilltotalbill, sellbilldate | |
| **buypriceshistorybook** | Purchase price history | productId, buyPrice, lastBuyPrice, meanBuyPrice | |
| **storedetail** | Inventory costs | productid, storeid, buyprice, lastbuyprice, meanbuyprice |
๐ Key Functions
1. Default Action - General Profit Overview
Location: Line 109
Purpose: Display system-wide profit summary and overview dashboard
Function Signature:
// Triggered when: empty $do
// No parameters required
Process Flow:
1. Include authentication check
2. Load general profit data from quickprofitgeneral table
3. Load YouTube tutorial links
4. Set empty dates flag for template
5. Display via general.html template
Features:
- โข System-wide profit overview
- โข Multiple cost calculation methods
- โข Tutorial links integration
- โข Clean dashboard view
---
2. day - Daily Profit Report
Location: Line 122
Purpose: Generate daily profit breakdown with date range filtering
Function Signature:
// Triggered when: do=day
$from = filter_input(INPUT_POST, "from");
$to = filter_input(INPUT_POST, "to");
$buyPriceType = filter_input(INPUT_POST, "buyPriceType");
Process Flow:
1. Parse and validate date parameters
2. Set default buy price type to "first" if not specified
3. Build dynamic query string for date filtering
4. Query quickprofitday table with date constraints
5. Handle empty date scenario (show general profits)
6. Display via day.html template
Query Building:
if (isset($from) && !empty($from)) {
$queryString .= 'and quickprofitday.theDate >= "' . $from . '" ';
}
if (isset($to) && !empty($to)) {
$queryString .= 'and quickprofitday.theDate <= "' . $to . '" ';
}
Features:
- โข Date range filtering
- โข Buy price type selection (first/last/mean)
- โข Fallback to general profits when no dates
- โข Daily profit trend analysis
---
3. storeday - Store-Specific Daily Profits
Location: Line 159
Purpose: Generate daily profit reports filtered by store and date range
Function Signature:
// Triggered when: do=storeday
$storeId = filter_input(INPUT_POST, "storeId");
$from = filter_input(INPUT_POST, "from");
$to = filter_input(INPUT_POST, "to");
$buyPriceType = filter_input(INPUT_POST, "buyPriceType");
Process Flow:
1. Load all store master data for dropdown
2. Parse store and date filter parameters
3. Build query with store and date constraints
4. Query quickprofitstore table
5. Display via storeDay.html template
Query Building:
if (isset($storeId) && !empty($storeId)) {
$queryString .= 'and quickprofitstore.storeId = "' . $storeId . '" ';
}
Features:
- โข Store-specific filtering
- โข Store dropdown population
- โข Date range analysis per store
- โข Store performance comparison capability
---
4. productday - Product-Level Profit Analysis
Location: Line 197
Purpose: Track profit performance for specific products over time
Function Signature:
// Triggered when: do=productday
$productId = filter_input(INPUT_POST, "productId");
$from = filter_input(INPUT_POST, "from");
$to = filter_input(INPUT_POST, "to");
$buyPriceType = filter_input(INPUT_POST, "buyPriceType");
Process Flow:
1. Load program settings for display configuration
2. Parse product and date parameters
3. Build query for product-specific filtering
4. Query quickprofitproduct table
5. Display via productDay.html template
Features:
- โข Individual product profit tracking
- โข Product performance over time
- โข Multiple cost calculation methods
- โข Product profitability analysis
---
5. catday - Category Profit Report
Location: Line 234
Purpose: Analyze profit performance by product category
Function Signature:
// Triggered when: do=catday
$lastCatId = filter_input(INPUT_POST, "lastCatId");
$from = filter_input(INPUT_POST, "from");
$to = filter_input(INPUT_POST, "to");
$buyPriceType = filter_input(INPUT_POST, "buyPriceType");
Process Flow:
1. Load program settings
2. Parse category and date parameters
3. Build query with category filtering via JOIN to productcat
4. Query quickprofitproduct with category constraints
5. Display via catDay.html template
Query Building:
if (isset($lastCatId) && !empty($lastCatId)) {
$queryString .= 'and productcat.productCatId = "' . $lastCatId . '" ';
}
Features:
- โข Category-level profit analysis
- โข Category performance comparison
- โข Product category filtering
- โข Category profitability insights
---
6. allcatday - Hierarchical Category Profit Summary
Location: Line 272
Purpose: Comprehensive category analysis with sub-category rollup
Function Signature:
// Triggered when: do=allcatday
$level = filter_input(INPUT_POST, 'level');
$productCatId = filter_input(INPUT_POST, 'productCatId' . $level);
$from = filter_input(INPUT_POST, "from");
$to = filter_input(INPUT_POST, "to");
$buyPriceType = filter_input(INPUT_POST, "buyPriceType");
Process Flow:
1. Load program settings and category hierarchy via getCategoryChilds()
2. Parse hierarchical category selection (supports multiple levels)
3. Handle category level fallback logic
4. Build category ID string including all subcategories via getAllSubCat()
5. Query with category IN clause for hierarchical inclusion
6. Use specialized queryAllEXGroupByCatAndDate() method
7. Display via allCatDay.html template
Category Hierarchy Processing:
$catsIDS = '' . $productCatId;
if ($productCatId != '') {
getAllSubCat($productCatId, 1); // mode = 1 get all sub cats
}
Advanced Query:
if (isset($catsIDS) && !empty($catsIDS)) {
$queryString .= 'and productcat.productCatId in (' . $catsIDS . ') ';
}
Features:
- โข Multi-level category hierarchy support
- โข Recursive subcategory inclusion
- โข Category tree navigation
- โข Aggregated subcategory profits
- โข Level-based category selection
---
7. clientday - Client Profit Analysis
Location: Line 323
Purpose: Track profit performance per customer over time
Function Signature:
// Triggered when: do=clientday
$clientId = filter_input(INPUT_POST, "clientId");
$from = filter_input(INPUT_POST, "from");
$to = filter_input(INPUT_POST, "to");
$buyPriceType = filter_input(INPUT_POST, "buyPriceType");
Process Flow:
1. Parse client and date filter parameters
2. Build query string for client-specific filtering
3. Query quickprofitclient table
4. Display via clientDay.html template
Features:
- โข Customer-specific profit tracking
- โข Client profitability analysis
- โข Customer performance over time
- โข Client profit contribution analysis
---
8. getAllSubCat() - Recursive Category Function
Location: Line 367
Purpose: Recursively build category ID list including all subcategories
Function Signature:
function getAllSubCat($catid, $mode)
Process Flow:
1. Query subcategories using queryByParentExt()
2. For each subcategory:
- Add to global $catsIDS string (mode 1)
- Or collect last-level categories (mode 2)
- Recursively call self for deeper levels
3. Build comma-separated ID string for SQL IN clauses
Modes:
- โข Mode 1: Collect all subcategory IDs for comprehensive reporting
- โข Mode 2: Collect only leaf-level categories (unused in this controller)
Recursive Logic:
foreach ($result as $data) {
if ($mode == 1) {
$catsIDS .= "," . $data->productCatId;
getAllSubCat($data->productCatId, $mode);
}
}
---
๐ Workflows
Workflow 1: Daily Profit Report Generation
---
Workflow 2: Hierarchical Category Profit Analysis
---
๐ URL Routes & Actions
| URL Parameter | Function Called | Description | |
|---|---|---|---|
| `do=` (empty) | Default action | General system profit overview | |
| `do=day` | Daily reporting | Daily profit breakdown with date filtering | |
| `do=storeday` | Store daily analysis | Store-specific daily profits | |
| `do=productday` | Product analysis | Individual product profit tracking | |
| `do=catday` | Category analysis | Single category profit report | |
| `do=allcatday` | Hierarchical categories | Multi-level category profit with rollup | |
| `do=clientday` | Client analysis | Customer-specific profit tracking |
General Report (do= empty):
- โข No parameters required
Daily Report (do=day):
- โข
from- Start date (YYYY-MM-DD) [optional] - โข
to- End date (YYYY-MM-DD) [optional] - โข
buyPriceType- Cost calculation method: "first", "last", "mean" [optional, defaults to "first"]
Store Daily (do=storeday):
- โข
storeId- Store ID [optional, for filtering specific store] - โข
from- Start date [optional] - โข
to- End date [optional] - โข
buyPriceType- Cost calculation method [optional]
Product Daily (do=productday):
- โข
productId- Product ID [optional, for specific product] - โข
from- Start date [optional] - โข
to- End date [optional] - โข
buyPriceType- Cost calculation method [optional]
Category Daily (do=catday):
- โข
lastCatId- Category ID [optional, for specific category] - โข
from- Start date [optional] - โข
to- End date [optional] - โข
buyPriceType- Cost calculation method [optional]
All Categories (do=allcatday):
- โข
level- Category hierarchy level number - โข
productCatId{level}- Category ID for specified level - โข
from- Start date [optional] - โข
to- End date [optional] - โข
buyPriceType- Cost calculation method [optional]
Client Daily (do=clientday):
- โข
clientId- Customer ID [optional, for specific client] - โข
from- Start date [optional] - โข
to- End date [optional] - โข
buyPriceType- Cost calculation method [optional]
---
๐งฎ Calculation Methods
Buy Price Types
The system supports multiple cost calculation methods controlled by $buyPriceType:
"first" - First Purchase Price:
- โข Uses original purchase cost from
sellCostBuyPricefields - โข Most conservative profit calculation
- โข Based on FIFO (First-In-First-Out) costing
"last" - Last Purchase Price:
- โข Uses most recent purchase cost from
sellCostLastBuyPricefields - โข Reflects current market conditions
- โข Based on LIFO (Last-In-First-Out) costing
"mean" - Average Purchase Price:
- โข Uses weighted average cost from
sellCostMeanBuyPricefields - โข Smooths price fluctuations
- โข Based on weighted average costing
"withDiscount" - Discount-Adjusted Prices:
- โข Available for both last and mean methods
- โข Fields:
sellCostLastBuyPricewithDiscount,sellCostMeanBuyPricewithDiscount - โข Accounts for volume discounts and supplier rebates
Profit Calculations
// Basic profit calculation
$profit = $sellVal - $sellCost;
$profitMargin = ($profit / $sellVal) * 100;
// Net profit (including returns)
$netProfit = ($sellVal - $returnSellVal) - ($sellCost - $returnSellCost);
Return Impact Analysis
// Returns reduce both revenue and cost
$netSellVal = $sellVal - $returnSellVal;
$netSellCost = $sellCost - $returnSellCost;
$netProfit = $netSellVal - $netSellCost;
---
๐ Security & Permissions
Authentication
include_once("../public/authentication.php");
- โข All actions require user authentication
- โข Session validation performed before data access
- โข Redirects to login if not authenticated
Input Sanitization
$from = filter_input(INPUT_POST, "from");
$to = filter_input(INPUT_POST, "to");
$buyPriceType = filter_input(INPUT_POST, "buyPriceType");
- โข All user inputs filtered through
filter_input() - โข SQL injection prevention via DAO layer
- โข Parameter validation before database queries
Data Access Control
- โข No explicit user-based filtering in this controller
- โข Assumes profit data is accessible to authenticated users
- โข Store/client filtering through form selection only
- โข No row-level security implementation
---
๐ Performance Considerations
Database Optimization Tips
1. Required Indexes:
-- Daily reports
CREATE INDEX idx_quickprofitday_date ON quickprofitday(theDate);
-- Store reports
CREATE INDEX idx_quickprofitstore_store_date ON quickprofitstore(storeId, theDate);
-- Product reports
CREATE INDEX idx_quickprofitproduct_product_date ON quickprofitproduct(productId, theDate);
-- Client reports
CREATE INDEX idx_quickprofitclient_client_date ON quickprofitclient(clientId, theDate);
-- Category hierarchy
CREATE INDEX idx_productcat_parent ON productcat(productCatParent);
```
2. **Query Optimization**:
- Date range queries benefit from proper date formatting
- Category hierarchy queries can be expensive with deep nesting
- Consider materialized views for complex aggregations
3. **Memory Management**:
- Large date ranges may return significant data
- Category recursion limited by available memory
- Template variable cleanup important for category reports
### Known Performance Issues
sql
-- Recursive category queries can be slow with deep hierarchies
-- Consider limiting recursion depth or using iterative approach
-- Date range queries without indexes
SELECT * FROM quickprofitday
WHERE theDate BETWEEN '2024-01-01' AND '2024-12-31';
-- Solution: Add proper date index and limit ranges
CREATE INDEX idx_quickprofitday_thedate ON quickprofitday(theDate);
---
## ๐ Common Issues & Troubleshooting
### 1. **Empty Profit Data**
**Issue**: Reports show no data despite having sales
**Cause**: Profit calculation process (`calcquickprofit.php`) not running
**Debug**:
sql
-- Check if profit tables are populated
SELECT COUNT(*) FROM quickprofitday WHERE theDate >= '2024-01-01';
SELECT COUNT(*) FROM quickprofitproduct WHERE theDate >= '2024-01-01';
**Fix**: Run profit calculation process to populate tables
### 2. **Category Hierarchy Issues**
**Issue**: Subcategories not included in reports
**Cause**: `getAllSubCat()` recursion failing or category relationships broken
**Debug**:
sql
-- Check category parent relationships
SELECT productCatId, productCatName, productCatParent
FROM productcat WHERE productCatParent IS NOT NULL;
-- Verify category hierarchy integrity
SELECT COUNT(*) as orphaned_categories
FROM productcat c1
LEFT JOIN productcat c2 ON c1.productCatParent = c2.productCatId
WHERE c1.productCatParent IS NOT NULL AND c2.productCatId IS NULL;
### 3. **Date Range Problems**
**Issue**: Date filters not working correctly
**Cause**: Date format mismatch or timezone issues
**Debug**:
php
// Check date format in queries
echo "Query String: " . $queryString . "
";
// Verify date format matches database
echo "From: " . $from . " To: " . $to . "
";
**Fix**:
php
// Ensure proper date format
if (!empty($from)) $from .= " 00:00:00";
if (!empty($to)) $to .= " 23:59:59";
### 4. **Buy Price Type Confusion**
**Issue**: Profit calculations inconsistent between reports
**Cause**: Different buy price types selected or default not set
**Fix**:
php
// Always set default buy price type
if (!isset($buyPriceType) || empty($buyPriceType)) {
$buyPriceType = "first";
}
---
## ๐งช Testing Scenarios
### Test Case 1: Daily Profit Accuracy
1. Create test sales with known costs
2. Run profit calculation process
3. Generate daily report for test date
4. Verify profit = revenue - cost matches manually calculated values
5. Test with different buy price types
### Test Case 2: Category Hierarchy Rollup
1. Create category structure: Parent > Child > Grandchild
2. Add products to grandchild category
3. Generate sales for these products
4. Run allcatday report selecting parent category
5. Verify totals include all descendant categories
### Test Case 3: Date Range Filtering
1. Create sales across multiple months
2. Test date range spanning partial months
3. Verify exact date boundary handling
4. Test edge cases (single day, year boundaries)
### Debug Mode Enable
php
// Add at top of controller for debugging
error_reporting(E_ALL);
ini_set('display_errors', 1);
// Debug query building
echo "Query String: " . $queryString . "
";
echo "Category IDs: " . $catsIDS . "
";
// Debug data results
echo "
";";print_r($quickProfitDay);
echo "
```
---
๐ Related Documentation
- โข CLAUDE.md - PHP 8.2 migration guide
- โข sellbillController.md - Sales operations
- โข buyBillController.md - Purchase operations
- โข calcquickprofit.php - Profit calculation engine
- โข reportfunctions.php - Shared reporting functions
- โข Database Schema Documentation - Table relationships
---
Documented By: AI Assistant
Review Status: โ Complete
Next Review: When major changes occur