openapi: 3.0.3
info:
  title: WMS API
  version: 0.1.0
  description: Endpoints de Armazéns, Bins, Inventário, Tracking e Mobile Collector.
servers:
  - url: http://localhost:8000
    description: Servidor local
tags:
  - name: Warehouses
  - name: Bins
  - name: Inventory
  - name: Tracking
  - name: Mobile
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
    apiKey:
      type: apiKey
      in: header
      name: x-api-key
  parameters:
    TenantHeader:
      name: x-tenant-id
      in: header
      required: true
      schema:
        type: string
      description: Identificador do tenant (ex. default)
    Page:
      name: page
      in: query
      schema:
        type: integer
        minimum: 1
      description: Página de resultados
    PerPage:
      name: per_page
      in: query
      schema:
        type: integer
        minimum: 1
        maximum: 100
      description: Itens por página
    Sort:
      name: sort
      in: query
      schema:
        type: string
        enum: [id, name, region, status, created_at]
    Order:
      name: order
      in: query
      schema:
        type: string
        enum: [asc, desc]
  schemas:
    Warehouse:
      type: object
      properties:
        id: { type: integer }
        name: { type: string }
        region: { type: string, nullable: true }
        status: { type: string, enum: [active, inactive] }
        location: { type: string, nullable: true }
        zones:
          type: array
          items: { type: string }
          nullable: true
        created_at: { type: string, format: date-time }
    Bin:
      type: object
      properties:
        id: { type: integer }
        warehouse_id: { type: integer }
        code: { type: string }
        description: { type: string, nullable: true }
    TrackingEvent:
      type: object
      properties:
        id: { type: integer }
        warehouse_id: { type: integer, nullable: true }
        type: { type: string }
        payload_json: { type: object }
        created_at: { type: string, format: date-time }
    InventorySession:
      type: object
      properties:
        id: { type: integer }
        type: { type: string }
        status: { type: string }
        created_at: { type: string, format: date-time }
    MobileIngestRequest:
      type: object
      required: [batch_id, items]
      properties:
        batch_id: { type: string }
        items:
          type: array
          items:
            type: object
            properties:
              product_id: { type: integer }
              product_code: { type: string }
              bin_id: { type: integer }
              bin_code: { type: string }
              quantity: { type: number }
    Error:
      type: object
      properties:
        error: { type: string }
