================================================================================ MPUMALANGA PVC - FINANCIAL DASHBOARD (app/home.php) ================================================================================ Last Updated: 2026-03-26 Path: /app/home.php ================================================================================ WHAT THIS PAGE DOES ------------------- The main landing page after login. Shows a comprehensive financial summary of the business broken down by South African financial year (1 March - last day of February). Has two tabs: current FY and previous FY, with KPI cards, trend charts, monthly breakdowns, and an unpaid invoices list. ================================================================================ FINANCIAL YEAR DEFINITION ================================================================================ South African financial year runs from 1 March to the last day of February. PHP Variables set at top of page: $fyStartYear = current month >= 3 ? current year : current year - 1 $fyEndYear = $fyStartYear + 1 $fyStart = "$fyStartYear-03-01 00:00:00" $fyEnd = "$fyEndYear-02-28 23:59:59" $fyLabel = "FY 2025/26" (example) $prevFyStartYear = $fyStartYear - 1 $prevFyEndYear = $fyStartYear $prevFyStart / $prevFyEnd / $prevFyLabel (same pattern for previous year) Example: In November 2025, FY is 2025/26 (March 2025 - Feb 2026). Example: In January 2026, FY is still 2025/26 (not yet March 2026). ================================================================================ PHP QUERIES (all filtered to current FY) ================================================================================ Total Revenue (current FY): SUM of invoice_list prices * qty for all invoices in FY range. Formula: SUM(CAST(REGEXP_REPLACE(price,...) AS DECIMAL) * qty) Joined against invoices.date_time_created for date filtering. Total Paid (current FY): SUM of payments.amount WHERE date_time BETWEEN fyStart AND fyEnd. Credit Notes (current FY): SUM of credit_notes_list.amount WHERE credit_notes.date_time BETWEEN fyStart AND fyEnd. NOTE: Uses cn.date_time (NOT cn.date_time_created - that column doesn't exist). Outstanding (current FY): Total Revenue minus Total Paid minus Credit Notes. Overdue Invoices: Invoices more than 30 days old that have not been fully paid. Paid Last 30 Days: SUM of payments in the last 30 calendar days (not FY-filtered). Top Clients (current FY): Invoices in FY grouped by client_id, sorted by invoice count descending. Monthly Breakdown (current FY): Revenue and payments grouped by month for each month in the FY. Returns 12 rows (one per month, March through February). Unpaid Invoices: All invoices with outstanding balance > 0, ordered by date. Each shows invoice number, client, total amount, amount paid, balance due, and age in days. All equivalent queries run for the previous FY using $prevFyStart/$prevFyEnd. ================================================================================ CSS DESIGN VARIABLES ================================================================================ --orange: #f15b23 --navy: #384b71 --green: #1e7e4a --red: #ff1900 --page-bg: #f2f4f7 --border: #e3e8ef Key CSS classes: .fy-tabs - Container for the tab buttons row .fy-tab - Individual tab button .fy-tab.active - Selected tab (orange bottom border) .fy-panel - Content panel (display:none by default) .fy-panel.active - Visible panel (display:block) .vs-pill - Comparison pill badge .vs-up - Green pill (current > previous) .vs-down - Red pill (current < previous) .vs-flat - Grey pill (no change) .kpi - KPI number display card .card - General card wrapper .outstanding - Unpaid invoice row .dt - Date/time cell .age-badge - Age pill for unpaid invoices .st-badge - Status pill .mb-track/.mb-fill - Monthly breakdown progress bar track and fill ================================================================================ PAGE STRUCTURE ================================================================================ 1. Ticker bar - Scrolling marquee showing key KPIs for the day. 2. FY Tab switcher - Two buttons: current FY and previous FY. - Clicking a tab calls switchFY('curr') or switchFY('prev'). 3. Panel: Current FY (id="panel-curr") a. KPI Cards row: Total Revenue, Total Paid, Outstanding, Overdue, Paid 30d b. Financials section: Revenue vs Payments bar chart (Chart.js) c. Trend section: Monthly revenue line chart d. Breakdown: Donut chart (invoiced vs paid) e. Monthly table: Table of each month's revenue and payments with bar f. Top clients: Client name, invoice count, estimated revenue g. Unpaid invoices: List of all unpaid invoices with age and balance 4. Panel: Previous FY (id="panel-prev") a. KPI comparison cards with vs-pills showing change from previous to current b. Trend charts for the previous year c. Monthly breakdown table for the previous year d. Top clients for the previous year ================================================================================ JAVASCRIPT ================================================================================ Global chartData object: Populated inline by PHP: chartData.curr.labels[] - Month labels for current FY chartData.curr.inv[] - Monthly revenue totals chartData.curr.pay[] - Monthly payment totals chartData.curr.donut[] - [invoiced, paid] for donut chart chartData.prev.* - Same structure for previous FY switchFY(id) - Hides all panels, shows the one matching id ('curr' or 'prev'). - Updates active tab styling. - First-time tab open: calls buildCharts(id) to render charts. - chartsInit{} object tracks which tabs have been initialized (lazy loading). buildCharts(id) - Creates three Chart.js charts for the given panel: 1. barChart_{id} - Bar chart: monthly revenue vs payments 2. payChart_{id} - Line chart: monthly revenue trend 3. donutChart_{id} - Doughnut: invoiced vs paid proportion Chart colours: Revenue/Invoiced: --orange (#f15b23) Payments/Paid: --green (#1e7e4a) Note: Charts are rendered lazily (only on first tab click) to avoid rendering hidden canvas elements, which Chart.js doesn't handle well. ================================================================================ KNOWN ISSUES / NOTES ================================================================================ 1. $fyEnd is hardcoded to Feb 28. In leap years, Feb 29 payments/invoices may be missed. Low priority but worth noting. 2. Revenue calculation uses REGEXP_REPLACE in SQL to strip currency characters from price strings. If price strings change format, this could break. 3. The previous FY comparison is display-only. No historical archiving is done. 4. Chart.js is loaded from CDN - requires internet connection to render charts. 5. The unpaid invoices list recalculates totals from invoice_list on every page load - on large datasets this could be slow. ================================================================================