openapi: 3.0.0
info:
  title: ERP Generic - Core API
  description: |
    API para el sistema ERP generico multitenant.

    ## Caracteristicas principales
    - Autenticacion JWT y gestion de sesiones
    - Multi-tenant con aislamiento de datos
    - Gestion financiera y contable
    - Control de inventario y almacenes
    - Compras y ventas
    - CRM y gestion de partners
    - Proyectos y recursos humanos
    - Sistema de permisos granular (API Keys)

    ## Autenticacion
    Todos los endpoints requieren autenticacion mediante Bearer Token (JWT).
    Algunos endpoints administrativos pueden requerir API Key especifica.

    ## Roles
    - `super_admin`: Acceso total al sistema
    - `admin`: Administrador de tenant
    - `manager`: Gerente con permisos amplios
    - `sales`: Ventas
    - `accountant`: Contabilidad
    - `warehouse`: Almacen
    - `user`: Usuario basico

  version: 1.0.0
  contact:
    name: ERP Generic Support
    email: support@erpgeneric.com
  license:
    name: Proprietary

servers:
  - url: http://localhost:3003/api/v1
    description: Desarrollo local
  - url: https://api.erpgeneric.com/api/v1
    description: Produccion

tags:
  - name: Auth
    description: Autenticacion y autorizacion
  - name: MFA
    description: Autenticacion Multi-Factor
  - name: API Keys
    description: Gestion de API Keys
  - name: Users
    description: Gestion de usuarios
  - name: Companies
    description: Gestion de empresas (tenants)
  - name: Partners
    description: Gestion de partners (clientes, proveedores, contactos)
  - name: Inventory
    description: Control de inventario y productos
  - name: Financial
    description: Gestion financiera y contable
  - name: Purchases
    description: Compras y ordenes de compra
  - name: Sales
    description: Ventas, cotizaciones y pedidos
  - name: Projects
    description: Gestion de proyectos y tareas
  - name: CRM
    description: CRM y gestion de oportunidades
  - name: HR
    description: Recursos humanos y empleados
  - name: Reports
    description: Reportes y analiticas
  - name: Dashboards
    description: Dashboards y widgets
  - name: Audit
    description: Auditoria y logs del sistema
  - name: System
    description: Configuracion del sistema
  - name: Health
    description: Health checks y monitoreo

