openapi: 3.0.3
info:
  title: Trento Core API — Endpoints requeridos por FTL Trace
  version: 1.0.0-draft
  description: 'Documento de referencia · 2026-05-14 · v1.0.


    Este Swagger acompaña al **documento técnico** (Docx) entregado por separado. Las rutas, parámetros y schemas son **propuestas**:
    Trento puede ajustar nombres y estructura siempre que la cobertura de campos se preserve.


    Para el detalle narrativo —contexto, autenticación, paginación, manejo de errores, rate limits, caching, versionado y
    roadmap— ver el Docx adjunto.


    ---


    **Ejemplos anclados en data real** — partida `24-06432` de la OP `6297` (id `6297`), cliente WORLD TEXTILE SOURCING INC
    / Peter Millar, estilo del piloto. Extraído del schema `trento.*` el 2026-05-14. Campos PII de individuos redactados a
    `null`. **El API no ejecuta** — el Try-it-out está deshabilitado porque el contrato aún no está implementado.'
  contact:
    name: FintechLab S.A.C. — FTL Trace
    email: info@fintechlab.la
  license:
    name: Documento confidencial interno
    url: https://fintechlab.la
servers:
- url: https://api-sandbox.trento.example/v1
  description: Sandbox (snapshot de OPs piloto)
- url: https://api.trento.example/v1
  description: Producción
tags:
- name: Maestros
  description: Categoría 1 (v1.5 sec 3.1). Productos, estilos, colores, proveedores, clientes, tallas, composición.
- name: Órdenes de Producción
  description: Categoría 2. OP master + planificación de corte. `op_id` es la llave universal.
- name: Recepciones
  description: Categoría 3. Entrada de tela y lookup GS1 por partida.
- name: Avíos
  description: Anexa P2. CP8.
- name: Lavado
  description: Anexa P2. CP3 (integración Qlever).
- name: Packing y Despacho
  description: Anexa P2. CP8 / CP9.
- name: Costura e Inspección
  description: Anexa P2. CP6 / CP7 (con gap aceptado).
- name: _meta
  description: Endpoints de salud y metadata del API.
