Build out the shop domain: Cart/CartItem (one open cart per user per club),
Order/OrderLine, Discount/AppliedDiscount, Payment and Invoice.
Order and Invoice allocate a per-club, per-year sequential number
(ORD-<year>-<seq> / INV-<year>-<seq>) via shared helpers, retrying on collision
with the (club, number) unique constraint as the source of truth.
Fixes found while testing:
- Invoice had no number generator, so a second invoice in a club collided on
the empty string and could never be created.
- AppliedDiscount printed a "%" suffix even for fixed-amount discounts, and had
no (order, discount) uniqueness, so a discount could be applied twice.
Every model validates its club-scoped FKs (product/team/discount/order/season/
staff_role) against the owning club, and Member FKs against club membership.
Register all models in the admin, with FK dropdowns scoped to the owning club.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>