Overview
Sorteos (lottery draws) follow a strict state machine with four main states. Understanding the lifecycle and valid transitions is critical for managing lottery operations.State Machine
Sorteo States
| State | Description | Ticket Creation | Evaluation |
|---|---|---|---|
| SCHEDULED | Future draw, not yet open | ❌ Blocked | ❌ Blocked |
| OPEN | Accepting bets | ✅ Allowed | ❌ Blocked |
| CLOSED | Betting closed, awaiting results | ❌ Blocked | ✅ Allowed |
| EVALUATED | Results published, tickets evaluated | ❌ Blocked | ✅ Can revert |
State Transitions
SCHEDULED → OPEN
Activate sorteo
Manually open a scheduled sorteo for betting.From
src/api/v1/controllers/sorteo.controller.ts:22-25:Opening a sorteo makes it visible to vendedores and enables ticket creation.
OPEN → CLOSED
Close betting before evaluating results.src/api/v1/controllers/sorteo.controller.ts:37-40:
CLOSED → EVALUATED
Evaluate sorteo with winning number and optional REVENTADO multiplier.src/api/v1/controllers/sorteo.controller.ts:42-50:
Evaluation Rules
Winning number validation
Winning number validation
- Must be exactly 2 digits (00-99) for standard lotteries
- Must be 3 digits (000-999) for monazos
- Validated against
Loteria.rulesJson.numberRange
REVENTADO multiplier requirements
REVENTADO multiplier requirements
When the winning number has REVENTADO bets:
- Required:
extraMultiplierIdof typeREVENTADO - Must be active (
isActive = true) - Must belong to same
loteriaId - If
appliesToSorteoIdis set, must match current sorteo - System snapshots
extraMultiplierXto sorteo
Ticket evaluation logic
Ticket evaluation logic
For each active ticket:
- NUMERO bets: Check if
jugada.number === winningNumber- If match:
isWinner = true,payout = amount × finalMultiplierX
- If match:
- REVENTADO bets: Check if
jugada.number === winningNumber- If match:
isWinner = true,payout = amount × finalMultiplierX - Snapshot
extraMultiplierXfrom sorteo to jugada
- If match:
- Update ticket:
status = 'EVALUATED'isActive = false- Calculate
totalPayout - Set
remainingAmount(for payment tracking)
EVALUATED → CLOSED (Revert)
Revert evaluation to fix errors.src/api/v1/controllers/sorteo.controller.ts:176-183:
Creating Sorteos
Manual Creation
Batch Creation (Seed)
Generate multiple sorteos based on loteria schedule rules.Idempotency: The seed endpoint uses
@@unique([loteriaId, scheduledAt]) constraint to prevent duplicates. Concurrent calls are safe.Listing Sorteos
loteriaId: Filter by lotterystatus:SCHEDULED|OPEN|CLOSED|EVALUATEDisActive:true|falsedate:today|tomorrow|week|month|rangefromDate,toDate: Fordate=range(ISO format)search: Search by name or winning numbergroupBy:hour|loteria-hour(grouped view)page,pageSize: Pagination
Grouped View
Fromsrc/api/v1/controllers/sorteo.controller.ts:127-130:
groupBy=hour:
Updating Sorteos
src/api/v1/controllers/sorteo.controller.ts:11-14:
name: Display namescheduledAt: Reschedule draw timeisActive: Visibility toggle
Soft Delete and Restore
Delete (Soft)
src/api/v1/controllers/sorteo.controller.ts:52-59:
Restore
src/api/v1/controllers/sorteo.controller.ts:61-64:
Reset to Scheduled
Reset sorteo back to SCHEDULED state (admin recovery tool).src/api/v1/controllers/sorteo.controller.ts:66-69:
Force Open (Override)
Force open a sorteo even if in CLOSED or EVALUATED state.src/api/v1/controllers/sorteo.controller.ts:27-30:
Evaluated Summary (Vendedor View)
Get summary of evaluated sorteos with win/loss statistics.src/api/v1/controllers/sorteo.controller.ts:185-212:
Best Practices
Use state-specific endpoints
Use state-specific endpoints
Always use dedicated transition endpoints (
/open, /close, /evaluate) instead of trying to change status via update.Validate before transitions
Validate before transitions
Check current state before calling transition endpoints to provide better UX error messages.
Seed in advance
Seed in advance
Use
/seed_sorteos to pre-create sorteos for the week. This prevents last-minute issues.Always include reason for reverts
Always include reason for reverts
Include
reason field when reverting evaluations for audit compliance.Monitor grouped views for operations
Monitor grouped views for operations
Use
groupBy=hour for operational dashboards to see all draws at the same time across lotteries.Related Guides
- Ticket Creation - Creating tickets for open sorteos
- Restriction Rules - Setting sales cutoff times
- Payments - Paying out winning tickets
- Analytics - Sorteo performance reports