| Server IP : 173.209.174.21 / Your IP : 216.73.216.89 Web Server : Apache/2.4.58 (Ubuntu) System : Linux wcfs-server 6.8.0-124-generic #124-Ubuntu SMP PREEMPT_DYNAMIC Tue May 26 13:00:45 UTC 2026 x86_64 User : nodor ( 1000) PHP Version : 8.3.6 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /var/www/wcfs/NAOPOS/src/lib/ |
Upload File : |
import { ReportCategory, SaleRecord } from "@/types/sales";
export const REPORT_CATEGORY_ORDER: ReportCategory[] = [
"Taxable",
"Non-Taxable",
"Unleaded",
"Unleaded Plus",
"Diesel",
"Off Road Diesel",
"Oil",
"Hardware",
"Other",
];
export interface CategoryBreakdown {
category: ReportCategory;
cashSales: number;
cashTax: number;
creditSales: number;
creditTax: number;
totalSales: number;
totalTax: number;
grandTotal: number;
}
export interface EndOfDayReport {
businessDate: string;
totalTransactions: number;
totalSales: number;
totalTax: number;
cashTotal: number;
creditTotal: number;
categoryBreakdown: CategoryBreakdown[];
}
export function formatBusinessDate(value: Date): string {
const year = value.getFullYear();
const month = `${value.getMonth() + 1}`.padStart(2, "0");
const day = `${value.getDate()}`.padStart(2, "0");
return `${year}-${month}-${day}`;
}
export function normalizeReportCategory(
label: string,
taxable: boolean,
): ReportCategory {
const normalized = label.trim().toLowerCase();
if (normalized.includes("off road diesel")) return "Off Road Diesel";
if (normalized.includes("unleaded plus")) return "Unleaded Plus";
if (normalized.includes("unleaded")) return "Unleaded";
if (normalized.includes("diesel")) return "Diesel";
if (normalized.includes("oil")) return "Oil";
if (normalized.includes("hardware")) return "Hardware";
if (normalized.includes("taxable")) return "Taxable";
if (normalized.includes("non-tax")) return "Non-Taxable";
if (normalized.includes("non tax")) return "Non-Taxable";
return taxable ? "Taxable" : "Non-Taxable";
}
export function buildEndOfDayReport(sales: SaleRecord[]): EndOfDayReport {
const businessDate = sales[0]?.businessDate ?? formatBusinessDate(new Date());
const categoryMap = new Map<ReportCategory, CategoryBreakdown>();
for (const category of REPORT_CATEGORY_ORDER) {
categoryMap.set(category, {
category,
cashSales: 0,
cashTax: 0,
creditSales: 0,
creditTax: 0,
totalSales: 0,
totalTax: 0,
grandTotal: 0,
});
}
for (const sale of sales) {
for (const item of sale.items) {
const entry = categoryMap.get(item.reportCategory) ?? {
category: item.reportCategory,
cashSales: 0,
cashTax: 0,
creditSales: 0,
creditTax: 0,
totalSales: 0,
totalTax: 0,
grandTotal: 0,
};
if (sale.paymentMethod === "cash") {
entry.cashSales += item.lineTotal;
entry.cashTax += item.taxAmount;
} else {
entry.creditSales += item.lineTotal;
entry.creditTax += item.taxAmount;
}
entry.totalSales += item.lineTotal;
entry.totalTax += item.taxAmount;
entry.grandTotal += item.lineTotal + item.taxAmount;
categoryMap.set(entry.category, entry);
}
}
const categoryBreakdown = REPORT_CATEGORY_ORDER
.map((category) => categoryMap.get(category)!)
.filter((entry) => entry.totalSales > 0 || entry.totalTax > 0);
const cashTotal = sales
.filter((sale) => sale.paymentMethod === "cash")
.reduce((sum, sale) => sum + sale.total, 0);
const creditTotal = sales
.filter((sale) => sale.paymentMethod === "credit")
.reduce((sum, sale) => sum + sale.total, 0);
return {
businessDate,
totalTransactions: sales.length,
totalSales: sales.reduce((sum, sale) => sum + sale.subtotal, 0),
totalTax: sales.reduce((sum, sale) => sum + sale.tax, 0),
cashTotal,
creditTotal,
categoryBreakdown,
};
}