Space earns money in five ways besides the café. People pay for a day at a desk, buy an hour package, rent a private office, hire the meeting or training room, or buy a ticket for the Thursday music night. The front desk records all five in one ledger, so the end-of-day count, what is owed and who paid are all answered in one place.
Who does what
| Screen | Route | Roles |
|---|---|---|
| Today (check-in, who's in) | /{lang}/dashboard/desk | Admin, Cashier |
| Customers, packages | /{lang}/dashboard/desk/customers | Admin, Cashier |
| Room schedule & billing | /{lang}/dashboard/desk/rooms | Admin, Cashier |
| Tickets (verify, door sales) | /{lang}/dashboard/desk/tickets | Admin, Cashier |
| Door (admit a ticket) | /{lang}/dashboard/desk/door | Admin, Cashier |
| Offices, contracts, rent | /{lang}/dashboard/desk/offices | Admin |
| Ledger, cash-up, owed | /{lang}/dashboard/desk/ledger | Admin |
| Prices & Bankak account | /{lang}/dashboard/desk/settings | Admin |
| Invoice / receipt (print) | /{lang}/dashboard/desk/charges/<id> | Admin, Cashier |
| Invoice link sent to a company | /{lang}/invoice/<token> | Anyone with the link |
| Buy tickets | the event page → /{lang}/tickets/<token> | Guests |
The ledger
Every sale is a charge: what someone owes, with a receipt number such as R-1042. Every pound received is a payment against a charge, made in cash or by Bankak (with the transaction number). A charge can be paid in parts. It shows as Unpaid, Part paid, Paid or Overdue (past its due date). An admin can void it only after any money on it has been voided.
The charge row is locked while money is recorded, so two cashiers taking payment at once can't overpay it. A payment entered by mistake is voided with a reason, never deleted, and the cash-up lists voids separately.
The five flows
Day pass
At check-in the cashier types the visitor's phone number. A returning visitor is found; a new one is added. A day-pass charge is raised at the price in settings, which the cashier can change, and paid then or at check-out.
Hour package
Sold from a customer's page at the published price (Trial, Basic, Professional, Flexible, Unlimited, Study). The Study package and Unlimited expire after one month. A package holder checks in with no charge; at check-out the minutes on the clock, which staff can correct, come off the package.
Office rent
An office gets a contract: company, monthly rent, due day, start and end dates, and an optional deposit. Each month an admin presses Issue invoices. That creates one rent charge per running contract, and pressing it twice is harmless. Unpaid rent past its due day appears on the overdue list, with a WhatsApp reminder that carries the invoice link.
Room hire
Room bookings still arrive as booking requests. The room schedule shows the week per room, flags clashes, and turns a booking into one charge (hours × the hourly rate in settings, editable).
Music-night tickets
Give an event ticket types (name, price, optional capacity), and its page sells tickets instead of registrations:
- The guest picks tickets. The seats are held (two hours by default) and the guest sees Space's Bankak account.
- The guest transfers the money and enters the transaction number. Each number can be used only once.
- Staff check the Bankak app, then verify the order. The tickets are issued as QR codes on the guest's order page, and the ledger records a Bankak payment.
- At the door, a staff phone scans the QR, which opens the door screen. Admit works once per ticket.
Staff can also sell at the door for cash or Bankak. Repeat next week copies the event and its ticket types seven days later, unpublished.
Done automatically
The first time anyone opens the desk each day, it runs the day's routines once:
- Rent invoices: this month's invoice for every running office contract. Running it twice is safe.
- Forgotten check-outs: a visit still open from an earlier day is closed at that day's closing time (22:00), and package minutes are drawn to closing.
- Past bookings: a confirmed booking whose time is over becomes
COMPLETED. - Stale requests: a request still unpaid after its time ended is closed. Requests with a transfer waiting to be checked are left alone.
A green note at the bottom of the desk lists what ran. The code is src/lib/desk/routines.ts. There's no cron to operate, because the desk is opened every working day.
End of day
Ledger → Cash-up shows the day's takings by method, by kind of sale and by staff member. It includes the café's paid orders, so cash expected in the drawer covers the whole building.
Code
Domain rules live in src/lib/desk/ (ledger, visits, packages, offices, rooms, tickets, reports), and screens live in src/components/dashboard/desk/. Money is whole Sudanese pounds stored as integers. The published package prices stay in src/components/site/membership/config.ts, and the desk sells from them.