3.9 KiB
3.9 KiB
Agent Skill: toldo-domain-modeling
Metadata
name: toldo-domain-modeling
description: Modelado de dominio CESTA (productos por productor, inventario, ventas, gastos, ajustes con motivo, cuadre QR/efectivo, reportes). Seguir reglas de negocio estrictamente.
When to use
Use this skill when:
- Modeling entities, value objects, or aggregates
- Implementing business rules
- Writing domain logic
- Creating use cases related to CESTA flows
- Validating invariants
Core Domain Concepts
Products are unique per producer
Critical Rule: Same product name from different producers = DIFFERENT products.
// CORRECT
Producto { productorId: "A", nombrePresentacion: "Café molido 250gr Santa Ana" }
Producto { productorId: "B", nombrePresentacion: "Café molido 250gr Familia Gonzalez" }
// WRONG - same entity for different producers
Uniqueness constraint: (productorId, nombrePresentacion)
Adjustments require reason
Critical Rule: ALL adjustments MUST have a non-empty motivo.
- Adjustments to inventory, sales, cash discrepancies, QR discrepancies all require reason
- Adjustments are tracked separately
- Must appear marked as "modificado/cambiado" in reports
- Store
cantidadAnterior,cantidadNueva,diferencia,motivo
Inventory Management
- Initial inventory: Should match previous day's final inventory
- Differences: If different, record difference and use real inventory
- Week restocks: Register with producto, cantidad, recibidoPor (person who received)
- End-of-day: Should match initial inventory minus sold products
Sales
- Lines with: productoId, cantidad, precioUnitario, formaPago (EFECTIVO | QR)
- Track separately for cash and QR reconciliation
- Each sale line has subtotal
Expenses (Gastos)
- Track during day: tape, pens, bags, transportation, etc.
- Include in reconciliation
Cash Reconciliation (Cuadre)
saldoEsperadoEfectivo = baseInicial + totalVentasEfectivo - totalGastosEfectivo
descuadreEfectivo = saldoRealEfectivo - saldoEsperadoEfectivo (or vice versa, track clearly)
totalVentas = totalVentasEfectivo + totalVentasQR
- Separate cash and QR
- Compare QR registrado vs QR banco
- Track discrepancies
Reports by Producer
Must include:
- Inventory differences vs previous day
- Initial inventory (real)
- Inventory movements from sales (salidas)
- Sales value for producer's products
- Total per producer
Consolidated Reports
By date range, week, or month aggregating all data.
Value Objects
Prefer value objects for primitives that have business meaning:
// Money value object
class Money {
constructor(private readonly cents: number) {}
add(other: Money): Money { ... }
subtract(other: Money): Money { ... }
// ...
}
// Quantity
class Quantity {
constructor(private readonly value: number) {}
// ensure non-negative, etc.
}
Domain Invariants
Enforce these invariants:
- Producto has valid productorId
- Ajuste always has non-empty motivo
- Venta has at least one line
- Cuadre calculations are consistent
- Inventory movements are traceable
- Payment methods are only EFECTIVO or QR
TDD for Domain
Always write tests first for domain logic:
- Write failing test for rule/invariant
- Implement minimal code to pass
- Refactor
- Repeat
Domain tests should be pure, fast, no I/O, no framework dependencies.
Common Pitfalls
- ❌ Treating same product name as same product across producers
- ❌ Allowing adjustments without motivo
- ❌ Mixing cash and QR totals
- ❌ Not tracking receivedBy for week restocks
- ❌ Forgetting to mark adjustments as changed in reports
- ❌ Losing traceability of modifications
Resources
- See
openspec/changes/add-toldo-poc-capacitor/specs/toldo-poc/spec.mdfor all scenarios - See
design.mdfor full entity definitions - Follow all business rules strictly