Sessions and Parked Sales
Open cash sessions, take breaks, declare tender, close with a Z-report, and park carts.
You track each cashier shift with apps/server/src/features/sessions/route.ts, validated by apps/server/src/features/sessions/schemas.ts, and you park interrupted carts with apps/server/src/features/parked/route.ts.
Log in first
Sessions and parked carts belong to you and your branch, so log in and keep the token for every call.
TOKEN=$(curl -s -X POST http://localhost:8000/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"admin@demo.pharmaflow","password":"Demo@1234"}' | python3 -c "import sys,json; print(json.load(sys.stdin)['token'])")
Open and check your session
You open with POST /sessions/open and an opening_float, and if you already have one open the server returns it instead of creating a duplicate. New sales automatically attach to your open session id.
curl -X POST http://localhost:8000/api/v1/sessions/open \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"opening_float": 200}'
curl http://localhost:8000/api/v1/sessions/current -H "Authorization: Bearer $TOKEN"
You review past shifts with GET /sessions/history, which returns your closed sessions newest first with revenue, VAT, and break minutes.
Take a break
You pause with POST /sessions/break/start and resume with POST /sessions/break/end. Ending the break adds the elapsed whole minutes to break_minutes, and closing while on break finalizes the open break first.
curl -X POST http://localhost:8000/api/v1/sessions/break/start \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"reason":"Lunch"}'
curl -X POST http://localhost:8000/api/v1/sessions/break/end \
-H "Authorization: Bearer $TOKEN"
Declare tender and read the verdict
You count the drawer and post POST /sessions/tender with declared_cash. The server computes expected cash as opening float plus cash sales minus cash refunds, then returns OVERAGE, SHORTAGE, or BALANCED with the difference.
curl -X POST http://localhost:8000/api/v1/sessions/tender \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"declared_cash": 1250.5, "notes":"End of morning count"}'
You list the last ten declarations with GET /sessions/tender/history before you close.
Close and print the Z-report
You close with POST /sessions/close, which aggregates sale count, revenue, VAT, and a per-method payment breakdown onto the session row. Then you fetch the printable report and the itemized sales list.
curl -X POST http://localhost:8000/api/v1/sessions/close -H "Authorization: Bearer $TOKEN"
curl http://localhost:8000/api/v1/sessions/SESSION_ID/z-report -H "Authorization: Bearer $TOKEN"
curl http://localhost:8000/api/v1/sessions/SESSION_ID/sales -H "Authorization: Bearer $TOKEN"
Park, recall, or void a cart
You park an interrupted cart with POST /parked, list your own PARKED carts, then recall one back to the register or void it when the customer walks away. Recall and void only work on your own parked rows.
curl -X POST http://localhost:8000/api/v1/parked \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"cart":[{"medicine_id":"MED-001","quantity":1,"unit_price":12.5}]}'
curl http://localhost:8000/api/v1/parked -H "Authorization: Bearer $TOKEN"
curl -X POST http://localhost:8000/api/v1/parked/PARKED_ID/recall -H "Authorization: Bearer $TOKEN"
curl -X POST http://localhost:8000/api/v1/parked/PARKED_ID/void -H "Authorization: Bearer $TOKEN"
Next steps
Ring the recalled cart in /sales/selling-at-the-counter, validate a parting coupon in /sales/coupons-and-discounts, and process any same-day comeback in /sales/returns-and-credit-notes.