# Agent Skill: toldo-domain-modeling ## Metadata ```yaml 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. ```typescript // 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) ```typescript 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: 1. Inventory differences vs previous day 2. Initial inventory (real) 3. Inventory movements from sales (salidas) 4. Sales value for producer's products 5. 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: ```typescript // 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:** 1. Write failing test for rule/invariant 2. Implement minimal code to pass 3. Refactor 4. 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.md` for all scenarios - See `design.md` for full entity definitions - Follow all business rules strictly