openapi: 3.0.0
info:
  title: K-NET API
  version: 1.0.0
  description: |
    Dokumentasi API untuk K-Net.  
    Gunakan tombol **Authorize** di kanan atas untuk masukin token Bearer.

servers:
  - url: http://k-net-local.test
    description: Local Environment
  - url: https://staging.k-net.co.id
    description: Staging Environment
  - url: https://k-net.co.id
    description: Production Environment

security: # <<< ini global
  - bearerAuth: [] # semua endpoint otomatis pake bearerAuth

paths:
  /api/list-stk-knet:
    get:
      tags:
        - Stockist
      summary: Get All Stockist
      description: Mengambil semua data stockist dari cache/model.
      responses:
        "200":
          description: Hasil request daftar stockist
          content:
            application/json:
              examples:
                Success:
                  summary: Contoh data ditemukan
                  value:
                    response: "true"
                    arrayData:
                      - stockist_code: "DC03"
                        full_name: "DISTRIBUTION CENTER SOLO"
                        address: "JL IR SOEKARNO,LJ08 SOLOBARU GROGOL SUKOHARJO JAWA TENGAH 57552 INDONESIA"
                        contact_no: "622129027000"
                        latitude: "-7.599627"
                        longitude: "110.814701"
                        pricecode: "12W4"
                      - stockist_code: "BID06"
                        full_name: "STOCKIST JAKARTA"
                        address: "Jl. Sudirman No.1 Jakarta"
                        contact_no: "622129011111"
                        latitude: "-6.200000"
                        longitude: "106.816666"
                        pricecode: "13X5"
                    message: "success"
                EmptyList:
                  summary: Contoh data tidak ditemukan
                  value:
                    response: "false"
                    arrayData: []
                    message: "Stockist tidak tersedia"
        "401":
          description: Unauthorized. Token tidak valid atau tidak ada.
        "405":
          description: Method Not Allowed. Gunakan GET.

  /api/list-stk-knet/{kode_stk}:
    get:
      tags:
        - Stockist
      summary: Get stockist by kode
      description: Cari detail 1 stockist berdasarkan kode stokis.
      parameters:
        - name: kode_stk
          in: path
          required: true
          description: Kode stockist
          schema:
            type: string
            example: BID06
      responses:
        "200":
          description: Hasil request data stockist berdasarkan kode
          content:
            application/json:
              examples:
                Success:
                  summary: Contoh data ditemukan
                  value:
                    response: "true"
                    arrayData:
                      - stockist_code: "DC03"
                        full_name: "DISTRIBUTION CENTER SOLO"
                        address: "JL IR SOEKARNO,LJ08 SOLOBARU GROGOL SUKOHARJO JAWA TENGAH 57552 INDONESIA"
                        contact_no: "622129027000"
                        latitude: "-7.599627"
                        longitude: "110.814701"
                        pricecode: "12W4"
                    message: "success"
                NotFound:
                  summary: Contoh data tidak ditemukan
                  value:
                    response: "false"
                    arrayData: []
                    message: "Stockist tidak ditemukan"
        "401":
          description: Unauthorized. Token tidak valid atau tidak ada.
        "405":
          description: Method Not Allowed. Gunakan GET.

  /api/list-bonus-period:
    get:
      tags:
        - Bonus Period
      summary: Get list Bonus Period
      description: Mengambil daftar periode bonus (format YYYY-MM-DD dan teks periode).
      responses:
        "200":
          description: List dari periode bonus
          content:
            application/json:
              schema:
                type: object
                properties:
                  response:
                    type: string
                    example: "true"
                  arrayData:
                    type: array
                    items:
                      type: object
                      properties:
                        period:
                          type: string
                          format: date
                          example: "2025-09-01"
                        period_text:
                          type: string
                          example: "September-2025"
                  message:
                    type: string
                    example: "success"
        "401":
          description: Unauthorized. Token tidak valid atau tidak ada.
        "405":
          description: Method Not Allowed. Gunakan GET.

  /api/list-marketing-plan:
    get:
      tags:
        - Marketing Plan
      summary: Get marketing plan list
      description: Mengambil daftar marketing plan yang tersedia.
      responses:
        "200":
          description: Hasil request daftar marketing plan
          content:
            application/json:
              examples:
                Success:
                  summary: Contoh data ditemukan
                  value:
                    response: "true"
                    arrayData:
                      - id: 1
                        marketingPlan: "Plan A"
                        description: "Plan A"
                      - id: 2
                        marketingPlan: "RO Smart Plan"
                        description: "Paket Repeat Order Smart Plan"
                    message: success
                EmptyList:
                  summary: Contoh data tidak ditemukan
                  value:
                    response: "false"
                    arrayData: []
                    message: "Marketing plan tidak tersedia"
        "401":
          description: Unauthorized. Token tidak valid atau tidak ada.
        "405":
          description: Method Not Allowed. Gunakan GET.

  /api/list-marketing-plan/{marketing_plan_id}:
    get:
      tags:
        - Marketing Plan
      summary: Get marketing plan by ID
      description: Mengambil detail marketing plan berdasarkan ID.
      parameters:
        - name: marketing_plan_id
          in: path
          required: true
          description: ID marketing plan
          schema:
            type: integer
            example: 2
      responses:
        "200":
          description: Hasil request marketing plan
          content:
            application/json:
              examples:
                Success:
                  summary: Contoh Response jika data ditemukan
                  value:
                    response: "true"
                    arrayData:
                      - id: 2
                        marketing_plan: "RO Smart Plan"
                        description: "Paket Repeat Order Smart Plan"
                    message: success
                NotFound:
                  summary: Contoh data tidak ditemukan
                  value:
                    response: "false"
                    arrayData: []
                    message: "Marketing Plan dengan ID tersebut tidak ditemukan"
        "401":
          description: Unauthorized. Token tidak valid atau tidak ada.
        "405":
          description: Method Not Allowed

  /api/member-check-status/{memberId}:
    get:
      tags:
        - Member
      summary: Check Status Aktivasi Member untuk Fast Track / Smart Reward / Weekly
      description: Check Apakah Member sudah pernah aktivasi Fast Track / Smart Reward / Weekly, ini  tidak berlaku untuk Plan A dan RO
      parameters:
        - name: memberId
          in: path
          required: true
          description: ID Member
          schema:
            type: string
            example: IDJHID000065
      responses:
        "200":
          description: Hasil pengecekan status aktivasi member
          content:
            application/json:
              examples:
                Success:
                  summary: Contoh data ditemukan
                  value:
                    response: "true"
                    arrayData:
                      - member_id: IDJHID000065
                        fullname: CALVIN
                        upline_sw: IDJKID000136
                        introducer_sw: IDJKID000136
                        sfno: IDJKID000136
                        sfno_reg: IDJKID000136
                        ft_status: N
                        sr_status: Y
                        swb_status: N
                        ft_activation_date: null
                        sr_activation_date: "2025-03-25"
                        swb_activation_date: null
                    message: success
                NotFound:
                  summary: Contoh data tidak ditemukan
                  value:
                    response: "false"
                    arrayData: []
                    message: "Data tidak ditemukan"
          "401":
            description: Unauthorized. Token tidak valid atau tidak ada.
          "405":
            description: Method Not Allowed

  /api/member-check-network:
    post:
      tags:
        - Member
      summary: Check Network Member
      description: >
        Mengecek apakah seorang member (`memberId`) berada dalam jaringan
        tertentu terhadap member lain (`checkNetworkWith`) berdasarkan jenis jaringan (`networkType`).
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - memberId
                - checkNetworkWith
                - networkType
              properties:
                memberId:
                  type: string
                  description: Kode unik member yang ingin dicek.
                  example: "IDJHID000065"
                checkNetworkWith:
                  type: string
                  description: Kode member target untuk membandingkan posisi jaringan.
                  example: "IDJKID000136"
                networkType:
                  type: string
                  description: Jenis jaringan yang ingin dicek.
                  enum: [plan-a, rekruiter, smart-reward]
                  example: "plan-a"
      responses:
        "200":
          description: Hasil pengecekan jaringan member.
          content:
            application/json:
              examples:
                DataFound:
                  summary: Contoh response jika Member berada dalam 1 jaringan
                  value:
                    response: "true"
                    arrayData:
                      - member_id: "IDJHID000065"
                        fullname: "CALVIN"
                        upline_sw: "IDJKID000136"
                        introducer_sw: "IDJKID000136"
                        sfno: "IDJKID000136"
                        sfno_reg: "IDJKID000136"
                        no_ktp: "0253022105670001"
                        email: "calvin_intl@yahoo.com"
                        no_hp: "081808070888"
                        stockist_code: "IDST373"
                    message: "ID Member IDJHID000065 1 jaringan Sponsor PLAN A dengan member IDJKID000136"
                DataNotFound:
                  summary: Contoh response jika Member TIDAK dalam 1 jaringan
                  value:
                    response: "false"
                    arrayData: []
                    message: "Member tidak 1 jaringan"
        "400":
          description: Invalid JSON payload atau parameter tidak valid.
        "401":
          description: Unauthorized. Token tidak valid atau tidak ada.
        "405":
          description: Method Not Allowed. Harus menggunakan POST.

  /api/member-check-data:
    get:
      tags:
        - Member
      summary: Cek data member
      description: >
        Mengecek data member berdasarkan salah satu parameter query:
        - **memberID**
        - **noKTP**
        - **noHP**
        - **email**

        Hanya salah satu parameter yang boleh dikirim dalam 1 request.
      parameters:
        - name: memberID
          in: query
          schema:
            type: string
          required: false
          description: ID member
        - name: noKTP
          in: query
          schema:
            type: string
          required: false
          description: Nomor KTP
        - name: noHP
          in: query
          schema:
            type: string
          required: false
          description: Nomor handphone
        - name: email
          in: query
          schema:
            type: string
          required: false
          description: Email member
      responses:
        "200":
          description: Data member ditemukan
          content:
            application/json:
              examples:
                MemberID:
                  summary: Contoh response pencarian dengan memberID
                  value:
                    response: "true"
                    arrayData:
                      - member_id: IDJHID000065
                        fullname: CALVIN
                        upline_sw: IDJKID000136
                        introducer_sw: IDJKID000136
                        sfno: IDJKID000136
                        sfno_reg: IDJKID000136
                        no_ktp: "09887887888723"
                        email: dion@gmail.com
                        no_hp: "08999898"
                        stockist_code: BID06
                    message: success
                NoKTP_Email_HP:
                  summary: Contoh response pencarian dengan noKTP / noHP / email
                  value:
                    response: "true"
                    arrayData:
                      - member_id: IDJHID000065
                        fullname: CALVIN
                        no_ktp: "09887887888723"
                        email: dion@gmail.com
                        no_hp: "08999898"
                    message: success
                NotFound:
                  summary: Contoh response data tidak ditemukan
                  value:
                    response: "false"
                    arrayData: []
                    message: "Data tidak ditemukan"
        "400":
          description: Parameter tidak valid (lebih dari satu dikirim)
        "401":
          description: Unauthorized (token invalid)
        "405":
          description: Method Not Allowed. Harus menggunakan GET.

  /api/member-list-sk:
    get:
      summary: Daftar Starterkit Member
      description: Mengambil daftar produk starterkit member, paket membership ini hanya ditampilkan jika pilihan marketing plan nya adalah `Plan A` atau `RO Smart Plan`.
      tags:
        - Member
      responses:
        "200":
          description: Response sukses
          content:
            application/json:
              schema:
                type: object
                properties:
                  response:
                    type: string
                    example: "true"
                  arrayData:
                    type: array
                    items:
                      type: object
                      properties:
                        prdcd:
                          type: string
                          example: "SK008"
                        prdnm:
                          type: string
                          example: "Join Member Free Susu Skim 15Sct"
                        prdcdcat:
                          type: string
                          example: "5"
                        prdnmcatnm:
                          type: string
                          example: "Health Drinks"
                        img_url:
                          type: string
                          format: uri
                          example: "https://www.k-net.co.id/assets/images/products/thumb/SUSU-SKIM-15.jpeg"
                        price_w:
                          type: number
                          example: 200000
                        price_e:
                          type: number
                          example: 210000
                        price_cw:
                          type: number
                          example: 200000
                        price_ce:
                          type: number
                          example: 210000
                        bv:
                          type: number
                          example: 0
                        weight:
                          type: number
                          example: 0.3
                        is_charge_ship:
                          type: string
                          enum: ["0", "1"]
                          example: "1"
                  message:
                    type: string
                    example: "success"
        "405":
          description: Method tidak diizinkan
          content:
            application/json:
              schema:
                type: object
                properties:
                  response:
                    type: string
                    example: "false"
                  message:
                    type: string
                    example: "Method Not Allowed. Use GET."

  /api/product-single:
    get:
      tags:
        - Product
      summary: Get single product Plan A dan RO Smart Plan
      description: >
        Mengambil detail 1 produk Marketing Plan **Plan A** atau **RO Smart Plan** dari system yang bertipe produk single / bukan bundling atau produk satuan.
      responses:
        "200":
          description: Response hasil ambil produk Plan A
          content:
            application/json:
              examples:
                Success:
                  summary: Contoh response berhasil
                  value:
                    response: "true"
                    arrayData:
                      prdcd: "AYU002E"
                      prdnm: "K-Ayurveda Ayuasmo 60"
                      prdcdcat: "1"
                      prdnmcatnm: "Ayurveda Series"
                      img_url: "https://www.k-net.co.id/assets/images/products/thumb/AYUASMO-60.jpg"
                      price_w: 360000
                      price_e: 385000
                      price_cw: 432000
                      price_ce: 462000
                      bv: 45
                      weight: 0.1
                      ecomm_status: "1"
                      is_discontinue: "0"
                      max_order: 100
                      prd_start_on: "2022-12-07 00:00:00"
                      prd_end_on: null
                      flag_showcustomer: 1
                    message: "success"
                NotFound:
                  summary: Contoh response jika produk tidak ditemukan
                  value:
                    response: "false"
                    arrayData: {}
                    message: "Data tidak ditemukan"
        "401":
          description: Unauthorized. Token tidak valid atau tidak ada.
        "405":
          description: Method Not Allowed. Gunakan GET.
  /api/product-bundle/{marketing_plan_id}:
    get:
      tags:
        - Product
      summary: Get List Kategori Paket Promo by Marketing Plan
      description: |
        Mengambil daftar paket produk atau Bundling berdasarkan **ID Marketing Plan**.  
        - Untuk marketing plan **Plan A**, **RO**, **Monthly Bonus**, jenis paket bisa langsung terlihat.  
        - Untuk marketing plan **Fast Track**, paket masih terbagi ke dalam beberapa pengelompokan:  
          1. Aktifasi Silver  
          2. Aktifasi Gold  
          3. Aktifasi Platinum
        - Untuk marketing plan **Special Weekly Bonus**, paket masih terbagi ke dalam beberapa pengelompokan:  
          1. Aktivasi Special Weekly Bonus (Member belum pernah aktifasi Weekly Bonus dan LifeStyle)  
          2. Upgrade LifeStyle ke Special Weekly (Member sudah pernah aktifasi LifeStyle tapi belum pernah aktifasi Weekly Bonus)
          3. Upgrade LifeStyle & Weekly ke Special Weekly (Member sudah pernah aktifasi LifeStyle dan Weekly Bonus)
      parameters:
        - name: marketing_plan_id
          in: path
          required: true
          description: ID Marketing Plan
          schema:
            type: integer
            example: 2
      responses:
        "200":
          description: Hasil request daftar paket promo
          content:
            application/json:
              examples:
                Success1:
                  summary: Contoh response List Paket untuk Plan A, RO, Monthly Bonus
                  value:
                    response: "true"
                    arrayData:
                      - id_group_promo: 461
                        nama_group_promo: "2 BOX AYURVEDA 30 CAPS"
                        tipe: "Plan A"
                      - id_group_promo: 460
                        nama_group_promo: "2 BOX AYURVEDA 60 CAPS"
                        tipe: "Plan A"
                      - id_group_promo: 861
                        nama_group_promo: "4 KOPI DURIAN"
                        tipe: "Plan A"
                    message: "success"
                Success2:
                  summary: Contoh response List Paket untuk Fast Track, Special Weekly Bonus
                  value:
                    response: "true"
                    arrayData:
                      - type: "full"
                        name: "AKTIVASI BUNDLING SPESIAL WEEKLY BONUS"
                        data:
                          - id_group_promo: 857
                            nama_group_promo: "1 NEXLIFE + 1 FILTER + 1 K-ION NANO SMART EYE"
                            tipe: "special_weekly_bonus"
                      - type: "weekly_swb"
                        name: "UPGRADE LIFESTYLE + SPESIAL WEEKLY BONUS"
                        data:
                          - id_group_promo: 858
                            nama_group_promo: "1 NANO WRIST + 2 LUXEIR + 1 K-SOMNUS + 1 PREM 7 SUNGLASS"
                            tipe: "special_weekly_bonus"
                      - type: "only_swb"
                        name: "UPGRADE SPESIAL WEEKLY BONUS"
                        data:
                          - id_group_promo: 859
                            nama_group_promo: "2 FILTER NEXLIFE + 1 K-SOMNUS + 1 PREM 8"
                            tipe: "special_weekly_bonus"
                    message: "success"
                NotFound:
                  summary: Contoh response data tidak ditemukan
                  value:
                    response: "false"
                    arrayData: []
                    message: "Data tidak ditemukan"
        "401":
          description: Unauthorized. Token tidak valid atau tidak ada.
        "405":
          description: Method Not Allowed. Gunakan GET.
  /api/product-bundle-list/{id_group_promo}:
    get:
      tags:
        - Product
      summary: Get List Paket Promo by Group ID Promo
      description: >
        Mengambil daftar List Paket Promo berdasarkan **Group ID Promo**. Ini hanya digunakan pada marketing Plan **Plan A** dan **RO**. 
        Untuk marketing Plan lain (Fast Track, Special Weekly Bonus, Monthly Bonus) silakan langsung gunakan endpoint `/api/product-bundle-detail/{id_paket}`.
        Endpoint ini menerima parameter `id_group_promo` pada path.
      parameters:
        - name: id_group_promo
          in: path
          required: true
          description: ID Group Promo
          schema:
            type: integer
            example: 539
      security:
        - bearerAuth: []
      responses:
        "200":
          description: Berhasil ambil data list bundling
          content:
            application/json:
              example:
                response: "true"
                arrayData:
                  - id: 539
                    nama_promo: "4 CHLOROPHYLL"
                    nama_pendek_promo: "4 CHLOROPHYLL"
                    status: "Aktif"
                    start_dt: null
                    end_dt: null
                    bv: 94
                    price_w: 600000
                    suffix_digit: 3
                message: "success"
        "404":
          description: Data tidak ditemukan
          content:
            application/json:
              example:
                response: "false"
                arrayData: []
                message: "Data tidak ditemukan"
        "405":
          description: Method Not Allowed (harus GET)
          content:
            application/json:
              example:
                response: "false"
                message: "Method Not Allowed. Use GET."

  /api/product-bundle-detail/{id_paket}:
    get:
      tags:
        - Product
      summary: Get Paket Detail by ID Promo
      description: >
        Mengambil detail paket bundling produk berdasarkan **id** pada API api/product-bundle-list  
        Response terdiri dari informasi **header promo**, **produk fixed**, dan **produk varian** dengan daftar variannya.
      parameters:
        - name: id_paket
          in: path
          required: true
          description: ID Paket Promo
          schema:
            type: integer
            example: 833
      responses:
        "200":
          description: Detail paket bundling berdasarkan ID promo
          content:
            application/json:
              schema:
                type: object
                properties:
                  response:
                    type: string
                    example: "true"
                  arrayData:
                    type: object
                    properties:
                      header:
                        type: array
                        items:
                          type: object
                          properties:
                            id_promo:
                              type: integer
                              example: 833
                            nama_promo:
                              type: string
                              example: "JULEHA I"
                            status:
                              type: string
                              example: "0"
                            prefix_promo:
                              type: string
                              example: "PJL"
                            start_dt:
                              type: string
                              example: "2025-07-08 00:00"
                            end_dt:
                              type: string
                              example: "2025-07-08 00:00"
                            bv:
                              type: integer
                              example: 100
                            cv:
                              type: integer
                              example: 0
                            price_w:
                              type: integer
                              example: 863000
                            price_e:
                              type: integer
                              example: 924000
                            price_tl:
                              type: integer
                              example: 71
                            price_cw:
                              type: integer
                              example: 863000
                            price_ce:
                              type: integer
                              example: 924000
                            price_tle:
                              type: integer
                              example: 71
                            max_tot_varian:
                              type: integer
                              example: 3
                            suffix_digit:
                              type: integer
                              example: 3
                            group_id_promo:
                              type: integer
                              example: 60
                      productFixed:
                        type: array
                        items:
                          type: object
                          properties:
                            kode_product:
                              type: string
                              example: "KMAPS-A"
                            product_name:
                              type: string
                              example: "FREE KAOS K-MART APPS ALLSIZE"
                            prefix:
                              type: string
                              example: ""
                            max_qty:
                              type: integer
                              example: 1
                            jenis_varian:
                              type: string
                              example: "-"
                            icon:
                              type: string
                              nullable: true
                              example: null
                            shortDesc:
                              type: string
                              example: ""
                      productVarian:
                        type: array
                        items:
                          type: object
                          properties:
                            prefix:
                              type: string
                              example: "KP8"
                            jenis_varian:
                              type: string
                              example: "K-ION NANO PREMIUM 8"
                            max_qty:
                              type: integer
                              example: 1
                            hitungan_qty:
                              type: integer
                              example: 1
                            list_varian:
                              type: array
                              items:
                                type: object
                                properties:
                                  kode_product:
                                    type: string
                                    example: "KP8BG"
                                  product_name:
                                    type: string
                                    example: "K-ION NANO PREMIUM 8 BLACK GOLD"
                                  prefix:
                                    type: string
                                    example: "KP8"
                                  status:
                                    type: string
                                    example: "1"
                                  hitungan_qty:
                                    type: integer
                                    example: 1
                                  icon:
                                    type: string
                                    example: "https://www.k-net.co.id/assets/nbs/satuan/K-ION NANO REGULER.jpg"
                                  shortDesc:
                                    type: string
                                    example: ""
                  message:
                    type: string
                    example: "success"
              examples:
                adaData:
                  summary: Contoh response jika data ada
                  value:
                    response: "true"
                    arrayData:
                      header:
                        - id_promo: 833
                          nama_promo: "JULEHA I"
                          status: "0"
                          prefix_promo: "PJL"
                          start_dt: "2025-07-08 00:00"
                          end_dt: "2025-07-08 00:00"
                          bv: 100
                          cv: 0
                          price_w: 863000
                          price_e: 924000
                          price_tl: 71
                          price_cw: 863000
                          price_ce: 924000
                          price_tle: 71
                          max_tot_varian: 3
                          suffix_digit: 3
                          group_id_promo: 60
                      productFixed:
                        - kode_product: "KMAPS-A"
                          product_name: "FREE KAOS K-MART APPS ALLSIZE"
                          prefix: ""
                          max_qty: 1
                          jenis_varian: "-"
                          icon: null
                          shortDesc: ""
                      productVarian:
                        - prefix: "KP8"
                          jenis_varian: "K-ION NANO PREMIUM 8"
                          max_qty: 1
                          hitungan_qty: 1
                          list_varian:
                            - kode_product: "KP8BG"
                              product_name: "K-ION NANO PREMIUM 8 BLACK GOLD"
                              prefix: "KP8"
                              status: "1"
                              hitungan_qty: 1
                              icon: ""
                              shortDesc: ""
                            - kode_product: "KP8WM"
                              product_name: "K-ION NANO PREMIUM 8 WHITE MATTE"
                              prefix: "KP8"
                              status: "1"
                              hitungan_qty: 1
                              icon: ""
                              shortDesc: ""
                    message: "success"
                tidakAdaData:
                  summary: Contoh response jika tidak ada data
                  value:
                    response: "false"
                    arrayData: {}
                    message: "Data promo tidak ditemukan"
        "401":
          description: Unauthorized. Token tidak valid atau tidak ada.
        "405":
          description: Method Not Allowed. Gunakan GET.

  /api/product-generate-code:
    post:
      tags:
        - Product
      summary: Generate Product Code
      description: >
        Endpoint untuk generate product code berdasarkan promo dan daftar produk yang dipilih.
        - Wajib kirim `id_group_promo`.  
        - `productFixed` atau `productVarian` salah satu harus ada isinya, bisa juga keduanya.  
        - Hasil berupa detail produk dan header informasi harga.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                id_group_promo:
                  type: integer
                  example: 76
                productFixed:
                  type: array
                  items:
                    type: object
                    properties:
                      kode_product:
                        type: string
                        example: "KMAPS-A"
                      qty:
                        type: integer
                        example: 1
                productVarian:
                  type: array
                  items:
                    type: object
                    properties:
                      kode_product:
                        type: string
                        example: "HC048L"
                      qty:
                        type: integer
                        example: 2
              required:
                - id_group_promo
      responses:
        "200":
          description: Berhasil generate product code
          content:
            application/json:
              example:
                response: "true"
                status: "1"
                header:
                  - prdcd: "QPCPH005"
                    prdnm: "2 K-Man & 2 K-Queen"
                    bv: "0"
                    price_w: "2500000.00"
                    price_e: "2675000.00"
                    price_tl: "250.00"
                    price_cw: "2500000.00"
                    price_ce: "2675000.00"
                    price_ctl: "250.00"
                    weight: "0.86"
                    rspoin: 1
                    is_reseller: "0"
                    cust_value: "2200000.00"
                detail:
                  - kode: "HC048L"
                    nama: "K-Man L"
                    qty: "1.00"
                  - kode: "HC055BLS"
                    nama: "K-Queen Seasonal Single Baby Pink L"
                    qty: "2.00"
        "400":
          description: Request tidak valid
          content:
            application/json:
              example:
                response: "false"
                message: "Minimal salah satu dari productFixed atau productVarian harus diisi."
        "405":
          description: Method salah (harus POST)
          content:
            application/json:
              example:
                response: "false"
                message: "Method Not Allowed. Use POST."

  /api/trx/save-temp:
    post:
      summary: Save Temporary Transaction
      description: Simpan transaksi sementara sebelum finalisasi.
      tags:
        - Transaction
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - transaction_id
                - member_id
                - periode_bonus
                - stockist_code
                - pricecode
                - total_dp
                - total_bv
                - tipe_plan
                - is_newmember
                - expiredt
                - products
              properties:
                transaction_id:
                  type: string
                  example: "KINV-293113231"
                member_id:
                  type: string
                  example: "IDSPAAA66834"
                periode_bonus:
                  type: string
                  format: date
                  example: "2025-10-01"
                stockist_code:
                  type: string
                  example: "BID06"
                pricecode:
                  type: string
                  example: "12W4"
                total_dp:
                  type: number
                  example: 12000000
                total_bv:
                  type: number
                  example: 100
                tipe_plan:
                  type: integer
                  example: 1
                is_newmember:
                  type: integer
                  description: "0 = existing member, 1 = new member"
                  example: 0
                expiredt:
                  type: string
                  format: date-time
                  description: "Tanggal & waktu kedaluwarsa transaksi (format: 'YYYY-MM-DD HH:MM:SS'). Jika tidak dikirim, sistem otomatis set 2 jam setelah waktu sekarang."
                  example: "2025-10-18 14:30:00"
                newmember_data:
                  type: object
                  required:
                    - fullname
                    - no_ktp
                    - no_hp
                    - email
                    - address
                    - sfno_reg
                    - sfno
                    - introducer_sw
                    - upline_sw
                    - stockist_code
                  properties:
                    fullname:
                      type: string
                      example: "ADADADDA"
                    no_ktp:
                      type: string
                      example: "1311231313313S"
                    birthdt:
                      type: string
                      example: "2025-10-10"
                    no_hp:
                      type: string
                      example: "087780441023"
                    email:
                      type: string
                      format: email
                      example: "dion@gmail.com"
                    address:
                      type: string
                      example: "JLN SADSDAD NO 23"
                    sfno_reg:
                      type: string
                      example: "ASADADA"
                    sfno:
                      type: string
                      example: "ASDADAD"
                    introducer_sw:
                      type: string
                      example: "ADADADAD"
                    upline_sw:
                      type: string
                      example: "ADADADAD"
                    stockist_code:
                      type: string
                      example: "BID06"
                products:
                  type: array
                  items:
                    type: object
                    required:
                      - prdcd
                      - prdnm
                      - qty
                      - dp
                      - bv
                    properties:
                      prdcd:
                        type: string
                        example: "IDSADA"
                      prdnm:
                        type: string
                        example: "NAMA"
                      qty:
                        type: integer
                        example: 1
                      dp:
                        type: number
                        example: 1000000
                      bv:
                        type: number
                        example: 80
      responses:
        "200":
          description: Transaksi berhasil disimpan
          content:
            application/json:
              schema:
                type: object
                properties:
                  response:
                    type: string
                    example: true
                  message:
                    type: string
                    example: "Temporary transaction saved successfully"
                  data:
                    type: object
                    example:
                      transaction_id: "KINV-293113231"
        "400":
          description: Request invalid
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: error
                  message:
                    type: string
                    example: "Invalid request data"
        "405":
          description: Method salah (harus POST)
          content:
            application/json:
              example:
                response: "false"
                message: "Method Not Allowed. Use POST."

  /api/trx/get-last-number:
    post:
      tags:
        - Transaction
      summary: Create or Get Last Sequence Number
      description: >
        Membuat record baru di tabel sequence `KSEQ_<YYMM>` berdasarkan `trx_type`, `year`, dan `month`.
        Jika `trx_type` = `invoice`, maka data akan diinsert ke tabel `KSEQ_<YYMM>`.
        Response berisi `last_number` hasil auto increment (`seqId`).
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - trx_type
                - year
                - month
              properties:
                trx_type:
                  type: string
                  example: invoice
                  description: Jenis transaksi (saat ini hanya mendukung "invoice")
                year:
                  type: integer
                  example: 2025
                  description: Tahun transaksi (4 digit)
                month:
                  type: integer
                  example: 1
                  description: Bulan transaksi (1–12)
      responses:
        "200":
          description: Berhasil insert data sequence
          content:
            application/json:
              schema:
                type: object
                properties:
                  response:
                    type: string
                    example: "true"
                  message:
                    type: string
                    example: "Insert ke KSEQ_2501 berhasil"
                  arrayData:
                    type: array
                    items:
                      type: object
                      properties:
                        last_number:
                          type: integer
                          example: 42
                          description: Nilai seqId terakhir yang baru dibuat

        "400":
          description: Bad Request / Missing field
          content:
            application/json:
              schema:
                type: object
                properties:
                  response:
                    type: string
                    example: "false"
                  message:
                    type: string
                    example: "Missing field: month"
        "405":
          description: Invalid HTTP Method
          content:
            application/json:
              schema:
                type: object
                properties:
                  response:
                    type: string
                    example: "false"
                  message:
                    type: string
                    example: "Method Not Allowed. Use POST."
        "500":
          description: Error saat eksekusi query MSSQL
          content:
            application/json:
              schema:
                type: object
                properties:
                  response:
                    type: string
                    example: "false"
                  message:
                    type: string
                    example: "Gagal insert ke KSEQ_2501"

  /api/trx/nexus-commision-report:
    post:
      summary: Get Nexus Bonus Commission All Member
      description: Ambil data komisi bonus Nexus berdasarkan periode tanggal `from` dan `to`.
      tags:
        - Nexus
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - from
                - to
              properties:
                from:
                  type: string
                  format: date
                  example: "2025-10-01"
                  description: Tanggal mulai periode (YYYY-MM-DD)
                to:
                  type: string
                  format: date
                  example: "2025-10-07"
                  description: Tanggal akhir periode (YYYY-MM-DD)
      responses:
        "200":
          description: Response sukses dengan data bonus
          content:
            application/json:
              schema:
                type: object
                properties:
                  response:
                    type: string
                    example: "true"
                    description: Indikasi bahwa request berhasil
                  arrayData:
                    type: array
                    description: Daftar detail bonus per user
                    items:
                      type: object
                      properties:
                        username:
                          type: string
                          example: "IDSULAA00214"
                        member_name:
                          type: string
                          example: "TESTING"
                        fast_sponsor_bonus:
                          type: string
                          example: "0.0000"
                        fast_sponsor_bonus_RP:
                          type: string
                          example: "0.0000"
                        fast_pairing_bonus:
                          type: string
                          example: "0.0000"
                        fast_pairing_bonus_RP:
                          type: string
                          example: "0.0000"
                        fast_matching_bonus:
                          type: string
                          example: "0.0000"
                        fast_matching_bonus_RP:
                          type: string
                          example: "0.0000"
                        smart_sponsor_bonus:
                          type: string
                          example: "29.4100"
                        smart_sponsor_bonus_RP:
                          type: string
                          example: "500000.0000"
                        smart_week_pairing_bonus:
                          type: string
                          example: "10.6700"
                        smart_week_pairing_bonus_RP:
                          type: string
                          example: "200000.0000"
                        smart_month_pairing_bonus:
                          type: string
                          example: "10.6700"
                        smart_month_pairing_bonus_RP:
                          type: string
                          example: "200000.0000"
                        swb_pairing_bonus_RP:
                          type: string
                          example: "200000.0000"
        "400":
          description: Request tidak valid
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: integer
                    example: 1
                  status_msg:
                    type: string
                    example: "Invalid request payload"
        "500":
          description: Internal server error
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: integer
                    example: 99
                  status_msg:
                    type: string
                    example: "Internal server error"

  /api/trx/nexus-commision-member:
    post:
      summary: Get Nexus Commission per Member
      description: Ambil data komisi Nexus per member berdasarkan periode tanggal `member_id`, `from` dan `to`.
      tags:
        - Nexus
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - member_id
                - from
                - to
              properties:
                member_id:
                  type: string
                  format: date
                  example: "IDJTID000065"
                  description: Member ID
                from:
                  type: string
                  format: date
                  example: "2025-10-01"
                  description: Tanggal mulai periode (format YYYY-MM-DD)
                to:
                  type: string
                  format: date
                  example: "2025-10-07"
                  description: Tanggal akhir periode (format YYYY-MM-DD)
      responses:
        "200":
          description: Response sukses dengan data bonus per member
          content:
            application/json:
              schema:
                type: object
                properties:
                  response:
                    type: string
                    example: "true"
                    description: Indikasi bahwa request berhasil
                  arrayData:
                    type: array
                    description: Daftar detail bonus
                    items:
                      type: object
                      properties:
                        fast_sponsor_bonus:
                          type: string
                          example: "0.0000"
                        fast_sponsor_bonus_RP:
                          type: string
                          example: "0.0000"
                        fast_pairing_bonus:
                          type: string
                          example: "0.0000"
                        fast_pairing_bonus_RP:
                          type: string
                          example: "0.0000"
                        fast_matching_bonus:
                          type: string
                          example: "0.0000"
                        fast_matching_bonus_RP:
                          type: string
                          example: "0.0000"
                        smart_sponsor_bonus:
                          type: string
                          example: "29.4100"
                        smart_sponsor_bonus_RP:
                          type: string
                          example: "500000.0000"
                        smart_week_pairing_bonus:
                          type: string
                          example: "10.6700"
                        smart_week_pairing_bonus_RP:
                          type: string
                          example: "200000.0000"
                        smart_month_pairing_bonus:
                          type: string
                          example: "10.6700"
                        smart_month_pairing_bonus_RP:
                          type: string
                          example: "200000.0000"
                        swb_pairing_bonus_RP:
                          type: string
                          example: "200000.0000"
        "400":
          description: Request tidak valid
          content:
            application/json:
              schema:
                type: object
                properties:
                  response:
                    type: string
                    example: "false"
                  message:
                    type: string
                    example: "Invalid request payload"
        "500":
          description: Internal server error
          content:
            application/json:
              schema:
                type: object
                properties:
                  response:
                    type: string
                    example: "false"
                  message:
                    type: string
                    example: "Internal server error"
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
