• Mahmoud Aglan's avatar
    fix(groups): show what a player paid this month, and why it is that number · d2f4bf17
    Mahmoud Aglan authored
    The roster's الدفع column answered a different question from the one it
    appeared to answer, in three compounding ways.
    
    It showed a LIFETIME subscription total beside a monthly bill. A player who paid
    650 in July, 1,200 for a kit bag and 650 in August read as "2,500" for the
    current month. Two months of subscriptions were simply added together.
    
    "Subscription" was defined as "an invoice line with no product link" — a
    negative definition, so every hand-typed line became subscription money. That
    kit bag was typed as free text, so it landed in the subscription figure, was
    missing from product revenue, and left the same screen reporting the player had
    never bought the kit they had paid for.
    
    The red "has not paid" flag came from an unrelated calculation: matching invoice
    text with ilike %اشتراك% plus the programme name. Substring matching on Arabic
    also decides that تجهيزي contains زي. On live data the flag and the amount
    disagreed on 28 of 247 active enrolments — red rows showing a green figure. The
    template's "show unpaid only if flagged AND the amount is zero" guard was not
    defensive coding; it was two sources of truth being reconciled where the
    disagreement stopped being visible.
    
    The figure is now this billing cycle only, derived from the programme's own
    cycle rather than the calendar month, and one computation feeds the amount, the
    row flag and the header counts — so they cannot contradict each other again.
    
    Each figure is colour-coded by WHY it is that number, with a legend above the
    table: paid in full, pro-rated for a mid-month join, admin discount, line price
    override, instalment, partial, unpaid, not yet billed, free. All of it was
    already recorded in invoice and line metadata and never surfaced; the reason,
    who applied it and the original price now appear on the row. Colour never
    carries the meaning alone — each amount also shows a glyph, a label and a
    screen-reader sentence, and every case sits at 4.5:1 against white.
    
    The migration links hand-typed product lines to their product where the full
    trimmed description matches a product name exactly. Substrings are deliberately
    not matched and ambiguous lines are left alone: 44 lines / 209,200 EGP link
    safely, 23 lines / 42,800 EGP are reported for a human instead of guessed at.
    
    Verified by replaying the real production rows behind both reported screenshots
    through the service: every figure the user questioned is now explained.
    Co-Authored-By: 's avatarClaude Opus 5 (1M context) <noreply@anthropic.com>
    d2f4bf17
Name
Last commit
Last update
..
CreateGroupWizard.php Loading commit data...
GroupForm.php Loading commit data...
GroupList.php Loading commit data...
GroupShow.php Loading commit data...