Feature #170
openCanteen: coupons — issue, print, redeem at POS, liability report feed
100%
Description
Prepaid meal coupons, issued in books and redeemed at the till.
- CouponBook (book number from Admin's canteen-coupon-book sequence, purpose, department, cost centre, quantity, value, price list, valid till) and its Coupon rows.
- CouponCodeGenerator: CP-0914-0001-K7 shape, a check character that catches every single-character typo, alphabet excludes I, L, O, U.
- GET coupons/resolve?code= -> valid / expired / redeemed / void / book closed.
- POS Coupon tab: the coupon covers up to its value, any remainder is cash. Redemption marks the coupon under a row lock, inside the same transaction that numbers the sale.
- A void un-redeems the coupon; two concurrent redemptions of one coupon settle to exactly one success; closing a book voids only the unredeemed coupons.
- /coupons page with an issue dialog and an A4 print sheet (3x7 cut-outs, barcode).
Depends on: Admin's coupon-book number sequence.
NP Updated by Navya P. about 1 month ago
- Status changed from New to In Progress
Backend done, tested, on integration/canteen-v1 (7 commits):
- CouponCodeGenerator: format + check digit, catches every single-character typo
- CouponBook / Coupon entities: issue, redeem, void, close-voids-unredeemed
- Database table + migration (coupon codes are per-hospital unique, not global -- caught by a test)
- ICouponService: issue a book, resolve a code (always 200), close a book
- Coupon redeemable at the till: prices at the book's Staff/Visitor rate, under a row lock so two tills can never redeem the same coupon
- Void gives a coupon back (V20/V21), race-tested
Still to do: API controller + permissions, portal /coupons page, POS Coupon tab, print page.
API: 503 unit + 621 integration tests, all green.
NP Updated by Navya P. about 1 month ago
Backend complete, tested, on integration/canteen-v1 (8 commits):
- CouponCodeGenerator, CouponBook/Coupon entities, database, ICouponService
- Redeemable at the till under a row lock; void gives the coupon back (V20/V21)
- CouponsController: issue/list/get/close a book, resolve a code at the till -- all gated, tested
API: 503 unit + 632 integration tests, all green.
Left: portal /coupons page (issue dialog, print page), POS Coupon tab.
NP Updated by Navya P. about 1 month ago
- % Done changed from 0 to 70
NP Updated by Navya P. about 1 month ago
Coupons (V1-8) done end to end, on integration/canteen-v1, pushed (11 commits):
- Issue a book -> generates every coupon, individually coded, check-digit protected
- Print: A4 sheet, hand-rolled Code 128 barcode under each code (no library added, per plan)
- POS Coupon tab: scan, see the book's price and value, ring it at the till, priced at Staff or Visitor per the book
- Void gives the coupon back (V20/V21), race-tested
- Close voids every unredeemed coupon; liability stat cards on /coupons
API: 503 unit + 632 integration. Portal: 445 tests. All green, tsc clean.
One caveat worth a manual check at UAT: the barcode's symbol table was hand-transcribed from the
Code 128 spec (no library) and could not be verified against a real scanner in this environment --
worth a physical scan test before relying on it.
NP Updated by Navya P. about 1 month ago
- Status changed from In Progress to Resolved
- Resolved By set to Navya P.
NP Updated by Navya P. about 1 month ago
- Due date set to 09/29/2026
- % Done changed from 70 to 100