Skip to main content

Branch-Warehouse Syncing

Dokumentasi lengkap untuk sync dan mapping branch dengan warehouse yang tersedia, termasuk support multiple warehouses per branch dengan priority system.

🎯 Overview

Fitur branch-warehouse syncing memungkinkan:
  • βœ… Auto-detect branch yang belum punya warehouse valid
  • βœ… List available warehouses untuk dipilih
  • βœ… Easy mapping via API
  • βœ… Multiple warehouses per branch (1 default + multiple backup)
  • βœ… Priority system untuk fallback inventory allocation
  • βœ… Monitoring dashboard untuk admin

πŸ“Š Database Schema

Table: branch_warehouses

CREATE TABLE branch_warehouses (
    id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    branch_id BIGINT UNSIGNED NOT NULL,
    warehouse_id BIGINT UNSIGNED NOT NULL,
    priority INT NOT NULL DEFAULT 0 COMMENT '0=default, 1=backup1, 2=backup2, dst',
    is_active TINYINT(1) NOT NULL DEFAULT 1,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    deleted_at TIMESTAMP NULL,
    
    FOREIGN KEY (branch_id) REFERENCES branches(id) ON DELETE CASCADE,
    FOREIGN KEY (warehouse_id) REFERENCES warehouses(id) ON DELETE CASCADE,
    
    UNIQUE KEY uk_branch_warehouse (branch_id, warehouse_id),
    INDEX idx_branch_priority (branch_id, priority),
    INDEX idx_warehouse (warehouse_id),
    INDEX idx_active (is_active)
);

Priority System

  • 0 = Default warehouse (primary)
  • 1 = Backup warehouse 1 (fallback pertama)
  • 2 = Backup warehouse 2 (fallback kedua)
  • 3+ = Backup warehouse berikutnya

πŸ“‘ API Endpoints

1. Get Branch Warehouse Status (Single Branch)

Cek status branch dan warehouse nya, apakah sudah ter-mapping atau belum.
GET /api/v1/syncing/branch/:branch_id/warehouse-status
Authorization: Bearer <jwt_token>
Response Success (Needs Mapping):
{
  "code": 200,
  "message": "Success",
  "data": {
    "branch_id": 1,
    "branch_code": "BRN-MST-DS000001",
    "branch_name": "Branch Pusat",
    "default_warehouse_id": 145,
    "warehouse_exists": false,
    "warehouse_info": null,
    "available_warehouses": [
      {
        "id": 1,
        "warehouse_code": "WH-001",
        "warehouse_name": "Warehouse Utama",
        "warehouse_type": "warehouse",
        "branch_id": null
      },
      {
        "id": 2,
        "warehouse_code": "WH-002",
        "warehouse_name": "Distribution Center",
        "warehouse_type": "distribution_center",
        "branch_id": null
      }
    ],
    "needs_mapping": true
  }
}
Response Success (Already Mapped):
{
  "code": 200,
  "message": "Success",
  "data": {
    "branch_id": 1,
    "branch_code": "BRN-MST-DS000001",
    "branch_name": "Branch Pusat",
    "default_warehouse_id": 1,
    "warehouse_exists": true,
    "warehouse_info": {
      "id": 1,
      "warehouse_code": "WH-001",
      "warehouse_name": "Warehouse Utama",
      "warehouse_type": "warehouse"
    },
    "available_warehouses": null,
    "needs_mapping": false
  }
}

2. Get All Branches Warehouse Status

Cek status semua branch (untuk admin/dashboard monitoring).
GET /api/v1/syncing/branches/warehouse-status?merchant_id=1
Authorization: Bearer <jwt_token>
Response:
{
  "code": 200,
  "message": "Success",
  "data": [
    {
      "branch_id": 1,
      "branch_code": "BRN-MST-DS000001",
      "branch_name": "Branch Pusat",
      "default_warehouse_id": 145,
      "warehouse_exists": false,
      "warehouse_info": null,
      "available_warehouses": [
        {
          "id": 1,
          "warehouse_code": "WH-001",
          "warehouse_name": "Warehouse Utama",
          "warehouse_type": "warehouse"
        }
      ],
      "needs_mapping": true
    },
    {
      "branch_id": 2,
      "branch_code": "BRN-002",
      "branch_name": "Branch Cabang",
      "default_warehouse_id": 1,
      "warehouse_exists": true,
      "warehouse_info": {
        "id": 1,
        "warehouse_code": "WH-001",
        "warehouse_name": "Warehouse Utama",
        "warehouse_type": "warehouse"
      },
      "available_warehouses": null,
      "needs_mapping": false
    }
  ]
}

3. Sync Branch Warehouse (Single Mapping)

Mapping branch ke warehouse yang dipilih.
POST /api/v1/syncing/branch/warehouse
Content-Type: application/json
Authorization: Bearer <jwt_token>

