AutoSalesReport Documentation

Auto Sales Report Controller Documentation

File: /controllers/autoSalesReport.php

Purpose: Generates automated sales reports comparing purchase and sale data to calculate profit margins

Last Updated: December 20, 2024

Total Functions: 4

Lines of Code: ~240

---

๐Ÿ“‹ Overview

The Auto Sales Report Controller is a specialized reporting module that provides comprehensive profit analysis by tracking products from purchase to sale. It handles:

Primary Functions

Related Controllers

---

๐Ÿ—„๏ธ Database Tables

Primary Tables (Direct Operations)

Table NamePurposeKey Columns
**sellbilldetail**Sales bill line itemssellbilldetailid, sellbillid, sellbilldetailproductid, parcode, sellbilldetailquantity
**productserial**Product serial number trackingserialnumber, billid, del
**sellbill**Sales bills mastersellbillid, sellbillclientid, sellbillaftertotalbill, sellbilldate, conditions
**buybill**Purchase bills masterbuybillid, buybillsupplierid, buybillaftertotalbill, buybilldate
### Reference Tables

Table NamePurposeKey Columns
**client**Customer informationclientid, clientname
**supplier**Supplier informationsupplierid, suppliername
**buybilldetail**Purchase bill line itemsbuybilldetailid, buybillid
**returnsellbill**Sales return billsreturnsellbillid, returnsellbillclientid, returnsellbilldate, conditions
**returnsellbilldetail**Return bill detailsreturnsellbilldetailid, returnsellbillid, parcode
---

๐Ÿ”‘ Key Functions

1. Default Action - Report Interface

Location: Line 25

Purpose: Display the main report interface

Process Flow:

1. Display header template

2. Load main report interface (autoSalesReportview/index.html)

3. Display footer template

---

2. select2supplier() - Supplier Search

Location: Line 45

Purpose: AJAX endpoint for supplier autocomplete functionality

Function Signature:

function select2supplier()

Process Flow:

1. Get search term from POST data

2. Query suppliers with LIKE match on supplier name

3. Format results for Select2 dropdown

4. Return JSON response

SQL Query:

SELECT supplierid, suppliername as name
FROM supplier
WHERE suppliername LIKE '%{searchTerm}%' 
LIMIT 50

---

3. select2client() - Client Search

Location: Line 63

Purpose: AJAX endpoint for client autocomplete functionality

Function Signature:

function select2client()

Process Flow:

1. Get search term from POST data

2. Query clients with LIKE match on client name

3. Format results for Select2 dropdown

4. Return JSON response

SQL Query:

SELECT clientid, clientname as name
FROM client 
WHERE clientname LIKE '%{searchTerm}%' 
LIMIT 50

---

4. select2code() - Product Code Search

Location: Line 81

Purpose: AJAX endpoint for product code autocomplete

Function Signature:

function select2code()

Process Flow:

1. Get search term from POST data

2. Query unique product codes from sales details

3. Format results for Select2 dropdown

4. Return JSON response

SQL Query:

SELECT parcode
FROM sellbilldetail 
WHERE parcode LIKE '%{searchTerm}%' 
LIMIT 50

---

5. showajax() - Main Report Data

Location: Line 99

Purpose: Generate profit analysis report with DataTables integration

Function Signature:

function showajax()

Process Flow:

1. Parse filter parameters (dates, supplier, client, product code)

2. Build dynamic WHERE clause based on filters

3. Execute complex JOIN query linking purchases to sales

4. Filter out returned items

5. Calculate profit margins

6. Format data for DataTables

7. Add totals row

8. Return JSON response

Key Features:

Complex SQL Query:

SELECT *, sellbilldetail.sellbillid as sellbillidend, 
       sellbilldetail.parcode as parcodes, 
       sellbill.sellbilldate as sellbilldates 
FROM sellbilldetail
LEFT JOIN sellbill ON sellbilldetail.sellbillid = sellbill.sellbillid 
    AND sellbill.conditions = 0 
LEFT JOIN client ON sellbill.sellbillclientid = client.clientid
LEFT JOIN productserial ON sellbilldetail.parcode = productserial.serialnumber
LEFT JOIN buybill ON productserial.billid = buybill.buybillid
LEFT JOIN buybilldetail ON buybill.buybillid = buybilldetail.buybillid
LEFT JOIN supplier ON buybill.buybillsupplierid = supplier.supplierid
WHERE productserial.del = 0 {searchQuery}

Return Check Logic:

