• Mahmoud Aglan's avatar
    fix(settlement): the card's price is the debt, not the sum of everything typed toward it · 396f19ac
    Mahmoud Aglan authored
    Participant 128 on OC-Sport: an 8,000 registration card, 2,500 paid in
    July and 2,500 in August. The settlement screen told the operator he had
    paid 5,000 of 10,500 and still owed 5,500, and offered a button to bill
    him that 5,500 on top.
    
    The 10,500 is real, and that is the problem. INV-000310 carried the first
    instalment on 2 July. On 5 August the full 8,000 card was invoiced again
    as INV-000588, 2,500 was collected against it, and the next day it was
    split — reduced to 2,500 with a 5,500 remainder as INV-000593 — by
    someone who never saw the July instalment. Three lines, 10,500, for a
    card that costs 8,000.
    
    bundleStatus() then read `max(billed, price)`. That reading treats
    hand-typed lines as if they defined the obligation, so every duplicate
    and every correction raised the debt, and the excess disappeared into a
    larger number instead of being noticed. But a hand-typed line is an
    instalment TOWARD a card whose price the product record still holds: the
    card is what is owed. A real product sale is different — its price froze
    at the till — so that keeps billing as the obligation.
    
    So: expected is the frozen sale price for a real sale, and the card's
    price otherwise. Anything typed past it is the same money entered twice
    and is reported as `over_billed_bundle` rather than absorbed. #128 now
    reads 5,000 of 8,000 with 3,000 left, flagged for a 2,500 double entry.
    A scan of the restored tenant finds exactly one such account: his.
    
    Two guards on the tool that produced it. The correction wizard clamped
    paid_amount down to the new total and rewrote the payment rows
    themselves, so cutting an invoice below what had been collected against
    it destroyed real money — the payment row said one thing and its
    double-entry transaction still said another, and nobody was told. It now
    refuses and names the settlement wizard, which can move the payment or
    credit it to a wallet. And the split step lists what the account already
    carries, so a second "first instalment" is visible before it is created
    rather than three weeks after.
    Co-Authored-By: 's avatarClaude Opus 5 (1M context) <noreply@anthropic.com>
    396f19ac
Name
Last commit
Last update
Screenshots Loading commit data...
app Loading commit data...
bootstrap Loading commit data...
config Loading commit data...
database Loading commit data...
docker Loading commit data...
docs Loading commit data...
docs-site Loading commit data...
flutter_shell Loading commit data...
gap-filling-plans Loading commit data...
lang Loading commit data...
marketing-site Loading commit data...
plans Loading commit data...
public Loading commit data...
reference/oc-sport Loading commit data...
resources Loading commit data...
routes Loading commit data...
scripts Loading commit data...
storage Loading commit data...
tests Loading commit data...
.dockerignore Loading commit data...
.editorconfig Loading commit data...
.env.example Loading commit data...
.gitattributes Loading commit data...
.gitignore Loading commit data...
.npmrc Loading commit data...
Beanding Guide.txt Loading commit data...
CLAUDE.md Loading commit data...
Dockerfile Loading commit data...
README.md Loading commit data...
artisan Loading commit data...
captain-definition Loading commit data...
composer.json Loading commit data...
composer.lock Loading commit data...
deploy.sh Loading commit data...
elcaptain-sportsonly-db.md Loading commit data...
one-click-app.yml Loading commit data...
package-lock.json Loading commit data...
package.json Loading commit data...
phpunit.xml Loading commit data...
system info.txt Loading commit data...
vite.config.js Loading commit data...
نادى الشيخ زايد كشف بيانات اللاعبين (2).html Loading commit data...