components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: Token JWT obtenido del endpoint de login

    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
      description: API Key para operaciones especificas

  schemas:
    # Common Response Types
    ApiResponse:
      type: object
      properties:
        success:
          type: boolean
        data:
          type: object
        error:
          type: string

    PaginatedResponse:
      type: object
      properties:
        success:
          type: boolean
          example: true
        data:
          type: array
          items:
            type: object
        pagination:
          $ref: '#/components/schemas/Pagination'

    Pagination:
      type: object
      properties:
        page:
          type: integer
          example: 1
        limit:
          type: integer
          example: 20
        total:
          type: integer
          example: 100
        totalPages:
          type: integer
          example: 5

    Error:
      type: object
      properties:
        success:
          type: boolean
          example: false
        error:
          type: string
          example: "Error message"

    # Auth Schemas
    LoginRequest:
      type: object
      required:
        - email
        - password
      properties:
        email:
          type: string
          format: email
          example: "user@example.com"
        password:
          type: string
          format: password
          example: "SecurePassword123"

    LoginResponse:
      type: object
      properties:
        success:
          type: boolean
          example: true
        data:
          type: object
          properties:
            token:
              type: string
              description: JWT access token
            refreshToken:
              type: string
              description: Token para renovar sesion
            user:
              $ref: '#/components/schemas/User'

    RegisterRequest:
      type: object
      required:
        - email
        - password
        - firstName
        - lastName
      properties:
        email:
          type: string
          format: email
        password:
          type: string
          format: password
          minLength: 8
        firstName:
          type: string
        lastName:
          type: string
        phone:
          type: string

    ChangePasswordRequest:
      type: object
      required:
        - currentPassword
        - newPassword
      properties:
        currentPassword:
          type: string
          format: password
        newPassword:
          type: string
          format: password
          minLength: 8

    # User Schema
    User:
      type: object
      properties:
        id:
          type: string
          format: uuid
        email:
          type: string
          format: email
        firstName:
          type: string
        lastName:
          type: string
        phone:
          type: string
        avatar:
          type: string
        role:
          type: string
          enum: [super_admin, admin, manager, sales, accountant, warehouse, user]
        isActive:
          type: boolean
        emailVerified:
          type: boolean
        mfaEnabled:
          type: boolean
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time

    CreateUserRequest:
      type: object
      required:
        - email
        - password
        - firstName
        - lastName
      properties:
        email:
          type: string
          format: email
        password:
          type: string
          format: password
        firstName:
          type: string
        lastName:
          type: string
        phone:
          type: string
        role:
          type: string
          enum: [admin, manager, sales, accountant, warehouse, user]
          default: user

    UpdateUserRequest:
      type: object
      properties:
        firstName:
          type: string
        lastName:
          type: string
        phone:
          type: string
        avatar:
          type: string
        isActive:
          type: boolean

    # Partner Schema
    Partner:
      type: object
      properties:
        id:
          type: string
          format: uuid
        tenantId:
          type: string
          format: uuid
        name:
          type: string
        displayName:
          type: string
        type:
          type: string
          enum: [company, individual]
        isCustomer:
          type: boolean
        isSupplier:
          type: boolean
        isEmployee:
          type: boolean
        email:
          type: string
          format: email
        phone:
          type: string
        mobile:
          type: string
        website:
          type: string
        taxId:
          type: string
        street:
          type: string
        street2:
          type: string
        city:
          type: string
        state:
          type: string
        zip:
          type: string
        countryCode:
          type: string
        creditLimit:
          type: number
        paymentTermId:
          type: string
          format: uuid
        salesRepId:
          type: string
          format: uuid
        isActive:
          type: boolean
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time

    CreatePartnerRequest:
      type: object
      required:
        - name
      properties:
        name:
          type: string
        displayName:
          type: string
        type:
          type: string
          enum: [company, individual]
          default: company
        isCustomer:
          type: boolean
          default: false
        isSupplier:
          type: boolean
          default: false
        email:
          type: string
          format: email
        phone:
          type: string
        mobile:
          type: string
        website:
          type: string
        taxId:
          type: string
        street:
          type: string
        city:
          type: string
        state:
          type: string
        zip:
          type: string
        countryCode:
          type: string
        creditLimit:
          type: number
        paymentTermId:
          type: string
          format: uuid

    # Product Schema
    Product:
      type: object
      properties:
        id:
          type: string
          format: uuid
        tenantId:
          type: string
          format: uuid
        code:
          type: string
        name:
          type: string
        description:
          type: string
        type:
          type: string
          enum: [product, service, consumable]
        categoryId:
          type: string
          format: uuid
        uomId:
          type: string
          format: uuid
        listPrice:
          type: number
        standardCost:
          type: number
        weight:
          type: number
        volume:
          type: number
        saleOk:
          type: boolean
        purchaseOk:
          type: boolean
        isActive:
          type: boolean
        barcode:
          type: string
        trackLots:
          type: boolean
        trackSerials:
          type: boolean
        createdAt:
          type: string
          format: date-time

    CreateProductRequest:
      type: object
      required:
        - name
        - type
      properties:
        code:
          type: string
        name:
          type: string
        description:
          type: string
        type:
          type: string
          enum: [product, service, consumable]
        categoryId:
          type: string
          format: uuid
        uomId:
          type: string
          format: uuid
        listPrice:
          type: number
        standardCost:
          type: number
        saleOk:
          type: boolean
        purchaseOk:
          type: boolean

    # Warehouse Schema
    Warehouse:
      type: object
      properties:
        id:
          type: string
          format: uuid
        tenantId:
          type: string
          format: uuid
        code:
          type: string
        name:
          type: string
        address:
          type: string
        isActive:
          type: boolean

    # Account Schema
    Account:
      type: object
      properties:
        id:
          type: string
          format: uuid
        tenantId:
          type: string
          format: uuid
        code:
          type: string
        name:
          type: string
        type:
          type: string
          enum: [asset, liability, equity, income, expense]
        reconcile:
          type: boolean
        deprecated:
          type: boolean
        isActive:
          type: boolean

    # Invoice Schema
    Invoice:
      type: object
      properties:
        id:
          type: string
          format: uuid
        tenantId:
          type: string
          format: uuid
        number:
          type: string
        partnerId:
          type: string
          format: uuid
        type:
          type: string
          enum: [out_invoice, in_invoice, out_refund, in_refund]
        state:
          type: string
          enum: [draft, posted, cancelled]
        invoiceDate:
          type: string
          format: date
        dueDate:
          type: string
          format: date
        amountUntaxed:
          type: number
        amountTax:
          type: number
        amountTotal:
          type: number
        amountResidual:
          type: number
        currencyCode:
          type: string

    # Employee Schema
    Employee:
      type: object
      properties:
        id:
          type: string
          format: uuid
        tenantId:
          type: string
          format: uuid
        employeeNumber:
          type: string
        firstName:
          type: string
        lastName:
          type: string
        email:
          type: string
          format: email
        phone:
          type: string
        departmentId:
          type: string
          format: uuid
        jobPositionId:
          type: string
          format: uuid
        managerId:
          type: string
          format: uuid
        hireDate:
          type: string
          format: date
        status:
          type: string
          enum: [active, on_leave, terminated]
        userId:
          type: string
          format: uuid

    # Department Schema
    Department:
      type: object
      properties:
        id:
          type: string
          format: uuid
        tenantId:
          type: string
          format: uuid
        name:
          type: string
        code:
          type: string
        parentId:
          type: string
          format: uuid
        managerId:
          type: string
          format: uuid
        isActive:
          type: boolean

    # Dashboard Schema
    Dashboard:
      type: object
      properties:
        id:
          type: string
          format: uuid
        tenantId:
          type: string
          format: uuid
        name:
          type: string
        description:
          type: string
        isDefault:
          type: boolean
        isShared:
          type: boolean
        layout:
          type: object
        createdBy:
          type: string
          format: uuid
        createdAt:
          type: string
          format: date-time

