feat(accounting): full bounced-cheque cycle, and the cheques the bank went quiet on
A bounce was one status change and one entry. It is actually four separate
facts, and collapsing them is where the books go wrong.
1. The debt comes back. A cheque was never money, it was a promise; when it
fails the drawer owes again. This part already worked.
2. The BANK charges the club. That charge leaves the club's account whoever
ends up bearing it, so it posts Dr مصروفات بنكية / Cr البنك the moment it
happens. Nothing recorded it before — which means the bank reconciliation
could never have tied out on any month with a bounce in it.
3. Somebody bears that charge. Billing the drawer is a separate claim posted
separately, so waiving it later does not touch the original debt. Saying
the club bears it while also billing the drawer is now refused: it is a
contradiction that quietly inflates income.
4. It has to end. Collected, replaced, re-presented and cleared, sent to
legal, or written off. A bounce with no ending is a receivable nobody is
chasing. Only the write-off posts here (Dr ديون معدومة / Cr شيكات مرتدة,
for the cheque plus any fees billed on top, because both are being given
up); the others are closed by events that already post on their own, and
posting again would double them.
The register now remembers what a bounce actually needs: the bank's reason code,
how many times the cheque has been presented, how many times it came back, what
the bank took, what was billed, who bore it, the protest number, and how it
ended. Reasons that carry criminal liability in Egypt — insufficient funds, a
closed account, a stop-payment on a valid cheque — are flagged, because the
club's response differs even though the entry does not.
The other half is delayed collection: a cheque past its due date that has NOT
bounced. The bank has said nothing, so there is no accounting event and the
screen posts nothing — but it is money the club is counting on and has not got,
split by whether it never went to the bank or went and never came back.
Also fixed: presentation_count only counted retries, so a cheque presented once
and returned read as never presented. It now increments on every trip to the
bank, in the transition itself rather than in the retry path.
Verified on a production clone through the real EventBus: a 50,000 cheque
deposited, bounced with a 75 bank charge and 100 billed to the drawer, produced
four correct entries; re-presented and bounced again, totals accumulated to 150
and 200; written off for 50,200; and every guard fired — bouncing something not
under collection, an unknown reason code, a negative charge, club-bears-plus-bill,
resolving twice, and re-presenting after resolution. Trial balance diff 0.00.
Co-Authored-By:
Claude Opus 5 <noreply@anthropic.com>
Showing
This diff is collapsed.
This diff is collapsed.
Please register or sign in to comment