• DevPilot's avatar
    fix(accounting): stop a failed claim from re-posting the accrual every run · 87c22aca
    DevPilot authored
    Booking the accruals against the live books exposed a real defect, and it cost
    one duplicate entry before it was caught.
    
    Nine rows in sa_players carry a membership NUMBER in member_id (101, 1015,
    897000) instead of a member row id. The accrual run reached the first of them,
    the foreign key on accounts_receivable.member_id refused the insert, and the
    exception escaped the loop that records claims in posting_accruals. That loop
    runs AFTER the journal entry is posted, so the entry stood at the full batch
    total with only the claims written before the failure. The next run read the
    remaining documents as never accrued and posted a SECOND entry for them — and
    would have posted one more every night, because the failure is deterministic.
    
    AccrualService::batch now treats a claim it cannot write as something to report,
    not something to throw: the entry is already posted, so abandoning the rest of
    the batch is the one response guaranteed to corrupt the ledger. A member id that
    does not resolve costs the receivable, never the claim — posting_accruals is the
    system of record and already tracks obligations for non-members. Member
    existence is resolved once per batch, not once per claim.
    
    Phase_112_003 repairs what the two runs left: the duplicate is reversed rather
    than deleted so the correction stays visible, its claims move to the entry that
    actually posted their money, and the 110 claims plus 32 receivables that were
    never written are backfilled against it. It verifies the entry and its claims
    agree before finishing, and does nothing at all unless production matches the
    exact broken shape.
    
    Why the clone missed it: the verification harness built tables with
    CREATE TABLE ... LIKE, which silently drops foreign keys — so the constraint
    that breaks production did not exist in the clone, and the run came back green.
    The harness now copies DDL via SHOW CREATE TABLE and asserts the foreign key
    count matches the source (409/409).
    
    Verified against a clone of the actual broken production state: net movement for
    sa_subscription_accrual is 104,769.00 not 184,938.00, all 135 claims equal their
    entry to the cent, 1,316 claims total 835,167.93, trial balance diff 0.00, and
    both the repair and the fixed runner post nothing on a second pass.
    Co-Authored-By: 's avatarClaude Opus 5 <noreply@anthropic.com>
    87c22aca
Name
Last commit
Last update
..
Academies Loading commit data...
AcademyContracts Loading commit data...
AccessMatrix Loading commit data...
Accounting Loading commit data...
Achievements Loading commit data...
ActivitySubscriptions Loading commit data...
Alerts Loading commit data...
Archive Loading commit data...
Audit Loading commit data...
Auth Loading commit data...
Branches Loading commit data...
Carnets Loading commit data...
Cashier Loading commit data...
Children Loading commit data...
Coaches Loading commit data...
Dashboard Loading commit data...
Death Loading commit data...
Disciplines Loading commit data...
Divorce Loading commit data...
Documents Loading commit data...
Facilities Loading commit data...
FacilityDashboards Loading commit data...
FacilityGrids Loading commit data...
Fines Loading commit data...
Foreign Loading commit data...
Forms Loading commit data...
HR Loading commit data...
Honorary Loading commit data...
Installments Loading commit data...
Interviews Loading commit data...
Inventory Loading commit data...
MatchCenter Loading commit data...
MedicalBoard Loading commit data...
Members Loading commit data...
News Loading commit data...
Notifications Loading commit data...
ParentPortal Loading commit data...
Payments Loading commit data...
PlayerAffairs Loading commit data...
PlayerApi Loading commit data...
PlayerAuth Loading commit data...
PlaygroundAdmin Loading commit data...
PoolManagement Loading commit data...
Pricing Loading commit data...
Procurement Loading commit data...
Receipts Loading commit data...
Rentals Loading commit data...
Reports Loading commit data...
Reservations Loading commit data...
Roles Loading commit data...
Rules Loading commit data...
Sales Loading commit data...
Scheduling Loading commit data...
Seasonal Loading commit data...
ServiceCatalog Loading commit data...
Sessions Loading commit data...
Settings Loading commit data...
Sports Loading commit data...
SportsActivity Loading commit data...
SportsDashboard Loading commit data...
Spouses Loading commit data...
Subscriptions Loading commit data...
Support Loading commit data...
Temporary Loading commit data...
Tournaments Loading commit data...
TrainerPortal Loading commit data...
Training Loading commit data...
TrainingGroups Loading commit data...
Transfers Loading commit data...
Treasury Loading commit data...
Tutorials Loading commit data...
Users Loading commit data...
Waiver Loading commit data...
Workflow Loading commit data...