================================================================================
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.

================================================================================