Cash Register Module — Architecture
Overview
The Cash Register module manages the POS shift lifecycle: physical register devices, cashier sessions (open/close), cash movements (cash-in, cash-out, safe drops), discrepancy detection, and reporting.
Module Structure
cash-register/
├── domain/ # Ports & domain utilities
│ ├── register-repository.domain.ts # IRegisterRepository interface + token
│ ├── cash-register-session-repository.domain.ts # ICashRegisterSessionRepository + token
│ ├── cash-movement-repository.domain.ts # ICashMovementRepository + token
│ └── cash-denomination.utils.ts # Denomination breakdown validation
├── application/ # Use cases & services
│ ├── register.service.ts # Register CRUD + activation
│ ├── cash-register-session.service.ts # Session lifecycle (open/close/review)
│ ├── cash-movement.service.ts # Cash movement creation + approval
│ ├── session-totals.service.ts # Expected cash & payment aggregation
│ ├── cash-register-settings.service.ts # Threshold resolution from parameters
│ ├── discrepancy.service.ts # Discrepancy calculation & validation
│ ├── closing-report.service.ts # Closing report data + PDF generation
│ ├── z-report.service.ts # Daily Z Report aggregation + PDF
│ └── events/ # Domain events
│ ├── on-open-cash-register-session.event.ts
│ ├── on-close-cash-register-session.event.ts
│ ├── on-cash-movement-created.event.ts
│ └── on-cash-register-discrepancy-detected.event.ts
├── infrastructure/ # Adapters (Kysely implementations)
│ ├── register.repository.ts # implements IRegisterRepository
│ ├── cash-register-session.repository.ts # implements ICashRegisterSessionRepository
│ └── cash-movement.repository.ts # implements ICashMovementRepository
├── interfaces/ # HTTP controllers & DTOs
│ ├── register.controller.ts # /registers endpoints
│ ├── cash-register-session.controller.ts # /cash-register-sessions endpoints
│ ├── cash-movement.controller.ts # /cash-movements endpoints
│ └── dtos/ # Request/query DTOs with validation
└── cash-register.module.ts # NestJS module (token-based DI)
Domain Concepts
Register
A physical cash register device at a location. Can be activated/deactivated.
Cash Register Session
A time-bounded shift during which a cashier operates a register. Lifecycle:
- open — Cashier opens session with an opening cash amount
- closed — Cashier counts cash, system calculates discrepancy
- reviewed — Manager verifies the closing report
Cash Movement
Money moving in/out of the register during a session:
cash_in— Adding cash to the drawercash_out— Removing cash (may require manager approval above threshold)safe_drop— Moving cash to a safeadjustment— Corrective adjustmenttip_in/tip_out— Tip-related movementsexpense— Petty cash expense
Discrepancy
The difference between the system-calculated expected cash and the physical cash count at closing. When it exceeds a configurable threshold, manager approval is required.
Reports
- X Report — Real-time inquiry of session totals (no session close)
- Closing Report — Full report generated when session is closed
- Z Report — Daily aggregate of all closed sessions at a location
Dependency Flow
Controller → Service → Domain Interface (Port) ← Repository (Adapter)
→ Domain Utilities
→ Domain Events (EventEmitter2)
Services depend on domain interfaces (ports), not concrete repositories. The module binds implementations via token-based injection:
{ provide: REGISTER_REPOSITORY, useClass: RegisterRepository }
{ provide: CASH_REGISTER_SESSION_REPOSITORY, useClass: CashRegisterSessionRepository }
{ provide: CASH_MOVEMENT_REPOSITORY, useClass: CashMovementRepository }
Key Design Decisions
-
Token-based DI — Repositories are injected via Symbol tokens, keeping application services decoupled from infrastructure.
-
Immutable closed sessions — The repository prevents updates to closed sessions. The only allowed transition from "closed" is to "reviewed" via a dedicated
transitionToReviewedmethod. -
Denomination breakdown validation — Shared utility in
domain/cash-denomination.utils.tsvalidates that physical cash counts match the reported totals, used during both opening and closing. -
Threshold-based approval — Both cash-out movements and closing discrepancies have configurable thresholds resolved from the parameter catalog with a location → business fallback chain.
-
Closing report delegation — The controller injects
ClosingReportServicedirectly (no pass-through methods on the session service) for PDF generation, HTML preview, and JSON report data.
API Endpoints Summary
Registers (/registers)
| Method | Path | Description |
|---|---|---|
| POST | /registers | Create register |
| GET | /registers | List registers (with optional pagination) |
| GET | /registers/:id | Get register by ID |
| PATCH | /registers/:id | Update register |
| DELETE | /registers/:id | Delete register |
| POST | /registers/:id/activate | Activate register |
| POST | /registers/:id/deactivate | Deactivate register |
Sessions (/cash-register-sessions)
| Method | Path | Description |
|---|---|---|
| POST | /cash-register-sessions | Open session |
| GET | /cash-register-sessions | List sessions |
| GET | /cash-register-sessions/search | Search sessions (advanced) |
| GET | /cash-register-sessions/:id | Get session by ID |
| POST | /cash-register-sessions/:id/close | Close session |
| POST | /cash-register-sessions/:id/review | Review closed session |
| POST | /cash-register-sessions/:id/cash-count/draft | Save cash count draft |
| GET | /cash-register-sessions/:id/totals | Get session totals |
| GET | /cash-register-sessions/:id/x-report | X Report (JSON) |
| GET | /cash-register-sessions/:id/x-report/pdf | X Report (PDF) |
| GET | /cash-register-sessions/:id/closing-report | Closing report (JSON) |
| GET | /cash-register-sessions/:id/closing-report/pdf | Closing report (PDF) |
| GET | /cash-register-sessions/:id/closing-report/pdf/content | Closing report (base64) |
| GET | /cash-register-sessions/:id/closing-report/print | Closing report (HTML) |
| GET | /cash-register-sessions/z-report | Z Report (JSON) |
| GET | /cash-register-sessions/z-report/pdf | Z Report (PDF) |
| GET | /cash-register-sessions/z-report/print | Z Report (HTML) |
Cash Movements (/cash-movements)
| Method | Path | Description |
|---|---|---|
| POST | /cash-movements | Create cash movement |
| POST | /cash-movements/:id/approve | Approve cash-out movement |
| GET | /cash-movements | List cash movements |
| GET | /cash-movements/:id | Get cash movement by ID |
External Dependencies
- PdfModule — PDF and HTML report generation (Puppeteer)
- SafeModule — Safe validation for safe drop movements
- EventEmitter2 — Domain event publication (session open/close, movement created, discrepancy detected)