Overview
Torn implements a blind cash count system where cashiers declare their cash totals without seeing the expected amount. This prevents bias and ensures accurate accountability.Cash Session Lifecycle
/app/models/cash.py:9-49
Opening a Cash Session
Source:
/app/routers/cash.py:24-85
Processing Sales During Session
Once the cash session is open, the cashier can process sales:- The cashier (
local_user) has an activeOPENcash session - Throws
409 Conflictif no session is open
/app/routers/sales.py:106-117
All sales are automatically linked to the cashier via
seller_id, enabling accurate cash count calculations at session close.Checking Session Status
Query the current session state:404 Not Found
Source: /app/routers/cash.py:88-137
Closing a Cash Session (Blind Count)
Cashier Counts Physical Cash
The cashier physically counts all cash in the drawer without looking at the system total.
System Calculates Difference
The backend:Interpretation:
- Queries all CASH payments for sales by this cashier since
start_time - Calculates expected cash:
start_amount + total_sales_cash - Compares with declared amount
- Stores the variance
final_cash_system: What the system expects (50,000 + 93,000 in sales)final_cash_declared: What the cashier counted (142,500)difference: -500 means 500 pesos short (faltante)
/app/routers/cash.py:140-199
Understanding Cash Calculations
Final Cash System (Expected)
/app/routers/cash.py:175-187
Difference Calculation
difference > 0: Overage (sobrante) - more cash than expecteddifference < 0: Shortage (faltante) - less cash than expecteddifference = 0: Perfect balance
Viewing Session History
List all cash sessions with user details:start_time DESC (newest first).
Source: /app/routers/cash.py:202-213
Session Status Values
| Status | Description |
|---|---|
OPEN | Session active, cashier can process sales |
CLOSED | Session closed normally via blind count |
CLOSED_SYSTEM | Session force-closed by system (e.g., when opening new session) |
/app/models/cash.py:42
Audit Metadata for System Users
When SaaS admins use system users to operate cash sessions, audit trails are preserved:/app/routers/cash.py:80, 194-195
Multi-Cashier Environments
Concurrent Sessions
Each cashier can have their own independent session:- Cashier A: Opens session at 08:00, closes at 14:00
- Cashier B: Opens session at 14:00, closes at 20:00
- Cashier C: Opens session at 10:00, closes at 18:00 (overlapping shifts)
seller_id, so cash counts remain accurate.
Shared Cash Drawer Considerations
Handling Common Scenarios
Forgotten Open Session
Scenario: Cashier forgets to close session at end of shift. Solution:status = "CLOSED_SYSTEM" and difference = 0 (no declared amount).
Mid-Day Cash Pickup
Scenario: Manager removes excess cash during shift for security. Current Limitation: Torn doesn’t have a native “cash pickup” event. Workaround:- Close current session (blind count including removed cash)
- Immediately open new session with adjusted start amount
cash_pickups table:
Split Payments (Mixed Methods)
Scenario: Sale paid with 50% cash, 50% card. The system only countsEFECTIVO payments toward final_cash_system. Card payments don’t affect cash count.
/app/routers/cash.py:181
Reporting and Analytics
Cashier Performance Report
Daily Cash Summary
Best Practices
Blind Count Policy
Enforce strict blind counts: cashiers should never see the expected amount before declaring their total. This is the core of accountability.
Variance Thresholds
Establish acceptable variance limits:
- ± 500: Acceptable (rounding/human error)
- ± 1000-5000: Warning (requires explanation)
- > 5000: Critical (investigation required)
Daily Reconciliation
Managers should review all session differences daily. Investigate patterns of consistent shortages.
Starting Float Consistency
Maintain consistent
start_amount values (e.g., always 50,000) to simplify cashier processes and reduce errors.End-of-Day Security
After closing sessions, physically secure all cash:
- Count and bag declared amounts
- Store in safe
- Prepare bank deposits
- Document deposit amounts
Integration with Other Modules
Sales Module
Sales automatically validate open cash sessions:/app/routers/sales.py:108-117
Returns Module
Cash returns should ideally require an open session, though current implementation may not enforce this. Consider adding validation.User Roles
Access control:- Cashiers (VENDEDOR): Can open/close their own sessions
- Managers (ADMINISTRADOR): Can view all sessions, force close sessions
- Auditors: Read-only access to session history
Related Guides
- Sales Process - How sales interact with cash sessions
- User Roles - Configuring permissions
- Returns & Refunds - Handling cash refunds