{
  "branch_id": 1,
  "warehouse_id": 1
}
Response Success:
{
  "code": 200,
  "message": "Success",
  "data": {
    "branch_id": 1,
    "branch_code": "BRN-MST-DS000001",
    "warehouse_id": 1,
    "warehouse_code": "WH-001",
    "warehouse_name": "Warehouse Utama",
    "message": "Branch BRN-MST-DS000001 berhasil di-sync dengan warehouse WH-001"
  }
}
Response Error (Warehouse not found):
{
  "code": 404,
  "message": "warehouse dengan ID 999 tidak ditemukan"
}

4. Get Branch Warehouses (Multiple)

Get list semua warehouses untuk 1 branch (default + backups).
GET /api/v1/syncing/branch/:branch_id/warehouses
Authorization: Bearer <jwt_token>
Response:
{
  "code": 200,
  "data": {
    "branch_id": 1,
    "branch_code": "BRN-MST-OSK00001",
    "branch_name": "Branch Mstore Osaka 01",
    "total_warehouses": 3,
    "warehouses": [
      {
        "warehouse_id": 224,
        "warehouse_code": "WH-MST-JPY-STR-2508-000001",
        "warehouse_name": "Warehouse Store Osaka 1",
        "warehouse_type": "store",
        "priority": 0,
        "priority_label": "default",
        "is_active": true
      },
      {
        "warehouse_id": 223,
        "warehouse_code": "WH-MST-JPY-DC-2508-000001",
        "warehouse_name": "Distribution Center Osaka 1",
        "warehouse_type": "distribution_center",
        "priority": 1,
        "priority_label": "backup1",
        "is_active": true
      },
      {
        "warehouse_id": 227,
        "warehouse_code": "WH-MST-JPY-DC-2508-000003",
        "warehouse_name": "Distribution Center Osaka 3",
        "warehouse_type": "distribution_center",
        "priority": 2,
        "priority_label": "backup2",
        "is_active": true
      }
    ]
  }
}

5. Sync Branch Multiple Warehouses

Set multiple warehouses untuk 1 branch sekaligus (replace existing).
POST /api/v1/syncing/branch/:branch_id/warehouses
Content-Type: application/json
Authorization: Bearer <jwt_token>

{
  "branch_id": 1,
  "warehouses": [
    {
      "warehouse_id": 224,
      "priority": 0  // default
    },
    {
      "warehouse_id": 223,
      "priority": 1  // backup1
    },
    {
      "warehouse_id": 227,
      "priority": 2  // backup2
    }
  ]
}
Response:
{
  "code": 200,
  "data": {
    "branch_id": 1,
    "branch_code": "BRN-MST-OSK00001",
    "branch_name": "Branch Mstore Osaka 01",
    "total_warehouses": 3,
    "warehouses": [
      {
        "warehouse_id": 224,
        "warehouse_code": "WH-MST-JPY-STR-2508-000001",
        "warehouse_name": "Warehouse Store Osaka 1",
        "warehouse_type": "store",
        "priority": 0,
        "priority_label": "default",
        "is_active": true
      },
      {
        "warehouse_id": 223,
        "warehouse_code": "WH-MST-JPY-DC-2508-000001",
        "warehouse_name": "Distribution Center Osaka 1",
        "warehouse_type": "distribution_center",
        "priority": 1,
        "priority_label": "backup1",
        "is_active": true
      },
      {
        "warehouse_id": 227,
        "warehouse_code": "WH-MST-JPY-DC-2508-000003",
        "warehouse_name": "Distribution Center Osaka 3",
        "warehouse_type": "distribution_center",
        "priority": 2,
        "priority_label": "backup2",
        "is_active": true
      }
    ],
    "message": "Berhasil sync 3 warehouses untuk branch BRN-MST-OSK00001"
  }
}

πŸ”„ Use Cases

Use Case 1: Branch Belum Punya Warehouse

  1. Cek status branch:
    GET /api/v1/syncing/branch/1/warehouse-status
    
  2. Response menunjukkan needs_mapping: true dan list available_warehouses
  3. Pilih warehouse dan mapping:
    POST /api/v1/syncing/branch/warehouse
    {
      "branch_id": 1,
      "warehouse_id": 1
    }
    
  4. Branch sekarang sudah ter-mapping ke warehouse

Use Case 2: Setup Default + Backup Warehouses

Branch perlu setup 1 default warehouse dan 2 backup warehouses untuk redundancy.
POST /api/v1/syncing/branch/1/warehouses
{
  "branch_id": 1,
  "warehouses": [
    {"warehouse_id": 224, "priority": 0},  // Default: Store warehouse
    {"warehouse_id": 223, "priority": 1},  // Backup1: Distribution center 1
    {"warehouse_id": 227, "priority": 2}   // Backup2: Distribution center 2
  ]
}

Use Case 3: Inventory Allocation Logic

Saat create transaction, sistem akan cek stock dengan priority: Implementation:
// Pseudocode
warehouses := GetBranchWarehouses(branchID) // Sorted by priority ASC
for _, wh := range warehouses {
    stock := CheckStock(wh.WarehouseID, inventoryID)
    if stock >= needed {
        ConsumeStock(wh.WarehouseID, inventoryID, needed)
        break
    }
}