security:
- bearerAuth: []
- apiKey: []
paths:
  /health:
    get:
      summary: Estado del API y lag de replicación
      description: Endpoint de salud. FTL lo consulta para detectar lag del replicador SQL Server → API.
      tags:
      - _meta
      operationId: health
      parameters: []
      security:
      - bearerAuth: []
      - apiKey: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    enum:
                    - ok
                    - degraded
                    - down
                    example: ok
                  replication_lag_seconds:
                    type: integer
                    example: 12
                  version:
                    type: string
                    example: 1.0.4
                  build:
                    type: string
                    format: date-time
                    example: '2026-05-12T18:00:00Z'
        4XX:
          description: 'Errores del cliente — agrupados.


            - **400** parámetros inválidos (formato, tipo, requeridos).

            - **401** token ausente o inválido. El cliente refresca y reintenta una vez.

            - **403** token válido pero scope insuficiente.

            - **404** recurso no encontrado. Tratar como ausencia, no como error.

            - **409** conflicto (ej. `partida` duplicada sin `supplier_ruc`).

            - **429** rate limit superado. Respeta `Retry-After`.'
          headers:
            Retry-After:
              schema:
                type: integer
              description: Solo en 429.
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
        5XX:
          description: 'Errores del servidor — agrupados.


            - **500** error interno. Cliente reintenta con backoff (máx. 3).

            - **503** indisponible o `replication_lag_seconds > 600` (10 min). Respeta `Retry-After`.'
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
  /products/{product_id}:
    get:
      summary: M-1 · Producto por id
      description: 'Devuelve descripción, código y tipo de tela. Hoy: parte de Q_CP1 sobre `trento."TblProductos"`.'
      tags:
      - Maestros
      operationId: getProductById
      parameters:
      - name: product_id
        in: path
        required: true
        schema:
          type: integer
        example: 12345
      security:
      - bearerAuth:
        - read:masters
      - apiKey: []
      responses:
        '200':
          description: Producto encontrado.
          content:
            application/json:
              schema:
                type: object
                required:
                - id
                - code
                properties:
                  id:
                    type: integer
                    example: 12345
                    description: trento.TblProductos.IdProducto
                  code:
                    type: string
                    example: TELA-PIMA-185
                  productive_description:
                    type: string
                    example: Jersey Pima 185g 93% Algodón Pima 7% Spandex
                  commercial_description:
                    type: string
                    example: Pima 100% premium
                  supplier_id:
                    type: integer
                    nullable: true
                    example: 9087
                  fabric_type:
                    type: string
                    example: JERSEY
              example:
                id: 41821
                code: '27881'
                productive_description: JERSEY LISTADO FULL LYCRA 93% PIMA COTTON ORGANICO 7% SPANDEX - RYLES STRIPE MS26K51
                commercial_description: JERSEY LISTADO FULL LYCRA 93% PIMA COTTON ORGANICO 7% SPANDEX
                supplier_id: 726
                fabric_type: JERSEY LISTADO FULL LYCRA 93% PIMA COTTON ORGANICO 7% SPANDEX
        4XX:
          description: 'Errores del cliente — agrupados.


            - **400** parámetros inválidos (formato, tipo, requeridos).

            - **401** token ausente o inválido. El cliente refresca y reintenta una vez.

            - **403** token válido pero scope insuficiente.

            - **404** recurso no encontrado. Tratar como ausencia, no como error.

            - **409** conflicto (ej. `partida` duplicada sin `supplier_ruc`).

            - **429** rate limit superado. Respeta `Retry-After`.'
          headers:
            Retry-After:
              schema:
                type: integer
              description: Solo en 429.
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
        5XX:
          description: 'Errores del servidor — agrupados.


            - **500** error interno. Cliente reintenta con backoff (máx. 3).

            - **503** indisponible o `replication_lag_seconds > 600` (10 min). Respeta `Retry-After`.'
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
  /products:
    get:
      summary: M-2 · Producto por código
      description: Lookup alternativo por `code` cuando el QR/SSCC trae el código humano.
      tags:
      - Maestros
      operationId: getProductByCode
      parameters:
      - name: code
        in: query
        required: true
        schema:
          type: string
        example: TELA-PIMA-185
      security:
      - bearerAuth:
        - read:masters
      - apiKey: []
      responses:
        '200':
          description: Producto encontrado.
          content:
            application/json:
              schema:
                type: object
                required:
                - id
                - code
                properties:
                  id:
                    type: integer
                    example: 12345
                    description: trento.TblProductos.IdProducto
                  code:
                    type: string
                    example: TELA-PIMA-185
                  productive_description:
                    type: string
                    example: Jersey Pima 185g 93% Algodón Pima 7% Spandex
                  commercial_description:
                    type: string
                    example: Pima 100% premium
                  supplier_id:
                    type: integer
                    nullable: true
                    example: 9087
                  fabric_type:
                    type: string
                    example: JERSEY
              example:
                id: 41821
                code: '27881'
                productive_description: JERSEY LISTADO FULL LYCRA 93% PIMA COTTON ORGANICO 7% SPANDEX - RYLES STRIPE MS26K51
                commercial_description: JERSEY LISTADO FULL LYCRA 93% PIMA COTTON ORGANICO 7% SPANDEX
                supplier_id: 726
                fabric_type: JERSEY LISTADO FULL LYCRA 93% PIMA COTTON ORGANICO 7% SPANDEX
        4XX:
          description: 'Errores del cliente — agrupados.


            - **400** parámetros inválidos (formato, tipo, requeridos).

            - **401** token ausente o inválido. El cliente refresca y reintenta una vez.

            - **403** token válido pero scope insuficiente.

            - **404** recurso no encontrado. Tratar como ausencia, no como error.

            - **409** conflicto (ej. `partida` duplicada sin `supplier_ruc`).

            - **429** rate limit superado. Respeta `Retry-After`.'
          headers:
            Retry-After:
              schema:
                type: integer
              description: Solo en 429.
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
        5XX:
          description: 'Errores del servidor — agrupados.


            - **500** error interno. Cliente reintenta con backoff (máx. 3).

            - **503** indisponible o `replication_lag_seconds > 600` (10 min). Respeta `Retry-After`.'
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
  /styles/{style_id}:
    get:
      summary: M-3 · Estilo por id (o code)
      description: Maestro de estilos `trento."UdpEstilo"`. Necesario para CP4 y CP8.
      tags:
      - Maestros
      operationId: getStyleById
      parameters:
      - name: style_id
        in: path
        required: true
        schema:
          type: string
        example: '4421'
        description: Acepta id numérico o `code` precedido por `code:`.
      security:
      - bearerAuth:
        - read:masters
      - apiKey: []
      responses:
        '200':
          description: Estilo encontrado.
          content:
            application/json:
              schema:
                type: object
                required:
                - id
                - code
                properties:
                  id:
                    type: integer
                    example: 4421
                  code:
                    type: string
                    example: P-12345
                  description:
                    type: string
                    example: Polo manga corta Pima
                  default_color_id:
                    type: integer
                    nullable: true
                    example: 88
              example:
                id: 34191
                code: MS26K51
                description: Polo Peter Millar línea MS26K51
                default_color_id: null
        4XX:
          description: 'Errores del cliente — agrupados.


            - **400** parámetros inválidos (formato, tipo, requeridos).

            - **401** token ausente o inválido. El cliente refresca y reintenta una vez.

            - **403** token válido pero scope insuficiente.

            - **404** recurso no encontrado. Tratar como ausencia, no como error.

            - **409** conflicto (ej. `partida` duplicada sin `supplier_ruc`).

            - **429** rate limit superado. Respeta `Retry-After`.'
          headers:
            Retry-After:
              schema:
                type: integer
              description: Solo en 429.
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
        5XX:
          description: 'Errores del servidor — agrupados.


            - **500** error interno. Cliente reintenta con backoff (máx. 3).

            - **503** indisponible o `replication_lag_seconds > 600` (10 min). Respeta `Retry-After`.'
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
  /colors/{color_id}:
    get:
      summary: M-4 · Color por id
      description: Maestro de colores `trento."UdpColor"` (y `TblDMaestro` para colores universales).
      tags:
      - Maestros
      operationId: getColorById
      parameters:
      - name: color_id
        in: path
        required: true
        schema:
          type: integer
        example: 88
      security:
      - bearerAuth:
        - read:masters
      - apiKey: []
      responses:
        '200':
          description: Color encontrado.
          content:
            application/json:
              schema:
                type: object
                required:
                - id
                - code
                properties:
                  id:
                    type: integer
                    example: 88
                  code:
                    type: string
                    example: BLANCO
                  description:
                    type: string
                    example: Blanco óptico
                  pantone:
                    type: string
                    nullable: true
                    example: 11-0601 TPX
              example:
                id: null
                code: WHT
                description: Blanco óptico
                pantone: null
        4XX:
          description: 'Errores del cliente — agrupados.


            - **400** parámetros inválidos (formato, tipo, requeridos).

            - **401** token ausente o inválido. El cliente refresca y reintenta una vez.

            - **403** token válido pero scope insuficiente.

            - **404** recurso no encontrado. Tratar como ausencia, no como error.

            - **409** conflicto (ej. `partida` duplicada sin `supplier_ruc`).

            - **429** rate limit superado. Respeta `Retry-After`.'
          headers:
            Retry-After:
              schema:
                type: integer
              description: Solo en 429.
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
        5XX:
          description: 'Errores del servidor — agrupados.


            - **500** error interno. Cliente reintenta con backoff (máx. 3).

            - **503** indisponible o `replication_lag_seconds > 600` (10 min). Respeta `Retry-After`.'
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
  /suppliers/{supplier_id}:
    get:
      summary: M-5 · Proveedor por id (P0)
      description: Datos de `trento."Persona"` (proveedor textil para CP1; proveedor de lavandería para CP3).
      tags:
      - Maestros
      operationId: getSupplierById
      parameters:
      - name: supplier_id
        in: path
        required: true
        schema:
          type: integer
        example: 9087
      - name: ruc
        in: query
        required: false
        schema:
          type: string
        description: Lookup alterno por RUC.
      security:
      - bearerAuth:
        - read:masters
      - apiKey: []
      responses:
        '200':
          description: Proveedor encontrado.
          content:
            application/json:
              schema:
                type: object
                required:
                - id
                - ruc
                - legal_name
                properties:
                  id:
                    type: integer
                    example: 9087
                    description: trento.Persona.IdPersona
                  ruc:
                    type: string
                    example: '20512345678'
                    description: trento.Persona.CodPersona
                  legal_name:
                    type: string
                    example: Hilanderías del Sur S.A.C.
                  address:
                    type: string
                    nullable: true
                    example: Av. Industrial 123, Lima, Perú
                  country_code:
                    type: string
                    nullable: true
                    example: PE
                    minLength: 2
                    maxLength: 2
                  tier:
                    type: string
                    nullable: true
                    enum:
                    - fabric_supplier
                    - laundry_supplier
                    - fiber_supplier
                    - accessories_supplier
                    - null
                    example: fabric_supplier
              example:
                id: 726
                ruc: '20102261551'
                legal_name: TEXTIL SAN RAMON S A
                address: null
                country_code: PE
                tier: fabric_supplier
        4XX:
          description: 'Errores del cliente — agrupados.


            - **400** parámetros inválidos (formato, tipo, requeridos).

            - **401** token ausente o inválido. El cliente refresca y reintenta una vez.

            - **403** token válido pero scope insuficiente.

            - **404** recurso no encontrado. Tratar como ausencia, no como error.

            - **409** conflicto (ej. `partida` duplicada sin `supplier_ruc`).

            - **429** rate limit superado. Respeta `Retry-After`.'
          headers:
            Retry-After:
              schema:
                type: integer
              description: Solo en 429.
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
        5XX:
          description: 'Errores del servidor — agrupados.


            - **500** error interno. Cliente reintenta con backoff (máx. 3).

            - **503** indisponible o `replication_lag_seconds > 600` (10 min). Respeta `Retry-After`.'
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
  /clients/by-op/{op_id}:
    get:
      summary: M-6 · Cliente por OP (P0)
      description: Resuelve `trento."ComCentroGestion"` encapsulando la concatenación `'OP-' + CodigoOP`.
      tags:
      - Maestros
      operationId: getClientByOp
      parameters:
      - name: op_id
        in: path
        required: true
        description: trento.UdpOrdenProduccion.IdOrdenProduccion (entero, PK).
        schema:
          type: integer
        example: 6223
      security:
      - bearerAuth:
        - read:masters
      - apiKey: []
      responses:
        '200':
          description: Cliente resuelto.
          content:
            application/json:
              schema:
                type: object
                required:
                - op_id
                - client_name
                properties:
                  op_id:
                    type: integer
                    example: 6223
                  client_name:
                    type: string
                    example: Brand X Apparel Ltd.
                  client_brand:
                    type: string
                    nullable: true
                    example: BX-Athleisure
                  style_code:
                    type: string
                    nullable: true
                    example: P-12345
              example:
                op_id: 6297
                client_name: WORLD TEXTILE SOURCING INC
                client_brand: PETER MILLAR
                style_code: MS26K51
        4XX:
          description: 'Errores del cliente — agrupados.


            - **400** parámetros inválidos (formato, tipo, requeridos).

            - **401** token ausente o inválido. El cliente refresca y reintenta una vez.

            - **403** token válido pero scope insuficiente.

            - **404** recurso no encontrado. Tratar como ausencia, no como error.

            - **409** conflicto (ej. `partida` duplicada sin `supplier_ruc`).

            - **429** rate limit superado. Respeta `Retry-After`.'
          headers:
            Retry-After:
              schema:
                type: integer
              description: Solo en 429.
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
        5XX:
          description: 'Errores del servidor — agrupados.


            - **500** error interno. Cliente reintenta con backoff (máx. 3).

            - **503** indisponible o `replication_lag_seconds > 600` (10 min). Respeta `Retry-After`.'
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
  /production-orders/{op_id}/size-distribution:
    get:
      summary: M-7 · Distribución de tallas asignada a la OP (P0)
      description: Reemplaza el adaptador `get_distribucion_tallas(op_id)`.
      tags:
      - Maestros
      operationId: getSizeDistributionByOp
      parameters:
      - name: op_id
        in: path
        required: true
        description: trento.UdpOrdenProduccion.IdOrdenProduccion (entero, PK).
        schema:
          type: integer
        example: 6223
      security:
      - bearerAuth:
        - read:masters
      - apiKey: []
      responses:
        '200':
          description: Distribución de tallas.
          content:
            application/json:
              schema:
                type: object
                required:
                - op_id
                - distribution
                - total
                properties:
                  op_id:
                    type: integer
                    example: 6223
                  production_order_code:
                    type: string
                    example: '6223'
                  distribution:
                    type: array
                    items:
                      type: object
                      required:
                      - size_code
                      - quantity
                      properties:
                        size_code:
                          type: string
                          example: M
                        quantity:
                          type: integer
                          minimum: 0
                          example: 240
                  total:
                    type: integer
                    minimum: 0
                    example: 640
              example:
                op_id: 6297
                production_order_code: '6297'
                distribution: []
                total: 0
        4XX:
          description: 'Errores del cliente — agrupados.


            - **400** parámetros inválidos (formato, tipo, requeridos).

            - **401** token ausente o inválido. El cliente refresca y reintenta una vez.

            - **403** token válido pero scope insuficiente.

            - **404** recurso no encontrado. Tratar como ausencia, no como error.

            - **409** conflicto (ej. `partida` duplicada sin `supplier_ruc`).

            - **429** rate limit superado. Respeta `Retry-After`.'
          headers:
            Retry-After:
              schema:
                type: integer
              description: Solo en 429.
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
        5XX:
          description: 'Errores del servidor — agrupados.


            - **500** error interno. Cliente reintenta con backoff (máx. 3).

            - **503** indisponible o `replication_lag_seconds > 600` (10 min). Respeta `Retry-After`.'
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
  /production-orders/{op_id}/material-composition:
    get:
      summary: M-8 · Composición de fibra parseada (P0)
      description: Composición ya estructurada (no string libre). Pilar del cálculo PEF LCS1.
      tags:
      - Maestros
      operationId: getMaterialCompositionByOp
      parameters:
      - name: op_id
        in: path
        required: true
        description: trento.UdpOrdenProduccion.IdOrdenProduccion (entero, PK).
        schema:
          type: integer
        example: 6223
      security:
      - bearerAuth:
        - read:masters
      - apiKey: []
      responses:
        '200':
          description: Composición parseada.
          content:
            application/json:
              schema:
                type: object
                required:
                - op_id
                - composition
                properties:
                  op_id:
                    type: integer
                    example: 6223
                  composition:
                    type: array
                    items:
                      type: object
                      required:
                      - material
                      - percentage
                      properties:
                        material:
                          type: string
                          example: cotton
                        percentage:
                          type: number
                          minimum: 0
                          maximum: 100
                          example: 93
                        organic:
                          type: boolean
                          example: true
                        iso_2076_code:
                          type: string
                          example: CO
                          description: ISO 2076 fibre code
                  total_percentage:
                    type: number
                    example: 100
                  raw_source_string:
                    type: string
                    nullable: true
                    example: 93% PIMA COTTON ORGANICO 7% SPANDEX
              example:
                op_id: 6297
                composition: []
                total_percentage: null
                raw_source_string: (27881) JERSEY LISTADO FULL LYCRA 93% PIMA COTTON ORGANICO 7% SPANDEX - RYLES STRIPE MS26K51
        4XX:
          description: 'Errores del cliente — agrupados.


            - **400** parámetros inválidos (formato, tipo, requeridos).

            - **401** token ausente o inválido. El cliente refresca y reintenta una vez.

            - **403** token válido pero scope insuficiente.

            - **404** recurso no encontrado. Tratar como ausencia, no como error.

            - **409** conflicto (ej. `partida` duplicada sin `supplier_ruc`).

            - **429** rate limit superado. Respeta `Retry-After`.'
          headers:
            Retry-After:
              schema:
                type: integer
              description: Solo en 429.
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
        5XX:
          description: 'Errores del servidor — agrupados.


            - **500** error interno. Cliente reintenta con backoff (máx. 3).

            - **503** indisponible o `replication_lag_seconds > 600` (10 min). Respeta `Retry-After`.'
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
  /production-orders/{op_id}:
    get:
      summary: OP-1 · OP master + detalle + ficha técnica (P0)
      description: Primer call del flujo CP1. Reemplaza el adaptador `get_op_metadata(op_id)`.
      tags:
      - Órdenes de Producción
      operationId: getProductionOrderById
      parameters:
      - name: op_id
        in: path
        required: true
        description: trento.UdpOrdenProduccion.IdOrdenProduccion (entero, PK).
        schema:
          type: integer
        example: 6223
      security:
      - bearerAuth:
        - read:production-orders
      - apiKey: []
      responses:
        '200':
          description: OP encontrada.
          content:
            application/json:
              schema:
                type: object
                required:
                - id
                - code
                properties:
                  id:
                    type: integer
                    example: 6223
                    description: trento.UdpOrdenProduccion.IdOrdenProduccion
                  code:
                    type: string
                    example: '6223'
                  purchase_order:
                    type: object
                    required:
                    - id
                    - code
                    properties:
                      id:
                        type: integer
                        example: 87123
                      code:
                        type: string
                        example: PO-2026-0042
                      planned_shipment_date:
                        type: string
                        format: date
                        nullable: true
                        example: '2026-07-15'
                      tolerance_pct:
                        type: number
                        nullable: true
                        example: 5
                      destination_country_code:
                        type: string
                        nullable: true
                        example: DE
                      destination_id:
                        type: integer
                        nullable: true
                        example: 412
                      transport_mode_id:
                        type: integer
                        nullable: true
                        example: 2
                  style:
                    type: object
                    properties:
                      id:
                        type: integer
                        example: 4421
                      code:
                        type: string
                        example: P-12345
                      description:
                        type: string
                        example: Polo manga corta Pima
                      technical_sheet_id:
                        type: integer
                        nullable: true
                        example: 1572
                  fabric_product_id:
                    type: integer
                    nullable: true
                    example: 12345
                  client:
                    type: object
                    properties:
                      id:
                        type: integer
                        example: 33
                      name:
                        type: string
                        example: Brand X Apparel Ltd.
                      brand:
                        type: string
                        nullable: true
                        example: BX-Athleisure
                  season:
                    type: string
                    nullable: true
                    example: SS-2026
                  created_at:
                    type: string
                    format: date-time
                    example: '2026-03-12T10:14:00-05:00'
                  lines:
                    type: array
                    items:
                      type: object
                      required:
                      - color_id
                      - size_code
                      - quantity
                      properties:
                        color_id:
                          type: integer
                          example: 88
                        size_code:
                          type: string
                          example: M
                        quantity:
                          type: integer
                          minimum: 0
                          example: 60
              example:
                id: 6297
                code: '6297'
                purchase_order:
                  id: 2226
                  code: '43713'
                  planned_shipment_date: '2026-01-16'
                  tolerance_pct: 5.0
                  destination_country_code: null
                  destination_id: 0
                  transport_mode_id: 627
                style:
                  id: 34191
                  code: MS26K51
                  description: null
                  technical_sheet_id: null
                fabric_product_id: 41821
                client:
                  id: null
                  name: WORLD TEXTILE SOURCING INC
                  brand: PETER MILLAR
                season: null
                created_at: null
                lines: []
        4XX:
          description: 'Errores del cliente — agrupados.


            - **400** parámetros inválidos (formato, tipo, requeridos).

            - **401** token ausente o inválido. El cliente refresca y reintenta una vez.

            - **403** token válido pero scope insuficiente.

            - **404** recurso no encontrado. Tratar como ausencia, no como error.

            - **409** conflicto (ej. `partida` duplicada sin `supplier_ruc`).

            - **429** rate limit superado. Respeta `Retry-After`.'
          headers:
            Retry-After:
              schema:
                type: integer
              description: Solo en 429.
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
        5XX:
          description: 'Errores del servidor — agrupados.


            - **500** error interno. Cliente reintenta con backoff (máx. 3).

            - **503** indisponible o `replication_lag_seconds > 600` (10 min). Respeta `Retry-After`.'
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
  /production-orders:
    get:
      summary: OP-2 · Listado paginado de OPs (P2)
      description: Para dashboard astro a futuro. No bloquea piloto.
      tags:
      - Órdenes de Producción
      operationId: listProductionOrders
      parameters:
      - name: from
        in: query
        schema:
          type: string
          format: date
      - name: to
        in: query
        schema:
          type: string
          format: date
      - name: client_id
        in: query
        schema:
          type: integer
      - name: status
        in: query
        schema:
          type: string
          enum:
          - active
          - closed
          - despatched
      - name: page
        in: query
        schema:
          type: integer
          minimum: 1
          default: 1
      - name: limit
        in: query
        schema:
          type: integer
          minimum: 1
          maximum: 200
          default: 50
      security:
      - bearerAuth:
        - read:production-orders
      - apiKey: []
      responses:
        '200':
          description: Listado paginado.
          content:
            application/json:
              schema:
                allOf:
                - type: object
                  required:
                  - page
                  - limit
                  - has_more
                  properties:
                    page:
                      type: integer
                      minimum: 1
                      example: 2
                    limit:
                      type: integer
                      minimum: 1
                      maximum: 200
                      example: 50
                    total:
                      type: integer
                      nullable: true
                      example: 312
                    has_more:
                      type: boolean
                      example: true
                - type: object
                  required:
                  - items
                  properties:
                    items:
                      type: array
                      items:
                        type: object
                        required:
                        - id
                        - code
                        properties:
                          id:
                            type: integer
                            example: 6223
                          code:
                            type: string
                            example: '6223'
                          client_id:
                            type: integer
                            nullable: true
                            example: 33
                          client_name:
                            type: string
                            nullable: true
                            example: Brand X Apparel Ltd.
                          status:
                            type: string
                            enum:
                            - active
                            - closed
                            - despatched
                            example: active
                          created_at:
                            type: string
                            format: date-time
        4XX:
          description: 'Errores del cliente — agrupados.


            - **400** parámetros inválidos (formato, tipo, requeridos).

            - **401** token ausente o inválido. El cliente refresca y reintenta una vez.

            - **403** token válido pero scope insuficiente.

            - **404** recurso no encontrado. Tratar como ausencia, no como error.

            - **409** conflicto (ej. `partida` duplicada sin `supplier_ruc`).

            - **429** rate limit superado. Respeta `Retry-After`.'
          headers:
            Retry-After:
              schema:
                type: integer
              description: Solo en 429.
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
        5XX:
          description: 'Errores del servidor — agrupados.


            - **500** error interno. Cliente reintenta con backoff (máx. 3).

            - **503** indisponible o `replication_lag_seconds > 600` (10 min). Respeta `Retry-After`.'
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
  /production-orders/{op_id}/cutting-orders:
    get:
      summary: OP-3 · Hojas de corte por OP (P0)
      description: CP2/CP4 precargado. `sizes` debe entregarse parseado de `ProdOrdenCorte.CampoTallas`.
      tags:
      - Órdenes de Producción
      operationId: getCuttingOrdersByOp
      parameters:
      - name: op_id
        in: path
        required: true
        description: trento.UdpOrdenProduccion.IdOrdenProduccion (entero, PK).
        schema:
          type: integer
        example: 6223
      security:
      - bearerAuth:
        - read:production-orders
      - apiKey: []
      responses:
        '200':
          description: Hojas de corte.
          content:
            application/json:
              schema:
                type: object
                required:
                - op_id
                - cutting_orders
                properties:
                  op_id:
                    type: integer
                    example: 6223
                  cutting_orders:
                    type: array
                    items:
                      type: object
                      required:
                      - id
                      - code
                      properties:
                        id:
                          type: integer
                          example: 901
                        code:
                          type: string
                          example: HC-6223-01
                        cutting_program_id:
                          type: integer
                          nullable: true
                          example: 514
                        cutting_date:
                          type: string
                          format: date
                          nullable: true
                          example: '2026-04-12'
                        total_units_cut:
                          type: integer
                          nullable: true
                          example: 320
                        sizes:
                          type: array
                          items:
                            type: object
                            required:
                            - size_code
                            - quantity
                            properties:
                              size_code:
                                type: string
                                example: M
                              quantity:
                                type: integer
                                minimum: 0
                                example: 240
              example:
                op_id: 6297
                cutting_orders:
                - id: 6711084
                  code: O - 0010090
                  cutting_program_id: 7231
                  cutting_date: '2025-12-19'
                  total_units_cut: 840.0
                  sizes: []
                - id: 6711084
                  code: O - 0010090
                  cutting_program_id: 7230
                  cutting_date: '2025-12-19'
                  total_units_cut: 840.0
                  sizes: []
                - id: 6711084
                  code: O - 0010090
                  cutting_program_id: 7347
                  cutting_date: '2025-12-29'
                  total_units_cut: 840.0
                  sizes: []
                - id: 6711085
                  code: O - 0010091
                  cutting_program_id: 7231
                  cutting_date: '2025-12-19'
                  total_units_cut: 840.0
                  sizes: []
                - id: 6711085
                  code: O - 0010091
                  cutting_program_id: 7230
                  cutting_date: '2025-12-19'
                  total_units_cut: 840.0
                  sizes: []
                - id: 6711085
                  code: O - 0010091
                  cutting_program_id: 7347
                  cutting_date: '2025-12-29'
                  total_units_cut: 840.0
                  sizes: []
                - id: 6711220
                  code: O - 0010226
                  cutting_program_id: 7230
                  cutting_date: '2025-12-19'
                  total_units_cut: 844.0
                  sizes: []
                - id: 6711220
                  code: O - 0010226
                  cutting_program_id: 7347
                  cutting_date: '2025-12-29'
                  total_units_cut: 844.0
                  sizes: []
                - id: 6711220
                  code: O - 0010226
                  cutting_program_id: 7231
                  cutting_date: '2025-12-19'
                  total_units_cut: 844.0
                  sizes: []
        4XX:
          description: 'Errores del cliente — agrupados.


            - **400** parámetros inválidos (formato, tipo, requeridos).

            - **401** token ausente o inválido. El cliente refresca y reintenta una vez.

            - **403** token válido pero scope insuficiente.

            - **404** recurso no encontrado. Tratar como ausencia, no como error.

            - **409** conflicto (ej. `partida` duplicada sin `supplier_ruc`).

            - **429** rate limit superado. Respeta `Retry-After`.'
          headers:
            Retry-After:
              schema:
                type: integer
              description: Solo en 429.
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
        5XX:
          description: 'Errores del servidor — agrupados.


            - **500** error interno. Cliente reintenta con backoff (máx. 3).

            - **503** indisponible o `replication_lag_seconds > 600` (10 min). Respeta `Retry-After`.'
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
  /cutting-orders/{cutting_id}:
    get:
      summary: OP-4 · Hoja de corte por id (P1)
      description: Drill-down individual.
      tags:
      - Órdenes de Producción
      operationId: getCuttingOrderById
      parameters:
      - name: cutting_id
        in: path
        required: true
        schema:
          type: integer
        example: 901
      security:
      - bearerAuth:
        - read:production-orders
      - apiKey: []
      responses:
        '200':
          description: Hoja de corte.
          content:
            application/json:
              schema:
                type: object
                required:
                - id
                - code
                properties:
                  id:
                    type: integer
                    example: 901
                  code:
                    type: string
                    example: HC-6223-01
                  cutting_program_id:
                    type: integer
                    nullable: true
                    example: 514
                  cutting_date:
                    type: string
                    format: date
                    nullable: true
                    example: '2026-04-12'
                  total_units_cut:
                    type: integer
                    nullable: true
                    example: 320
                  sizes:
                    type: array
                    items:
                      type: object
                      required:
                      - size_code
                      - quantity
                      properties:
                        size_code:
                          type: string
                          example: M
                        quantity:
                          type: integer
                          minimum: 0
                          example: 240
              example:
                id: 6711084
                code: O - 0010090
                cutting_program_id: 7231
                cutting_date: '2025-12-19'
                total_units_cut: 840.0
                sizes: []
        4XX:
          description: 'Errores del cliente — agrupados.


            - **400** parámetros inválidos (formato, tipo, requeridos).

            - **401** token ausente o inválido. El cliente refresca y reintenta una vez.

            - **403** token válido pero scope insuficiente.

            - **404** recurso no encontrado. Tratar como ausencia, no como error.

            - **409** conflicto (ej. `partida` duplicada sin `supplier_ruc`).

            - **429** rate limit superado. Respeta `Retry-After`.'
          headers:
            Retry-After:
              schema:
                type: integer
              description: Solo en 429.
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
        5XX:
          description: 'Errores del servidor — agrupados.


            - **500** error interno. Cliente reintenta con backoff (máx. 3).

            - **503** indisponible o `replication_lag_seconds > 600` (10 min). Respeta `Retry-After`.'
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
  /production-orders/{op_id}/size-analysis:
    get:
      summary: OP-5 · Análisis programado vs pedido por talla y color (P1)
      description: CP4 (corte de piezas + GTIN).
      tags:
      - Órdenes de Producción
      operationId: getSizeAnalysisByOp
      parameters:
      - name: op_id
        in: path
        required: true
        description: trento.UdpOrdenProduccion.IdOrdenProduccion (entero, PK).
        schema:
          type: integer
        example: 6223
      security:
      - bearerAuth:
        - read:production-orders
      - apiKey: []
      responses:
        '200':
          description: Análisis.
          content:
            application/json:
              schema:
                type: object
                required:
                - op_id
                - analysis
                properties:
                  op_id:
                    type: integer
                    example: 6223
                  analysis:
                    type: array
                    items:
                      type: object
                      properties:
                        color_id:
                          type: integer
                          example: 88
                        total_planned:
                          type: integer
                          example: 320
                        total_original_order:
                          type: integer
                          example: 320
                        by_size:
                          type: array
                          items:
                            type: object
                            properties:
                              size_code:
                                type: string
                                example: S
                              planned:
                                type: integer
                                example: 60
                              original:
                                type: integer
                                example: 60
              example:
                op_id: 6297
                analysis:
                - color_id: 829
                  total_planned: 840.0
                  total_original_order: 800.0
                  by_size: []
                - color_id: 832
                  total_planned: 840.0
                  total_original_order: 800.0
                  by_size: []
                - color_id: 5489
                  total_planned: 843.0
                  total_original_order: 800.0
                  by_size: []
        4XX:
          description: 'Errores del cliente — agrupados.


            - **400** parámetros inválidos (formato, tipo, requeridos).

            - **401** token ausente o inválido. El cliente refresca y reintenta una vez.

            - **403** token válido pero scope insuficiente.

            - **404** recurso no encontrado. Tratar como ausencia, no como error.

            - **409** conflicto (ej. `partida` duplicada sin `supplier_ruc`).

            - **429** rate limit superado. Respeta `Retry-After`.'
          headers:
            Retry-After:
              schema:
                type: integer
              description: Solo en 429.
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
        5XX:
          description: 'Errores del servidor — agrupados.


            - **500** error interno. Cliente reintenta con backoff (máx. 3).

            - **503** indisponible o `replication_lag_seconds > 600` (10 min). Respeta `Retry-After`.'
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
  /production-orders/{op_id}/cutting-closure:
    get:
      summary: OP-6 · Cierre QA del corte (P1)
      description: 'CP5: fecha de habilitado + tipos de consumo presentes.'
      tags:
      - Órdenes de Producción
      operationId: getCuttingClosureByOp
      parameters:
      - name: op_id
        in: path
        required: true
        description: trento.UdpOrdenProduccion.IdOrdenProduccion (entero, PK).
        schema:
          type: integer
        example: 6223
      security:
      - bearerAuth:
        - read:production-orders
      - apiKey: []
      responses:
        '200':
          description: Cierre QA.
          content:
            application/json:
              schema:
                type: object
                properties:
                  op_id:
                    type: integer
                    example: 6223
                  enabled_date:
                    type: string
                    format: date
                    nullable: true
                    example: '2026-04-20'
                  consumption_types_present:
                    type: array
                    items:
                      type: integer
                    example:
                    - 1
                    - 2
                    - 3
              example:
                op_id: 6297
                enabled_date: '2025-12-29'
                consumption_types_present:
                - 1
                - 5
        4XX:
          description: 'Errores del cliente — agrupados.


            - **400** parámetros inválidos (formato, tipo, requeridos).

            - **401** token ausente o inválido. El cliente refresca y reintenta una vez.

            - **403** token válido pero scope insuficiente.

            - **404** recurso no encontrado. Tratar como ausencia, no como error.

            - **409** conflicto (ej. `partida` duplicada sin `supplier_ruc`).

            - **429** rate limit superado. Respeta `Retry-After`.'
          headers:
            Retry-After:
              schema:
                type: integer
              description: Solo en 429.
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
        5XX:
          description: 'Errores del servidor — agrupados.


            - **500** error interno. Cliente reintenta con backoff (máx. 3).

            - **503** indisponible o `replication_lag_seconds > 600` (10 min). Respeta `Retry-After`.'
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
  /production-orders/{op_id}/consumption-sheet:
    get:
      summary: OP-7 · Hoja de consumo por talla y color (P1)
      description: Filtrable por `consumption_type` (1=tela, otros=avíos/embalaje).
      tags:
      - Órdenes de Producción
      operationId: getConsumptionSheetByOp
      parameters:
      - name: op_id
        in: path
        required: true
        description: trento.UdpOrdenProduccion.IdOrdenProduccion (entero, PK).
        schema:
          type: integer
        example: 6223
      - name: consumption_type
        in: query
        schema:
          type: integer
        description: 1 = tela; otros = avíos/embalaje.
      security:
      - bearerAuth:
        - read:production-orders
      - apiKey: []
      responses:
        '200':
          description: Hoja de consumo.
          content:
            application/json:
              schema:
                type: object
                required:
                - op_id
                - sheets
                properties:
                  op_id:
                    type: integer
                    example: 6223
                  sheets:
                    type: array
                    items:
                      type: object
                      properties:
                        consumption_type:
                          type: integer
                          example: 1
                        label:
                          type: string
                          enum:
                          - fabric
                          - accessories
                          - packaging
                          - other
                          example: fabric
                        consumption_per_unit:
                          type: number
                          nullable: true
                          example: 0.45
                        unit:
                          type: string
                          nullable: true
                          example: kg/garment
              example:
                op_id: 6297
                sheets:
                - consumption_type: 1
                  label: fabric
                  consumption_per_unit: 0.329
                  unit: kg/garment
                - consumption_type: 5
                  label: other
                  consumption_per_unit: null
                  unit: null
        4XX:
          description: 'Errores del cliente — agrupados.


            - **400** parámetros inválidos (formato, tipo, requeridos).

            - **401** token ausente o inválido. El cliente refresca y reintenta una vez.

            - **403** token válido pero scope insuficiente.

            - **404** recurso no encontrado. Tratar como ausencia, no como error.

            - **409** conflicto (ej. `partida` duplicada sin `supplier_ruc`).

            - **429** rate limit superado. Respeta `Retry-After`.'
          headers:
            Retry-After:
              schema:
                type: integer
              description: Solo en 429.
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
        5XX:
          description: 'Errores del servidor — agrupados.


            - **500** error interno. Cliente reintenta con backoff (máx. 3).

            - **503** indisponible o `replication_lag_seconds > 600` (10 min). Respeta `Retry-After`.'
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
  /production-orders/{op_id}/fabric-receipts:
    get:
      summary: RC-1 · Recepciones de tela por OP (P0)
      description: Cuello de botella del piloto. Sin esto CP1 mobile no opera.
      tags:
      - Recepciones
      operationId: getFabricReceiptsByOp
      parameters:
      - name: op_id
        in: path
        required: true
        description: trento.UdpOrdenProduccion.IdOrdenProduccion (entero, PK).
        schema:
          type: integer
        example: 6223
      security:
      - bearerAuth:
        - read:fabric-receipts
      - apiKey: []
      responses:
        '200':
          description: Recepciones de tela.
          content:
            application/json:
              schema:
                type: object
                required:
                - op_id
                - receipts
                properties:
                  op_id:
                    type: integer
                    example: 6223
                  production_order_code:
                    type: string
                    example: '6223'
                  fabric_purchase_order:
                    type: object
                    required:
                    - id
                    - code
                    properties:
                      id:
                        type: integer
                        example: 87123
                      code:
                        type: string
                        example: PO-2026-0042
                      planned_shipment_date:
                        type: string
                        format: date
                        nullable: true
                        example: '2026-07-15'
                      tolerance_pct:
                        type: number
                        nullable: true
                        example: 5
                      destination_country_code:
                        type: string
                        nullable: true
                        example: DE
                      destination_id:
                        type: integer
                        nullable: true
                        example: 412
                      transport_mode_id:
                        type: integer
                        nullable: true
                        example: 2
                  supplier:
                    type: object
                    required:
                    - id
                    - ruc
                    - legal_name
                    properties:
                      id:
                        type: integer
                        example: 9087
                        description: trento.Persona.IdPersona
                      ruc:
                        type: string
                        example: '20512345678'
                        description: trento.Persona.CodPersona
                      legal_name:
                        type: string
                        example: Hilanderías del Sur S.A.C.
                      address:
                        type: string
                        nullable: true
                        example: Av. Industrial 123, Lima, Perú
                      country_code:
                        type: string
                        nullable: true
                        example: PE
                        minLength: 2
                        maxLength: 2
                      tier:
                        type: string
                        nullable: true
                        enum:
                        - fabric_supplier
                        - laundry_supplier
                        - fiber_supplier
                        - accessories_supplier
                        - null
                        example: fabric_supplier
                  fabric:
                    type: object
                    required:
                    - id
                    - code
                    properties:
                      id:
                        type: integer
                        example: 12345
                        description: trento.TblProductos.IdProducto
                      code:
                        type: string
                        example: TELA-PIMA-185
                      productive_description:
                        type: string
                        example: Jersey Pima 185g 93% Algodón Pima 7% Spandex
                      commercial_description:
                        type: string
                        example: Pima 100% premium
                      supplier_id:
                        type: integer
                        nullable: true
                        example: 9087
                      fabric_type:
                        type: string
                        example: JERSEY
                  receipts:
                    type: array
                    items:
                      type: object
                      properties:
                        receipt_id:
                          type: integer
                          example: 50211
                        lot_number_header:
                          type: string
                          example: P-2026-3344
                        reception_date:
                          type: string
                          format: date
                          example: '2026-04-05'
                        reception_time:
                          type: string
                          example: '10:23:00'
                        total_weight_kg:
                          type: number
                          nullable: true
                          example: 845.6
                        fabric_width_cm:
                          type: number
                          nullable: true
                          example: 152.4
                        fabric_density_gsm:
                          type: number
                          nullable: true
                          example: 185
                        shrinkage_width_pct:
                          type: number
                          nullable: true
                          example: -3.2
                        shrinkage_length_pct:
                          type: number
                          nullable: true
                          example: -4.1
                        lots:
                          type: array
                          items:
                            type: object
                            properties:
                              lot_detail_number:
                                type: string
                                example: P-2026-3344-A
                              weight_kg:
                                type: number
                                example: 422.8
                  consumption_per_unit_kg:
                    type: number
                    nullable: true
                    example: 0.45
                  material_composition_raw:
                    type: string
                    nullable: true
                    example: 93% PIMA COTTON ORGANICO 7% SPANDEX
              example:
                op_id: 6297
                production_order_code: '6297'
                fabric_purchase_order:
                  id: 2226
                  code: '43713'
                supplier:
                  id: 726
                  ruc: '20102261551'
                  legal_name: TEXTIL SAN RAMON S A
                  address: null
                  country_code: PE
                  tier: fabric_supplier
                fabric:
                  id: 41821
                  code: '27881'
                  productive_description: JERSEY LISTADO FULL LYCRA 93% PIMA COTTON ORGANICO 7% SPANDEX - RYLES STRIPE MS26K51
                  commercial_description: JERSEY LISTADO FULL LYCRA 93% PIMA COTTON ORGANICO 7% SPANDEX
                  supplier_id: 726
                  fabric_type: JERSEY LISTADO FULL LYCRA 93% PIMA COTTON ORGANICO 7% SPANDEX
                receipts:
                - receipt_id: 4181
                  lot_number_header: 24-08038,24-06432
                  reception_date: '2024-10-29'
                  reception_time: 07:44:45
                  total_weight_kg: 535.6
                  fabric_width_cm: 1.95
                  fabric_density_gsm: 0.162
                  shrinkage_width_pct: 10.0
                  shrinkage_length_pct: 13.0
                  lots:
                  - lot_detail_number: 24-06432
                    weight_kg: 9.05
                  - lot_detail_number: 24-06432
                    weight_kg: 9.05
                  - lot_detail_number: 24-06432
                    weight_kg: 11.3
                  - lot_detail_number: 24-06432
                    weight_kg: 429.7
                  - lot_detail_number: 24-06432
                    weight_kg: 25.5
                  - lot_detail_number: 24-08038
                    weight_kg: 35.0
                  - lot_detail_number: 24-08038
                    weight_kg: 16.0
                consumption_per_unit_kg: 0.329
                material_composition_raw: (27881) JERSEY LISTADO FULL LYCRA 93% PIMA COTTON ORGANICO 7% SPANDEX - RYLES STRIPE
                  MS26K51
        4XX:
          description: 'Errores del cliente — agrupados.


            - **400** parámetros inválidos (formato, tipo, requeridos).

            - **401** token ausente o inválido. El cliente refresca y reintenta una vez.

            - **403** token válido pero scope insuficiente.

            - **404** recurso no encontrado. Tratar como ausencia, no como error.

            - **409** conflicto (ej. `partida` duplicada sin `supplier_ruc`).

            - **429** rate limit superado. Respeta `Retry-After`.'
          headers:
            Retry-After:
              schema:
                type: integer
              description: Solo en 429.
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
        5XX:
          description: 'Errores del servidor — agrupados.


            - **500** error interno. Cliente reintenta con backoff (máx. 3).

            - **503** indisponible o `replication_lag_seconds > 600` (10 min). Respeta `Retry-After`.'
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
  /fabric-receipts/{receipt_id}:
    get:
      summary: RC-2 · Drill-down de recepción individual (P1)
      description: ''
      tags:
      - Recepciones
      operationId: getFabricReceiptById
      parameters:
      - name: receipt_id
        in: path
        required: true
        schema:
          type: integer
        example: 50211
      security:
      - bearerAuth:
        - read:fabric-receipts
      - apiKey: []
      responses:
        '200':
          description: Recepción.
          content:
            application/json:
              schema:
                allOf:
                - type: object
                  properties:
                    receipt_id:
                      type: integer
                      example: 50211
                    lot_number_header:
                      type: string
                      example: P-2026-3344
                    reception_date:
                      type: string
                      format: date
                      example: '2026-04-05'
                    reception_time:
                      type: string
                      example: '10:23:00'
                    total_weight_kg:
                      type: number
                      nullable: true
                      example: 845.6
                    fabric_width_cm:
                      type: number
                      nullable: true
                      example: 152.4
                    fabric_density_gsm:
                      type: number
                      nullable: true
                      example: 185
                    shrinkage_width_pct:
                      type: number
                      nullable: true
                      example: -3.2
                    shrinkage_length_pct:
                      type: number
                      nullable: true
                      example: -4.1
                    lots:
                      type: array
                      items:
                        type: object
                        properties:
                          lot_detail_number:
                            type: string
                            example: P-2026-3344-A
                          weight_kg:
                            type: number
                            example: 422.8
                - type: object
                  properties:
                    op_id:
                      type: integer
                      example: 6223
                    supplier_id:
                      type: integer
                      example: 9087
              example:
                receipt_id: 4181
                lot_number_header: 24-08038,24-06432
                reception_date: '2024-10-29'
                reception_time: 07:44:45
                total_weight_kg: 535.6
                fabric_width_cm: 1.95
                fabric_density_gsm: 0.162
                shrinkage_width_pct: 10.0
                shrinkage_length_pct: 13.0
                lots:
                - lot_detail_number: 24-06432
                  weight_kg: 9.05
                - lot_detail_number: 24-06432
                  weight_kg: 9.05
                - lot_detail_number: 24-06432
                  weight_kg: 11.3
                - lot_detail_number: 24-06432
                  weight_kg: 429.7
                - lot_detail_number: 24-06432
                  weight_kg: 25.5
                - lot_detail_number: 24-08038
                  weight_kg: 35.0
                - lot_detail_number: 24-08038
                  weight_kg: 16.0
                op_id: 6297
                supplier_id: 726
        4XX:
          description: 'Errores del cliente — agrupados.


            - **400** parámetros inválidos (formato, tipo, requeridos).

            - **401** token ausente o inválido. El cliente refresca y reintenta una vez.

            - **403** token válido pero scope insuficiente.

            - **404** recurso no encontrado. Tratar como ausencia, no como error.

            - **409** conflicto (ej. `partida` duplicada sin `supplier_ruc`).

            - **429** rate limit superado. Respeta `Retry-After`.'
          headers:
            Retry-After:
              schema:
                type: integer
              description: Solo en 429.
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
        5XX:
          description: 'Errores del servidor — agrupados.


            - **500** error interno. Cliente reintenta con backoff (máx. 3).

            - **503** indisponible o `replication_lag_seconds > 600` (10 min). Respeta `Retry-After`.'
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
  /fabric-receipts:
    get:
      summary: RC-3 · Lookup por partida (GS1 AI 240) (P0)
      description: Mobile escanea GS1-128 → resuelve `op_id` por número de partida. Debe ser indexado.
      tags:
      - Recepciones
      operationId: lookupFabricReceiptByPartida
      parameters:
      - name: partida
        in: query
        required: true
        schema:
          type: string
        example: P-2026-3344-A
      - name: supplier_ruc
        in: query
        schema:
          type: string
        description: Desambiguación si la partida está duplicada.
      security:
      - bearerAuth:
        - read:fabric-receipts
      - apiKey: []
      responses:
        '200':
          description: Partida resuelta.
          content:
            application/json:
              schema:
                type: object
                required:
                - partida
                - op_id
                properties:
                  partida:
                    type: string
                    example: P-2026-3344-A
                  op_id:
                    type: integer
                    example: 6223
                  production_order_code:
                    type: string
                    example: '6223'
                  receipt_id:
                    type: integer
                    example: 50211
                  lot_detail_number:
                    type: string
                    example: P-2026-3344-A
                  weight_kg:
                    type: number
                    nullable: true
                    example: 422.8
                  supplier_ruc:
                    type: string
                    example: '20512345678'
              example:
                partida: 24-06432
                op_id: 6297
                production_order_code: '6297'
                receipt_id: 4181
                lot_detail_number: 24-06432
                weight_kg: 9.05
                supplier_ruc: '20102261551'
        4XX:
          description: 'Errores del cliente — agrupados.


            - **400** parámetros inválidos (formato, tipo, requeridos).

            - **401** token ausente o inválido. El cliente refresca y reintenta una vez.

            - **403** token válido pero scope insuficiente.

            - **404** recurso no encontrado. Tratar como ausencia, no como error.

            - **409** conflicto (ej. `partida` duplicada sin `supplier_ruc`).

            - **429** rate limit superado. Respeta `Retry-After`.'
          headers:
            Retry-After:
              schema:
                type: integer
              description: Solo en 429.
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
        5XX:
          description: 'Errores del servidor — agrupados.


            - **500** error interno. Cliente reintenta con backoff (máx. 3).

            - **503** indisponible o `replication_lag_seconds > 600` (10 min). Respeta `Retry-After`.'
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
  /production-orders/{op_id}/fabric-lots-summary:
    get:
      summary: RC-4 · Resumen de lotes por OP (P1)
      description: CP2 muestra lote origen como referencia.
      tags:
      - Recepciones
      operationId: getFabricLotsSummaryByOp
      parameters:
      - name: op_id
        in: path
        required: true
        description: trento.UdpOrdenProduccion.IdOrdenProduccion (entero, PK).
        schema:
          type: integer
        example: 6223
      security:
      - bearerAuth:
        - read:fabric-receipts
      - apiKey: []
      responses:
        '200':
          description: Resumen.
          content:
            application/json:
              schema:
                type: object
                properties:
                  op_id:
                    type: integer
                    example: 6223
                  lots:
                    type: array
                    items:
                      type: object
                      properties:
                        lot_number:
                          type: string
                          example: P-2026-3344
                        weight_kg:
                          type: number
                          example: 845.6
                        lot_details_count:
                          type: integer
                          example: 2
              example:
                op_id: 6297
                lots:
                - lot_number: 24-08038,24-06432
                  weight_kg: 535.5999999999999
                  lot_details_count: 7
        4XX:
          description: 'Errores del cliente — agrupados.


            - **400** parámetros inválidos (formato, tipo, requeridos).

            - **401** token ausente o inválido. El cliente refresca y reintenta una vez.

            - **403** token válido pero scope insuficiente.

            - **404** recurso no encontrado. Tratar como ausencia, no como error.

            - **409** conflicto (ej. `partida` duplicada sin `supplier_ruc`).

            - **429** rate limit superado. Respeta `Retry-After`.'
          headers:
            Retry-After:
              schema:
                type: integer
              description: Solo en 429.
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
        5XX:
          description: 'Errores del servidor — agrupados.


            - **500** error interno. Cliente reintenta con backoff (máx. 3).

            - **503** indisponible o `replication_lag_seconds > 600` (10 min). Respeta `Retry-After`.'
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
  /accessories:
    get:
      summary: AV-1 · Avíos por estilo + color (P2)
      description: Cacheable 1h. Avío `115` debe entregarse splitted en `115-A` (bolsa) y `115-B` (etiqueta).
      tags:
      - Avíos
      operationId: getAccessoriesByStyleColor
      parameters:
      - name: style
        in: query
        required: true
        schema:
          type: string
        example: P-12345
      - name: color
        in: query
        required: true
        schema:
          type: string
        example: BLANCO
      security:
      - bearerAuth:
        - read:accessories
      - apiKey: []
      responses:
        '200':
          description: Avíos por (estilo, color).
          content:
            application/json:
              schema:
                type: object
                properties:
                  style:
                    type: string
                    example: P-12345
                  color:
                    type: string
                    example: BLANCO
                  accessories:
                    type: array
                    items:
                      type: object
                      properties:
                        code:
                          type: string
                          example: 115-A
                          description: Códigos como `115` pueden venir splitted en `115-A`/`115-B`.
                        description:
                          type: string
                          example: Bolsa de polietileno
                        quantity_per_garment:
                          type: number
                          example: 1
        4XX:
          description: 'Errores del cliente — agrupados.


            - **400** parámetros inválidos (formato, tipo, requeridos).

            - **401** token ausente o inválido. El cliente refresca y reintenta una vez.

            - **403** token válido pero scope insuficiente.

            - **404** recurso no encontrado. Tratar como ausencia, no como error.

            - **409** conflicto (ej. `partida` duplicada sin `supplier_ruc`).

            - **429** rate limit superado. Respeta `Retry-After`.'
          headers:
            Retry-After:
              schema:
                type: integer
              description: Solo en 429.
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
        5XX:
          description: 'Errores del servidor — agrupados.


            - **500** error interno. Cliente reintenta con backoff (máx. 3).

            - **503** indisponible o `replication_lag_seconds > 600` (10 min). Respeta `Retry-After`.'
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
  /production-orders/{op_id}/laundry-movements:
    get:
      summary: LV-1 · Movimientos de lavado por OP (P2)
      description: Tipos S=salida, I=ingreso. El API debe encapsular `IdCore = IdTraCorte`.
      tags:
      - Lavado
      operationId: getLaundryMovementsByOp
      parameters:
      - name: op_id
        in: path
        required: true
        description: trento.UdpOrdenProduccion.IdOrdenProduccion (entero, PK).
        schema:
          type: integer
        example: 6223
      security:
      - bearerAuth:
        - read:laundry
      - apiKey: []
      responses:
        '200':
          description: Movimientos.
          content:
            application/json:
              schema:
                type: object
                properties:
                  op_id:
                    type: integer
                    example: 6223
                  movements:
                    type: array
                    items:
                      type: object
                      properties:
                        movement_id:
                          type: integer
                          example: 7711
                        transfer_code:
                          type: string
                          nullable: true
                          example: TC-6223-001
                        laundry_supplier_code:
                          type: string
                          nullable: true
                          example: LAV-NORTE
                        laundry_supplier_name:
                          type: string
                          nullable: true
                          example: Lavandería del Norte S.A.C.
                        warehouse_origin:
                          type: string
                          nullable: true
                          example: PLANTA-01
                        warehouse_destination:
                          type: string
                          nullable: true
                          example: LAV-NORTE-01
                        movement_date:
                          type: string
                          format: date
                          example: '2026-04-22'
                        movement_type:
                          type: string
                          enum:
                          - S
                          - I
                          example: S
                        guide_number:
                          type: string
                          nullable: true
                          example: G-2026-0421
                        service_description:
                          type: string
                          nullable: true
                          example: Lavado enzimático + suavizado
                        items:
                          type: array
                          items:
                            type: object
                            properties:
                              item_name:
                                type: string
                                example: Panos Pima 185g
                              quantity:
                                type: number
                                example: 320
                              lot_number:
                                type: string
                                nullable: true
                                example: P-2026-3344-A
              example:
                op_id: 6297
                movements:
                - movement_id: 18204
                  transfer_code: T-COR - 0010376
                  laundry_supplier_code: null
                  warehouse_origin: 24.0
                  warehouse_destination: 0.0
                  movement_date: 02-01-2026
                  movement_type: I
                  guide_number: 86
                  service_description: null
                  laundry_supplier_name: null
                  items:
                  - item_name: (MS26K51) CROWN FLEX COTTON SS POLO - RYLES STRIPE, WHT, S - PP
                    quantity: 30.0
                    lot_number: null
                  - item_name: (MS26K51) CROWN FLEX COTTON SS POLO - RYLES STRIPE, WHT, M - PP
                    quantity: 239.0
                    lot_number: null
                  - item_name: (MS26K51) CROWN FLEX COTTON SS POLO - RYLES STRIPE, WHT, L - PP
                    quantity: 334.0
                    lot_number: null
                  - item_name: (MS26K51) CROWN FLEX COTTON SS POLO - RYLES STRIPE, WHT, XL - PP
                    quantity: 197.0
                    lot_number: null
                  - item_name: (MS26K51) CROWN FLEX COTTON SS POLO - RYLES STRIPE, WHT, XXL - PP
                    quantity: 42.0
                    lot_number: null
                - movement_id: 18203
                  transfer_code: T-COR - 0010376
                  laundry_supplier_code: null
                  warehouse_origin: 23.0
                  warehouse_destination: 0.0
                  movement_date: 02-01-2026
                  movement_type: S
                  guide_number: 85
                  service_description: null
                  laundry_supplier_name: null
                  items:
                  - item_name: (27881) JERSEY LISTADO FULL LYCRA 93% PIMA COTTON ORGANICO 7% SPANDEX - RYLES STRIPE MS26K51
                    quantity: 60.77
                    lot_number: 25-10343
                  - item_name: (27881) JERSEY LISTADO FULL LYCRA 93% PIMA COTTON ORGANICO 7% SPANDEX - RYLES STRIPE MS26K51
                    quantity: 60.13
                    lot_number: 25-10344
                - movement_id: 18263
                  transfer_code: T-COR - 0010419
                  laundry_supplier_code: null
                  warehouse_origin: 24.0
                  warehouse_destination: 0.0
                  movement_date: 12-01-2026
                  movement_type: I
                  guide_number: 758
                  service_description: null
                  laundry_supplier_name: null
                  items:
                  - item_name: (MS26K51) CROWN FLEX COTTON SS POLO - RYLES STRIPE, CLDYB, S - PP
                    quantity: 36.0
                    lot_number: null
                  - item_name: (MS26K51) CROWN FLEX COTTON SS POLO - RYLES STRIPE, CLDYB, M - PP
                    quantity: 233.0
                    lot_number: null
                  - item_name: (MS26K51) CROWN FLEX COTTON SS POLO - RYLES STRIPE, CLDYB, L - PP
                    quantity: 323.0
                    lot_number: null
                  - item_name: (MS26K51) CROWN FLEX COTTON SS POLO - RYLES STRIPE, CLDYB, XL - PP
                    quantity: 199.0
                    lot_number: null
                  - item_name: (MS26K51) CROWN FLEX COTTON SS POLO - RYLES STRIPE, CLDYB, XXL - PP
                    quantity: 53.0
                    lot_number: null
                - movement_id: 18262
                  transfer_code: T-COR - 0010419
                  laundry_supplier_code: null
                  warehouse_origin: 23.0
                  warehouse_destination: 0.0
                  movement_date: 12-01-2026
                  movement_type: S
                  guide_number: 730
                  service_description: null
                  laundry_supplier_name: null
                  items:
                  - item_name: (27881) JERSEY LISTADO FULL LYCRA 93% PIMA COTTON ORGANICO 7% SPANDEX - RYLES STRIPE MS26K51
                    quantity: 108.59
                    lot_number: 25-10339
                  - item_name: (27881) JERSEY LISTADO FULL LYCRA 93% PIMA COTTON ORGANICO 7% SPANDEX - RYLES STRIPE MS26K51
                    quantity: 104.41
                    lot_number: 25-10340
                - movement_id: 18141
                  transfer_code: T-COR - 0010281
                  laundry_supplier_code: null
                  warehouse_origin: 24.0
                  warehouse_destination: 0.0
                  movement_date: 27-12-2025
                  movement_type: I
                  guide_number: 27052
                  service_description: null
                  laundry_supplier_name: null
                  items:
                  - item_name: (MS26K51) CROWN FLEX COTTON SS POLO - RYLES STRIPE, NAV, S - PP
                    quantity: 30.0
                    lot_number: null
                  - item_name: (MS26K51) CROWN FLEX COTTON SS POLO - RYLES STRIPE, NAV, M - PP
                    quantity: 226.0
                    lot_number: null
                  - item_name: (MS26K51) CROWN FLEX COTTON SS POLO - RYLES STRIPE, NAV, L - PP
                    quantity: 321.0
                    lot_number: null
                  - item_name: (MS26K51) CROWN FLEX COTTON SS POLO - RYLES STRIPE, NAV, XL - PP
                    quantity: 205.0
                    lot_number: null
                  - item_name: (MS26K51) CROWN FLEX COTTON SS POLO - RYLES STRIPE, NAV, XXL - PP
                    quantity: 58.0
                    lot_number: null
                - movement_id: 18140
                  transfer_code: T-COR - 0010281
                  laundry_supplier_code: null
                  warehouse_origin: 23.0
                  warehouse_destination: 0.0
                  movement_date: 27-12-2025
                  movement_type: S
                  guide_number: 24779
                  service_description: null
                  laundry_supplier_name: null
                  items:
                  - item_name: (27881) JERSEY LISTADO FULL LYCRA 93% PIMA COTTON ORGANICO 7% SPANDEX - RYLES STRIPE MS26K51
                    quantity: 60.8
                    lot_number: 25-10341
                  - item_name: (27881) JERSEY LISTADO FULL LYCRA 93% PIMA COTTON ORGANICO 7% SPANDEX - RYLES STRIPE MS26K51
                    quantity: 61.4
                    lot_number: 25-10342
        4XX:
          description: 'Errores del cliente — agrupados.


            - **400** parámetros inválidos (formato, tipo, requeridos).

            - **401** token ausente o inválido. El cliente refresca y reintenta una vez.

            - **403** token válido pero scope insuficiente.

            - **404** recurso no encontrado. Tratar como ausencia, no como error.

            - **409** conflicto (ej. `partida` duplicada sin `supplier_ruc`).

            - **429** rate limit superado. Respeta `Retry-After`.'
          headers:
            Retry-After:
              schema:
                type: integer
              description: Solo en 429.
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
        5XX:
          description: 'Errores del servidor — agrupados.


            - **500** error interno. Cliente reintenta con backoff (máx. 3).

            - **503** indisponible o `replication_lag_seconds > 600` (10 min). Respeta `Retry-After`.'
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
  /laundry-movements/{movement_id}:
    get:
      summary: LV-2 · Movimiento de lavado por id (P2)
      description: ''
      tags:
      - Lavado
      operationId: getLaundryMovementById
      parameters:
      - name: movement_id
        in: path
        required: true
        schema:
          type: integer
        example: 7711
      security:
      - bearerAuth:
        - read:laundry
      - apiKey: []
      responses:
        '200':
          description: Movimiento.
          content:
            application/json:
              schema:
                type: object
                properties:
                  movement_id:
                    type: integer
                    example: 7711
                  transfer_code:
                    type: string
                    nullable: true
                    example: TC-6223-001
                  laundry_supplier_code:
                    type: string
                    nullable: true
                    example: LAV-NORTE
                  laundry_supplier_name:
                    type: string
                    nullable: true
                    example: Lavandería del Norte S.A.C.
                  warehouse_origin:
                    type: string
                    nullable: true
                    example: PLANTA-01
                  warehouse_destination:
                    type: string
                    nullable: true
                    example: LAV-NORTE-01
                  movement_date:
                    type: string
                    format: date
                    example: '2026-04-22'
                  movement_type:
                    type: string
                    enum:
                    - S
                    - I
                    example: S
                  guide_number:
                    type: string
                    nullable: true
                    example: G-2026-0421
                  service_description:
                    type: string
                    nullable: true
                    example: Lavado enzimático + suavizado
                  items:
                    type: array
                    items:
                      type: object
                      properties:
                        item_name:
                          type: string
                          example: Panos Pima 185g
                        quantity:
                          type: number
                          example: 320
                        lot_number:
                          type: string
                          nullable: true
                          example: P-2026-3344-A
              example:
                movement_id: 18204
                transfer_code: T-COR - 0010376
                laundry_supplier_code: null
                warehouse_origin: 24.0
                warehouse_destination: 0.0
                movement_date: 02-01-2026
                movement_type: I
                guide_number: 86
                service_description: null
                laundry_supplier_name: null
                items:
                - item_name: (MS26K51) CROWN FLEX COTTON SS POLO - RYLES STRIPE, WHT, S - PP
                  quantity: 30.0
                  lot_number: null
                - item_name: (MS26K51) CROWN FLEX COTTON SS POLO - RYLES STRIPE, WHT, M - PP
                  quantity: 239.0
                  lot_number: null
                - item_name: (MS26K51) CROWN FLEX COTTON SS POLO - RYLES STRIPE, WHT, L - PP
                  quantity: 334.0
                  lot_number: null
                - item_name: (MS26K51) CROWN FLEX COTTON SS POLO - RYLES STRIPE, WHT, XL - PP
                  quantity: 197.0
                  lot_number: null
                - item_name: (MS26K51) CROWN FLEX COTTON SS POLO - RYLES STRIPE, WHT, XXL - PP
                  quantity: 42.0
                  lot_number: null
        4XX:
          description: 'Errores del cliente — agrupados.


            - **400** parámetros inválidos (formato, tipo, requeridos).

            - **401** token ausente o inválido. El cliente refresca y reintenta una vez.

            - **403** token válido pero scope insuficiente.

            - **404** recurso no encontrado. Tratar como ausencia, no como error.

            - **409** conflicto (ej. `partida` duplicada sin `supplier_ruc`).

            - **429** rate limit superado. Respeta `Retry-After`.'
          headers:
            Retry-After:
              schema:
                type: integer
              description: Solo en 429.
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
        5XX:
          description: 'Errores del servidor — agrupados.


            - **500** error interno. Cliente reintenta con backoff (máx. 3).

            - **503** indisponible o `replication_lag_seconds > 600` (10 min). Respeta `Retry-After`.'
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
  /production-orders/{op_id}/boxes:
    get:
      summary: PK-1 · Cajas/bultos por OP (P2)
      description: '`gross_weight_kg` puede venir 0 en piloto; consultar `gross_weight_from_scale`.'
      tags:
      - Packing y Despacho
      operationId: getBoxesByOp
      parameters:
      - name: op_id
        in: path
        required: true
        description: trento.UdpOrdenProduccion.IdOrdenProduccion (entero, PK).
        schema:
          type: integer
        example: 6223
      security:
      - bearerAuth:
        - read:packing
      - apiKey: []
      responses:
        '200':
          description: Cajas.
          content:
            application/json:
              schema:
                type: object
                properties:
                  op_id:
                    type: integer
                    example: 6223
                  boxes:
                    type: array
                    items:
                      type: object
                      properties:
                        box_number:
                          type: integer
                          example: 1
                        total_finished_garments:
                          type: integer
                          example: 24
                        gross_weight_kg:
                          type: number
                          nullable: true
                          example: 0
                          description: En piloto suele venir 0; ver `gross_weight_from_scale` flag.
                        gross_weight_from_scale:
                          type: boolean
                          example: false
                        net_weight_kg:
                          type: number
                          nullable: true
                          example: 5.2
                        box_tare_kg:
                          type: number
                          nullable: true
                          example: 0.3
                        dimensions_cm:
                          type: object
                          properties:
                            height:
                              type: number
                              example: 35
                            width:
                              type: number
                              example: 45
                            length:
                              type: number
                              example: 60
                        carton_label:
                          type: string
                          nullable: true
                          example: C-001
                        sizes:
                          type: array
                          items:
                            type: object
                            required:
                            - size_code
                            - quantity
                            properties:
                              size_code:
                                type: string
                                example: M
                              quantity:
                                type: integer
                                minimum: 0
                                example: 240
              example:
                op_id: 6297
                boxes:
                - box_number: 1
                  total_finished_garments: 34.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 2
                  total_finished_garments: 60.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 3
                  total_finished_garments: 60.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 4
                  total_finished_garments: 60.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 5
                  total_finished_garments: 46.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 6
                  total_finished_garments: 54.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 7
                  total_finished_garments: 54.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 8
                  total_finished_garments: 54.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 9
                  total_finished_garments: 54.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 10
                  total_finished_garments: 54.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 11
                  total_finished_garments: 45.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 12
                  total_finished_garments: 51.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 13
                  total_finished_garments: 51.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 14
                  total_finished_garments: 51.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 15
                  total_finished_garments: 43.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 16
                  total_finished_garments: 50.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 17
                  total_finished_garments: 30.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 18
                  total_finished_garments: 60.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 19
                  total_finished_garments: 60.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 20
                  total_finished_garments: 60.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 21
                  total_finished_garments: 46.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 22
                  total_finished_garments: 54.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 23
                  total_finished_garments: 54.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 24
                  total_finished_garments: 54.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 25
                  total_finished_garments: 54.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 26
                  total_finished_garments: 54.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 27
                  total_finished_garments: 43.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 28
                  total_finished_garments: 51.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 29
                  total_finished_garments: 51.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 30
                  total_finished_garments: 51.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 31
                  total_finished_garments: 51.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 32
                  total_finished_garments: 48.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 33
                  total_finished_garments: 10.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 34
                  total_finished_garments: 29.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 35
                  total_finished_garments: 60.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 36
                  total_finished_garments: 60.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 37
                  total_finished_garments: 60.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 38
                  total_finished_garments: 55.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 39
                  total_finished_garments: 54.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 40
                  total_finished_garments: 54.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 41
                  total_finished_garments: 54.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 42
                  total_finished_garments: 54.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 43
                  total_finished_garments: 54.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 44
                  total_finished_garments: 56.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 45
                  total_finished_garments: 51.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 46
                  total_finished_garments: 51.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 47
                  total_finished_garments: 51.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 48
                  total_finished_garments: 34.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
                - box_number: 49
                  total_finished_garments: 42.0
                  gross_weight_kg: 0.0
                  gross_weight_from_scale: false
                  net_weight_kg: -1.4
                  box_tare_kg: 1.4
                  dimensions_cm:
                    height: 26.0
                    width: 40.0
                    length: 88.0
                  carton_label: 1
                  sizes: []
        4XX:
          description: 'Errores del cliente — agrupados.


            - **400** parámetros inválidos (formato, tipo, requeridos).

            - **401** token ausente o inválido. El cliente refresca y reintenta una vez.

            - **403** token válido pero scope insuficiente.

            - **404** recurso no encontrado. Tratar como ausencia, no como error.

            - **409** conflicto (ej. `partida` duplicada sin `supplier_ruc`).

            - **429** rate limit superado. Respeta `Retry-After`.'
          headers:
            Retry-After:
              schema:
                type: integer
              description: Solo en 429.
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
        5XX:
          description: 'Errores del servidor — agrupados.


            - **500** error interno. Cliente reintenta con backoff (máx. 3).

            - **503** indisponible o `replication_lag_seconds > 600` (10 min). Respeta `Retry-After`.'
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
  /production-orders/{op_id}/packing-list:
    get:
      summary: PK-2 · Packing list por OP (P2)
      description: ''
      tags:
      - Packing y Despacho
      operationId: getPackingListByOp
      parameters:
      - name: op_id
        in: path
        required: true
        description: trento.UdpOrdenProduccion.IdOrdenProduccion (entero, PK).
        schema:
          type: integer
        example: 6223
      security:
      - bearerAuth:
        - read:packing
      - apiKey: []
      responses:
        '200':
          description: Packing list.
          content:
            application/json:
              schema:
                type: object
                properties:
                  op_id:
                    type: integer
                    example: 6223
                  packing_list:
                    type: object
                    properties:
                      code:
                        type: string
                        example: PL-2026-0042
                      shipment_date:
                        type: string
                        format: date
                        nullable: true
                        example: '2026-06-10'
                      total_boxes:
                        type: integer
                        example: 22
                      consolidated_transfer_id:
                        type: integer
                        nullable: true
                        example: 8812
              example:
                op_id: 6297
                packing_list:
                  code: PALIST - 0001716
                  shipment_date: '2026-01-16'
                  consolidated_transfer_id: 2722
                  total_boxes: 49
        4XX:
          description: 'Errores del cliente — agrupados.


            - **400** parámetros inválidos (formato, tipo, requeridos).

            - **401** token ausente o inválido. El cliente refresca y reintenta una vez.

            - **403** token válido pero scope insuficiente.

            - **404** recurso no encontrado. Tratar como ausencia, no como error.

            - **409** conflicto (ej. `partida` duplicada sin `supplier_ruc`).

            - **429** rate limit superado. Respeta `Retry-After`.'
          headers:
            Retry-After:
              schema:
                type: integer
              description: Solo en 429.
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
        5XX:
          description: 'Errores del servidor — agrupados.


            - **500** error interno. Cliente reintenta con backoff (máx. 3).

            - **503** indisponible o `replication_lag_seconds > 600` (10 min). Respeta `Retry-After`.'
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
  /production-orders/{op_id}/shipment-program:
    get:
      summary: PK-3 · Programa de embarque (P2)
      description: '`actual_dispatched` puede venir 0; `destination_id = 0` se trata como ausencia.'
      tags:
      - Packing y Despacho
      operationId: getShipmentProgramByOp
      parameters:
      - name: op_id
        in: path
        required: true
        description: trento.UdpOrdenProduccion.IdOrdenProduccion (entero, PK).
        schema:
          type: integer
        example: 6223
      security:
      - bearerAuth:
        - read:packing
      - apiKey: []
      responses:
        '200':
          description: Programa.
          content:
            application/json:
              schema:
                type: object
                properties:
                  op_id:
                    type: integer
                    example: 6223
                  planned_shipment_date:
                    type: string
                    format: date
                    nullable: true
                    example: '2026-07-15'
                  actual_shipment_date:
                    type: string
                    format: date
                    nullable: true
                    example: '2026-07-12'
                  destination_country_code:
                    type: string
                    nullable: true
                    example: DE
                  destination_id:
                    type: integer
                    nullable: true
                    example: 412
                    description: 0 se trata como ausencia.
                  transport_mode_id:
                    type: integer
                    nullable: true
                    example: 2
                  tolerance_pct:
                    type: number
                    nullable: true
                    example: 5
                  quantity_planned:
                    type: integer
                    nullable: true
                    example: 640
                  quantity_dispatched:
                    type: integer
                    nullable: true
                    example: 638
                  actual_dispatched:
                    type: integer
                    nullable: true
                    example: 0
                    description: En piloto suele venir 0.
                  qlever_po_number:
                    type: string
                    nullable: true
                    example: OC-Q-2026-0042
              example:
                op_id: 6297
                planned_shipment_date: '2026-01-16'
                actual_shipment_date: '2026-01-16'
                destination_country_code: null
                destination_id: 0
                transport_mode_id: 627
                tolerance_pct: 5.0
                quantity_planned: 800.0
                quantity_dispatched: 800.0
                actual_dispatched: 0.0
                qlever_po_number: null
        4XX:
          description: 'Errores del cliente — agrupados.


            - **400** parámetros inválidos (formato, tipo, requeridos).

            - **401** token ausente o inválido. El cliente refresca y reintenta una vez.

            - **403** token válido pero scope insuficiente.

            - **404** recurso no encontrado. Tratar como ausencia, no como error.

            - **409** conflicto (ej. `partida` duplicada sin `supplier_ruc`).

            - **429** rate limit superado. Respeta `Retry-After`.'
          headers:
            Retry-After:
              schema:
                type: integer
              description: Solo en 429.
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
        5XX:
          description: 'Errores del servidor — agrupados.


            - **500** error interno. Cliente reintenta con backoff (máx. 3).

            - **503** indisponible o `replication_lag_seconds > 600` (10 min). Respeta `Retry-After`.'
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
  /production-orders/{op_id}/sewing-dispatches:
    get:
      summary: IN-1 · Despachos a costura por OP (P2)
      description: CP6.
      tags:
      - Costura e Inspección
      operationId: getSewingDispatchesByOp
      parameters:
      - name: op_id
        in: path
        required: true
        description: trento.UdpOrdenProduccion.IdOrdenProduccion (entero, PK).
        schema:
          type: integer
        example: 6223
      security:
      - bearerAuth:
        - read:inspection
      - apiKey: []
      responses:
        '200':
          description: Despachos.
          content:
            application/json:
              schema:
                type: object
                properties:
                  op_id:
                    type: integer
                    example: 6223
                  dispatches:
                    type: array
                    items:
                      type: object
                      properties:
                        destination_id:
                          type: integer
                          nullable: true
                          example: 33
                        destination_name:
                          type: string
                          nullable: true
                          example: Taller Costura San Juan
                        total_garments_sewn:
                          type: integer
                          nullable: true
                          example: 638
                        sewing_date:
                          type: string
                          format: date
                          nullable: true
                          example: '2026-05-05'
                        total_boxes:
                          type: integer
                          nullable: true
                          example: 22
                        total_bundles:
                          type: integer
                          nullable: true
                          example: 110
              example:
                op_id: 6297
                dispatches:
                - destination_id: 1299
                  total_garments_sewn: 840.0
                  sewing_date: '2025-12-23'
                  total_boxes: 0.0
                  total_bundles: 0.0
                  destination_name: null
                - destination_id: 1299
                  total_garments_sewn: 842.0
                  sewing_date: '2025-12-26'
                  total_boxes: 0.0
                  total_bundles: 0.0
                  destination_name: null
                - destination_id: 1299
                  total_garments_sewn: 844.0
                  sewing_date: '2025-12-29'
                  total_boxes: 0.0
                  total_bundles: 0.0
                  destination_name: null
                - destination_id: 1299
                  total_garments_sewn: 840.0
                  sewing_date: '2025-12-23'
                  total_boxes: 0.0
                  total_bundles: 0.0
                  destination_name: null
                - destination_id: 1299
                  total_garments_sewn: 842.0
                  sewing_date: '2025-12-26'
                  total_boxes: 0.0
                  total_bundles: 0.0
                  destination_name: null
                - destination_id: 1299
                  total_garments_sewn: 844.0
                  sewing_date: '2025-12-29'
                  total_boxes: 0.0
                  total_bundles: 0.0
                  destination_name: null
                - destination_id: 1299
                  total_garments_sewn: 840.0
                  sewing_date: '2025-12-23'
                  total_boxes: 0.0
                  total_bundles: 0.0
                  destination_name: null
                - destination_id: 1299
                  total_garments_sewn: 842.0
                  sewing_date: '2025-12-26'
                  total_boxes: 0.0
                  total_bundles: 0.0
                  destination_name: null
                - destination_id: 1299
                  total_garments_sewn: 844.0
                  sewing_date: '2025-12-29'
                  total_boxes: 0.0
                  total_bundles: 0.0
                  destination_name: null
        4XX:
          description: 'Errores del cliente — agrupados.


            - **400** parámetros inválidos (formato, tipo, requeridos).

            - **401** token ausente o inválido. El cliente refresca y reintenta una vez.

            - **403** token válido pero scope insuficiente.

            - **404** recurso no encontrado. Tratar como ausencia, no como error.

            - **409** conflicto (ej. `partida` duplicada sin `supplier_ruc`).

            - **429** rate limit superado. Respeta `Retry-After`.'
          headers:
            Retry-After:
              schema:
                type: integer
              description: Solo en 429.
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
        5XX:
          description: 'Errores del servidor — agrupados.


            - **500** error interno. Cliente reintenta con backoff (máx. 3).

            - **503** indisponible o `replication_lag_seconds > 600` (10 min). Respeta `Retry-After`.'
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
  /production-orders/{op_id}/finished-garments:
    get:
      summary: IN-2 · Prendas terminadas / inspecciones por OP (P2, con gap)
      description: Para OPs piloto 6223–6230 devolver array vacío sin error.
      tags:
      - Costura e Inspección
      operationId: getFinishedGarmentsByOp
      parameters:
      - name: op_id
        in: path
        required: true
        description: trento.UdpOrdenProduccion.IdOrdenProduccion (entero, PK).
        schema:
          type: integer
        example: 6223
      security:
      - bearerAuth:
        - read:inspection
      - apiKey: []
      responses:
        '200':
          description: Inspecciones.
          content:
            application/json:
              schema:
                type: object
                properties:
                  op_id:
                    type: integer
                    example: 6223
                  finished_garments:
                    type: array
                    items:
                      type: object
                      properties:
                        finished_garment_id:
                          type: integer
                          example: 121345
                        inspection_date:
                          type: string
                          format: date
                          nullable: true
                          example: '2026-05-20'
                    description: Para OPs piloto 6223–6230 puede devolver array vacío (gap aceptado).
              example:
                op_id: 6297
                finished_garments: []
        4XX:
          description: 'Errores del cliente — agrupados.


            - **400** parámetros inválidos (formato, tipo, requeridos).

            - **401** token ausente o inválido. El cliente refresca y reintenta una vez.

            - **403** token válido pero scope insuficiente.

            - **404** recurso no encontrado. Tratar como ausencia, no como error.

            - **409** conflicto (ej. `partida` duplicada sin `supplier_ruc`).

            - **429** rate limit superado. Respeta `Retry-After`.'
          headers:
            Retry-After:
              schema:
                type: integer
              description: Solo en 429.
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
        5XX:
          description: 'Errores del servidor — agrupados.


            - **500** error interno. Cliente reintenta con backoff (máx. 3).

            - **503** indisponible o `replication_lag_seconds > 600` (10 min). Respeta `Retry-After`.'
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: object
                    required:
                    - code
                    - message
                    properties:
                      code:
                        type: string
                        example: production_order_not_found
                      message:
                        type: string
                        example: OP 9999 no existe en Trento Core.
                      details:
                        type: object
                        additionalProperties: true
                      request_id:
                        type: string
                        example: req_abc123
