---
openapi: 3.0.0
paths:
  "/products":
    get:
      operationId: ProductController_findList
      parameters:
      - name: page
        required: false
        in: query
        description: Trang, bắt đầu từ 1
        schema:
          minimum: 1
          default: 1
          type: number
      - name: page_size
        required: false
        in: query
        description: Số bản ghi mỗi trang
        schema:
          minimum: 1
          maximum: 500
          default: 20
          type: number
      - name: search
        required: false
        in: query
        description: Tìm theo tên hoặc SKU
        schema:
          type: string
      - name: is_active
        required: false
        in: query
        description: Chỉ lấy sản phẩm đang bán
        schema:
          type: boolean
      - name: sort_by
        required: false
        in: query
        description: Cột sắp xếp
        schema:
          type: string
          enum:
          - name
          - sku
          - retail_price
          - available_quantity
          - created_at
          - updated_at
      - name: sort_order
        required: false
        in: query
        description: Chiều sắp xếp
        schema:
          type: string
          enum:
          - asc
          - desc
      responses:
        '200':
          description: ''
      tags:
      - Product
  "/shipping/address/{carrier}/provinces":
    get:
      operationId: AddressController_listProvinces
      parameters:
      - name: carrier
        required: true
        in: path
        schema:
          type: number
      responses:
        '200':
          description: ''
      tags:
      - Address
  "/shipping/address/{carrier}/districts":
    get:
      operationId: AddressController_listDistricts
      parameters:
      - name: carrier
        required: true
        in: path
        schema:
          type: number
      - name: provinceId
        required: true
        in: query
        schema:
          type: number
      responses:
        '200':
          description: ''
      tags:
      - Address
  "/shipping/address/{carrier}/wards":
    get:
      operationId: AddressController_listWards
      parameters:
      - name: carrier
        required: true
        in: path
        schema:
          type: number
      - name: districtId
        required: true
        in: query
        schema:
          type: number
      responses:
        '200':
          description: ''
      tags:
      - Address
  "/orders":
    get:
      description: Paginated, filterable.
      operationId: DealerOrderController_listOrders
      parameters:
      - name: page
        required: false
        in: query
        description: Trang, bắt đầu từ 1
        schema:
          minimum: 1
          default: 1
          type: number
      - name: page_size
        required: false
        in: query
        description: Số bản ghi mỗi trang
        schema:
          minimum: 1
          maximum: 500
          default: 20
          type: number
      - name: search
        required: false
        in: query
        description: Free-text search across tracking_number / customer_name / customer_phone
        schema:
          maxLength: 100
          type: string
      - name: status
        required: false
        in: query
        description: Filter by OrderStatus code
        schema:
          type: number
          enum:
          - -1
          - 0
          - 1
          - 16
          - 17
          - 18
          - 2
          - 3
          - 4
          - 5
          - 6
          - 7
          - 8
          - 9
          - 10
          - 11
          - 12
          - 13
          - 14
          - 15
          - 99
      - name: category
        required: false
        in: query
        description: Dashboard status bucket (timestamp-driven). Applies the cutover
          floor date.
        schema:
          type: string
          enum:
          - today
          - shipped_today
          - in_transit
          - returned
          - need_print
          - awaiting_ship
          - cancelled
      - name: statuses
        required: false
        in: query
        description: Lọc nhiều trạng thái cùng lúc (OR). Kết hợp AND với `status`
          nếu gửi cả hai.
        schema:
          type: array
          items:
            type: number
            enum:
            - -1
            - 0
            - 1
            - 16
            - 17
            - 18
            - 2
            - 3
            - 4
            - 5
            - 6
            - 7
            - 8
            - 9
            - 10
            - 11
            - 12
            - 13
            - 14
            - 15
            - 99
      - name: from_date
        required: false
        in: query
        description: Ngày tạo từ (YYYY-MM-DD, giờ Việt Nam)
        schema:
          type: string
      - name: to_date
        required: false
        in: query
        description: Ngày tạo đến (YYYY-MM-DD, giờ Việt Nam, bao gồm cả ngày)
        schema:
          type: string
      - name: carrier
        required: false
        in: query
        description: Lọc theo hãng vận chuyển
        schema:
          type: number
          enum:
          - 0
          - 1
          - 2
          - 3
          - 4
          - 99
      - name: source
        required: false
        in: query
        description: Nguồn đơn (dealer_app | pancake | ...)
        schema:
          maxLength: 40
          type: string
      - name: product
        required: false
        in: query
        description: Lọc theo tên sản phẩm trong đơn
        schema:
          maxLength: 100
          type: string
      - name: cod_from
        required: false
        in: query
        description: COD tối thiểu (NUMERIC dạng chuỗi)
        schema:
          type: string
      - name: cod_to
        required: false
        in: query
        description: COD tối đa (NUMERIC dạng chuỗi)
        schema:
          type: string
      responses:
        '200':
          description: Paginated order list with `{ data, meta }`
      security:
      - session: []
      summary: List orders for current dealer
      tags:
      - Dealer Self — Orders
    post:
      description: Single entry point for dealer-app order creation (VTP, GHTK, J&T,
        Grab). Gọi bằng API key bị giới hạn 1 đơn / 2 phút mỗi đại lý (429 kèm `Retry-After`);
        phiên đăng nhập trên app không bị siết.
      operationId: DealerOrderController_createOrder
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CreateDealerOrderDto"
      responses:
        '201':
          description: Order created with tracking number
        '429':
          description: Vượt hạn mức tạo đơn qua API key — `ORDER_CREATE_RATE_LIMIT_EXCEEDED`
      security:
      - session: []
      summary: Create dealer order
      tags:
      - Dealer Self — Orders
  "/orders/summary":
    get:
      description: Order counts per timestamp-driven status bucket, since the cutover
        floor date.
      operationId: DealerOrderController_getOrderSummary
      parameters: []
      responses:
        '200':
          description: Counts keyed by DealerOrderCategory
      security:
      - session: []
      summary: Dashboard status-bucket counts
      tags:
      - Dealer Self — Orders
  "/orders/{id}":
    get:
      operationId: DealerOrderController_getOrder
      parameters:
      - name: id
        required: true
        in: path
        description: Order id
        schema:
          type: string
      responses:
        '200':
          description: Order detail
      security:
      - session: []
      summary: Get dealer order by id (scoped to current dealer)
      tags:
      - Dealer Self — Orders
  "/orders/{id}/breakdown":
    get:
      description: Retail vs dealer buy price per line, order profit (COD − cost),
        and upline dealers.
      operationId: DealerOrderController_getOrderBreakdown
      parameters:
      - name: id
        required: true
        in: path
        description: Order id
        schema:
          type: string
      responses:
        '200':
          description: Order profit breakdown
      security:
      - session: []
      summary: Profit breakdown for a dealer order
      tags:
      - Dealer Self — Orders
  "/customers":
    get:
      description: Paginated, searchable by name or phone. Ranked by most-recent order.
      operationId: DealerCustomerController_listCustomers
      parameters:
      - name: page
        required: false
        in: query
        description: Trang, bắt đầu từ 1
        schema:
          minimum: 1
          default: 1
          type: number
      - name: page_size
        required: false
        in: query
        description: Số bản ghi mỗi trang
        schema:
          minimum: 1
          maximum: 500
          default: 20
          type: number
      - name: search
        required: false
        in: query
        description: Free-text search across name / phone
        schema:
          maxLength: 100
          type: string
      responses:
        '200':
          description: Paginated customer list with `{ data, meta }`
      security:
      - session: []
      summary: List customers for current dealer
      tags:
      - Dealer Self — Customers
  "/customers/search":
    get:
      description: Autocomplete for dealer app order form. Returns up to 10 matches
        ordered by most-recent order. Empty when phone < 3 chars.
      operationId: DealerCustomerController_searchByPhone
      parameters:
      - name: phone
        required: false
        in: query
        description: Phone prefix (≥3 chars)
        schema:
          type: string
      responses:
        '200':
          description: Array of dealer-scoped customer matches
      security:
      - session: []
      summary: Search customers by phone (prefix)
      tags:
      - Dealer Self — Customers
  "/senders":
    get:
      operationId: DealerSenderController_list
      parameters: []
      responses:
        '200':
          description: Array of sender profiles owned by current dealer
      security:
      - session: []
      summary: List dealer sender profiles
      tags:
      - Dealer Self — Senders
  "/wallet/me":
    get:
      description: Main wallet + commission wallet + commission accrued this month.
      operationId: DealerWalletSelfController_getMyWallet
      parameters: []
      responses:
        '200':
          description: Wallet snapshot for the logged-in dealer
      security:
      - session: []
      summary: Get current dealer wallet snapshot
      tags:
      - Dealer Self — Wallet
  "/wallet/transactions":
    get:
      description: Unified, paginated feed across trading + commission wallet ledgers.
      operationId: DealerWalletSelfController_listTransactions
      parameters:
      - name: page
        required: false
        in: query
        description: Trang, bắt đầu từ 1
        schema:
          minimum: 1
          default: 1
          type: number
      - name: page_size
        required: false
        in: query
        description: Số bản ghi mỗi trang
        schema:
          minimum: 1
          maximum: 500
          default: 20
          type: number
      - name: wallet
        required: false
        in: query
        description: 'Wallet filter: ''all'' merges both ledgers, else a single wallet'
        schema:
          type: string
          enum:
          - all
          - goods
          - commission
      - name: type
        required: false
        in: query
        description: Filter by TransactionType code
        schema:
          type: number
          enum:
          - 0
          - 1
          - 2
          - 3
          - 4
          - 5
          - 6
          - 7
          - 8
          - 9
          - 10
          - 11
          - 12
          - 13
          - 14
      - name: search
        required: false
        in: query
        description: Free-text search across reference_id / description
        schema:
          maxLength: 100
          type: string
      responses:
        '200':
          description: Paginated transaction feed with `{ data, meta }`
      security:
      - session: []
      summary: List wallet transactions for current dealer
      tags:
      - Dealer Self — Wallet