paths:
  /api/wms/warehouses:
    get:
      tags: [Warehouses]
      security: [{ bearerAuth: [] }]
      parameters:
        - $ref: '#/components/parameters/TenantHeader'
        - name: q
          in: query
          schema: { type: string }
        - name: region
          in: query
          schema: { type: string }
        - name: status
          in: query
          schema: { type: string, enum: [active, inactive] }
        - name: zone
          in: query
          schema: { type: string }
        - name: start
          in: query
          schema: { type: string, format: date }
        - name: end
          in: query
          schema: { type: string, format: date }
        - $ref: '#/components/parameters/Page'
        - $ref: '#/components/parameters/PerPage'
        - $ref: '#/components/parameters/Sort'
        - $ref: '#/components/parameters/Order'
      responses:
        '200':
          description: Lista de armazéns com paginação
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items: { $ref: '#/components/schemas/Warehouse' }
                  page: { type: integer }
                  per_page: { type: integer }
                  total: { type: integer }
                  total_pages: { type: integer }
                  pending_count: { type: integer }
    post:
      tags: [Warehouses]
      security: [{ bearerAuth: [] }]
      parameters:
        - $ref: '#/components/parameters/TenantHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [name]
              properties:
                name: { type: string, minLength: 3 }
                region: { type: string }
                status: { type: string, enum: [active, inactive] }
                location: { type: string }
                zones: { type: array, items: { type: string } }
      responses:
        '201':
          description: Criado
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id: { type: integer }
        '422': { description: Dados inválidos }
  /api/wms/warehouses/filters:
    get:
      tags: [Warehouses]
      security: [{ bearerAuth: [] }]
      parameters:
        - $ref: '#/components/parameters/TenantHeader'
      responses:
        '200':
          description: Valores de filtros disponíveis
          content:
            application/json:
              schema:
                type: object
                properties:
                  regions: { type: array, items: { type: string } }
                  statuses: { type: array, items: { type: string } }
                  zones: { type: array, items: { type: string } }
  /api/wms/warehouses/{id}:
    put:
      tags: [Warehouses]
      security: [{ bearerAuth: [] }]
      parameters:
        - $ref: '#/components/parameters/TenantHeader'
        - name: id
          in: path
          required: true
          schema: { type: integer }
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name: { type: string, minLength: 3 }
                region: { type: string }
                status: { type: string, enum: [active, inactive] }
                location: { type: string }
                zones: { type: array, items: { type: string } }
      responses:
        '200': { description: Atualizado }
        '422': { description: Dados inválidos }
    delete:
      tags: [Warehouses]
      security: [{ bearerAuth: [] }]
      parameters:
        - $ref: '#/components/parameters/TenantHeader'
        - name: id
          in: path
          required: true
          schema: { type: integer }
      responses:
        '200': { description: Removido }
        '422': { description: Dados inválidos }
  /api/wms/bins:
    get:
      tags: [Bins]
      security: [{ bearerAuth: [] }]
      parameters:
        - $ref: '#/components/parameters/TenantHeader'
      responses:
        '200':
          description: Lista de bins
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items: { $ref: '#/components/schemas/Bin' }
    post:
      tags: [Bins]
      security: [{ bearerAuth: [] }]
      parameters:
        - $ref: '#/components/parameters/TenantHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [warehouse_id, code]
              properties:
                warehouse_id: { type: integer }
                code: { type: string }
                description: { type: string }
      responses:
        '201': { description: Criado }
        '422': { description: Dados inválidos }
  /api/wms/bins/{id}:
    put:
      tags: [Bins]
      security: [{ bearerAuth: [] }]
      parameters:
        - $ref: '#/components/parameters/TenantHeader'
        - name: id
          in: path
          required: true
          schema: { type: integer }
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                code: { type: string }
                description: { type: string }
      responses:
        '200': { description: Atualizado }
        '422': { description: Dados inválidos }
    delete:
      tags: [Bins]
      security: [{ bearerAuth: [] }]
      parameters:
        - $ref: '#/components/parameters/TenantHeader'
        - name: id
          in: path
          required: true
          schema: { type: integer }
      responses:
        '200': { description: Removido }
        '422': { description: Dados inválidos }
  /api/wms/inventory:
    get:
      tags: [Inventory]
      security: [{ bearerAuth: [] }]
      parameters:
        - $ref: '#/components/parameters/TenantHeader'
      responses:
        '200':
          description: Lista sessões de inventário
          content:
            application/json:
              schema:
                type: object
                properties:
                  sessions:
                    type: array
                    items: { $ref: '#/components/schemas/InventorySession' }
  /api/wms/inventory/start:
    post:
      tags: [Inventory]
      security: [{ bearerAuth: [] }]
      parameters:
        - $ref: '#/components/parameters/TenantHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                type: { type: string }
                entries_count: { type: integer }
      responses:
        '200': { description: Sessão criada }
  /api/wms/tracking/events:
    get:
      tags: [Tracking]
      security: [{ bearerAuth: [] }]
      parameters:
        - $ref: '#/components/parameters/TenantHeader'
        - name: since
          in: query
          schema: { type: string, format: date-time }
      responses:
        '200':
          description: Lista eventos
          content:
            application/json:
              schema:
                type: object
                properties:
                  events:
                    type: array
                    items: { $ref: '#/components/schemas/TrackingEvent' }
    post:
      tags: [Tracking]
      security: [{ bearerAuth: [] }]
      parameters:
        - $ref: '#/components/parameters/TenantHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [type, payload]
              properties:
                warehouse_id: { type: integer }
                type: { type: string }
                payload: { type: object }
      responses:
        '201': { description: Registrado }
        '422': { description: Dados inválidos }
  /api/wms/mobile/inventory/ingest:
    post:
      tags: [Mobile]
      security: [{ apiKey: [] }, { bearerAuth: [] }]
      parameters:
        - $ref: '#/components/parameters/TenantHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/MobileIngestRequest' }
      responses:
        '202': { description: Itens recebidos/validados }
        '207': { description: Erros parciais }
  /api/wms/mobile/inventory/validate:
    post:
      tags: [Mobile]
      security: [{ bearerAuth: [] }]
      parameters:
        - $ref: '#/components/parameters/TenantHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/MobileIngestRequest' }
      responses:
        '200': { description: Todos válidos }
        '207': { description: Erros parciais }
  /api/wms/mobile/inventory/confirm:
    post:
      tags: [Mobile]
      security: [{ apiKey: [] }, { bearerAuth: [] }]
      parameters:
        - $ref: '#/components/parameters/TenantHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [batch_id, session_id]
              properties:
                batch_id: { type: string }
                session_id: { type: integer }
      responses:
        '200': { description: Confirmado }
  /api/wms/mobile/inventory/queue/pending:
    get:
      tags: [Mobile]
      security: [{ bearerAuth: [] }]
      parameters:
        - $ref: '#/components/parameters/TenantHeader'
      responses:
        '200': { description: Itens pendentes em fila }
  /api/wms/mobile/inventory/queue/process:
    post:
      tags: [Mobile]
      security: [{ bearerAuth: [] }]
      parameters:
        - $ref: '#/components/parameters/TenantHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                limit: { type: integer }
                session_id: { type: integer }
      responses:
        '200': { description: Processamento realizado }