components:
  schemas:
    ErrorResponse:
      type: object
      required:
      - error
      properties:
        error:
          type: object
          required:
          - code
          - message
          properties:
            code:
              type: string
              example: production_order_not_found
            message:
              type: string
              example: OP 9999 no existe en Trento Core.
            details:
              type: object
              additionalProperties: true
            request_id:
              type: string
              example: req_abc123
    PaginationMeta:
      type: object
      required:
      - page
      - limit
      - has_more
      properties:
        page:
          type: integer
          minimum: 1
          example: 2
        limit:
          type: integer
          minimum: 1
          maximum: 200
          example: 50
        total:
          type: integer
          nullable: true
          example: 312
        has_more:
          type: boolean
          example: true
    Product:
      type: object
      required:
      - id
      - code
      properties:
        id:
          type: integer
          example: 12345
          description: trento.TblProductos.IdProducto
        code:
          type: string
          example: TELA-PIMA-185
        productive_description:
          type: string
          example: Jersey Pima 185g 93% Algodón Pima 7% Spandex
        commercial_description:
          type: string
          example: Pima 100% premium
        supplier_id:
          type: integer
          nullable: true
          example: 9087
        fabric_type:
          type: string
          example: JERSEY
    Style:
      type: object
      required:
      - id
      - code
      properties:
        id:
          type: integer
          example: 4421
        code:
          type: string
          example: P-12345
        description:
          type: string
          example: Polo manga corta Pima
        default_color_id:
          type: integer
          nullable: true
          example: 88
    Color:
      type: object
      required:
      - id
      - code
      properties:
        id:
          type: integer
          example: 88
        code:
          type: string
          example: BLANCO
        description:
          type: string
          example: Blanco óptico
        pantone:
          type: string
          nullable: true
          example: 11-0601 TPX
    Supplier:
      type: object
      required:
      - id
      - ruc
      - legal_name
      properties:
        id:
          type: integer
          example: 9087
          description: trento.Persona.IdPersona
        ruc:
          type: string
          example: '20512345678'
          description: trento.Persona.CodPersona
        legal_name:
          type: string
          example: Hilanderías del Sur S.A.C.
        address:
          type: string
          nullable: true
          example: Av. Industrial 123, Lima, Perú
        country_code:
          type: string
          nullable: true
          example: PE
          minLength: 2
          maxLength: 2
        tier:
          type: string
          nullable: true
          enum:
          - fabric_supplier
          - laundry_supplier
          - fiber_supplier
          - accessories_supplier
          - null
          example: fabric_supplier
    ClientByOp:
      type: object
      required:
      - op_id
      - client_name
      properties:
        op_id:
          type: integer
          example: 6223
        client_name:
          type: string
          example: Brand X Apparel Ltd.
        client_brand:
          type: string
          nullable: true
          example: BX-Athleisure
        style_code:
          type: string
          nullable: true
          example: P-12345
    SizeDistributionEntry:
      type: object
      required:
      - size_code
      - quantity
      properties:
        size_code:
          type: string
          example: M
        quantity:
          type: integer
          minimum: 0
          example: 240
    SizeDistribution:
      type: object
      required:
      - op_id
      - distribution
      - total
      properties:
        op_id:
          type: integer
          example: 6223
        production_order_code:
          type: string
          example: '6223'
        distribution:
          type: array
          items:
            $ref: '#/components/schemas/SizeDistributionEntry'
        total:
          type: integer
          minimum: 0
          example: 640
    MaterialEntry:
      type: object
      required:
      - material
      - percentage
      properties:
        material:
          type: string
          example: cotton
        percentage:
          type: number
          minimum: 0
          maximum: 100
          example: 93
        organic:
          type: boolean
          example: true
        iso_2076_code:
          type: string
          example: CO
          description: ISO 2076 fibre code
    MaterialComposition:
      type: object
      required:
      - op_id
      - composition
      properties:
        op_id:
          type: integer
          example: 6223
        composition:
          type: array
          items:
            $ref: '#/components/schemas/MaterialEntry'
        total_percentage:
          type: number
          example: 100
        raw_source_string:
          type: string
          nullable: true
          example: 93% PIMA COTTON ORGANICO 7% SPANDEX
    PurchaseOrder:
      type: object
      required:
      - id
      - code
      properties:
        id:
          type: integer
          example: 87123
        code:
          type: string
          example: PO-2026-0042
        planned_shipment_date:
          type: string
          format: date
          nullable: true
          example: '2026-07-15'
        tolerance_pct:
          type: number
          nullable: true
          example: 5
        destination_country_code:
          type: string
          nullable: true
          example: DE
        destination_id:
          type: integer
          nullable: true
          example: 412
        transport_mode_id:
          type: integer
          nullable: true
          example: 2
    OpLine:
      type: object
      required:
      - color_id
      - size_code
      - quantity
      properties:
        color_id:
          type: integer
          example: 88
        size_code:
          type: string
          example: M
        quantity:
          type: integer
          minimum: 0
          example: 60
    ProductionOrder:
      type: object
      required:
      - id
      - code
      properties:
        id:
          type: integer
          example: 6223
          description: trento.UdpOrdenProduccion.IdOrdenProduccion
        code:
          type: string
          example: '6223'
        purchase_order:
          $ref: '#/components/schemas/PurchaseOrder'
        style:
          type: object
          properties:
            id:
              type: integer
              example: 4421
            code:
              type: string
              example: P-12345
            description:
              type: string
              example: Polo manga corta Pima
            technical_sheet_id:
              type: integer
              nullable: true
              example: 1572
        fabric_product_id:
          type: integer
          nullable: true
          example: 12345
        client:
          type: object
          properties:
            id:
              type: integer
              example: 33
            name:
              type: string
              example: Brand X Apparel Ltd.
            brand:
              type: string
              nullable: true
              example: BX-Athleisure
        season:
          type: string
          nullable: true
          example: SS-2026
        created_at:
          type: string
          format: date-time
          example: '2026-03-12T10:14:00-05:00'
        lines:
          type: array
          items:
            $ref: '#/components/schemas/OpLine'
    ProductionOrderSummary:
      type: object
      required:
      - id
      - code
      properties:
        id:
          type: integer
          example: 6223
        code:
          type: string
          example: '6223'
        client_id:
          type: integer
          nullable: true
          example: 33
        client_name:
          type: string
          nullable: true
          example: Brand X Apparel Ltd.
        status:
          type: string
          enum:
          - active
          - closed
          - despatched
          example: active
        created_at:
          type: string
          format: date-time
    ProductionOrdersList:
      allOf:
      - $ref: '#/components/schemas/PaginationMeta'
      - type: object
        required:
        - items
        properties:
          items:
            type: array
            items:
              $ref: '#/components/schemas/ProductionOrderSummary'
    CuttingOrder:
      type: object
      required:
      - id
      - code
      properties:
        id:
          type: integer
          example: 901
        code:
          type: string
          example: HC-6223-01
        cutting_program_id:
          type: integer
          nullable: true
          example: 514
        cutting_date:
          type: string
          format: date
          nullable: true
          example: '2026-04-12'
        total_units_cut:
          type: integer
          nullable: true
          example: 320
        sizes:
          type: array
          items:
            $ref: '#/components/schemas/SizeDistributionEntry'
    CuttingOrdersResponse:
      type: object
      required:
      - op_id
      - cutting_orders
      properties:
        op_id:
          type: integer
          example: 6223
        cutting_orders:
          type: array
          items:
            $ref: '#/components/schemas/CuttingOrder'
    SizeAnalysisEntry:
      type: object
      properties:
        color_id:
          type: integer
          example: 88
        total_planned:
          type: integer
          example: 320
        total_original_order:
          type: integer
          example: 320
        by_size:
          type: array
          items:
            type: object
            properties:
              size_code:
                type: string
                example: S
              planned:
                type: integer
                example: 60
              original:
                type: integer
                example: 60
    SizeAnalysis:
      type: object
      required:
      - op_id
      - analysis
      properties:
        op_id:
          type: integer
          example: 6223
        analysis:
          type: array
          items:
            $ref: '#/components/schemas/SizeAnalysisEntry'
    CuttingClosure:
      type: object
      properties:
        op_id:
          type: integer
          example: 6223
        enabled_date:
          type: string
          format: date
          nullable: true
          example: '2026-04-20'
        consumption_types_present:
          type: array
          items:
            type: integer
          example:
          - 1
          - 2
          - 3
    ConsumptionSheetItem:
      type: object
      properties:
        consumption_type:
          type: integer
          example: 1
        label:
          type: string
          enum:
          - fabric
          - accessories
          - packaging
          - other
          example: fabric
        consumption_per_unit:
          type: number
          nullable: true
          example: 0.45
        unit:
          type: string
          nullable: true
          example: kg/garment
    ConsumptionSheet:
      type: object
      required:
      - op_id
      - sheets
      properties:
        op_id:
          type: integer
          example: 6223
        sheets:
          type: array
          items:
            $ref: '#/components/schemas/ConsumptionSheetItem'
    FabricLotDetail:
      type: object
      properties:
        lot_detail_number:
          type: string
          example: P-2026-3344-A
        weight_kg:
          type: number
          example: 422.8
    FabricReceiptHeader:
      type: object
      properties:
        receipt_id:
          type: integer
          example: 50211
        lot_number_header:
          type: string
          example: P-2026-3344
        reception_date:
          type: string
          format: date
          example: '2026-04-05'
        reception_time:
          type: string
          example: '10:23:00'
        total_weight_kg:
          type: number
          nullable: true
          example: 845.6
        fabric_width_cm:
          type: number
          nullable: true
          example: 152.4
        fabric_density_gsm:
          type: number
          nullable: true
          example: 185
        shrinkage_width_pct:
          type: number
          nullable: true
          example: -3.2
        shrinkage_length_pct:
          type: number
          nullable: true
          example: -4.1
        lots:
          type: array
          items:
            $ref: '#/components/schemas/FabricLotDetail'
    FabricReceiptsByOp:
      type: object
      required:
      - op_id
      - receipts
      properties:
        op_id:
          type: integer
          example: 6223
        production_order_code:
          type: string
          example: '6223'
        fabric_purchase_order:
          $ref: '#/components/schemas/PurchaseOrder'
        supplier:
          $ref: '#/components/schemas/Supplier'
        fabric:
          $ref: '#/components/schemas/Product'
        receipts:
          type: array
          items:
            $ref: '#/components/schemas/FabricReceiptHeader'
        consumption_per_unit_kg:
          type: number
          nullable: true
          example: 0.45
        material_composition_raw:
          type: string
          nullable: true
          example: 93% PIMA COTTON ORGANICO 7% SPANDEX
    FabricReceiptDetail:
      allOf:
      - $ref: '#/components/schemas/FabricReceiptHeader'
      - type: object
        properties:
          op_id:
            type: integer
            example: 6223
          supplier_id:
            type: integer
            example: 9087
    PartidaLookup:
      type: object
      required:
      - partida
      - op_id
      properties:
        partida:
          type: string
          example: P-2026-3344-A
        op_id:
          type: integer
          example: 6223
        production_order_code:
          type: string
          example: '6223'
        receipt_id:
          type: integer
          example: 50211
        lot_detail_number:
          type: string
          example: P-2026-3344-A
        weight_kg:
          type: number
          nullable: true
          example: 422.8
        supplier_ruc:
          type: string
          example: '20512345678'
    FabricLotSummaryItem:
      type: object
      properties:
        lot_number:
          type: string
          example: P-2026-3344
        weight_kg:
          type: number
          example: 845.6
        lot_details_count:
          type: integer
          example: 2
    FabricLotsSummary:
      type: object
      properties:
        op_id:
          type: integer
          example: 6223
        lots:
          type: array
          items:
            $ref: '#/components/schemas/FabricLotSummaryItem'
    Accessory:
      type: object
      properties:
        code:
          type: string
          example: 115-A
          description: Códigos como `115` pueden venir splitted en `115-A`/`115-B`.
        description:
          type: string
          example: Bolsa de polietileno
        quantity_per_garment:
          type: number
          example: 1
    Accessories:
      type: object
      properties:
        style:
          type: string
          example: P-12345
        color:
          type: string
          example: BLANCO
        accessories:
          type: array
          items:
            $ref: '#/components/schemas/Accessory'
    LaundryMovementItem:
      type: object
      properties:
        item_name:
          type: string
          example: Panos Pima 185g
        quantity:
          type: number
          example: 320
        lot_number:
          type: string
          nullable: true
          example: P-2026-3344-A
    LaundryMovement:
      type: object
      properties:
        movement_id:
          type: integer
          example: 7711
        transfer_code:
          type: string
          nullable: true
          example: TC-6223-001
        laundry_supplier_code:
          type: string
          nullable: true
          example: LAV-NORTE
        laundry_supplier_name:
          type: string
          nullable: true
          example: Lavandería del Norte S.A.C.
        warehouse_origin:
          type: string
          nullable: true
          example: PLANTA-01
        warehouse_destination:
          type: string
          nullable: true
          example: LAV-NORTE-01
        movement_date:
          type: string
          format: date
          example: '2026-04-22'
        movement_type:
          type: string
          enum:
          - S
          - I
          example: S
        guide_number:
          type: string
          nullable: true
          example: G-2026-0421
        service_description:
          type: string
          nullable: true
          example: Lavado enzimático + suavizado
        items:
          type: array
          items:
            $ref: '#/components/schemas/LaundryMovementItem'
    LaundryMovementsByOp:
      type: object
      properties:
        op_id:
          type: integer
          example: 6223
        movements:
          type: array
          items:
            $ref: '#/components/schemas/LaundryMovement'
    Box:
      type: object
      properties:
        box_number:
          type: integer
          example: 1
        total_finished_garments:
          type: integer
          example: 24
        gross_weight_kg:
          type: number
          nullable: true
          example: 0
          description: En piloto suele venir 0; ver `gross_weight_from_scale` flag.
        gross_weight_from_scale:
          type: boolean
          example: false
        net_weight_kg:
          type: number
          nullable: true
          example: 5.2
        box_tare_kg:
          type: number
          nullable: true
          example: 0.3
        dimensions_cm:
          type: object
          properties:
            height:
              type: number
              example: 35
            width:
              type: number
              example: 45
            length:
              type: number
              example: 60
        carton_label:
          type: string
          nullable: true
          example: C-001
        sizes:
          type: array
          items:
            $ref: '#/components/schemas/SizeDistributionEntry'
    BoxesByOp:
      type: object
      properties:
        op_id:
          type: integer
          example: 6223
        boxes:
          type: array
          items:
            $ref: '#/components/schemas/Box'
    PackingList:
      type: object
      properties:
        op_id:
          type: integer
          example: 6223
        packing_list:
          type: object
          properties:
            code:
              type: string
              example: PL-2026-0042
            shipment_date:
              type: string
              format: date
              nullable: true
              example: '2026-06-10'
            total_boxes:
              type: integer
              example: 22
            consolidated_transfer_id:
              type: integer
              nullable: true
              example: 8812
    ShipmentProgram:
      type: object
      properties:
        op_id:
          type: integer
          example: 6223
        planned_shipment_date:
          type: string
          format: date
          nullable: true
          example: '2026-07-15'
        actual_shipment_date:
          type: string
          format: date
          nullable: true
          example: '2026-07-12'
        destination_country_code:
          type: string
          nullable: true
          example: DE
        destination_id:
          type: integer
          nullable: true
          example: 412
          description: 0 se trata como ausencia.
        transport_mode_id:
          type: integer
          nullable: true
          example: 2
        tolerance_pct:
          type: number
          nullable: true
          example: 5
        quantity_planned:
          type: integer
          nullable: true
          example: 640
        quantity_dispatched:
          type: integer
          nullable: true
          example: 638
        actual_dispatched:
          type: integer
          nullable: true
          example: 0
          description: En piloto suele venir 0.
        qlever_po_number:
          type: string
          nullable: true
          example: OC-Q-2026-0042
    SewingDispatch:
      type: object
      properties:
        destination_id:
          type: integer
          nullable: true
          example: 33
        destination_name:
          type: string
          nullable: true
          example: Taller Costura San Juan
        total_garments_sewn:
          type: integer
          nullable: true
          example: 638
        sewing_date:
          type: string
          format: date
          nullable: true
          example: '2026-05-05'
        total_boxes:
          type: integer
          nullable: true
          example: 22
        total_bundles:
          type: integer
          nullable: true
          example: 110
    SewingDispatchesByOp:
      type: object
      properties:
        op_id:
          type: integer
          example: 6223
        dispatches:
          type: array
          items:
            $ref: '#/components/schemas/SewingDispatch'
    FinishedGarment:
      type: object
      properties:
        finished_garment_id:
          type: integer
          example: 121345
        inspection_date:
          type: string
          format: date
          nullable: true
          example: '2026-05-20'
    FinishedGarmentsByOp:
      type: object
      properties:
        op_id:
          type: integer
          example: 6223
        finished_garments:
          type: array
          items:
            $ref: '#/components/schemas/FinishedGarment'
          description: Para OPs piloto 6223–6230 puede devolver array vacío (gap aceptado).
    HealthStatus:
      type: object
      properties:
        status:
          type: string
          enum:
          - ok
          - degraded
          - down
          example: ok
        replication_lag_seconds:
          type: integer
          example: 12
        version:
          type: string
          example: 1.0.4
        build:
          type: string
          format: date-time
          example: '2026-05-12T18:00:00Z'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: 'OAuth 2.0 client credentials grant. Scopes: read:masters, read:production-orders, read:fabric-receipts,
        read:laundry, read:packing, read:inspection, read:accessories.'
    apiKey:
      type: apiKey
      in: header
      name: X-API-Key
      description: Alternativa para v1 si no se implementa OAuth.