Use Case 4: Monitoring Dashboard (Admin)

  1. Get all branches status:
    GET /api/v1/syncing/branches/warehouse-status?merchant_id=1
    
  2. Dashboard menampilkan:
    • βœ… Branch yang sudah ter-mapping (hijau)
    • ⚠️ Branch yang needs mapping (kuning/merah)
    • List available warehouses untuk mapping
  3. Admin bisa langsung mapping dari dashboard

πŸ“Š Response Fields Explanation

ResponseBranchWarehouseStatus

FieldTypeDescription
branch_idint64ID branch
branch_codestringKode branch
branch_namestringNama branch
default_warehouse_idint64 (nullable)Warehouse ID yang ter-assign di branch
warehouse_existsbooleanApakah warehouse ID tersebut exist di database
warehouse_infoobject (nullable)Info warehouse jika sudah ter-mapping
available_warehousesarrayList warehouse yang tersedia untuk mapping (hanya muncul jika needs_mapping: true)
needs_mappingbooleanApakah branch perlu di-mapping ke warehouse

WarehouseInfo

FieldTypeDescription
idint64Warehouse ID
warehouse_codestringKode warehouse
warehouse_namestringNama warehouse
warehouse_typestringTipe: warehouse atau distribution_center

πŸ”§ Integration Example

Frontend: Check & Fix Branch Warehouse

// 1. Cek status branch
const checkBranchStatus = async (branchId) => {
  const response = await fetch(`/api/v1/syncing/branch/${branchId}/warehouse-status`, {
    headers: {
      'Authorization': `Bearer ${token}`
    }
  });
  const data = await response.json();
  
  if (data.data.needs_mapping) {
    // Show modal untuk pilih warehouse
    showWarehouseSelectionModal(data.data.available_warehouses);
  }
};

// 2. Mapping branch ke warehouse
const syncBranchWarehouse = async (branchId, warehouseId) => {
  const response = await fetch('/api/v1/syncing/branch/warehouse', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      branch_id: branchId,
      warehouse_id: warehouseId
    })
  });
  
  const data = await response.json();
  if (data.code === 200) {
    alert(data.data.message);
  }
};

// 3. Setup multiple warehouses
const setupMultipleWarehouses = async (branchId, warehouses) => {
  const response = await fetch(`/api/v1/syncing/branch/${branchId}/warehouses`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      branch_id: branchId,
      warehouses: warehouses
    })
  });
  
  const data = await response.json();
  if (data.code === 200) {
    console.log(`Synced ${data.data.total_warehouses} warehouses`);
  }
};

πŸ“Š Benefits

  1. βœ… High Availability: Jika default warehouse stock habis, auto fallback ke backup
  2. βœ… Flexibility: Bisa define berapa banyak backup warehouses sesuai kebutuhan
  3. βœ… Clear Priority: Priority system yang jelas (0=default, 1+=backup)
  4. βœ… Easy Management: Single API call untuk setup multiple warehouses
  5. βœ… Redundancy: Mengurangi risk β€œstock tidak cukup” dengan backup warehouses
  6. βœ… Auto-detect: Sistem otomatis detect branch yang belum ter-mapping
  7. βœ… Monitoring: Dashboard untuk admin monitoring status semua branch

⚠️ Important Notes

  1. Priority 0 wajib ada: Setiap branch harus punya minimal 1 warehouse dengan priority=0 (default)
  2. Unique constraint: 1 branch tidak boleh punya warehouse yang sama 2x
  3. Soft delete: Gunakan deleted_at untuk soft delete, jangan hard delete
  4. Backward compatible: Existing branches.default_warehouse_id tetap bisa digunakan sebagai fallback

πŸš€ Testing

Postman Collection

# 1. Get branch status
GET {{host}}/api/v1/syncing/branch/1/warehouse-status
Authorization: Bearer {{token}}

# 2. Get all branches status
GET {{host}}/api/v1/syncing/branches/warehouse-status?merchant_id=1
Authorization: Bearer {{token}}

# 3. Sync branch warehouse (single)
POST {{host}}/api/v1/syncing/branch/warehouse
Authorization: Bearer {{token}}
Content-Type: application/json

{
  "branch_id": 1,
  "warehouse_id": 1
}

# 4. Get branch warehouses (multiple)
GET {{host}}/api/v1/syncing/branch/1/warehouses
Authorization: Bearer {{token}}

# 5. Sync branch warehouses (multiple)
POST {{host}}/api/v1/syncing/branch/1/warehouses
Authorization: Bearer {{token}}
Content-Type: application/json

{
  "branch_id": 1,
  "warehouses": [
    {"warehouse_id": 224, "priority": 0},
    {"warehouse_id": 223, "priority": 1},
    {"warehouse_id": 227, "priority": 2}
  ]
}

Inventory Flow

Inventory management & warehouse stocks

Transaction Flow

Transaction creation & inventory consumption

Database ERD

Complete database schema

Need Help? Contact backend team atau check GitHub Issues