Skip to main content

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 drawer
  • cash_out — Removing cash (may require manager approval above threshold)
  • safe_drop — Moving cash to a safe
  • adjustment — Corrective adjustment
  • tip_in / tip_out — Tip-related movements
  • expense — 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

  1. Token-based DI — Repositories are injected via Symbol tokens, keeping application services decoupled from infrastructure.

  2. Immutable closed sessions — The repository prevents updates to closed sessions. The only allowed transition from "closed" is to "reviewed" via a dedicated transitionToReviewed method.

  3. Denomination breakdown validation — Shared utility in domain/cash-denomination.utils.ts validates that physical cash counts match the reported totals, used during both opening and closing.

  4. Threshold-based approval — Both cash-out movements and closing discrepancies have configurable thresholds resolved from the parameter catalog with a location → business fallback chain.

  5. Closing report delegation — The controller injects ClosingReportService directly (no pass-through methods on the session service) for PDF generation, HTML preview, and JSON report data.

API Endpoints Summary

Registers (/registers)

MethodPathDescription
POST/registersCreate register
GET/registersList registers (with optional pagination)
GET/registers/:idGet register by ID
PATCH/registers/:idUpdate register
DELETE/registers/:idDelete register
POST/registers/:id/activateActivate register
POST/registers/:id/deactivateDeactivate register

Sessions (/cash-register-sessions)

MethodPathDescription
POST/cash-register-sessionsOpen session
GET/cash-register-sessionsList sessions
GET/cash-register-sessions/searchSearch sessions (advanced)
GET/cash-register-sessions/:idGet session by ID
POST/cash-register-sessions/:id/closeClose session
POST/cash-register-sessions/:id/reviewReview closed session
POST/cash-register-sessions/:id/cash-count/draftSave cash count draft
GET/cash-register-sessions/:id/totalsGet session totals
GET/cash-register-sessions/:id/x-reportX Report (JSON)
GET/cash-register-sessions/:id/x-report/pdfX Report (PDF)
GET/cash-register-sessions/:id/closing-reportClosing report (JSON)
GET/cash-register-sessions/:id/closing-report/pdfClosing report (PDF)
GET/cash-register-sessions/:id/closing-report/pdf/contentClosing report (base64)
GET/cash-register-sessions/:id/closing-report/printClosing report (HTML)
GET/cash-register-sessions/z-reportZ Report (JSON)
GET/cash-register-sessions/z-report/pdfZ Report (PDF)
GET/cash-register-sessions/z-report/printZ Report (HTML)

Cash Movements (/cash-movements)

MethodPathDescription
POST/cash-movementsCreate cash movement
POST/cash-movements/:id/approveApprove cash-out movement
GET/cash-movementsList cash movements
GET/cash-movements/:idGet 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)