$countreturnsellbill = R::count("returnsellbill",
    " LEFT JOIN returnsellbilldetail ON returnsellbill.returnsellbillid = returnsellbilldetail.returnsellbillid  
    WHERE returnsellbilldetail.parcode = ? 
    AND returnsellbill.returnsellbilldate >= ? 
    AND returnsellbill.conditions = 0 ", 
    [$row["parcodes"], $row["sellbilldates"]]);

---

๐Ÿ”„ Workflows

Workflow 1: Profit Analysis Report Generation

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
START: Load Report Interface
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
1User Sets Filters
- Date range (from/to)
- Supplier (optional)
- Client (optional)
- Product code (optional)
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
2AJAX Call to showajax()
- Parse filter parameters
- Build search query string
- Apply date filters (default: today)
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
3Execute Complex JOIN Query
- Link sellbilldetail to productserial via parcode
- Link productserial to buybill via billid
- Include supplier and client information
- Filter by search criteria
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
4Process Each Result Row
FOR EACH matching product:
โ”‚
โ†’ Check for returns after sale date
โ”‚ โ”‚ โ””โ”€ Exclude if product was returned โ”‚
โ”‚
โ†’ Calculate profit margin
โ”‚ โ”‚ โ””โ”€ Sell price - Buy price โ”‚
โ”‚
โ†’ Format data for DataTable
โ”‚
โ”‚ โ””โ”€โ†’ Add to totals โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
5Generate Summary Row
- Total buy amount
- Total sell amount
- Total profit
- Current timestamp
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
6Return JSON Response
- Data array for DataTable
- Record counts
- Summary totals
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

---

๐ŸŒ URL Routes & Actions

URL ParameterFunction CalledDescription
`do=` (empty)Default actionMain report interface
`do=select2client``select2client()`Client autocomplete
`do=select2supplier``select2supplier()`Supplier autocomplete
`do=showajax``showajax()`Report data via AJAX
`do=select2code``select2code()`Product code autocomplete
### AJAX Endpoints

Client Search (do=select2client):

Supplier Search (do=select2supplier):

Report Data (do=showajax):

---

๐Ÿงฎ Calculation Methods

Profit Calculation

$finaltotals += round($row["sellbillaftertotalbill"] - $row["buybillaftertotalbill"]);

Return Detection Logic

$countreturnsellbill = R::count("returnsellbill",
    " LEFT JOIN returnsellbilldetail ON returnsellbill.returnsellbillid = returnsellbilldetail.returnsellbillid  
    WHERE returnsellbilldetail.parcode = ? 
    AND returnsellbill.returnsellbilldate >= ? 
    AND returnsellbill.conditions = 0 ", 
    [$row["parcodes"], $row["sellbilldates"]]);
    
if ($countreturnsellbill == 0) {
    // Include in profit calculation
}

Date Range Handling

if ($fromdate != '' && $todate != '') {
    $searchQuery .= " and sellbilldate >= '$fromdate' and sellbilldate <= '$todate' ";
} else {
    $today = date("Y-m-d");
    $searchQuery .= 'and sellbilldate >= "' . $today . ' 00-00-00" and sellbilldate <= "' . $today . ' 23-59-55" ';
}

---

๐Ÿ”’ Security & Permissions

Input Sanitization

Current Security Issues

// VULNERABLE CODE
$searchQuery .= " and client.clientid = " . $clientid . " ";
$searchQuery .= " and supplier.supplierid = " . $supplierid . " ";

// SHOULD BE
$searchQuery .= " and client.clientid = ? ";
// With parameter binding

---

๐Ÿ“Š Performance Considerations

Database Optimization Tips

1. Required Indexes:

- productserial(serialnumber, billid)

- sellbilldetail(parcode, sellbillid)

- sellbill(sellbilldate, conditions)

- buybill(buybillid, buybillsupplierid)

2. Query Performance:

- Complex JOIN across 6+ tables

- No LIMIT on main query (potential memory issues)

- Subquery for each row to check returns

Known Performance Issues

---

๐Ÿ› Common Issues & Troubleshooting

1. Missing Products in Report

Issue: Products don't appear in profit analysis

Cause: Product missing from productserial table or del = 1

Debug:

SELECT * FROM productserial WHERE serialnumber = '{code}';

2. Incorrect Profit Calculations

Issue: Profit margins don't match expected values

Cause: Return exclusion or wrong price fields

Check:

SELECT sellbillaftertotalbill, buybillaftertotalbill 
FROM sellbill s, buybill b 
WHERE s.sellbillid = {sellbillid} AND b.buybillid = {buybillid};

3. Performance Issues

Issue: Report loads slowly or times out

Cause: Large date ranges or missing indexes

Solutions:

---

๐Ÿ“š Related Documentation

---

Documented By: AI Assistant

Review Status: โœ… Complete

Next Review: When major changes occur