Skip to main content

Data Sync Integration Guide

Hướng dẫn tích hợp push dữ liệu từ OMS, WMS, Helpdesk, và Accounting vào hệ thống SOS để tính điểm Seller. Tất cả sync endpoints sử dụng upsert (INSERT...ON CONFLICT UPDATE), đảm bảo idempotent — gọi nhiều lần vẫn an toàn.


Integration Sequence

┌────────┐     ┌──────────┐     ┌──────────────┐     ┌────────────┐
│ OMS │ │ WMS │ │ Helpdesk │ │ Accounting │
│ │ │ │ │ (Frappe) │ │ │
└───┬────┘ └────┬─────┘ └──────┬───────┘ └─────┬──────┘
│ │ │ │
│ /sync/orders │ /sync/inventory │ /sync/tickets │ /sync/payments
│ /sync/forecasts │ │ /sync/revenue
│ /sync/campaign-actuals │ │
│ │ │ │
▼ ▼ ▼ ▼
┌───────────────────────────────────────────────────────────────────┐
│ Boxme SOS API (/api/sync/*) │
│ │
│ sos_order_operation_raw sos_inventory_health_raw │
│ seller_forecast_submission sos_ticket_sla_raw │
│ campaign_actual_result sos_payment_raw │
│ am_portfolio_period_score │
└─────────────────────────────────┬─────────────────────────────────┘

POST /api/sos/monthly/calculate


Scoring Engine (P/O/T/F/I)

1. OMS → Orders (O-Score)

Endpoint: POST /api/sync/orders

Push dữ liệu thời gian push đơn hàng. Hệ thống nhận pre-aggregated data theo period.

{
"seller_code": "SEL001",
"period": "2026-02",
"total_orders": 150,
"orders_within_30min": 140,
"orders_late": 10,
"avg_push_time_minutes": 18.5
}
FieldRequiredDescription
seller_codeMã seller
periodFormat: YYYY-MM
total_ordersTổng số đơn trong kỳ
orders_within_30minSố đơn push trong 30 phút
orders_lateSố đơn push trễ
avg_push_time_minutesThời gian push trung bình

Upsert: ON CONFLICT(seller_id, period) DO UPDATE

Tần suất khuyến nghị: Daily hoặc cuối tháng trước ngày tính điểm.


2. OMS → Forecasts (P-Score)

Endpoint: POST /api/sync/forecasts

Push forecast submission cho campaign cụ thể.

{
"seller_code": "SEL001",
"campaign_code": "CAMP-2026-02",
"submitted_at": "2026-01-28T10:00:00Z",
"forecasted_order_volume": 5000,
"forecasted_sku_breakdown": { "SKU001": 2000, "SKU002": 3000 },
"notes": "Valentine sale forecast"
}
FieldRequiredDescription
seller_codeMã seller
campaign_codeMã campaign (phải tồn tại)
forecasted_order_volumeSản lượng dự báo
submitted_atThời điểm submit (default: now)

Versioning: Hệ thống tự track submission_version. Submit lần 1 → is_first_submission = true.


3. WMS/OMS → Campaign Actuals (P-Score)

Endpoint: POST /api/sync/campaign-actuals

Push kết quả thực tế sau campaign để so sánh với forecast.

{
"seller_code": "SEL001",
"campaign_code": "CAMP-2026-02",
"actual_order_volume": 4800,
"actual_sku_breakdown": { "SKU001": 1900, "SKU002": 2900 }
}

Upsert: ON CONFLICT(seller_id, campaign_id) DO UPDATE


4. Helpdesk → Tickets (T-Score)

Endpoint: POST /api/sync/tickets

Push ticket SLA metrics từ Frappe Helpdesk.

{
"seller_code": "SEL001",
"period": "2026-02",
"total_tickets": 25,
"avg_response_time_hours": 3.5,
"breakdown": {
"under_4h": 18,
"4h_8h": 4,
"8h_16h": 2,
"over_16h": 1
}
}
FieldRequiredDescription
seller_codeMã seller
periodFormat: YYYY-MM
total_ticketsTổng số ticket
avg_response_time_hoursThời gian phản hồi trung bình
breakdownPhân bổ theo khung giờ

Upsert: ON CONFLICT(seller_id, period) DO UPDATE


5. Accounting → Payments (F-Score)

Endpoint: POST /api/sync/payments

Push dữ liệu thanh toán. Hỗ trợ 2 format: pre-aggregated hoặc raw invoices.

Format A: Pre-aggregated

{
"seller_code": "SEL001",
"period": "2026-02",
"total_invoices": 10,
"invoices_on_time": 7,
"invoices_late_1_7": 2,
"invoices_late_7_15": 1,
"invoices_late_15_20": 0,
"invoices_late_over_20": 0,
"worst_days_late": 12,
"total_outstanding_amount": 15000000,
"currency": "VND"
}

Format B: Raw invoices

{
"seller_code": "SEL001",
"period": "2026-02",
"invoices": [
{ "invoice_id": "INV001", "days_late": 0, "amount": 5000000 },
{ "invoice_id": "INV002", "days_late": 5, "amount": 3000000 },
{ "invoice_id": "INV003", "days_late": 12, "amount": 7000000 }
],
"currency": "VND"
}

Hệ thống tự aggregate từ mảng invoices: tính worst_days_late, total_outstanding_amount, phân nhóm trễ.


6. WMS → Inventory (I-Score)

Endpoint: POST /api/sync/inventory

Push snapshot tồn kho.

{
"seller_code": "SEL001",
"snapshot_date": "2026-02-28",
"total_cbm": 150.5,
"total_sku_qty": 12000,
"aging_over_90d_cbm": 22.3,
"aging_over_90d_sku_qty": 1800,
"aging_over_180d_cbm": 5.1,
"aging_over_180d_pct": 3.4
}

Tính toán tự động:

  • aging_pct_by_cbm = aging_over_90d_cbm / total_cbm × 100
  • aging_pct_by_qty = aging_over_90d_sku_qty / total_sku_qty × 100
  • aging_pct_used = MAX(aging_pct_by_cbm, aging_pct_by_qty) — giá trị này dùng để tính I-Score

Upsert: ON CONFLICT(seller_id, period) DO UPDATE


7. Accounting → AM Revenue

Endpoint: POST /api/sync/revenue

Push dữ liệu doanh thu AM để tính AM KPI.

{
"am_id": 1,
"period": "2026-02",
"revenue_target": 500000000,
"revenue_actual": 450000000
}

Tính toán tự động: revenue_achievement_pct = actual / target × 100


Implementation Checklist

StepHệ thốngEndpointTần suấtPriority
1OMS/sync/ordersDaily🔴 High
2OMS/sync/forecastsPer campaign🟡 Medium
3WMS/OMS/sync/campaign-actualsPost-campaign🟡 Medium
4Helpdesk/sync/ticketsDaily🔴 High
5Accounting/sync/paymentsWeekly🔴 High
6WMS/sync/inventoryMonthly🟡 Medium
7Accounting/sync/revenueMonthly🟢 Low

Error Handling

Tất cả sync endpoints trả về:

// Success
{ "success": true }

// Seller not found
{ "error": "Seller SEL001 not found" } // 404

// Missing required fields
{ "error": "seller_code and period required" } // 400

Recommendation: Triển khai retry logic (3 retries, exponential backoff) ở phía caller cho trường hợp network error hoặc 500.