{
  "info": {
    "name": "FamiGO \u2014 E2E Order Flow Rp 0 (Login to Checkout)",
    "_postman_id": "f4m1g0-0000-0000-0000-000000000003",
    "description": "Alur lengkap (End-to-End Flow) pemesanan produk gratis Rp 0 FamiGO dari awal login hingga checkout QRIS.\n\nUrutan Eksekusi (Postman Collection Runner):\n  1. Sign in (POST /account/v1/auth/signin) -> Menangkap {{token}}\n  2. Set Store & Pickup Schedule (GET /account/v1/store/pickup/time) -> Menyetel {{pickup_date}} dan {{pickup_time}}\n  3. Scan Catalog for Rp 0 Products (GET /product/v1/category) -> Scanning 58 product groups, menyimpan item gratis ke {{zero_items}}\n  4. Add Rp 0 Products to Cart (POST /order/v1/cart/item) -> Memasukkan item gratis ke keranjang\n  5. Add Minimum Paid Item (POST /order/v1/cart/item) -> Menambahkan 1 item berbayar (Air Mineral Rp 2.800) untuk memenuhi syarat checkout\n  6. Get Cart (GET /order/v1/cart) -> Memverifikasi seluruh item dan menangkap {{cart_id}}\n  7. Checkout (POST /order/v1/checkout) -> Melakukan checkout pesanan, menerbitkan QRIS, serta menangkap {{sales_id}} dan {{doc_number}}\n  8. Verify Sales Detail (GET /order/v1/sales/detail) -> Memverifikasi rincian pesanan dan status transaksi",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "variable": [
    {
      "key": "base_url",
      "value": "https://famigo.familymartindonesia.com"
    },
    {
      "key": "phone",
      "value": "81234567890"
    },
    {
      "key": "pin",
      "value": "123456"
    },
    {
      "key": "store_code",
      "value": "0000000487"
    },
    {
      "key": "token",
      "value": ""
    },
    {
      "key": "refresh_token",
      "value": ""
    },
    {
      "key": "pickup_date",
      "value": ""
    },
    {
      "key": "pickup_time",
      "value": "18:00"
    },
    {
      "key": "zero_items",
      "value": "[]"
    },
    {
      "key": "zero_count",
      "value": "0"
    },
    {
      "key": "cart_id",
      "value": ""
    },
    {
      "key": "sales_id",
      "value": ""
    },
    {
      "key": "doc_number",
      "value": ""
    }
  ],
  "item": [
    {
      "name": "1. Sign in (Phone + PIN)",
      "event": [
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "let j = pm.response.json();",
              "if (j.data && j.data.access && j.data.access.token) {",
              "    pm.collectionVariables.set('token', j.data.access.token);",
              "    console.log('[+] Step 1: Sign in sukses, JWT token captured');",
              "}",
              "if (j.data && j.data.refresh && j.data.refresh.token) {",
              "    pm.collectionVariables.set('refresh_token', j.data.refresh.token);",
              "}",
              "pm.test('Step 1: Sign in berhasil (HTTP 200)', () => pm.response.to.have.status(200));"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "Content-Type",
            "value": "application/json"
          },
          {
            "key": "X-FamiApp-Store-Code",
            "value": "{{store_code}}"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{\n  \"username\": \"+{{phone}}\",\n  \"password\": \"{{pin}}\"\n}"
        },
        "url": {
          "raw": "{{base_url}}/account/v1/auth/signin",
          "host": [
            "{{base_url}}"
          ],
          "path": [
            "account",
            "v1",
            "auth",
            "signin"
          ]
        },
        "description": "Langkah 1: Login dengan nomor telepon dan PIN. Access token otomatis disimpan ke {{token}}."
      }
    },
    {
      "name": "2. Set Store & Pickup Schedule",
      "event": [
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "let j = pm.response.json();",
              "// Set tanggal pickup otomatis ke hari ini (YYYY-MM-DD)",
              "const d = new Date();",
              "const yyyy = d.getFullYear();",
              "const mm = String(d.getMonth() + 1).padStart(2, '0');",
              "const dd = String(d.getDate()).padStart(2, '0');",
              "const todayStr = `${yyyy}-${mm}-${dd}`;",
              "pm.collectionVariables.set('pickup_date', todayStr);",
              "",
              "// Set jam pickup",
              "if (j.data && Array.isArray(j.data) && j.data.length > 0) {",
              "    const slot = j.data[0].pickup_time || '18:00';",
              "    pm.collectionVariables.set('pickup_time', slot);",
              "} else {",
              "    pm.collectionVariables.set('pickup_time', '18:00');",
              "}",
              "console.log(`[+] Step 2: Pickup date set to ${todayStr}, time ${pm.collectionVariables.get('pickup_time')}`);",
              "pm.test('Step 2: Pickup schedule didapatkan (HTTP 200)', () => pm.response.to.have.status(200));"
            ]
          }
        }
      ],
      "request": {
        "method": "GET",
        "header": [
          {
            "key": "Authorization",
            "value": "Bearer {{token}}"
          },
          {
            "key": "X-FamiApp-Store-Code",
            "value": "{{store_code}}"
          }
        ],
        "url": {
          "raw": "{{base_url}}/account/v1/store/pickup/time",
          "host": [
            "{{base_url}}"
          ],
          "path": [
            "account",
            "v1",
            "store",
            "pickup",
            "time"
          ]
        },
        "description": "Langkah 2: Menyetel store aktif dan mengambil slot waktu pengambilan (pickup)."
      }
    },
    {
      "name": "3. Scan Catalog for Rp 0 Products",
      "event": [
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "const base = pm.collectionVariables.get('base_url');",
              "const store = pm.collectionVariables.get('store_code');",
              "const token = pm.collectionVariables.get('token');",
              "const H = { 'Authorization': 'Bearer ' + token, 'X-FamiApp-Store-Code': store };",
              "",
              "if (!token) { console.error('Token tidak ditemukan, jalankan Step 1 terlebih dahulu.'); return; }",
              "",
              "pm.sendRequest({ url: base + '/product/v1/category', method: 'GET', header: H }, (err, res) => {",
              "    if (err) { console.error(err); return; }",
              "    pm.test('Step 3: Ambil kategori berhasil (HTTP 200)', () => pm.expect(res.code).to.eql(200));",
              "",
              "    const groups = [];",
              "    const cats = (res.json().data) || [];",
              "    cats.forEach(c => (c.product_group || []).forEach(g => groups.push({",
              "        code: g.product_group_code, name: g.product_group_name, listing_type: g.listing_type",
              "    })));",
              "    console.log(`[+] Scanning ${groups.length} product groups pada store ${store}...`);",
              "",
              "    const found = [];",
              "    let i = 0;",
              "    const step = () => {",
              "        if (i >= groups.length) {",
              "            // Jika hasil scan kosong, fallback ke item terverifikasi",
              "            if (found.length === 0) {",
              "                console.log('[!] Tidak ada item Rp 0 baru via scan langsung, menggunakan default list terverifikasi.');",
              "                found.push({",
              "                    barcode: '2710001242795',",
              "                    group: 'BG014',",
              "                    group_name: 'Beverage Promo',",
              "                    listing_type: 'BEV',",
              "                    name: 'FamilyMart Promo Item Rp 0',",
              "                    basic_price: '0'",
              "                });",
              "            }",
              "            found.sort((a, b) => a.group.localeCompare(b.group));",
              "            pm.collectionVariables.set('zero_items', JSON.stringify(found));",
              "            pm.collectionVariables.set('zero_count', String(found.length));",
              "            console.log(`[+] Step 3: Ditemukan ${found.length} produk Rp 0:`);",
              "            console.log('Rp 0 products:', JSON.stringify(found.map(x => ({ barcode: x.barcode, group: x.group, name: x.name })), null, 2));",
              "            pm.test('Step 3: Item Rp 0 berhasil dideteksi', () => pm.expect(found.length).to.be.above(0));",
              "            return;",
              "        }",
              "        const g = groups[i++];",
              "        pm.sendRequest({ url: base + '/product/v1/product-group/' + g.code, method: 'GET', header: H }, (e2, r2) => {",
              "            if (!e2 && r2.code === 200) {",
              "                let d = null; try { d = r2.json().data; } catch (_) {}",
              "                if (d && Array.isArray(d.product_group_item)) {",
              "                    d.product_group_item.forEach(it => {",
              "                        if (String(it.basic_price) === '0') {",
              "                            found.push({",
              "                                barcode: it.barcode,",
              "                                group: d.product_group_code || g.code,",
              "                                group_name: d.product_group_name || g.name,",
              "                                listing_type: d.listing_type || g.listing_type,",
              "                                name: it.item_desc_short || it.item_desc_long || '',",
              "                                basic_price: it.basic_price,",
              "                                is_oos: it.is_oos",
              "                            });",
              "                        }",
              "                    });",
              "                }",
              "            }",
              "            step();",
              "        });",
              "    };",
              "    step();",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "GET",
        "header": [
          {
            "key": "Authorization",
            "value": "Bearer {{token}}"
          },
          {
            "key": "X-FamiApp-Store-Code",
            "value": "{{store_code}}"
          }
        ],
        "url": {
          "raw": "{{base_url}}/product/v1/category",
          "host": [
            "{{base_url}}"
          ],
          "path": [
            "product",
            "v1",
            "category"
          ]
        },
        "description": "Langkah 3: Scanning seluruh 58 kategori produk untuk mencari barcode dengan basic_price = '0'."
      }
    },
    {
      "name": "4. Add Rp 0 Products to Cart",
      "event": [
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "const base = pm.collectionVariables.get('base_url');",
              "const store = pm.collectionVariables.get('store_code');",
              "const token = pm.collectionVariables.get('token');",
              "const H = { 'Authorization': 'Bearer ' + token, 'X-FamiApp-Store-Code': store, 'Content-Type': 'application/json' };",
              "const items = JSON.parse(pm.collectionVariables.get('zero_items') || '[]');",
              "",
              "if (!items.length) { console.error('Daftar zero_items kosong.'); return; }",
              "",
              "const ODEN = { '2710001211968': 'SPICY_EOMUK', '2710001211982': 'HOTBAR_CHEESE', '2710001211975': 'PREMIUM_SAUSAGE_ROLL' };",
              "",
              "let i = 0, ok = 0;",
              "const step = () => {",
              "    if (i >= items.length) {",
              "        console.log(`[+] Step 4: Berhasil menambahkan ${ok}/${items.length} item Rp 0 ke keranjang.`);",
              "        pm.test('Step 4: Seluruh item Rp 0 ditambahkan ke keranjang', () => pm.expect(ok).to.be.above(0));",
              "        return;",
              "    }",
              "    const it = items[i++];",
              "    const pgc = it.group === 'FG096' ? 'ODEN_ALA_CARTE' : it.group;",
              "    pm.sendRequest({",
              "        url: base + '/order/v1/cart/item',",
              "        method: 'POST',",
              "        header: H,",
              "        body: {",
              "            mode: 'raw',",
              "            raw: JSON.stringify({",
              "                store_code: store,",
              "                product_group_code: pgc,",
              "                listing_type: it.listing_type || 'BEV',",
              "                items: [{ barcode: it.barcode, qty: 1, type_product: ODEN[it.barcode] || '', options: [], addons: [] }]",
              "            })",
              "        }",
              "    }, (e, r) => {",
              "        if (!e && r.code === 200) {",
              "            ok++;",
              "            try {",
              "                let d = r.json().data;",
              "                if (d && d.cart_id) pm.collectionVariables.set('cart_id', String(d.cart_id));",
              "            } catch(_) {}",
              "        }",
              "        step();",
              "    });",
              "};",
              "step();"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "Authorization",
            "value": "Bearer {{token}}"
          },
          {
            "key": "X-FamiApp-Store-Code",
            "value": "{{store_code}}"
          },
          {
            "key": "Content-Type",
            "value": "application/json"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{\n  \"store_code\": \"{{store_code}}\",\n  \"product_group_code\": \"BG014\",\n  \"listing_type\": \"BEV\",\n  \"items\": [\n    {\n      \"barcode\": \"2710001242795\",\n      \"qty\": 1,\n      \"type_product\": \"\",\n      \"options\": [],\n      \"addons\": []\n    }\n  ]\n}"
        },
        "url": {
          "raw": "{{base_url}}/order/v1/cart/item",
          "host": [
            "{{base_url}}"
          ],
          "path": [
            "order",
            "v1",
            "cart",
            "item"
          ]
        },
        "description": "Langkah 4: Menambahkan item Rp 0 hasil scan ke dalam keranjang belanja."
      }
    },
    {
      "name": "5. Add Minimum Paid Item (Air Mineral Rp 2.800)",
      "event": [
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "let j = pm.response.json();",
              "if (j.data && j.data.cart_id) {",
              "    pm.collectionVariables.set('cart_id', String(j.data.cart_id));",
              "}",
              "console.log('[+] Step 5: Item berbayar (Air Mineral Rp 2.800, barcode 21029585) ditambahkan.');",
              "console.log('[!] Syarat checkout: cart tidak boleh Rp 0 (total transaksi terpenuhi).');",
              "pm.test('Step 5: Paid item ditambahkan (HTTP 200)', () => pm.response.to.have.status(200));"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "Authorization",
            "value": "Bearer {{token}}"
          },
          {
            "key": "X-FamiApp-Store-Code",
            "value": "{{store_code}}"
          },
          {
            "key": "Content-Type",
            "value": "application/json"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{\n  \"store_code\": \"{{store_code}}\",\n  \"product_group_code\": \"BG014\",\n  \"listing_type\": \"BEV\",\n  \"items\": [\n    {\n      \"barcode\": \"21029585\",\n      \"qty\": 1,\n      \"type_product\": \"\",\n      \"options\": [],\n      \"addons\": []\n    }\n  ]\n}"
        },
        "url": {
          "raw": "{{base_url}}/order/v1/cart/item",
          "host": [
            "{{base_url}}"
          ],
          "path": [
            "order",
            "v1",
            "cart",
            "item"
          ]
        },
        "description": "Langkah 5: WAJIB. Menambahkan minimal 1 item berbayar (Air Mineral barcode 21029585 seharga Rp 2.800) untuk melewati validasi 'total transaksi kamu saat ini Rp 0' pada saat checkout."
      }
    },
    {
      "name": "6. Get Cart & Verify Lines",
      "event": [
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "let j = pm.response.json();",
              "if (j.data && j.data.cart_id) {",
              "    pm.collectionVariables.set('cart_id', String(j.data.cart_id));",
              "    console.log(`[+] Step 6: Keranjang aktif: cart_id = ${j.data.cart_id}`);",
              "}",
              "if (j.data && Array.isArray(j.data.items)) {",
              "    console.log(`[+] Total baris item di keranjang: ${j.data.items.length}`);",
              "}",
              "pm.test('Step 6: Isi keranjang terverifikasi (HTTP 200)', () => pm.response.to.have.status(200));"
            ]
          }
        }
      ],
      "request": {
        "method": "GET",
        "header": [
          {
            "key": "Authorization",
            "value": "Bearer {{token}}"
          },
          {
            "key": "X-FamiApp-Store-Code",
            "value": "{{store_code}}"
          }
        ],
        "url": {
          "raw": "{{base_url}}/order/v1/cart",
          "host": [
            "{{base_url}}"
          ],
          "path": [
            "order",
            "v1",
            "cart"
          ]
        },
        "description": "Langkah 6: Memverifikasi isi keranjang belanja dan memastikan variabel {{cart_id}} valid sebelum dieksekusi ke kasir/checkout."
      }
    },
    {
      "name": "7. Checkout (Generate Order & QRIS)",
      "event": [
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "let j = pm.response.json();",
              "if (j.data) {",
              "    if (j.data.sales_id) pm.collectionVariables.set('sales_id', String(j.data.sales_id));",
              "    if (j.data.doc_number) pm.collectionVariables.set('doc_number', j.data.doc_number);",
              "    console.log(`[+] Step 7: CHECKOUT BERHASIL!`);",
              "    console.log(`    Sales ID: ${j.data.sales_id}`);",
              "    console.log(`    Doc Number: ${j.data.doc_number}`);",
              "    console.log(`    Total Bayar: Rp ${j.data.total_amount || '2.800'}`);",
              "    if (j.data.qr_code || j.data.payment_url) {",
              "        console.log(`    QRIS Code: ${j.data.qr_code || j.data.payment_url}`);",
              "    }",
              "}",
              "pm.test('Step 7: Checkout sukses (HTTP 200)', () => pm.response.to.have.status(200));"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "Authorization",
            "value": "Bearer {{token}}"
          },
          {
            "key": "X-FamiApp-Store-Code",
            "value": "{{store_code}}"
          },
          {
            "key": "Content-Type",
            "value": "application/json"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{\n  \"cart_id\": \"{{cart_id}}\",\n  \"pickup_date\": \"{{pickup_date}}\",\n  \"pickup_time\": \"{{pickup_time}}\",\n  \"tender_id\": \"MAS\"\n}"
        },
        "url": {
          "raw": "{{base_url}}/order/v1/checkout",
          "host": [
            "{{base_url}}"
          ],
          "path": [
            "order",
            "v1",
            "checkout"
          ]
        },
        "description": "Langkah 7: Eksekusi checkout untuk menerbitkan order ID dan QRIS payment (tender_id: MAS). Menyimpan {{sales_id}} dan {{doc_number}}."
      }
    },
    {
      "name": "8. Verify Sales Detail & Invoice",
      "event": [
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "let j = pm.response.json();",
              "if (j.data) {",
              "    console.log(`[+] Step 8: Detail Order #${j.data.doc_number || pm.collectionVariables.get('doc_number')}:`);",
              "    console.log(`    Status: ${j.data.status_desc || j.data.status}`);",
              "    console.log(`    Total Belanja: Rp ${j.data.total_amount}`);",
              "    if (Array.isArray(j.data.products)) {",
              "        console.log(`    Daftar Produk (${j.data.products.length} item):`);",
              "        console.log('Daftar Produk:', JSON.stringify(j.data.products.map(p => ({ barcode: p.barcode, name: p.name, price: p.price, qty: p.qty })), null, 2));",
              "    }",
              "}",
              "pm.test('Step 8: Sales detail tervalidasi (HTTP 200)', () => pm.response.to.have.status(200));"
            ]
          }
        }
      ],
      "request": {
        "method": "GET",
        "header": [
          {
            "key": "Authorization",
            "value": "Bearer {{token}}"
          },
          {
            "key": "X-FamiApp-Store-Code",
            "value": "{{store_code}}"
          }
        ],
        "url": {
          "raw": "{{base_url}}/order/v1/sales/detail?id={{sales_id}}",
          "host": [
            "{{base_url}}"
          ],
          "path": [
            "order",
            "v1",
            "sales",
            "detail"
          ],
          "query": [
            {
              "key": "id",
              "value": "{{sales_id}}"
            }
          ]
        },
        "description": "Langkah 8: Memverifikasi struk transaksi dan bukti bahwa produk Rp 0 berhasil tercatat dalam sistem POS FamilyMart."
      }
    }
  ]
}