openapi: 3.1.0
info:
  title: Medware API v1
  version: 1.0.0
  description: >-
    API publica read-only por tenant de Medware, autenticada por API key
    (header x-api-key). Cada llamada opera sobre los datos del tenant dueno de
    la llave. Importes monetarios en centavos (enteros); fechas en ISO 8601 UTC;
    los campos opcionales se omiten cuando no aplican.
servers:
  - url: https://api.medware.example/v1
    description: Host placeholder. El host real lo enruta el gateway publico por prefijo de servicio.
security:
  - ApiKeyAuth: []
tags:
  - name: Inventory
    description: Existencias del tenant agregadas por producto/lote.
  - name: WMS
    description: Tareas de piso de almacen para un WCS externo, y confirmacion de ejecucion.
  - name: Catalog
    description: Catalogo de productos del tenant con atributos farmaceuticos/SAT.
  - name: Sales
    description: Documentos comerciales (cotizacion, pedido, remision) del tenant.
  - name: Pricing
    description: Listas de precios y precios por producto del tenant.
  - name: Customers
    description: Maestro de personas/clientes del tenant.
  - name: Facturacion
    description: CFDIs emitidos por el tenant (metadatos; sin XML ni sello crudos).
paths:
  /inventory/stock:
    get:
      operationId: getInventoryStock
      summary: Existencias del tenant
      tags:
        - Inventory
      responses:
        '200':
          description: Lista de existencias agregadas por producto/lote.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/InventoryStock'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /wms/tasks:
    get:
      operationId: listWmsTasks
      summary: Tareas de almacen para el WCS
      description: >-
        Sin ?status= devuelve las tareas abiertas (pending + assigned). Con
        ?status= filtra por ese estado.
      tags:
        - WMS
      parameters:
        - name: status
          in: query
          required: false
          description: Filtra por estado de la tarea.
          schema:
            type: string
            enum:
              - pending
              - assigned
              - in_progress
              - done
              - cancelled
      responses:
        '200':
          description: Lista de tareas de almacen.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/WmsTask'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /wms/tasks/{id}/confirm:
    post:
      operationId: confirmWmsTask
      summary: Confirmar ejecucion de una tarea
      description: >-
        El WCS confirma la ejecucion de una tarea. Aplica el movimiento de stock
        por bin correspondiente y devuelve la tarea actualizada.
      tags:
        - WMS
      parameters:
        - $ref: '#/components/parameters/IdPath'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WmsTaskConfirm'
      responses:
        '200':
          description: Tarea actualizada.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WmsTask'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /catalog/products:
    get:
      operationId: listCatalogProducts
      summary: Productos del tenant
      tags:
        - Catalog
      responses:
        '200':
          description: Lista de productos del catalogo.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/CatalogProduct'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /sales/documents:
    get:
      operationId: listSalesDocuments
      summary: Documentos comerciales del tenant
      tags:
        - Sales
      parameters:
        - name: type
          in: query
          required: false
          description: Filtra por tipo de documento.
          schema:
            type: string
            enum:
              - quotation
              - order
              - remission
      responses:
        '200':
          description: Lista de documentos comerciales.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/SalesDocument'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /sales/documents/{id}:
    get:
      operationId: getSalesDocument
      summary: Un documento comercial con sus lineas
      tags:
        - Sales
      parameters:
        - $ref: '#/components/parameters/IdPath'
      responses:
        '200':
          description: Documento comercial con su detalle de lineas.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SalesDocumentDetail'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /pricing/lists:
    get:
      operationId: listPriceLists
      summary: Listas de precios del tenant
      tags:
        - Pricing
      responses:
        '200':
          description: Lista de listas de precios.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/PriceList'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /pricing/prices:
    get:
      operationId: listProductPrices
      summary: Precios por (lista, producto)
      description: Ambos query params son obligatorios.
      tags:
        - Pricing
      parameters:
        - name: priceListId
          in: query
          required: true
          description: Id de la lista de precios.
          schema:
            type: string
            format: uuid
        - name: productId
          in: query
          required: true
          description: Id del producto.
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Lista de precios para la (lista, producto) indicada.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/ProductPrice'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /customers:
    get:
      operationId: listCustomers
      summary: Personas/clientes del tenant
      tags:
        - Customers
      responses:
        '200':
          description: Lista de personas/clientes.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Customer'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /customers/{id}:
    get:
      operationId: getCustomer
      summary: Una persona/cliente por id
      tags:
        - Customers
      parameters:
        - $ref: '#/components/parameters/IdPath'
      responses:
        '200':
          description: Persona/cliente.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Customer'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /facturacion/cfdis:
    get:
      operationId: listCfdis
      summary: CFDIs emitidos por el tenant
      tags:
        - Facturacion
      parameters:
        - name: status
          in: query
          required: false
          description: Filtra por estado del CFDI.
          schema:
            type: string
      responses:
        '200':
          description: Lista de CFDIs.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Cfdi'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /facturacion/cfdis/{id}:
    get:
      operationId: getCfdi
      summary: Un CFDI por id
      tags:
        - Facturacion
      parameters:
        - $ref: '#/components/parameters/IdPath'
      responses:
        '200':
          description: CFDI.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Cfdi'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
  parameters:
    IdPath:
      name: id
      in: path
      required: true
      description: Identificador del recurso.
      schema:
        type: string
        format: uuid
  responses:
    Unauthorized:
      description: API key ausente, invalida o revocada.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    NotFound:
      description: Recurso no encontrado.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  schemas:
    Error:
      type: object
      description: Formato de error estandar de Nest.
      properties:
        statusCode:
          type: integer
        message:
          type: string
        error:
          type: string
      required:
        - statusCode
        - message
    InventoryStock:
      type: object
      description: Linea de existencias agregada por producto/lote.
      properties:
        productId:
          type: string
          format: uuid
        sku:
          type: string
        lot:
          type: string
        expiry:
          type: string
          format: date
        quantity:
          type: integer
      required:
        - productId
        - quantity
    WmsTask:
      type: object
      description: Tarea de piso de almacen que un WCS debe ejecutar.
      properties:
        id:
          type: string
          format: uuid
        type:
          type: string
          enum:
            - pick
            - putaway
            - replenish
            - count
            - transfer
        status:
          type: string
          enum:
            - pending
            - assigned
            - in_progress
            - done
            - cancelled
        lotRef:
          type: string
        productRef:
          type: string
          format: uuid
        fromLocationId:
          type: string
          format: uuid
        toLocationId:
          type: string
          format: uuid
        qty:
          type: integer
        assignedTo:
          type: string
          format: uuid
      required:
        - id
        - type
        - status
        - lotRef
    WmsTaskConfirm:
      type: object
      description: Body de confirmacion de una tarea. locationId y lotRef son opcionales segun el tipo de tarea.
      properties:
        qty:
          type: integer
        locationId:
          type: string
          format: uuid
        lotRef:
          type: string
      required:
        - qty
    CatalogProduct:
      type: object
      description: Producto del catalogo con atributos farmaceuticos/SAT.
      properties:
        id:
          type: string
          format: uuid
        sku:
          type: string
        name:
          type: string
        unit:
          type: string
        controlled:
          type: boolean
        requiresPrescription:
          type: boolean
        description:
          type: string
        form:
          type: string
        satClaveProdServ:
          type: string
        satClaveUnidad:
          type: string
        satObjetoImp:
          type: string
      required:
        - id
        - sku
        - name
        - unit
        - controlled
        - requiresPrescription
    SalesDocument:
      type: object
      description: Documento comercial (cotizacion/pedido/remision).
      properties:
        id:
          type: string
          format: uuid
        type:
          type: string
          enum:
            - quotation
            - order
            - remission
        status:
          type: string
          enum:
            - open
            - converted
            - cancelled
        customerId:
          type: string
          format: uuid
        currency:
          type: string
        subtotalCents:
          type: integer
        discountCents:
          type: integer
        taxCents:
          type: integer
        totalCents:
          type: integer
        createdAt:
          type: string
          format: date-time
      required:
        - id
        - type
        - status
        - currency
        - subtotalCents
        - discountCents
        - taxCents
        - totalCents
        - createdAt
    SalesDocumentDetail:
      type: object
      description: Documento comercial con sus lineas de detalle.
      properties:
        id:
          type: string
          format: uuid
        type:
          type: string
          enum:
            - quotation
            - order
            - remission
        status:
          type: string
          enum:
            - open
            - converted
            - cancelled
        customerId:
          type: string
          format: uuid
        currency:
          type: string
        subtotalCents:
          type: integer
        discountCents:
          type: integer
        taxCents:
          type: integer
        totalCents:
          type: integer
        createdAt:
          type: string
          format: date-time
        lines:
          type: array
          items:
            $ref: '#/components/schemas/SalesDocumentLine'
      required:
        - id
        - type
        - status
        - currency
        - subtotalCents
        - discountCents
        - taxCents
        - totalCents
        - createdAt
        - lines
    SalesDocumentLine:
      type: object
      description: Linea de un documento comercial.
      properties:
        productId:
          type: string
          format: uuid
        qty:
          type: integer
        unitPriceCents:
          type: integer
        discountCents:
          type: integer
        taxCents:
          type: integer
        lineTotalCents:
          type: integer
        lotNumber:
          type: string
      required:
        - productId
        - qty
        - unitPriceCents
        - discountCents
        - taxCents
        - lineTotalCents
    PriceList:
      type: object
      description: Lista de precios del tenant.
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
        code:
          type: string
        currency:
          type: string
        active:
          type: boolean
      required:
        - id
        - name
        - code
        - currency
        - active
    ProductPrice:
      type: object
      description: Precio de un producto dentro de una lista.
      properties:
        id:
          type: string
          format: uuid
        listId:
          type: string
          format: uuid
        productId:
          type: string
          format: uuid
        priceCents:
          type: integer
        active:
          type: boolean
        branchId:
          type: string
          format: uuid
        validFrom:
          type: string
          format: date
        validTo:
          type: string
          format: date
      required:
        - id
        - listId
        - productId
        - priceCents
        - active
    Customer:
      type: object
      description: Persona/cliente del tenant (person master).
      properties:
        id:
          type: string
          format: uuid
        fullName:
          type: string
        roles:
          type: array
          items:
            type: string
            enum:
              - customer
              - patient
              - healthcare_provider
              - employee
              - subscriber
        email:
          type: string
        phone:
          type: string
        externalRef:
          type: string
      required:
        - id
        - fullName
        - roles
    Cfdi:
      type: object
      description: CFDI emitido por el tenant. No expone XML ni sello crudos.
      properties:
        id:
          type: string
          format: uuid
        cfdiType:
          type: string
          description: I (ingreso), E (egreso), etc.
        status:
          type: string
        receiverRfc:
          type: string
        receiverName:
          type: string
        currency:
          type: string
        totalCents:
          type: integer
        uuid:
          type: string
          description: Folio fiscal, presente al timbrar.
        stampedAt:
          type: string
          format: date-time
        createdAt:
          type: string
          format: date-time
      required:
        - id
        - cfdiType
        - status
        - receiverRfc
        - receiverName
        - currency
        - totalCents
        - createdAt