security:
  - BearerAuth: []

paths:
  # ==================== HEALTH ====================
  /health:
    get:
      tags:
        - Health
      summary: Health check del servidor
      security: []
      responses:
        '200':
          description: Servidor funcionando correctamente
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: ok
                  timestamp:
                    type: string
                    format: date-time

  # ==================== AUTH ====================
  /auth/login:
    post:
      tags:
        - Auth
      summary: Iniciar sesion
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/LoginRequest'
      responses:
        '200':
          description: Login exitoso
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LoginResponse'
        '401':
          description: Credenciales invalidas
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /auth/register:
    post:
      tags:
        - Auth
      summary: Registrar nuevo usuario
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RegisterRequest'
      responses:
        '201':
          description: Usuario registrado exitosamente
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LoginResponse'
        '400':
          description: Datos invalidos o email ya registrado
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /auth/refresh:
    post:
      tags:
        - Auth
      summary: Renovar token de acceso
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - refreshToken
              properties:
                refreshToken:
                  type: string
      responses:
        '200':
          description: Token renovado
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      token:
                        type: string
                      refreshToken:
                        type: string

  /auth/profile:
    get:
      tags:
        - Auth
      summary: Obtener perfil del usuario autenticado
      responses:
        '200':
          description: Perfil del usuario
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    $ref: '#/components/schemas/User'

  /auth/change-password:
    post:
      tags:
        - Auth
      summary: Cambiar contrasena
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ChangePasswordRequest'
      responses:
        '200':
          description: Contrasena cambiada exitosamente
        '400':
          description: Contrasena actual incorrecta

  /auth/logout:
    post:
      tags:
        - Auth
      summary: Cerrar sesion actual
      responses:
        '200':
          description: Sesion cerrada

  /auth/logout-all:
    post:
      tags:
        - Auth
      summary: Cerrar todas las sesiones
      responses:
        '200':
          description: Todas las sesiones cerradas

  # ==================== MFA ====================
  /auth/mfa/setup:
    post:
      tags:
        - MFA
      summary: Configurar MFA (TOTP)
      responses:
        '200':
          description: QR code y secret para configurar authenticator
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      secret:
                        type: string
                      qrCode:
                        type: string
                        description: Data URL de imagen QR

  /auth/mfa/verify:
    post:
      tags:
        - MFA
      summary: Verificar y activar MFA
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - code
              properties:
                code:
                  type: string
                  description: Codigo TOTP de 6 digitos
      responses:
        '200':
          description: MFA activado exitosamente
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      backupCodes:
                        type: array
                        items:
                          type: string

  /auth/mfa/disable:
    post:
      tags:
        - MFA
      summary: Desactivar MFA
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - code
              properties:
                code:
                  type: string
      responses:
        '200':
          description: MFA desactivado

  # ==================== API KEYS ====================
  /auth/api-keys:
    get:
      tags:
        - API Keys
      summary: Listar API Keys del usuario
      responses:
        '200':
          description: Lista de API Keys
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        name:
                          type: string
                        lastUsedAt:
                          type: string
                          format: date-time
                        expiresAt:
                          type: string
                          format: date-time
                        isActive:
                          type: boolean

    post:
      tags:
        - API Keys
      summary: Crear nueva API Key
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - name
              properties:
                name:
                  type: string
                expiresAt:
                  type: string
                  format: date-time
                permissions:
                  type: array
                  items:
                    type: string
      responses:
        '201':
          description: API Key creada (el key solo se muestra una vez)
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                      key:
                        type: string
                        description: El API Key (guardar, no se mostrara de nuevo)

  /auth/api-keys/{id}:
    delete:
      tags:
        - API Keys
      summary: Revocar API Key
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: API Key revocada

  # ==================== USERS ====================
  /users:
    get:
      tags:
        - Users
      summary: Listar usuarios
      description: Requiere rol admin o super_admin
      parameters:
        - name: page
          in: query
          schema:
            type: integer
            default: 1
        - name: limit
          in: query
          schema:
            type: integer
            default: 20
        - name: search
          in: query
          schema:
            type: string
        - name: role
          in: query
          schema:
            type: string
        - name: isActive
          in: query
          schema:
            type: boolean
      responses:
        '200':
          description: Lista paginada de usuarios
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/PaginatedResponse'
                  - type: object
                    properties:
                      data:
                        type: array
                        items:
                          $ref: '#/components/schemas/User'

    post:
      tags:
        - Users
      summary: Crear usuario
      description: Requiere rol admin o super_admin
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateUserRequest'
      responses:
        '201':
          description: Usuario creado
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    $ref: '#/components/schemas/User'

  /users/{id}:
    get:
      tags:
        - Users
      summary: Obtener usuario por ID
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Datos del usuario
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    $ref: '#/components/schemas/User'
        '404':
          description: Usuario no encontrado

    put:
      tags:
        - Users
      summary: Actualizar usuario
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateUserRequest'
      responses:
        '200':
          description: Usuario actualizado

    delete:
      tags:
        - Users
      summary: Eliminar usuario
      description: Requiere rol super_admin
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Usuario eliminado

  # ==================== PARTNERS ====================
  /partners:
    get:
      tags:
        - Partners
      summary: Listar partners
      parameters:
        - name: page
          in: query
          schema:
            type: integer
            default: 1
        - name: limit
          in: query
          schema:
            type: integer
            default: 20
        - name: search
          in: query
          schema:
            type: string
        - name: type
          in: query
          schema:
            type: string
            enum: [company, individual]
        - name: isCustomer
          in: query
          schema:
            type: boolean
        - name: isSupplier
          in: query
          schema:
            type: boolean
        - name: isActive
          in: query
          schema:
            type: boolean
      responses:
        '200':
          description: Lista paginada de partners
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/PaginatedResponse'
                  - type: object
                    properties:
                      data:
                        type: array
                        items:
                          $ref: '#/components/schemas/Partner'

    post:
      tags:
        - Partners
      summary: Crear partner
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreatePartnerRequest'
      responses:
        '201':
          description: Partner creado
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    $ref: '#/components/schemas/Partner'

  /partners/customers:
    get:
      tags:
        - Partners
      summary: Listar solo clientes
      parameters:
        - name: page
          in: query
          schema:
            type: integer
        - name: limit
          in: query
          schema:
            type: integer
        - name: search
          in: query
          schema:
            type: string
      responses:
        '200':
          description: Lista de clientes
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedResponse'

  /partners/suppliers:
    get:
      tags:
        - Partners
      summary: Listar solo proveedores
      parameters:
        - name: page
          in: query
          schema:
            type: integer
        - name: limit
          in: query
          schema:
            type: integer
        - name: search
          in: query
          schema:
            type: string
      responses:
        '200':
          description: Lista de proveedores
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedResponse'

  /partners/{id}:
    get:
      tags:
        - Partners
      summary: Obtener partner por ID
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Datos del partner
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    $ref: '#/components/schemas/Partner'

    put:
      tags:
        - Partners
      summary: Actualizar partner
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreatePartnerRequest'
      responses:
        '200':
          description: Partner actualizado

    delete:
      tags:
        - Partners
      summary: Eliminar partner
      description: Requiere rol admin o super_admin
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Partner eliminado

  # ==================== INVENTORY ====================
  /inventory/products:
    get:
      tags:
        - Inventory
      summary: Listar productos
      parameters:
        - name: page
          in: query
          schema:
            type: integer
        - name: limit
          in: query
          schema:
            type: integer
        - name: search
          in: query
          schema:
            type: string
        - name: type
          in: query
          schema:
            type: string
            enum: [product, service, consumable]
        - name: categoryId
          in: query
          schema:
            type: string
            format: uuid
        - name: saleOk
          in: query
          schema:
            type: boolean
        - name: purchaseOk
          in: query
          schema:
            type: boolean
      responses:
        '200':
          description: Lista de productos
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/PaginatedResponse'
                  - type: object
                    properties:
                      data:
                        type: array
                        items:
                          $ref: '#/components/schemas/Product'

    post:
      tags:
        - Inventory
      summary: Crear producto
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateProductRequest'
      responses:
        '201':
          description: Producto creado

  /inventory/products/{id}:
    get:
      tags:
        - Inventory
      summary: Obtener producto por ID
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Datos del producto

    put:
      tags:
        - Inventory
      summary: Actualizar producto
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateProductRequest'
      responses:
        '200':
          description: Producto actualizado

    delete:
      tags:
        - Inventory
      summary: Eliminar producto
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Producto eliminado

  /inventory/products/{id}/stock:
    get:
      tags:
        - Inventory
      summary: Obtener stock del producto
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Stock por ubicacion
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        locationId:
                          type: string
                        locationName:
                          type: string
                        quantity:
                          type: number
                        reservedQty:
                          type: number
                        availableQty:
                          type: number

  /inventory/warehouses:
    get:
      tags:
        - Inventory
      summary: Listar almacenes
      responses:
        '200':
          description: Lista de almacenes
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Warehouse'

    post:
      tags:
        - Inventory
      summary: Crear almacen
      description: Requiere rol admin o super_admin
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - name
                - code
              properties:
                name:
                  type: string
                code:
                  type: string
                address:
                  type: string
      responses:
        '201':
          description: Almacen creado

  /inventory/warehouses/{id}:
    get:
      tags:
        - Inventory
      summary: Obtener almacen por ID
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Datos del almacen

    put:
      tags:
        - Inventory
      summary: Actualizar almacen
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Almacen actualizado

    delete:
      tags:
        - Inventory
      summary: Eliminar almacen
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Almacen eliminado

  /inventory/warehouses/{id}/stock:
    get:
      tags:
        - Inventory
      summary: Obtener stock del almacen
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Stock por producto en el almacen

  /inventory/pickings:
    get:
      tags:
        - Inventory
      summary: Listar movimientos de inventario
      parameters:
        - name: page
          in: query
          schema:
            type: integer
        - name: limit
          in: query
          schema:
            type: integer
        - name: state
          in: query
          schema:
            type: string
            enum: [draft, confirmed, assigned, done, cancel]
        - name: pickingTypeId
          in: query
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Lista de pickings

    post:
      tags:
        - Inventory
      summary: Crear picking
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - pickingTypeId
              properties:
                pickingTypeId:
                  type: string
                  format: uuid
                partnerId:
                  type: string
                  format: uuid
                scheduledDate:
                  type: string
                  format: date
                origin:
                  type: string
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      productId:
                        type: string
                        format: uuid
                      quantity:
                        type: number
                      locationId:
                        type: string
                        format: uuid
                      locationDestId:
                        type: string
                        format: uuid
      responses:
        '201':
          description: Picking creado

  /inventory/pickings/{id}/confirm:
    post:
      tags:
        - Inventory
      summary: Confirmar picking
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Picking confirmado

  /inventory/pickings/{id}/validate:
    post:
      tags:
        - Inventory
      summary: Validar picking (completar)
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Picking validado

  /inventory/pickings/{id}/cancel:
    post:
      tags:
        - Inventory
      summary: Cancelar picking
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Picking cancelado

  # ==================== FINANCIAL ====================
  /financial/accounts:
    get:
      tags:
        - Financial
      summary: Listar cuentas contables
      parameters:
        - name: page
          in: query
          schema:
            type: integer
        - name: limit
          in: query
          schema:
            type: integer
        - name: type
          in: query
          schema:
            type: string
            enum: [asset, liability, equity, income, expense]
        - name: reconcile
          in: query
          schema:
            type: boolean
      responses:
        '200':
          description: Lista de cuentas
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/PaginatedResponse'
                  - type: object
                    properties:
                      data:
                        type: array
                        items:
                          $ref: '#/components/schemas/Account'

    post:
      tags:
        - Financial
      summary: Crear cuenta contable
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - code
                - name
                - type
              properties:
                code:
                  type: string
                name:
                  type: string
                type:
                  type: string
                  enum: [asset, liability, equity, income, expense]
                reconcile:
                  type: boolean
      responses:
        '201':
          description: Cuenta creada

  /financial/invoices:
    get:
      tags:
        - Financial
      summary: Listar facturas
      parameters:
        - name: page
          in: query
          schema:
            type: integer
        - name: limit
          in: query
          schema:
            type: integer
        - name: type
          in: query
          schema:
            type: string
            enum: [out_invoice, in_invoice, out_refund, in_refund]
        - name: state
          in: query
          schema:
            type: string
            enum: [draft, posted, cancelled]
        - name: partnerId
          in: query
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Lista de facturas
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/PaginatedResponse'
                  - type: object
                    properties:
                      data:
                        type: array
                        items:
                          $ref: '#/components/schemas/Invoice'

    post:
      tags:
        - Financial
      summary: Crear factura
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - partnerId
                - type
              properties:
                partnerId:
                  type: string
                  format: uuid
                type:
                  type: string
                  enum: [out_invoice, in_invoice, out_refund, in_refund]
                invoiceDate:
                  type: string
                  format: date
                dueDate:
                  type: string
                  format: date
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      productId:
                        type: string
                        format: uuid
                      name:
                        type: string
                      quantity:
                        type: number
                      priceUnit:
                        type: number
                      taxIds:
                        type: array
                        items:
                          type: string
                          format: uuid
      responses:
        '201':
          description: Factura creada

  /financial/invoices/{id}:
    get:
      tags:
        - Financial
      summary: Obtener factura por ID
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Datos de la factura

    put:
      tags:
        - Financial
      summary: Actualizar factura
      description: Solo facturas en estado draft
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Factura actualizada

    delete:
      tags:
        - Financial
      summary: Eliminar factura
      description: Solo facturas en estado draft
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Factura eliminada

  /financial/invoices/{id}/post:
    post:
      tags:
        - Financial
      summary: Publicar factura
      description: Cambia estado de draft a posted
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Factura publicada

  /financial/invoices/{id}/cancel:
    post:
      tags:
        - Financial
      summary: Cancelar factura
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Factura cancelada

  /financial/payments:
    get:
      tags:
        - Financial
      summary: Listar pagos
      parameters:
        - name: page
          in: query
          schema:
            type: integer
        - name: limit
          in: query
          schema:
            type: integer
        - name: type
          in: query
          schema:
            type: string
            enum: [inbound, outbound]
        - name: state
          in: query
          schema:
            type: string
            enum: [draft, posted, reconciled, cancelled]
      responses:
        '200':
          description: Lista de pagos

    post:
      tags:
        - Financial
      summary: Crear pago
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - partnerId
                - amount
                - paymentType
              properties:
                partnerId:
                  type: string
                  format: uuid
                amount:
                  type: number
                paymentType:
                  type: string
                  enum: [inbound, outbound]
                paymentMethodId:
                  type: string
                  format: uuid
                journalId:
                  type: string
                  format: uuid
                paymentDate:
                  type: string
                  format: date
                memo:
                  type: string
      responses:
        '201':
          description: Pago creado

  /financial/payments/{id}/post:
    post:
      tags:
        - Financial
      summary: Publicar pago
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Pago publicado

  /financial/reconcile-models:
    get:
      tags:
        - Financial
      summary: Listar modelos de reconciliacion
      responses:
        '200':
          description: Lista de modelos

    post:
      tags:
        - Financial
      summary: Crear modelo de reconciliacion
      responses:
        '201':
          description: Modelo creado

  # ==================== HR ====================
  /hr/employees:
    get:
      tags:
        - HR
      summary: Listar empleados
      parameters:
        - name: page
          in: query
          schema:
            type: integer
        - name: limit
          in: query
          schema:
            type: integer
        - name: departmentId
          in: query
          schema:
            type: string
            format: uuid
        - name: status
          in: query
          schema:
            type: string
            enum: [active, on_leave, terminated]
      responses:
        '200':
          description: Lista de empleados
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/PaginatedResponse'
                  - type: object
                    properties:
                      data:
                        type: array
                        items:
                          $ref: '#/components/schemas/Employee'

    post:
      tags:
        - HR
      summary: Crear empleado
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - firstName
                - lastName
              properties:
                firstName:
                  type: string
                lastName:
                  type: string
                email:
                  type: string
                  format: email
                phone:
                  type: string
                departmentId:
                  type: string
                  format: uuid
                jobPositionId:
                  type: string
                  format: uuid
                managerId:
                  type: string
                  format: uuid
                hireDate:
                  type: string
                  format: date
      responses:
        '201':
          description: Empleado creado

  /hr/employees/{id}:
    get:
      tags:
        - HR
      summary: Obtener empleado por ID
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Datos del empleado

    put:
      tags:
        - HR
      summary: Actualizar empleado
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Empleado actualizado

  /hr/employees/{id}/terminate:
    post:
      tags:
        - HR
      summary: Terminar contrato del empleado
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                terminationDate:
                  type: string
                  format: date
                reason:
                  type: string
      responses:
        '200':
          description: Empleado terminado

  /hr/departments:
    get:
      tags:
        - HR
      summary: Listar departamentos
      responses:
        '200':
          description: Lista de departamentos
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Department'

    post:
      tags:
        - HR
      summary: Crear departamento
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - name
              properties:
                name:
                  type: string
                code:
                  type: string
                parentId:
                  type: string
                  format: uuid
                managerId:
                  type: string
                  format: uuid
      responses:
        '201':
          description: Departamento creado

  /hr/leaves:
    get:
      tags:
        - HR
      summary: Listar solicitudes de ausencia
      parameters:
        - name: employeeId
          in: query
          schema:
            type: string
            format: uuid
        - name: state
          in: query
          schema:
            type: string
            enum: [draft, submitted, approved, rejected, cancelled]
      responses:
        '200':
          description: Lista de ausencias

    post:
      tags:
        - HR
      summary: Crear solicitud de ausencia
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - employeeId
                - leaveTypeId
                - dateFrom
                - dateTo
              properties:
                employeeId:
                  type: string
                  format: uuid
                leaveTypeId:
                  type: string
                  format: uuid
                dateFrom:
                  type: string
                  format: date
                dateTo:
                  type: string
                  format: date
                reason:
                  type: string
      responses:
        '201':
          description: Solicitud creada

  /hr/leaves/{id}/approve:
    post:
      tags:
        - HR
      summary: Aprobar solicitud de ausencia
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Solicitud aprobada

  /hr/leaves/{id}/reject:
    post:
      tags:
        - HR
      summary: Rechazar solicitud de ausencia
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Solicitud rechazada

  /hr/payslips:
    get:
      tags:
        - HR
      summary: Listar nominas
      parameters:
        - name: employeeId
          in: query
          schema:
            type: string
            format: uuid
        - name: state
          in: query
          schema:
            type: string
            enum: [draft, verify, done, cancel]
      responses:
        '200':
          description: Lista de nominas

    post:
      tags:
        - HR
      summary: Crear nomina
      responses:
        '201':
          description: Nomina creada

  /hr/payslips/{id}/verify:
    post:
      tags:
        - HR
      summary: Verificar nomina
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Nomina verificada

  /hr/payslips/{id}/confirm:
    post:
      tags:
        - HR
      summary: Confirmar nomina
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Nomina confirmada

  /hr/expense-sheets:
    get:
      tags:
        - HR
      summary: Listar hojas de gastos
      responses:
        '200':
          description: Lista de hojas de gastos

    post:
      tags:
        - HR
      summary: Crear hoja de gastos
      responses:
        '201':
          description: Hoja creada

  /hr/expense-sheets/{id}/submit:
    post:
      tags:
        - HR
      summary: Enviar hoja de gastos para aprobacion
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Hoja enviada

  /hr/expense-sheets/{id}/approve:
    post:
      tags:
        - HR
      summary: Aprobar hoja de gastos
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Hoja aprobada

  # ==================== DASHBOARDS ====================
  /dashboards:
    get:
      tags:
        - Dashboards
      summary: Listar dashboards
      responses:
        '200':
          description: Lista de dashboards
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Dashboard'

    post:
      tags:
        - Dashboards
      summary: Crear dashboard
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - name
              properties:
                name:
                  type: string
                description:
                  type: string
                isShared:
                  type: boolean
                layout:
                  type: object
      responses:
        '201':
          description: Dashboard creado

  /dashboards/{id}:
    get:
      tags:
        - Dashboards
      summary: Obtener dashboard por ID
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Datos del dashboard

    put:
      tags:
        - Dashboards
      summary: Actualizar dashboard
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Dashboard actualizado

    delete:
      tags:
        - Dashboards
      summary: Eliminar dashboard
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Dashboard eliminado

  /dashboards/{id}/widgets:
    get:
      tags:
        - Dashboards
      summary: Listar widgets del dashboard
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Lista de widgets

    post:
      tags:
        - Dashboards
      summary: Agregar widget al dashboard
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - type
                - title
              properties:
                type:
                  type: string
                  enum: [kpi, chart, table, list]
                title:
                  type: string
                config:
                  type: object
                position:
                  type: object
                  properties:
                    x:
                      type: integer
                    y:
                      type: integer
                    w:
                      type: integer
                    h:
                      type: integer
      responses:
        '201':
          description: Widget agregado

  # ==================== REPORTS ====================
  /reports:
    get:
      tags:
        - Reports
      summary: Listar reportes disponibles
      responses:
        '200':
          description: Lista de reportes

  /reports/definitions:
    get:
      tags:
        - Reports
      summary: Listar definiciones de reportes
      responses:
        '200':
          description: Lista de definiciones

    post:
      tags:
        - Reports
      summary: Crear definicion de reporte
      responses:
        '201':
          description: Definicion creada

  /reports/executions:
    get:
      tags:
        - Reports
      summary: Listar ejecuciones de reportes
      responses:
        '200':
          description: Lista de ejecuciones

    post:
      tags:
        - Reports
      summary: Ejecutar reporte
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - definitionId
              properties:
                definitionId:
                  type: string
                  format: uuid
                parameters:
                  type: object
      responses:
        '201':
          description: Reporte ejecutado

  /reports/executions/{id}/export:
    post:
      tags:
        - Reports
      summary: Exportar reporte
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - format
              properties:
                format:
                  type: string
                  enum: [pdf, xlsx, csv, json, html]
      responses:
        '200':
          description: Archivo exportado
          content:
            application/pdf:
              schema:
                type: string
                format: binary
            application/vnd.openxmlformats-officedocument.spreadsheetml.sheet:
              schema:
                type: string
                format: binary

  /reports/trial-balance:
    get:
      tags:
        - Reports
      summary: Obtener balance de comprobacion
      parameters:
        - name: dateFrom
          in: query
          schema:
            type: string
            format: date
        - name: dateTo
          in: query
          schema:
            type: string
            format: date
      responses:
        '200':
          description: Balance de comprobacion

  # ==================== AUDIT ====================
  /audit/logs:
    get:
      tags:
        - Audit
      summary: Listar logs de auditoria
      parameters:
        - name: page
          in: query
          schema:
            type: integer
        - name: limit
          in: query
          schema:
            type: integer
        - name: userId
          in: query
          schema:
            type: string
            format: uuid
        - name: action
          in: query
          schema:
            type: string
        - name: entityType
          in: query
          schema:
            type: string
        - name: dateFrom
          in: query
          schema:
            type: string
            format: date
        - name: dateTo
          in: query
          schema:
            type: string
            format: date
      responses:
        '200':
          description: Lista de logs

  /audit/logs/{id}:
    get:
      tags:
        - Audit
      summary: Obtener detalle de log
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Detalle del log con cambios

  /security/events:
    get:
      tags:
        - Audit
      summary: Listar eventos de seguridad
      parameters:
        - name: type
          in: query
          schema:
            type: string
            enum: [login_success, login_failed, logout, password_change, mfa_enabled, mfa_disabled]
      responses:
        '200':
          description: Lista de eventos

  # ==================== SYSTEM ====================
  /system/settings:
    get:
      tags:
        - System
      summary: Obtener configuracion del sistema
      responses:
        '200':
          description: Configuracion actual

    put:
      tags:
        - System
      summary: Actualizar configuracion
      description: Requiere rol admin o super_admin
      responses:
        '200':
          description: Configuracion actualizada
