# GRAFO DE DEPENDENCIAS VALIDADO - RETAIL # Fecha: 2025-12-18 # Fase: 4 - Validacion metadata: version: "1.0" proyecto: erp-suite/retail total_modulos: 10 total_entidades: 56 total_servicios: 48 # ============================================================ # MODULOS CORE (PRERREQUISITOS) # ============================================================ core_modules: MGN-001-auth: nombre: "Autenticacion" estado: 40% requerido: 100% bloqueante: true entidades: - name: tenants schema: auth estado: existe usado_por: [todos] - name: users schema: auth estado: existe usado_por: [RT-001, RT-002, RT-007] - name: roles schema: auth estado: parcial usado_por: [RT-001] - name: permissions schema: auth estado: no_existe usado_por: [RT-001] - name: user_roles schema: auth estado: no_existe usado_por: [RT-001] servicios: - name: AuthService estado: parcial metodos_faltantes: [validatePermission, refreshToken] - name: PermissionsService estado: no_existe dependencias: [] MGN-005-catalogs: nombre: "Catalogos" estado: 0% requerido: 100% bloqueante: true entidades: - name: countries schema: core estado: no_existe usado_por: [MGN-012] - name: currencies schema: core estado: no_existe usado_por: [RT-006, RT-010] - name: uom_categories schema: core estado: no_existe usado_por: [MGN-011] - name: uom schema: core estado: no_existe usado_por: [MGN-011, RT-010] - name: sequences schema: core estado: no_existe usado_por: [RT-002, RT-003, RT-004, RT-009, RT-010] servicios: - name: CountriesService estado: no_existe - name: CurrenciesService estado: no_existe - name: UoMService estado: no_existe - name: SequencesService estado: no_existe dependencias: [] MGN-010-financial: nombre: "Financiero" estado: 70% requerido: 90% bloqueante: true entidades: - name: tax_groups schema: financial estado: no_existe usado_por: [RT-010] - name: taxes schema: financial estado: existe usado_por: [RT-006, RT-010] - name: accounts schema: financial estado: existe usado_por: [] - name: journals schema: financial estado: existe usado_por: [] - name: payment_methods schema: financial estado: no_existe usado_por: [RT-002, RT-009] servicios: - name: TaxesService estado: parcial nota: "Migrar a TypeORM" - name: PaymentMethodsService estado: no_existe dependencias: [MGN-001-auth] MGN-011-inventory: nombre: "Inventario" estado: 60% requerido: 80% bloqueante: true entidades: - name: product_categories schema: inventory estado: existe usado_por: [RT-006] - name: products schema: inventory estado: existe usado_por: [RT-002, RT-003, RT-004, RT-006, RT-009, RT-010] - name: warehouses schema: inventory estado: existe usado_por: [RT-001, RT-003] - name: stock_quants schema: inventory estado: parcial usado_por: [RT-003, RT-008] servicios: - name: ProductsService estado: existe - name: WarehousesService estado: existe - name: StockService estado: parcial nota: "Falta reservar/liberar stock" dependencias: [MGN-001-auth, MGN-005-catalogs] MGN-012-partners: nombre: "Partners" estado: 50% requerido: 80% bloqueante: false entidades: - name: partners schema: core estado: parcial usado_por: [RT-002, RT-004, RT-005, RT-009, RT-010] servicios: - name: PartnersService estado: parcial metodos_faltantes: [getCustomers, getSuppliers] dependencias: [MGN-001-auth, MGN-005-catalogs] MGN-013-sales: nombre: "Ventas" estado: 50% requerido: 70% bloqueante: true entidades: - name: pricelists schema: sales estado: no_existe usado_por: [RT-006] - name: pricelist_items schema: sales estado: no_existe usado_por: [RT-006] servicios: - name: PricelistsService estado: no_existe dependencias: [MGN-001-auth, MGN-011-inventory] # ============================================================ # MODULOS RETAIL # ============================================================ retail_modules: RT-001-fundamentos: nombre: "Fundamentos Retail" prioridad: P0 story_points: 0 herencia: 100% sprint: 5 entidades: - name: branches schema: retail estado: planificado columnas: [id, tenant_id, code, name, address, phone, email, warehouse_id, is_active, is_main, config] foreign_keys: - column: tenant_id references: auth.tenants(id) - column: warehouse_id references: inventory.warehouses(id) indices: [tenant_id] rls: true - name: cash_registers schema: retail estado: planificado columnas: [id, tenant_id, branch_id, code, name, is_active, default_payment_method, config] foreign_keys: - column: tenant_id references: auth.tenants(id) - column: branch_id references: retail.branches(id) indices: [branch_id] rls: true - name: branch_users schema: retail estado: planificado columnas: [id, tenant_id, branch_id, user_id, role, is_primary] foreign_keys: - column: tenant_id references: auth.tenants(id) - column: branch_id references: retail.branches(id) - column: user_id references: auth.users(id) indices: [user_id] unique: [tenant_id, branch_id, user_id] rls: true servicios: - name: BranchesService tipo: nuevo metodos: [create, findAll, findById, update, delete, getByTenant] - name: CashRegistersService tipo: nuevo metodos: [create, findByBranch, activate, deactivate] - name: BranchUsersService tipo: nuevo metodos: [assign, remove, getByUser, getByBranch] dependencias: core: [MGN-001-auth, MGN-011-inventory] retail: [] RT-002-pos: nombre: "Punto de Venta" prioridad: P0 story_points: 55 herencia: 20% sprint: [8, 9, 10, 11] entidades: - name: pos_sessions schema: retail estado: planificado columnas: [id, tenant_id, branch_id, register_id, user_id, status, opening_balance, closing_balance, opened_at, closed_at, notes] foreign_keys: - column: tenant_id references: auth.tenants(id) - column: branch_id references: retail.branches(id) - column: register_id references: retail.cash_registers(id) - column: user_id references: auth.users(id) indices: [branch_id, user_id, status] rls: true - name: pos_orders schema: retail estado: planificado columnas: [id, tenant_id, session_id, order_number, customer_id, status, order_date, subtotal, discount_amount, tax_amount, total, notes, offline_id, synced_at, is_invoiced, invoice_id] foreign_keys: - column: tenant_id references: auth.tenants(id) - column: session_id references: retail.pos_sessions(id) - column: customer_id references: core.partners(id) indices: [session_id, customer_id, order_date, offline_id] unique: [tenant_id, order_number] rls: true - name: pos_order_lines schema: retail estado: planificado columnas: [id, tenant_id, order_id, product_id, product_name, quantity, unit_price, discount_percent, discount_amount, tax_amount, total, notes] foreign_keys: - column: tenant_id references: auth.tenants(id) - column: order_id references: retail.pos_orders(id) - column: product_id references: inventory.products(id) indices: [product_id] rls: true - name: pos_payments schema: retail estado: planificado columnas: [id, tenant_id, order_id, payment_method, amount, received_amount, change_amount, reference, card_last_four, authorization_code] foreign_keys: - column: tenant_id references: auth.tenants(id) - column: order_id references: retail.pos_orders(id) indices: [order_id] rls: true servicios: - name: POSSessionService tipo: nuevo metodos: [openSession, closeSession, getActiveSession, getSummary] dependencias: [CashRegistersService] - name: POSOrderService tipo: nuevo metodos: [createOrder, addLine, updateLine, removeLine, setCustomer, applyDiscount, confirmOrder, refundOrder, cancelOrder] dependencias: [PriceEngineService, RetailStockService, LoyaltyService] - name: POSPaymentService tipo: nuevo metodos: [addPayment, processPayments, calculateChange] - name: POSSyncService tipo: nuevo metodos: [syncOfflineOrders, getByOfflineId] dependencias: [POSOrderService] controllers: - name: POSController endpoints: - POST /pos/sessions/open - GET /pos/sessions/active - POST /pos/sessions/:id/close - POST /pos/orders - POST /pos/orders/:id/lines - POST /pos/orders/:id/confirm - POST /pos/orders/:id/refund - POST /pos/sync gateways: - name: POSGateway namespace: /pos events: [sync:orders, order:created, session:updated] frontend: pages: - path: /login componentes: [LoginForm, BranchSelector] - path: /select-register componentes: [RegisterList] - path: /open-session componentes: [OpenSessionForm] - path: /sales componentes: [ProductSearch, CategoryTabs, ProductGrid, OrderLines, OrderTotals, CustomerSelector] - path: /sales/checkout componentes: [PaymentMethodButton, CashPaymentInput, CardPaymentInput, PointsRedemption, PaymentsList] - path: /history componentes: [OrderHistoryList] - path: /offline componentes: [SyncQueue, SyncStatus] dependencias: core: [MGN-001-auth, MGN-010-financial, MGN-011-inventory, MGN-012-partners] retail: [RT-001-fundamentos, RT-006-precios, RT-003-inventario, RT-005-clientes] RT-003-inventario: nombre: "Inventario Multi-sucursal" prioridad: P0 story_points: 42 herencia: 60% sprint: 7 entidades: - name: stock_transfers schema: retail estado: planificado columnas: [id, tenant_id, transfer_number, source_branch_id, dest_branch_id, status, requested_by, confirmed_by, received_by, requested_date, confirmed_date, received_date, notes] foreign_keys: - column: source_branch_id references: retail.branches(id) - column: dest_branch_id references: retail.branches(id) indices: [source_branch_id, dest_branch_id, status] unique: [tenant_id, transfer_number] rls: true - name: stock_transfer_lines schema: retail estado: planificado foreign_keys: - column: transfer_id references: retail.stock_transfers(id) - column: product_id references: inventory.products(id) rls: true - name: stock_adjustments schema: retail estado: planificado foreign_keys: - column: branch_id references: retail.branches(id) indices: [branch_id] unique: [tenant_id, adjustment_number] rls: true - name: stock_adjustment_lines schema: retail estado: planificado foreign_keys: - column: adjustment_id references: retail.stock_adjustments(id) - column: product_id references: inventory.products(id) rls: true views: - name: branch_stock schema: retail tipo: view descripcion: "Vista de stock por sucursal" tablas_fuente: [inventory.stock_quants, retail.branches, inventory.products] servicios: - name: RetailStockService tipo: extendido extiende: StockService metodos: [getStockByBranch, getMultiBranchStock, decrementStock, incrementStock] - name: TransfersService tipo: nuevo metodos: [createTransfer, confirmTransfer, sendTransfer, receiveTransfer, cancelTransfer] - name: AdjustmentsService tipo: nuevo metodos: [createAdjustment, confirmAdjustment, cancelAdjustment] dependencias: core: [MGN-011-inventory] retail: [RT-001-fundamentos] RT-004-compras: nombre: "Compras y Reabastecimiento" prioridad: P1 story_points: 38 herencia: 80% sprint: 15 entidades: - name: purchase_suggestions schema: retail estado: planificado rls: true - name: supplier_orders schema: retail estado: planificado foreign_keys: - column: supplier_id references: core.partners(id) - column: branch_id references: retail.branches(id) rls: true - name: supplier_order_lines schema: retail estado: planificado foreign_keys: - column: order_id references: retail.supplier_orders(id) - column: product_id references: inventory.products(id) rls: true - name: goods_receipts schema: retail estado: planificado foreign_keys: - column: supplier_order_id references: retail.supplier_orders(id) - column: branch_id references: retail.branches(id) rls: true - name: goods_receipt_lines schema: retail estado: planificado rls: true servicios: - name: RetailPurchaseService tipo: extendido extiende: PurchaseService metodos: [suggestRestock, createFromSuggestion] - name: PurchaseSuggestionsService tipo: nuevo metodos: [generate, getByBranch, markOrdered, markIgnored] - name: GoodsReceiptService tipo: nuevo metodos: [createReceipt, confirmReceipt, cancelReceipt] dependencias: core: [MGN-011-inventory, MGN-012-partners] retail: [RT-001-fundamentos, RT-003-inventario] RT-005-clientes: nombre: "Clientes y Lealtad" prioridad: P1 story_points: 34 herencia: 40% sprint: 14 entidades: - name: loyalty_programs schema: retail estado: planificado rls: true - name: membership_levels schema: retail estado: planificado foreign_keys: - column: program_id references: retail.loyalty_programs(id) rls: true - name: loyalty_transactions schema: retail estado: planificado foreign_keys: - column: customer_id references: core.partners(id) - column: program_id references: retail.loyalty_programs(id) - column: order_id references: retail.pos_orders(id) indices: [customer_id, created_at] rls: true - name: customer_memberships schema: retail estado: planificado foreign_keys: - column: customer_id references: core.partners(id) - column: program_id references: retail.loyalty_programs(id) - column: level_id references: retail.membership_levels(id) unique: [tenant_id, membership_number] rls: true servicios: - name: RetailCustomersService tipo: extendido extiende: PartnersService metodos: [createCustomer, getWithMembership, searchByPhone] - name: LoyaltyService tipo: nuevo metodos: [enrollCustomer, earnPoints, redeemPoints, getBalance, getHistory, checkLevelUpgrade] dependencias: core: [MGN-012-partners] retail: [RT-001-fundamentos, RT-002-pos] RT-006-precios: nombre: "Precios y Promociones" prioridad: P0 story_points: 36 herencia: 30% sprint: 6 entidades: - name: promotions schema: retail estado: planificado indices: [is_active, start_date, end_date, branch_ids] rls: true - name: promotion_products schema: retail estado: planificado foreign_keys: - column: promotion_id references: retail.promotions(id) - column: product_id references: inventory.products(id) - column: category_id references: inventory.product_categories(id) rls: true - name: coupons schema: retail estado: planificado foreign_keys: - column: customer_id references: core.partners(id) indices: [code, valid_from, valid_until] unique: [tenant_id, code] rls: true - name: coupon_redemptions schema: retail estado: planificado foreign_keys: - column: coupon_id references: retail.coupons(id) - column: order_id references: retail.pos_orders(id) rls: true servicios: - name: PriceEngineService tipo: nuevo metodos: [calculatePrice, applyPricelist, evaluatePromotions, evaluateVolumeDiscount] dependencias: [PricelistsService, PromotionsService, CouponsService] - name: PromotionsService tipo: nuevo metodos: [create, update, activate, deactivate, getActiveForProduct, incrementUse] - name: CouponsService tipo: nuevo metodos: [generate, validate, redeem, getByCode] dependencias: core: [MGN-011-inventory, MGN-013-sales] retail: [RT-001-fundamentos] RT-007-caja: nombre: "Caja y Cortes" prioridad: P0 story_points: 28 herencia: 10% sprint: 10 entidades: - name: cash_movements schema: retail estado: planificado foreign_keys: - column: session_id references: retail.pos_sessions(id) - column: authorized_by references: auth.users(id) indices: [session_id] rls: true - name: cash_closings schema: retail estado: planificado columnas_generadas: - name: cash_difference formula: "declared_cash - expected_cash" - name: card_difference formula: "declared_card - expected_card" - name: transfer_difference formula: "declared_transfer - expected_transfer" foreign_keys: - column: session_id references: retail.pos_sessions(id) unique: [session_id] indices: [closing_date] rls: true - name: cash_counts schema: retail estado: planificado columnas_generadas: - name: difference formula: "counted_amount - expected_amount" foreign_keys: - column: session_id references: retail.pos_sessions(id) indices: [session_id] rls: true servicios: - name: CashSessionService tipo: nuevo metodos: [getSummary, calculateExpected] dependencias: [POSSessionService] - name: CashMovementService tipo: nuevo metodos: [createIn, createOut, getBySession, validateAuthorization] - name: CashClosingService tipo: nuevo metodos: [prepareClosing, createClosing, approveClosing, rejectClosing] dependencias: core: [MGN-001-auth] retail: [RT-001-fundamentos, RT-002-pos] RT-008-reportes: nombre: "Reportes y Dashboard" prioridad: P1 story_points: 30 herencia: 70% sprint: 16 materialized_views: - name: mv_daily_sales schema: retail refresh: "hourly" indices: [sale_date, tenant_id, branch_id, cashier_id] - name: mv_product_sales schema: retail refresh: "hourly" indices: [product_id, tenant_id, branch_id, sale_month] - name: mv_branch_stock_summary schema: retail refresh: "hourly" indices: [tenant_id, branch_id] servicios: - name: DashboardService tipo: nuevo metodos: [getDashboard, getKPIs, getCharts, getAlerts] - name: SalesReportService tipo: extendido extiende: ReportsService metodos: [generate, getByPeriod, getSalesByHour, getSalesByCashier] - name: ProductReportService tipo: nuevo metodos: [getTopSelling, getSlowMoving, getABCAnalysis] - name: CashReportService tipo: nuevo metodos: [getClosingsReport, getDifferencesReport] - name: ExportService tipo: nuevo metodos: [toExcel, toPDF] dependencias: core: [] retail: [RT-002-pos, RT-003-inventario, RT-005-clientes, RT-007-caja] RT-009-ecommerce: nombre: "E-commerce" prioridad: P2 story_points: 55 herencia: 20% sprint: [17, 18, 19, 20] entidades: - name: carts schema: retail estado: planificado foreign_keys: - column: customer_id references: core.partners(id) indices: [customer_id, session_id, expires_at] rls: true - name: cart_items schema: retail estado: planificado foreign_keys: - column: cart_id references: retail.carts(id) - column: product_id references: inventory.products(id) rls: true - name: ecommerce_orders schema: retail estado: planificado foreign_keys: - column: customer_id references: core.partners(id) - column: pickup_branch_id references: retail.branches(id) indices: [customer_id, status, order_date] unique: [tenant_id, order_number] rls: true - name: ecommerce_order_lines schema: retail estado: planificado foreign_keys: - column: order_id references: retail.ecommerce_orders(id) - column: product_id references: inventory.products(id) rls: true - name: shipping_rates schema: retail estado: planificado rls: true servicios: - name: CatalogService tipo: nuevo metodos: [search, getProduct, getByCategory, getRelated] - name: CartService tipo: nuevo metodos: [getOrCreateCart, addItem, updateItem, removeItem, clear, mergeGuestCart] - name: CheckoutService tipo: nuevo metodos: [validate, calculateTotals, complete] dependencias: [CartService, PriceEngineService, RetailStockService] - name: PaymentGatewayService tipo: nuevo metodos: [createPayment, capturePayment, refund, handleWebhook] providers: [StripeGateway, ConektaGateway, MercadoPagoGateway] - name: ShippingService tipo: nuevo metodos: [calculateRates, createShipment, getTracking] providers: [FedexProvider, DHLProvider] - name: EcommerceOrderService tipo: nuevo metodos: [create, updateStatus, getByCustomer, markAsShipped] controllers: - name: StorefrontController endpoints: - GET /store/products - GET /store/products/:id - GET /store/products/search - GET /store/categories - GET /store/cart - POST /store/cart/items - PUT /store/cart/items/:id - DELETE /store/cart/items/:id - POST /store/checkout/validate - GET /store/checkout/shipping-rates - POST /store/checkout/complete - POST /store/payments/create - POST /store/payments/webhook - GET /store/orders - GET /store/orders/:id - name: EcommerceAdminController endpoints: - GET /ecommerce/orders - PUT /ecommerce/orders/:id/status - POST /ecommerce/orders/:id/ship - GET /ecommerce/shipping-rates - POST /ecommerce/shipping-rates dependencias: core: [MGN-011-inventory, MGN-012-partners] retail: [RT-001-fundamentos, RT-003-inventario, RT-005-clientes, RT-006-precios] RT-010-facturacion: nombre: "Facturacion CFDI 4.0" prioridad: P0 story_points: 35 herencia: 60% sprint: [12, 13] entidades: - name: cfdi_config schema: retail estado: planificado unique: [tenant_id] rls: true - name: cfdis schema: retail estado: planificado foreign_keys: - column: source_id references: dynamic nota: "pos_orders o ecommerce_orders segun source_type" indices: [source_type, source_id, uuid, fecha_emision, receptor_rfc, status] unique: [tenant_id, uuid] rls: true servicios: - name: CFDIService tipo: nuevo metodos: [generateFromPOS, generateFromEcommerce, generatePublicInvoice, cancel, getXML, getPDF] dependencias: [CFDIBuilderService, PACService, XMLService, PDFService] - name: CFDIBuilderService tipo: nuevo metodos: [fromPOSOrder, fromEcommerceOrder, buildConceptos, buildImpuestos] - name: PACService tipo: nuevo metodos: [timbrar, consultar, cancelar] providers: [FinkokPAC, FacturamaPAC] - name: XMLService tipo: nuevo metodos: [buildXML, parseXML, sign, validate] - name: PDFService tipo: nuevo metodos: [generate, getTemplate] - name: AutofacturaService tipo: nuevo metodos: [validateTicket, generateFromTicket] dependencias: [CFDIService] controllers: - name: CFDIController endpoints: - POST /cfdi/pos/:orderId - POST /cfdi/ecommerce/:orderId - POST /cfdi/public/:orderId - GET /cfdi/:id - GET /cfdi/:id/xml - GET /cfdi/:id/pdf - POST /cfdi/:id/cancel - POST /cfdi/credit-note - GET /cfdi/report/monthly - name: AutofacturaController endpoints: - GET /autofactura/validate/:ticketNumber - POST /autofactura/generate - GET /autofactura/download/:uuid dependencias: core: [MGN-010-financial, MGN-012-partners] retail: [RT-002-pos, RT-009-ecommerce] # ============================================================ # VALIDACION DE DEPENDENCIAS # ============================================================ validation: resultado: "APROBADO_CON_GAPS" gaps_bloqueantes: 4 gaps_no_bloqueantes: 0 gaps: - id: GAP-DEP-001 tipo: bloqueante origen: MGN-005-catalogs descripcion: "Modulo de catalogos no implementado" impacto: [RT-001, RT-006, RT-010] accion: "Implementar en Sprints 1-2" - id: GAP-DEP-002 tipo: bloqueante origen: MGN-001-auth descripcion: "Sistema de permisos incompleto" impacto: [RT-001, RT-002] accion: "Completar en Sprint 1" - id: GAP-DEP-003 tipo: bloqueante origen: MGN-013-sales descripcion: "Pricelists no implementado" impacto: [RT-006] accion: "Implementar en Sprint 4" - id: GAP-DEP-004 tipo: bloqueante origen: MGN-010-financial descripcion: "PaymentMethods no implementado" impacto: [RT-002, RT-009] accion: "Implementar en Sprint 3" dependencias_circulares: [] orden_implementacion: - paso: 1 modulos: [MGN-001-auth, MGN-005-catalogs] sprint: [1, 2] - paso: 2 modulos: [MGN-010-financial, MGN-011-inventory] sprint: [3, 4] - paso: 3 modulos: [MGN-012-partners, MGN-013-sales] sprint: [4] - paso: 4 modulos: [RT-001-fundamentos] sprint: [5] - paso: 5 modulos: [RT-006-precios, RT-003-inventario] sprint: [6, 7] - paso: 6 modulos: [RT-002-pos] sprint: [8, 9] - paso: 7 modulos: [RT-007-caja] sprint: [10] - paso: 8 modulos: [RT-010-facturacion] sprint: [12, 13] - paso: 9 modulos: [RT-005-clientes] sprint: [14] - paso: 10 modulos: [RT-004-compras, RT-008-reportes] sprint: [15, 16] - paso: 11 modulos: [RT-009-ecommerce] sprint: [17, 18, 19, 20]