info:
  title: DILIM — API Đại lý
  description: 'API dành cho đại lý DILIM tích hợp hệ thống riêng: tạo đơn, tra cứu
    đơn, sản phẩm, khách hàng và ví. Xác thực bằng API key (`X-Api-Key`) tạo trong
    app đại lý — Cài đặt → Kết nối. Key hết hạn sau 90 ngày. Tạo đơn giới hạn 1 đơn
    / 120 giây mỗi đại lý; vượt hạn mức trả 429 kèm `Retry-After`.'
  version: '1.0'
  contact: {}
tags: []
servers:
- url: https://api-dealer.dilisupplement.com/api
  description: Production
components:
  securitySchemes:
    api-key:
      type: apiKey
      in: header
      name: X-Api-Key
  schemas:
    CreateDealerOrderDto:
      type: object
      properties:
        sender_id:
          type: string
          description: Dealer sender profile UUID. Optional for PICKUP_AT_COMPANY
            (sender may be empty); required for other carriers.
        customer_name:
          type: string
          description: Customer full name. Skipped for PICKUP_AT_COMPANY (backend
            fills from dealer).
          maxLength: 255
        customer_phone:
          type: string
          description: Customer phone. Skipped for PICKUP_AT_COMPANY.
          example: '0912345678'
          maxLength: 20
        customer_address:
          type: string
          description: Customer street address. Skipped for PICKUP_AT_COMPANY.
          maxLength: 500
        receiver_province_id:
          type: number
          description: VTP receiver province id
        receiver_district_id:
          type: number
          description: VTP receiver district id
        receiver_ward_id:
          type: number
          description: VTP receiver ward id
        receiver_province:
          type: string
          description: Receiver province name
          maxLength: 100
        receiver_district:
          type: string
          description: Receiver district name
          maxLength: 100
        receiver_ward:
          type: string
          description: Receiver ward name
          maxLength: 100
        items:
          description: Order line items (≥1)
          type: array
          items:
            "$ref": "#/components/schemas/DealerOrderItemDto"
        carrier:
          type: number
          enum:
          - 0
          - 1
          - 2
          - 3
          - 4
          - 99
          description: Shipping carrier. Defaults to VTP for backward compatibility.
        order_service:
          type: string
          description: Carrier service code (e.g., VTP service)
        order_payment:
          type: number
          enum:
          - 1
          - 2
          - 3
          - 4
          description: Who pays ship fee
        product_weight:
          type: number
          description: Product weight in grams
          minimum: 1
        money_collection:
          type: number
          description: COD money to collect on delivery
          minimum: 0
        prepaid_amount:
          type: string
          description: Prepaid amount (decimal string)
          example: '0.00'
        notes:
          type: string
          description: Internal note
          maxLength: 500
        order_service_add:
          type: string
          description: Extra carrier service options
        is_draft:
          type: boolean
          description: Save as draft (skip carrier API submit)
          default: false
        is_use_carton:
          type: boolean
          description: Đơn có dùng thùng carton hay không. Bỏ trống → suy ra từ carrier
            (Grab / lấy tại công ty = không dùng).
      required:
      - items
      - order_service
      - order_payment
      - product_weight
      - money_collection
    DealerOrderItemDto:
      type: object
      properties:
        kind:
          type: string
          enum:
          - product
          - combo
          description: Line kind
        ref_id:
          type: string
          description: Reference id of product or combo
        quantity:
          type: number
          description: Quantity (1..9999)
          minimum: 1
          maximum: 9999
      required:
      - kind
      - ref_id
      - quantity
security:
- api-key: []
