1. Câu chuyện thật: Khi Shopee đổi rule, hệ thống “vỡ” trong 2 giờ
Tháng 3/2024, team BI của một công ty e-commerce đang vận hành hệ thống reconciliation doanh thu cho các nền tảng: Shopee, Lazada và TikTok Shop.
Rule gốc khá đơn giản:
- Commission fee = NMV * rate theo từng platform.
- Rate được hard-code ngay trong SQL.
Query chính dài hơn 800 dòng, chạy mỗi đêm để cập nhật dashboard revenue.
Một buổi sáng, Shopee thay đổi cách tính phí:
Từ “5% cố định” → “3% cho order dưới 500k, 6% cho order trên 500k”.
Chỉ 1 thay đổi nhỏ, nhưng hệ thống vỡ hàng loạt:
- Airflow DAG fail do CASE WHEN không match logic mới.
- Power BI hiển thị commission sai → lệch hàng trăm triệu.
- Accounting phải tạm dừng reconciliation 2 ngày.
2. Phân tích nguyên nhân
Khi review pipeline, nhóm phát hiện:-
SQL hard-code trực tiếp:
CASE WHEN platform = 'Shopee' THEN nmv * 0.05 WHEN platform = 'Lazada' THEN nmv * 0.04 WHEN platform = 'TikTok' THEN nmv * 0.03 END AS commission_fee - Không có bảng rule riêng → mọi thay đổi phải sửa query.
- Rule cũ không versioned, không có effective_date → không thể audit dữ liệu tháng trước.
- Shopee đổi rule giữa tháng → query chỉ chạy đúng một nửa tháng, nửa còn lại sai.
Tóm lại: hệ thống phụ thuộc hoàn toàn vào query, chứ không phải dữ liệu.
3. Giải pháp refactor: chuyển logic sang config-driven model
Team quyết định refactor toàn bộ tầng logic trong 3 bước.
Bước 1: Chuẩn hóa bảng config
Tạo bảng config_commission_rules trong schema data_config, chứa thông tin theo phiên bản và thời gian hiệu lực:
| platform | min_amount | max_amount | rate | effective_date | expiry_date | version |
|---|---|---|---|---|---|---|
| Shopee | 0 | 500000 | 0.03 | 2024-03-01 | 9999-12-31 | v2 |
| Shopee | 500000 | 999999999 | 0.06 | 2024-03-01 | 9999-12-31 | v2 |
| Lazada | 0 | null | 0.04 | 2024-01-01 | 9999-12-31 | v1 |
| TikTok | 0 | null | 0.03 | 2024-01-01 | 9999-12-31 | v1 |
Rule mới giờ được lưu trong data, không nằm trong query.
Bảng này được upload định kỳ từ Excel (Accounting quản lý), rồi sync vào Postgres bằng Airflow job.
Bước 2: Tạo view logic – tách khỏi query chính
Tạo view vw_commission_rate:
CREATE OR REPLACE VIEW data_config.vw_commission_rate AS
SELECT
platform,
min_amount,
max_amount,
rate,
effective_date,
expiry_date
FROM data_config.config_commission_rules
WHERE CURRENT_DATE BETWEEN effective_date AND expiry_date;
→ View này đóng vai trò "semantic layer", cung cấp rule đang hiệu lực.
→ Khi rule mới được cập nhật, view tự động phản ánh đúng mà không cần deploy SQL.
Bước 3: Viết lại query tính phí theo modular logic
Query reconciliation refactor lại:
SELECT
o.order_id,
o.platform,
o.nmv,
o.order_created_date,
o.order_amount,
c.rate AS commission_rate,
o.nmv * c.rate AS commission_fee
FROM data_warehouse.reconcile_order_raw o
LEFT JOIN data_config.vw_commission_rate c
ON o.platform = c.platform
AND o.order_amount BETWEEN c.min_amount AND c.max_amount
AND o.order_created_date BETWEEN c.effective_date AND c.expiry_date;
Điểm khác biệt:
- Không còn CASE WHEN.
- Có thể thêm rule mới mà không sửa query.
- Có thể audit version cũ bằng cách filter theo
versionhoặceffective_date.
4. Kết quả sau khi refactor
| Hạng mục | Trước refactor | Sau refactor |
|---|---|---|
| Số dòng query | ~850 dòng | 240 dòng |
| Thời gian fix rule mới | 2 ngày | 15 phút |
| DAG fail khi Shopee đổi rule | Có (2 lần/tháng) | 0 lần |
| Business chủ động thay rule | Không | Có (qua Excel config) |
| Power BI refresh | 7 phút | 2 phút (do query nhẹ hơn) |
5. Mở rộng: Ứng dụng semantic layer & dbt
Sau 3 tháng, team mở rộng mô hình này thành tầng semantic chung cho toàn bộ business rule:
vw_commission_rate– rule phí nền tảngvw_logistics_fee_rule– rule vận chuyểnvw_rebate_rule– rule rebate theo brand
Các view được tạo bằng dbt models với version control.
Khi có rule mới, chỉ cần merge pull request.
Cấu trúc thư mục dbt:
models/
├── staging/
│ ├── stg_orders.sql
│ └── stg_config_rules.sql
├── intermediate/
│ ├── int_orders__with_commission.sql
│ ├── int_orders__with_logistics.sql
├── marts/
│ └── finance__reconciliation_summary.sql
Lúc này, query trong Power BI chỉ cần:
SELECT * FROM finance__reconciliation_summary
Không còn logic nghiệp vụ trong dashboard.
Mọi thứ được quản lý version, có test, có lineage.
6. Lợi ích ngoài mong đợi
Refactor này không chỉ giảm lỗi, mà còn mang lại nhiều lợi ích “vô hình”:
- Accounting chủ động thay đổi rule mà không cần IT support.
- Ops có thể mô phỏng rule mới để test KPI trước khi áp dụng.
- BI team tiết kiệm 4–6 giờ mỗi tuần không phải fix query.
- Data lineage rõ ràng – có thể truy ngược xem order tháng 4 dùng rule nào.
- Audit dễ dàng khi so sánh version v1 vs v2.
7. Bài học rút ra
“Query chạy được không có nghĩa là hệ thống có thể sống được.”
Từ một case thực tế, team rút ra 3 nguyên tắc vàng:
-
Logic là data, không phải code.
→ Nếu business có thể thay rule, rule đó nên nằm trong bảng. -
Query chỉ nên thể hiện quan hệ, không nên thể hiện policy.
→ Policy = config. Relation = query. -
Scale bắt đầu từ cấu trúc, không phải từ công cụ.
→ Dùng Power BI, dbt hay Snowflake đều vô nghĩa nếu model không chuẩn hoá.
8. Kết luận
Sau khi chuyển sang mô hình config-driven, hệ thống reconciliation của team đã chạy ổn định hơn 6 tháng.
Khi Shopee đổi rule thêm 2 lần, team chỉ cần 5 phút cập nhật file config, không một dashboard nào bị lỗi.
Câu chuyện này là minh chứng rõ ràng rằng:
Scalability trong BI không đến từ việc viết SQL giỏi hơn,
mà đến từ việc tách biệt logic và dữ liệu – thiết kế để thay đổi mà không chạm code.
Xem thêm: Khi SQL không còn scale – câu chuyện thật từ BI
Theo dõi blog Rabit Learn Data để đọc thêm các case study BI & Data Engineering thực tế.

0 Nhận xét