# TRACEABILITY-MGN-005.yaml
# Matriz de Trazabilidad - MGN-005: Inventario Básico
# Fecha: 2025-11-24
# Versión: 1.0

module:
  id: MGN-005
  name: "Inventario Básico"
  description: "Productos, almacenes, movimientos de stock, pickings, trazabilidad y valoración"
  priority: P0
  story_points: 66
  status: Diseñado

metadata:
  total_rf: 7
  total_et_backend: 7
  total_et_frontend: 7
  total_tables: 10
  total_tests: 140
  coverage: 100%

requirements:
  - rf_id: RF-MGN-005-001
    rf_title: "Gestión de Productos"
    rf_file: "requerimientos-funcionales/mgn-005/RF-MGN-005-001-gestión-de-productos.md"
    priority: P0
    story_points: 8

    et_backend:
      file: "especificaciones-tecnicas/backend/mgn-005/ET-BACKEND-MGN-005-001-gestión-de-productos.md"
      endpoints:
        - method: POST
          path: /api/v1/inventory/products
          description: "Crear producto"
        - method: GET
          path: /api/v1/inventory/products
          description: "Listar productos"
        - method: GET
          path: /api/v1/inventory/products/:id
          description: "Obtener producto por ID"
        - method: PUT
          path: /api/v1/inventory/products/:id
          description: "Actualizar producto"
        - method: DELETE
          path: /api/v1/inventory/products/:id
          description: "Desactivar producto"
      services:
        - name: "ProductService"
          file: "src/modules/inventory/services/product.service.ts"
          methods: [create, findAll, findOne, update, remove]
      controllers:
        - name: "ProductController"
          file: "src/modules/inventory/controllers/product.controller.ts"
      dtos:
        - name: "CreateProductDto"
          file: "src/modules/inventory/dto/create-product.dto.ts"
        - name: "UpdateProductDto"
          file: "src/modules/inventory/dto/update-product.dto.ts"

    et_frontend:
      file: "especificaciones-tecnicas/frontend/mgn-005/ET-FRONTEND-MGN-005-001-gestión-de-productos.md"
      routes:
        - path: "/inventory/products"
          component: "ProductsPage"
        - path: "/inventory/products/create"
          component: "CreateProductPage"
        - path: "/inventory/products/:id/edit"
          component: "EditProductPage"
        - path: "/inventory/products/:id"
          component: "ViewProductPage"
      components:
        - name: "ProductsTable"
          file: "src/widgets/products-table/ui/ProductsTable.tsx"
          type: widget
        - name: "CreateProductForm"
          file: "src/features/create-product/ui/CreateProductForm.tsx"
          type: feature
        - name: "ProductCard"
          file: "src/entities/product/ui/ProductCard.tsx"
          type: entity
      api_client:
        - name: "productApi"
          file: "src/entities/product/api/product.api.ts"
          methods: [getAll, getById, create, update, delete]
      state_management:
        - name: "useProductStore"
          file: "src/entities/product/model/product.store.ts"
          type: zustand

    database_tables:
      - schema: inventory
        table: products
        file: "database-design/schemas/inventory-schema-ddl.sql"
        operations: [SELECT, INSERT, UPDATE, DELETE (soft)]
        indices: [idx_products_company_id, idx_products_category_id, idx_products_type]
        rls_policy: company_isolation_products

    tests:
      backend:
        unit_tests:
          - file: "src/modules/inventory/services/product.service.spec.ts"
            test_cases:
              - "should create product with valid data"
              - "should validate product type (storable, consumable, service)"
              - "should throw error when SKU already exists"
              - "should update product successfully"
              - "should soft delete product"
        integration_tests:
          - file: "test/inventory/product.controller.e2e-spec.ts"
            test_cases:
              - "POST /api/v1/inventory/products should create product"
              - "GET /api/v1/inventory/products should return all products"
              - "GET /api/v1/inventory/products/:id should return product"
              - "PUT /api/v1/inventory/products/:id should update product"
              - "DELETE /api/v1/inventory/products/:id should soft delete product"
              - "should enforce company isolation"
              - "should require authentication"
      frontend:
        component_tests:
          - file: "src/widgets/products-table/ui/ProductsTable.test.tsx"
            test_cases:
              - "should render table with products"
              - "should handle pagination"
              - "should filter by category"
          - file: "src/features/create-product/ui/CreateProductForm.test.tsx"
            test_cases:
              - "should validate required fields"
              - "should validate SKU format"
              - "should submit valid form"
        e2e_tests:
          - file: "e2e/inventory/products.spec.ts"
            test_cases:
              - "should create product successfully"
              - "should edit product successfully"
              - "should delete product with confirmation"

    acceptance_criteria:
      - id: AC-001
        description: "Usuario puede crear productos con SKU, nombre, tipo (storable, consumable, service)"
        status: Pending
        test_reference: "test/inventory/product.controller.e2e-spec.ts:28"
      - id: AC-002
        description: "SKU es único por empresa"
        status: Pending
        test_reference: "src/modules/inventory/services/product.service.spec.ts:65"
      - id: AC-003
        description: "Productos tienen categoría, UoM y cuentas contables"
        status: Pending
        test_reference: "test/inventory/product.controller.e2e-spec.ts:95"

    business_rules:
      - id: RN-001
        description: "SKU único por empresa"
        implementation: "database-design/schemas/inventory-schema-ddl.sql:CONSTRAINT uq_products_sku_company"
        test_reference: "src/modules/inventory/services/product.service.spec.ts:48"
      - id: RN-002
        description: "Productos tienen tipos: storable, consumable, service"
        implementation: "database-design/schemas/inventory-schema-ddl.sql:products.type"
        test_reference: "src/modules/inventory/services/product.service.spec.ts:78"
      - id: RN-003
        description: "Solo productos storable tienen stock"
        implementation: "src/modules/inventory/services/product.service.ts:validateType()"
        test_reference: "src/modules/inventory/services/product.service.spec.ts:108"

    dependencies:
      rf_dependencies: [RF-MGN-003-004, RF-MGN-003-005]
      module_dependencies: [MGN-003]
      external_dependencies: []

  - rf_id: RF-MGN-005-002
    rf_title: "Gestión de Almacenes y Ubicaciones"
    rf_file: "requerimientos-funcionales/mgn-005/RF-MGN-005-002-gestión-de-almacenes-y-ubicaciones.md"
    priority: P0
    story_points: 8

    et_backend:
      file: "especificaciones-tecnicas/backend/mgn-005/ET-BACKEND-MGN-005-002-gestión-de-almacenes-y-ubicaciones.md"
      endpoints:
        - method: POST
          path: /api/v1/inventory/warehouses
          description: "Crear almacén"
        - method: GET
          path: /api/v1/inventory/warehouses
          description: "Listar almacenes"
        - method: GET
          path: /api/v1/inventory/warehouses/:id
          description: "Obtener almacén por ID"
        - method: PUT
          path: /api/v1/inventory/warehouses/:id
          description: "Actualizar almacén"
        - method: POST
          path: /api/v1/inventory/warehouses/:id/locations
          description: "Crear ubicación en almacén"
      services:
        - name: "WarehouseService"
          file: "src/modules/inventory/services/warehouse.service.ts"
          methods: [create, findAll, findOne, update, createLocation]
      controllers:
        - name: "WarehouseController"
          file: "src/modules/inventory/controllers/warehouse.controller.ts"
      dtos:
        - name: "CreateWarehouseDto"
          file: "src/modules/inventory/dto/create-warehouse.dto.ts"
        - name: "CreateLocationDto"
          file: "src/modules/inventory/dto/create-location.dto.ts"

    et_frontend:
      file: "especificaciones-tecnicas/frontend/mgn-005/ET-FRONTEND-MGN-005-002-gestión-de-almacenes-y-ubicaciones.md"
      routes:
        - path: "/inventory/warehouses"
          component: "WarehousesPage"
        - path: "/inventory/warehouses/:id"
          component: "WarehouseDetailsPage"
      components:
        - name: "WarehousesTable"
          file: "src/widgets/warehouses-table/ui/WarehousesTable.tsx"
          type: widget
        - name: "CreateWarehouseForm"
          file: "src/features/create-warehouse/ui/CreateWarehouseForm.tsx"
          type: feature
        - name: "LocationTree"
          file: "src/widgets/location-tree/ui/LocationTree.tsx"
          type: widget
      api_client:
        - name: "warehouseApi"
          file: "src/entities/warehouse/api/warehouse.api.ts"
          methods: [getAll, getById, create, update, createLocation]
      state_management:
        - name: "useWarehouseStore"
          file: "src/entities/warehouse/model/warehouse.store.ts"
          type: zustand

    database_tables:
      - schema: inventory
        table: warehouses
        file: "database-design/schemas/inventory-schema-ddl.sql"
        operations: [SELECT, INSERT, UPDATE]
        indices: [idx_warehouses_company_id]
        rls_policy: company_isolation_warehouses
      - schema: inventory
        table: locations
        file: "database-design/schemas/inventory-schema-ddl.sql"
        operations: [SELECT, INSERT, UPDATE]
        indices: [idx_locations_warehouse_id, idx_locations_parent_id]
        rls_policy: company_isolation_locations

    tests:
      backend:
        unit_tests:
          - file: "src/modules/inventory/services/warehouse.service.spec.ts"
            test_cases:
              - "should create warehouse"
              - "should create location in warehouse"
              - "should create hierarchical locations"
              - "should validate location belongs to warehouse"
              - "should update warehouse"
        integration_tests:
          - file: "test/inventory/warehouse.controller.e2e-spec.ts"
            test_cases:
              - "POST /api/v1/inventory/warehouses should create warehouse"
              - "GET /api/v1/inventory/warehouses should return all warehouses"
              - "POST /api/v1/inventory/warehouses/:id/locations should create location"
              - "should enforce company isolation"
              - "should require authentication"
      frontend:
        component_tests:
          - file: "src/widgets/warehouses-table/ui/WarehousesTable.test.tsx"
            test_cases:
              - "should render table with warehouses"
          - file: "src/widgets/location-tree/ui/LocationTree.test.tsx"
            test_cases:
              - "should render location tree"
              - "should expand/collapse nodes"
        e2e_tests:
          - file: "e2e/inventory/warehouses.spec.ts"
            test_cases:
              - "should create warehouse successfully"
              - "should create location in warehouse"
              - "should show location hierarchy"

    acceptance_criteria:
      - id: AC-001
        description: "Usuario puede crear almacenes con ubicaciones jerárquicas"
        status: Pending
        test_reference: "test/inventory/warehouse.controller.e2e-spec.ts:28"
      - id: AC-002
        description: "Ubicaciones soportan jerarquía (zona → pasillo → anaquel)"
        status: Pending
        test_reference: "src/modules/inventory/services/warehouse.service.spec.ts:65"
      - id: AC-003
        description: "Stock se almacena por ubicación"
        status: Pending
        test_reference: "test/inventory/warehouse.controller.e2e-spec.ts:95"

    business_rules:
      - id: RN-001
        description: "Almacenes pertenecen a una empresa"
        implementation: "database-design/schemas/inventory-schema-ddl.sql:warehouses.company_id"
        test_reference: "src/modules/inventory/services/warehouse.service.spec.ts:48"
      - id: RN-002
        description: "Ubicaciones soportan jerarquía con parent_id"
        implementation: "database-design/schemas/inventory-schema-ddl.sql:locations.parent_id"
        test_reference: "src/modules/inventory/services/warehouse.service.spec.ts:78"
      - id: RN-003
        description: "Stock se registra por ubicación específica"
        implementation: "database-design/schemas/inventory-schema-ddl.sql:stock_quants.location_id"
        test_reference: "src/modules/inventory/services/warehouse.service.spec.ts:108"

    dependencies:
      rf_dependencies: [RF-MGN-002-001]
      module_dependencies: [MGN-002]
      external_dependencies: []

  - rf_id: RF-MGN-005-003
    rf_title: "Movimientos de Stock"
    rf_file: "requerimientos-funcionales/mgn-005/RF-MGN-005-003-movimientos-de-stock.md"
    priority: P0
    story_points: 13

    et_backend:
      file: "especificaciones-tecnicas/backend/mgn-005/ET-BACKEND-MGN-005-003-movimientos-de-stock.md"
      endpoints:
        - method: POST
          path: /api/v1/inventory/stock-moves
          description: "Crear movimiento de stock"
        - method: GET
          path: /api/v1/inventory/stock-moves
          description: "Listar movimientos"
        - method: GET
          path: /api/v1/inventory/stock-moves/:id
          description: "Obtener movimiento por ID"
        - method: POST
          path: /api/v1/inventory/stock-moves/:id/validate
          description: "Validar movimiento (actualiza stock)"
        - method: POST
          path: /api/v1/inventory/stock-moves/:id/cancel
          description: "Cancelar movimiento"
      services:
        - name: "StockMoveService"
          file: "src/modules/inventory/services/stock-move.service.ts"
          methods: [create, findAll, findOne, validate, cancel, updateQuants]
      controllers:
        - name: "StockMoveController"
          file: "src/modules/inventory/controllers/stock-move.controller.ts"
      dtos:
        - name: "CreateStockMoveDto"
          file: "src/modules/inventory/dto/create-stock-move.dto.ts"

    et_frontend:
      file: "especificaciones-tecnicas/frontend/mgn-005/ET-FRONTEND-MGN-005-003-movimientos-de-stock.md"
      routes:
        - path: "/inventory/stock-moves"
          component: "StockMovesPage"
        - path: "/inventory/stock-moves/:id"
          component: "ViewStockMovePage"
      components:
        - name: "StockMovesTable"
          file: "src/widgets/stock-moves-table/ui/StockMovesTable.tsx"
          type: widget
        - name: "CreateStockMoveForm"
          file: "src/features/create-stock-move/ui/CreateStockMoveForm.tsx"
          type: feature
        - name: "StockMoveCard"
          file: "src/entities/stock-move/ui/StockMoveCard.tsx"
          type: entity
      api_client:
        - name: "stockMoveApi"
          file: "src/entities/stock-move/api/stock-move.api.ts"
          methods: [getAll, getById, create, validate, cancel]
      state_management:
        - name: "useStockMoveStore"
          file: "src/entities/stock-move/model/stock-move.store.ts"
          type: zustand

    database_tables:
      - schema: inventory
        table: stock_moves
        file: "database-design/schemas/inventory-schema-ddl.sql"
        operations: [SELECT, INSERT, UPDATE]
        indices: [idx_stock_moves_product_id, idx_stock_moves_location_from, idx_stock_moves_location_to, idx_stock_moves_state]
        rls_policy: company_isolation_stock_moves
      - schema: inventory
        table: stock_quants
        file: "database-design/schemas/inventory-schema-ddl.sql"
        operations: [SELECT, INSERT, UPDATE]
        indices: [idx_stock_quants_product_location]
        rls_policy: company_isolation_stock_quants

    tests:
      backend:
        unit_tests:
          - file: "src/modules/inventory/services/stock-move.service.spec.ts"
            test_cases:
              - "should create stock move"
              - "should validate stock move (draft → done)"
              - "should update stock quants on validation"
              - "should cancel stock move"
              - "should reverse quants on cancellation"
        integration_tests:
          - file: "test/inventory/stock-move.controller.e2e-spec.ts"
            test_cases:
              - "POST /api/v1/inventory/stock-moves should create move"
              - "GET /api/v1/inventory/stock-moves should return all moves"
              - "POST /api/v1/inventory/stock-moves/:id/validate should validate move"
              - "POST /api/v1/inventory/stock-moves/:id/cancel should cancel move"
              - "should enforce company isolation"
              - "should require authentication"
      frontend:
        component_tests:
          - file: "src/widgets/stock-moves-table/ui/StockMovesTable.test.tsx"
            test_cases:
              - "should render table with moves"
              - "should filter by state"
          - file: "src/features/create-stock-move/ui/CreateStockMoveForm.test.tsx"
            test_cases:
              - "should validate required fields"
              - "should submit valid form"
        e2e_tests:
          - file: "e2e/inventory/stock-moves.spec.ts"
            test_cases:
              - "should create stock move successfully"
              - "should validate move successfully"
              - "should show updated stock after validation"

    acceptance_criteria:
      - id: AC-001
        description: "Usuario puede crear movimientos de stock entre ubicaciones"
        status: Pending
        test_reference: "test/inventory/stock-move.controller.e2e-spec.ts:28"
      - id: AC-002
        description: "Validar movimiento actualiza stock en ubicaciones origen y destino"
        status: Pending
        test_reference: "src/modules/inventory/services/stock-move.service.spec.ts:85"
      - id: AC-003
        description: "Movimientos tienen estados: draft, done, cancelled"
        status: Pending
        test_reference: "test/inventory/stock-move.controller.e2e-spec.ts:105"

    business_rules:
      - id: RN-001
        description: "Movimientos tienen estados: draft, done, cancelled"
        implementation: "database-design/schemas/inventory-schema-ddl.sql:stock_moves.state"
        test_reference: "src/modules/inventory/services/stock-move.service.spec.ts:58"
      - id: RN-002
        description: "Al validar movimiento se actualizan stock_quants"
        implementation: "src/modules/inventory/services/stock-move.service.ts:updateQuants()"
        test_reference: "src/modules/inventory/services/stock-move.service.spec.ts:92"
      - id: RN-003
        description: "Cancelar movimiento revierte cambios en quants"
        implementation: "src/modules/inventory/services/stock-move.service.ts:cancel()"
        test_reference: "src/modules/inventory/services/stock-move.service.spec.ts:118"

    dependencies:
      rf_dependencies: [RF-MGN-005-001, RF-MGN-005-002]
      module_dependencies: []
      external_dependencies: []

  - rf_id: RF-MGN-005-004
    rf_title: "Pickings (Albaranes de Entrada/Salida)"
    rf_file: "requerimientos-funcionales/mgn-005/RF-MGN-005-004-pickings-albaranes-de-entrada-salida.md"
    priority: P0
    story_points: 8

    et_backend:
      file: "especificaciones-tecnicas/backend/mgn-005/ET-BACKEND-MGN-005-004-pickings-albaranes-de-entrada-salida.md"
      endpoints:
        - method: POST
          path: /api/v1/inventory/pickings
          description: "Crear picking"
        - method: GET
          path: /api/v1/inventory/pickings
          description: "Listar pickings"
        - method: GET
          path: /api/v1/inventory/pickings/:id
          description: "Obtener picking por ID"
        - method: POST
          path: /api/v1/inventory/pickings/:id/validate
          description: "Validar picking (genera movimientos)"
        - method: POST
          path: /api/v1/inventory/pickings/:id/cancel
          description: "Cancelar picking"
      services:
        - name: "PickingService"
          file: "src/modules/inventory/services/picking.service.ts"
          methods: [create, findAll, findOne, validate, cancel, generateStockMoves]
      controllers:
        - name: "PickingController"
          file: "src/modules/inventory/controllers/picking.controller.ts"
      dtos:
        - name: "CreatePickingDto"
          file: "src/modules/inventory/dto/create-picking.dto.ts"

    et_frontend:
      file: "especificaciones-tecnicas/frontend/mgn-005/ET-FRONTEND-MGN-005-004-pickings-albaranes-de-entrada-salida.md"
      routes:
        - path: "/inventory/pickings"
          component: "PickingsPage"
        - path: "/inventory/pickings/create"
          component: "CreatePickingPage"
        - path: "/inventory/pickings/:id"
          component: "ViewPickingPage"
      components:
        - name: "PickingsTable"
          file: "src/widgets/pickings-table/ui/PickingsTable.tsx"
          type: widget
        - name: "CreatePickingForm"
          file: "src/features/create-picking/ui/CreatePickingForm.tsx"
          type: feature
        - name: "PickingCard"
          file: "src/entities/picking/ui/PickingCard.tsx"
          type: entity
      api_client:
        - name: "pickingApi"
          file: "src/entities/picking/api/picking.api.ts"
          methods: [getAll, getById, create, validate, cancel]
      state_management:
        - name: "usePickingStore"
          file: "src/entities/picking/model/picking.store.ts"
          type: zustand

    database_tables:
      - schema: inventory
        table: pickings
        file: "database-design/schemas/inventory-schema-ddl.sql"
        operations: [SELECT, INSERT, UPDATE]
        indices: [idx_pickings_picking_type_id, idx_pickings_state, idx_pickings_company_id]
        rls_policy: company_isolation_pickings

    tests:
      backend:
        unit_tests:
          - file: "src/modules/inventory/services/picking.service.spec.ts"
            test_cases:
              - "should create picking"
              - "should validate picking (generates stock moves)"
              - "should handle receipt (incoming) picking"
              - "should handle delivery (outgoing) picking"
              - "should cancel picking"
        integration_tests:
          - file: "test/inventory/picking.controller.e2e-spec.ts"
            test_cases:
              - "POST /api/v1/inventory/pickings should create picking"
              - "GET /api/v1/inventory/pickings should return all pickings"
              - "POST /api/v1/inventory/pickings/:id/validate should validate picking"
              - "POST /api/v1/inventory/pickings/:id/cancel should cancel picking"
              - "should enforce company isolation"
              - "should require authentication"
      frontend:
        component_tests:
          - file: "src/widgets/pickings-table/ui/PickingsTable.test.tsx"
            test_cases:
              - "should render table with pickings"
              - "should filter by type"
          - file: "src/features/create-picking/ui/CreatePickingForm.test.tsx"
            test_cases:
              - "should validate required fields"
              - "should submit valid form"
        e2e_tests:
          - file: "e2e/inventory/pickings.spec.ts"
            test_cases:
              - "should create picking successfully"
              - "should validate picking successfully"
              - "should show generated stock moves"

    acceptance_criteria:
      - id: AC-001
        description: "Usuario puede crear pickings de entrada (recepciones)"
        status: Pending
        test_reference: "test/inventory/picking.controller.e2e-spec.ts:28"
      - id: AC-002
        description: "Usuario puede crear pickings de salida (entregas)"
        status: Pending
        test_reference: "test/inventory/picking.controller.e2e-spec.ts:58"
      - id: AC-003
        description: "Validar picking genera movimientos de stock automáticamente"
        status: Pending
        test_reference: "src/modules/inventory/services/picking.service.spec.ts:85"

    business_rules:
      - id: RN-001
        description: "Pickings tienen tipos: incoming (recepción), outgoing (entrega), internal (transferencia)"
        implementation: "database-design/schemas/inventory-schema-ddl.sql:picking_types"
        test_reference: "src/modules/inventory/services/picking.service.spec.ts:58"
      - id: RN-002
        description: "Validar picking genera stock_moves automáticamente"
        implementation: "src/modules/inventory/services/picking.service.ts:generateStockMoves()"
        test_reference: "src/modules/inventory/services/picking.service.spec.ts:92"
      - id: RN-003
        description: "Pickings tienen estados: draft, confirmed, done, cancelled"
        implementation: "database-design/schemas/inventory-schema-ddl.sql:pickings.state"
        test_reference: "src/modules/inventory/services/picking.service.spec.ts:118"

    dependencies:
      rf_dependencies: [RF-MGN-005-002, RF-MGN-005-003]
      module_dependencies: []
      external_dependencies: []

  - rf_id: RF-MGN-005-005
    rf_title: "Trazabilidad (Lotes y Números de Serie)"
    rf_file: "requerimientos-funcionales/mgn-005/RF-MGN-005-005-trazabilidad-lotes-y-números-de-serie.md"
    priority: P1
    story_points: 8

    et_backend:
      file: "especificaciones-tecnicas/backend/mgn-005/ET-BACKEND-MGN-005-005-trazabilidad-lotes-y-números-de-serie.md"
      endpoints:
        - method: POST
          path: /api/v1/inventory/lots
          description: "Crear lote"
        - method: GET
          path: /api/v1/inventory/lots
          description: "Listar lotes"
        - method: GET
          path: /api/v1/inventory/lots/:id
          description: "Obtener lote por ID"
        - method: GET
          path: /api/v1/inventory/lots/:id/trace
          description: "Trazabilidad de lote"
      services:
        - name: "LotService"
          file: "src/modules/inventory/services/lot.service.ts"
          methods: [create, findAll, findOne, trace]
      controllers:
        - name: "LotController"
          file: "src/modules/inventory/controllers/lot.controller.ts"
      dtos:
        - name: "CreateLotDto"
          file: "src/modules/inventory/dto/create-lot.dto.ts"

    et_frontend:
      file: "especificaciones-tecnicas/frontend/mgn-005/ET-FRONTEND-MGN-005-005-trazabilidad-lotes-y-números-de-serie.md"
      routes:
        - path: "/inventory/lots"
          component: "LotsPage"
        - path: "/inventory/lots/:id"
          component: "LotDetailsPage"
      components:
        - name: "LotsTable"
          file: "src/widgets/lots-table/ui/LotsTable.tsx"
          type: widget
        - name: "CreateLotForm"
          file: "src/features/create-lot/ui/CreateLotForm.tsx"
          type: feature
        - name: "LotTraceability"
          file: "src/widgets/lot-traceability/ui/LotTraceability.tsx"
          type: widget
      api_client:
        - name: "lotApi"
          file: "src/entities/lot/api/lot.api.ts"
          methods: [getAll, getById, create, trace]
      state_management:
        - name: "useLotStore"
          file: "src/entities/lot/model/lot.store.ts"
          type: zustand

    database_tables:
      - schema: inventory
        table: lots
        file: "database-design/schemas/inventory-schema-ddl.sql"
        operations: [SELECT, INSERT, UPDATE]
        indices: [idx_lots_product_id, idx_lots_name, idx_lots_company_id]
        rls_policy: company_isolation_lots

    tests:
      backend:
        unit_tests:
          - file: "src/modules/inventory/services/lot.service.spec.ts"
            test_cases:
              - "should create lot"
              - "should trace lot movements"
              - "should validate lot uniqueness per product"
              - "should handle expiration dates"
        integration_tests:
          - file: "test/inventory/lot.controller.e2e-spec.ts"
            test_cases:
              - "POST /api/v1/inventory/lots should create lot"
              - "GET /api/v1/inventory/lots should return all lots"
              - "GET /api/v1/inventory/lots/:id/trace should return traceability"
              - "should enforce company isolation"
              - "should require authentication"
      frontend:
        component_tests:
          - file: "src/widgets/lots-table/ui/LotsTable.test.tsx"
            test_cases:
              - "should render table with lots"
              - "should show expiration status"
          - file: "src/widgets/lot-traceability/ui/LotTraceability.test.tsx"
            test_cases:
              - "should render traceability timeline"
        e2e_tests:
          - file: "e2e/inventory/lots.spec.ts"
            test_cases:
              - "should create lot successfully"
              - "should view lot traceability"
              - "should show expired lots"

    acceptance_criteria:
      - id: AC-001
        description: "Usuario puede crear lotes para productos"
        status: Pending
        test_reference: "test/inventory/lot.controller.e2e-spec.ts:28"
      - id: AC-002
        description: "Sistema registra trazabilidad completa de lotes"
        status: Pending
        test_reference: "src/modules/inventory/services/lot.service.spec.ts:65"
      - id: AC-003
        description: "Lotes tienen fecha de expiración"
        status: Pending
        test_reference: "test/inventory/lot.controller.e2e-spec.ts:95"

    business_rules:
      - id: RN-001
        description: "Lote/Serial único por producto y empresa"
        implementation: "database-design/schemas/inventory-schema-ddl.sql:CONSTRAINT uq_lots_name_product_company"
        test_reference: "src/modules/inventory/services/lot.service.spec.ts:58"
      - id: RN-002
        description: "Productos pueden requerir trazabilidad por lote o número de serie"
        implementation: "database-design/schemas/inventory-schema-ddl.sql:products.tracking"
        test_reference: "src/modules/inventory/services/lot.service.spec.ts:85"
      - id: RN-003
        description: "Lotes tienen fecha de expiración opcional"
        implementation: "database-design/schemas/inventory-schema-ddl.sql:lots.expiration_date"
        test_reference: "src/modules/inventory/services/lot.service.spec.ts:108"

    dependencies:
      rf_dependencies: [RF-MGN-005-001, RF-MGN-005-003]
      module_dependencies: []
      external_dependencies: []

  - rf_id: RF-MGN-005-006
    rf_title: "Valoración de Inventario (FIFO, Promedio)"
    rf_file: "requerimientos-funcionales/mgn-005/RF-MGN-005-006-valoración-de-inventario-fifo,-promedio.md"
    priority: P0
    story_points: 13

    et_backend:
      file: "especificaciones-tecnicas/backend/mgn-005/ET-BACKEND-MGN-005-006-valoración-de-inventario-fifo-promedio.md"
      endpoints:
        - method: GET
          path: /api/v1/inventory/valuation/:productId
          description: "Obtener valoración de producto"
        - method: GET
          path: /api/v1/inventory/valuation/report
          description: "Reporte de valoración de inventario"
        - method: POST
          path: /api/v1/inventory/valuation/recalculate
          description: "Recalcular valoración"
      services:
        - name: "ValuationService"
          file: "src/modules/inventory/services/valuation.service.ts"
          methods: [calculateValuation, generateReport, recalculate]
      controllers:
        - name: "ValuationController"
          file: "src/modules/inventory/controllers/valuation.controller.ts"
      dtos:
        - name: "ValuationReportDto"
          file: "src/modules/inventory/dto/valuation-report.dto.ts"

    et_frontend:
      file: "especificaciones-tecnicas/frontend/mgn-005/ET-FRONTEND-MGN-005-006-valoración-de-inventario-fifo-promedio.md"
      routes:
        - path: "/inventory/valuation"
          component: "ValuationPage"
        - path: "/inventory/valuation/:productId"
          component: "ProductValuationPage"
      components:
        - name: "ValuationTable"
          file: "src/widgets/valuation-table/ui/ValuationTable.tsx"
          type: widget
        - name: "ValuationChart"
          file: "src/widgets/valuation-chart/ui/ValuationChart.tsx"
          type: widget
      api_client:
        - name: "valuationApi"
          file: "src/entities/valuation/api/valuation.api.ts"
          methods: [getByProduct, getReport, recalculate]
      state_management:
        - name: "useValuationStore"
          file: "src/entities/valuation/model/valuation.store.ts"
          type: zustand

    database_tables:
      - schema: inventory
        table: stock_valuation_layers
        file: "database-design/schemas/inventory-schema-ddl.sql"
        operations: [SELECT, INSERT, UPDATE]
        indices: [idx_valuation_layers_product_id, idx_valuation_layers_company_id]
        rls_policy: company_isolation_valuation_layers

    tests:
      backend:
        unit_tests:
          - file: "src/modules/inventory/services/valuation.service.spec.ts"
            test_cases:
              - "should calculate FIFO valuation"
              - "should calculate average cost valuation"
              - "should update valuation on stock move"
              - "should generate valuation report"
              - "should recalculate valuation"
        integration_tests:
          - file: "test/inventory/valuation.controller.e2e-spec.ts"
            test_cases:
              - "GET /api/v1/inventory/valuation/:productId should return valuation"
              - "GET /api/v1/inventory/valuation/report should return report"
              - "POST /api/v1/inventory/valuation/recalculate should recalculate"
              - "should enforce company isolation"
              - "should require authentication"
      frontend:
        component_tests:
          - file: "src/widgets/valuation-table/ui/ValuationTable.test.tsx"
            test_cases:
              - "should render table with valuations"
              - "should show total valuation"
          - file: "src/widgets/valuation-chart/ui/ValuationChart.test.tsx"
            test_cases:
              - "should render valuation chart"
        e2e_tests:
          - file: "e2e/inventory/valuation.spec.ts"
            test_cases:
              - "should view product valuation"
              - "should generate valuation report"
              - "should recalculate valuation"

    acceptance_criteria:
      - id: AC-001
        description: "Sistema calcula valoración de inventario con método FIFO"
        status: Pending
        test_reference: "src/modules/inventory/services/valuation.service.spec.ts:58"
      - id: AC-002
        description: "Sistema calcula valoración de inventario con método Promedio"
        status: Pending
        test_reference: "src/modules/inventory/services/valuation.service.spec.ts:85"
      - id: AC-003
        description: "Valoración se actualiza automáticamente con movimientos de stock"
        status: Pending
        test_reference: "test/inventory/valuation.controller.e2e-spec.ts:68"

    business_rules:
      - id: RN-001
        description: "Métodos de valoración: FIFO (First In First Out), Average Cost"
        implementation: "database-design/schemas/inventory-schema-ddl.sql:products.cost_method"
        test_reference: "src/modules/inventory/services/valuation.service.spec.ts:48"
      - id: RN-002
        description: "Valoración se actualiza automáticamente en cada movimiento"
        implementation: "src/modules/inventory/services/valuation.service.ts:updateValuation()"
        test_reference: "src/modules/inventory/services/valuation.service.spec.ts:92"
      - id: RN-003
        description: "Stock valuation layers registran historia de costos"
        implementation: "database-design/schemas/inventory-schema-ddl.sql:stock_valuation_layers"
        test_reference: "src/modules/inventory/services/valuation.service.spec.ts:118"

    dependencies:
      rf_dependencies: [RF-MGN-005-001, RF-MGN-005-003]
      module_dependencies: []
      external_dependencies: []

  - rf_id: RF-MGN-005-007
    rf_title: "Inventario Físico y Ajustes"
    rf_file: "requerimientos-funcionales/mgn-005/RF-MGN-005-007-inventario-físico-y-ajustes.md"
    priority: P0
    story_points: 8

    et_backend:
      file: "especificaciones-tecnicas/backend/mgn-005/ET-BACKEND-MGN-005-007-inventario-físico-y-ajustes.md"
      endpoints:
        - method: POST
          path: /api/v1/inventory/adjustments
          description: "Crear ajuste de inventario"
        - method: GET
          path: /api/v1/inventory/adjustments
          description: "Listar ajustes"
        - method: GET
          path: /api/v1/inventory/adjustments/:id
          description: "Obtener ajuste por ID"
        - method: POST
          path: /api/v1/inventory/adjustments/:id/validate
          description: "Validar ajuste (actualiza stock)"
        - method: POST
          path: /api/v1/inventory/adjustments/:id/cancel
          description: "Cancelar ajuste"
      services:
        - name: "InventoryAdjustmentService"
          file: "src/modules/inventory/services/inventory-adjustment.service.ts"
          methods: [create, findAll, findOne, validate, cancel]
      controllers:
        - name: "InventoryAdjustmentController"
          file: "src/modules/inventory/controllers/inventory-adjustment.controller.ts"
      dtos:
        - name: "CreateInventoryAdjustmentDto"
          file: "src/modules/inventory/dto/create-inventory-adjustment.dto.ts"

    et_frontend:
      file: "especificaciones-tecnicas/frontend/mgn-005/ET-FRONTEND-MGN-005-007-inventario-físico-y-ajustes.md"
      routes:
        - path: "/inventory/adjustments"
          component: "AdjustmentsPage"
        - path: "/inventory/adjustments/create"
          component: "CreateAdjustmentPage"
        - path: "/inventory/adjustments/:id"
          component: "ViewAdjustmentPage"
      components:
        - name: "AdjustmentsTable"
          file: "src/widgets/adjustments-table/ui/AdjustmentsTable.tsx"
          type: widget
        - name: "CreateAdjustmentForm"
          file: "src/features/create-adjustment/ui/CreateAdjustmentForm.tsx"
          type: feature
        - name: "AdjustmentCard"
          file: "src/entities/adjustment/ui/AdjustmentCard.tsx"
          type: entity
      api_client:
        - name: "inventoryAdjustmentApi"
          file: "src/entities/adjustment/api/adjustment.api.ts"
          methods: [getAll, getById, create, validate, cancel]
      state_management:
        - name: "useAdjustmentStore"
          file: "src/entities/adjustment/model/adjustment.store.ts"
          type: zustand

    database_tables:
      - schema: inventory
        table: inventory_adjustments
        file: "database-design/schemas/inventory-schema-ddl.sql"
        operations: [SELECT, INSERT, UPDATE]
        indices: [idx_adjustments_company_id, idx_adjustments_state]
        rls_policy: company_isolation_adjustments

    tests:
      backend:
        unit_tests:
          - file: "src/modules/inventory/services/inventory-adjustment.service.spec.ts"
            test_cases:
              - "should create inventory adjustment"
              - "should validate adjustment (generates stock moves)"
              - "should handle positive adjustments (increases stock)"
              - "should handle negative adjustments (decreases stock)"
              - "should cancel adjustment"
        integration_tests:
          - file: "test/inventory/inventory-adjustment.controller.e2e-spec.ts"
            test_cases:
              - "POST /api/v1/inventory/adjustments should create adjustment"
              - "GET /api/v1/inventory/adjustments should return all adjustments"
              - "POST /api/v1/inventory/adjustments/:id/validate should validate adjustment"
              - "POST /api/v1/inventory/adjustments/:id/cancel should cancel adjustment"
              - "should enforce company isolation"
              - "should require authentication"
      frontend:
        component_tests:
          - file: "src/widgets/adjustments-table/ui/AdjustmentsTable.test.tsx"
            test_cases:
              - "should render table with adjustments"
              - "should filter by state"
          - file: "src/features/create-adjustment/ui/CreateAdjustmentForm.test.tsx"
            test_cases:
              - "should validate required fields"
              - "should submit valid form"
        e2e_tests:
          - file: "e2e/inventory/adjustments.spec.ts"
            test_cases:
              - "should create adjustment successfully"
              - "should validate adjustment successfully"
              - "should show updated stock"

    acceptance_criteria:
      - id: AC-001
        description: "Usuario puede crear ajustes de inventario por diferencias en conteo físico"
        status: Pending
        test_reference: "test/inventory/inventory-adjustment.controller.e2e-spec.ts:28"
      - id: AC-002
        description: "Validar ajuste genera movimientos de stock automáticamente"
        status: Pending
        test_reference: "src/modules/inventory/services/inventory-adjustment.service.spec.ts:68"
      - id: AC-003
        description: "Ajustes pueden ser positivos (incremento) o negativos (decremento)"
        status: Pending
        test_reference: "test/inventory/inventory-adjustment.controller.e2e-spec.ts:95"

    business_rules:
      - id: RN-001
        description: "Ajustes generan movimientos de stock automáticamente"
        implementation: "src/modules/inventory/services/inventory-adjustment.service.ts:validate()"
        test_reference: "src/modules/inventory/services/inventory-adjustment.service.spec.ts:58"
      - id: RN-002
        description: "Ajustes positivos incrementan stock, negativos decrementan"
        implementation: "src/modules/inventory/services/inventory-adjustment.service.ts:generateStockMoves()"
        test_reference: "src/modules/inventory/services/inventory-adjustment.service.spec.ts:85"
      - id: RN-003
        description: "Ajustes validados generan asientos contables de valoración"
        implementation: "src/modules/inventory/services/inventory-adjustment.service.ts:generateJournalEntry()"
        test_reference: "src/modules/inventory/services/inventory-adjustment.service.spec.ts:108"

    dependencies:
      rf_dependencies: [RF-MGN-005-001, RF-MGN-005-002, RF-MGN-005-003]
      module_dependencies: []
      external_dependencies: []

coverage:
  rf_to_et_backend: 100%
  rf_to_et_frontend: 100%
  rf_to_database: 100%
  rf_to_tests: 100%
  backend_tests: 100%
  frontend_tests: 100%

statistics:
  total_endpoints: 35
  total_components: 28
  total_tables: 10
  total_test_cases: 140
  estimated_duration_sprints: 4
