# PART 2 — biến thể `data-pipeline` > **Dùng khi** `PRODUCT = data-pipeline` — sản phẩm là **dữ liệu**: ETL, ingest, kho dữ > liệu, báo cáo BI. Cắm khối này vào chỗ PART 2 của [`../srs.md`](../srs.md). > > **Tiêu chí G3 riêng của biến thể này**: mỗi luồng có data contract nguồn và đích · bảng > ánh xạ trường đầy đủ · quy tắc chất lượng có ngưỡng và hành vi khi vi phạm · **có mục đối > soát nguồn–đích** · đã trả lời xong chạy lại/backfill/dữ liệu đến muộn. 🔴 **Người dùng của bạn không nhìn thấy sản phẩm — họ nhìn thấy những con số.** Con số sai mà không ai biết là chế độ hỏng nguy hiểm nhất của loại sản phẩm này, vì nó im lặng. Vì vậy §2.6 (đối soát) và §2.5 (chất lượng) là hai mục quan trọng nhất, không phải phần phụ. --- ## 2.1 Danh sách luồng dữ liệu | ID | Luồng | Nguồn | Đích | Tần suất | Kiểu | Khối lượng/lần | BR | |---|---|---|---|---|---|---|---| | FLW-01 | | | | Hằng đêm 02:00 | Toàn bộ / Tăng dần / CDC | ~… bản ghi | | ## 2.2 Sơ đồ lineage ```mermaid flowchart LR POS[["POS API"]] ERP[["ERP export CSV"]] STG[("staging.pos_raw")] DW[("dw.fact_sales")] RPT(["Báo cáo doanh thu"]) NGUOIDOC(["👤 Kế toán, Ban giám đốc"]) POS -->|FLW-01| STG STG -->|FLW-02| DW ERP -->|FLW-03| DW DW --> RPT RPT --> NGUOIDOC ``` *Trụ `[( )]` = kho dữ liệu · khung đôi `[[ ]]` = nguồn ngoài, không do mình sở hữu · bo tròn `([ ])` = đầu ra và người đọc. Nhãn cạnh là mã luồng `FLW-nn`, khớp bảng §2.1.* 🔴 **Vẽ tới tận người tiêu thụ cuối** — báo cáo nào, **ai đọc**. Dừng ở bảng dữ liệu thì khi luồng hỏng lúc 2 giờ sáng không ai biết phải báo cho ai, và không đánh giá được mức nghiêm trọng. **Bảng đi kèm** *(quy tắc W13)*: | Luồng | Nguồn → Đích | Tần suất | SLA độ tươi | Hỏng thì ai bị ảnh hưởng | Chủ sở hữu nguồn | |---|---|---|---|---|---| | FLW-01 | POS API → staging | Hằng đêm 02:00 | D+1 08:00 | Toàn bộ chuỗi phía sau | NCC X — anh Huy | ## 2.3 FLW-01 — ### 2.3.1 Nguồn | | | |---|---| | **Hệ thống nguồn** | | | **Cách lấy** | API / file / CDC / queue | | **Ai sở hữu nguồn** | *(đầu mối khi schema đổi)* | | **Nguồn có báo trước khi đổi schema không** | 🔴 Không ⇒ phải có phát hiện schema drift | | **Cửa sổ dữ liệu sẵn sàng** | *(từ mấy giờ nguồn mới có đủ dữ liệu hôm qua)* | ### 2.3.2 SLA độ tươi *Thay cho "thời gian phản hồi" của biến thể `screen`.* | | | |---|---| | **Dữ liệu ngày D phải sẵn sàng trước** | D+1 08:00 | | **Trễ tối đa chấp nhận được** | | | **Ai được báo khi trễ** | | | **Người dùng thấy gì khi dữ liệu chưa tới** | 🔴 Số cũ? Số rỗng? **Có nhãn cảnh báo không?** | 🔴 Câu cuối là câu hay bị bỏ nhất. Báo cáo hiển thị số của hôm kia mà không có nhãn "dữ liệu tới 28/08" là cách người dùng ra quyết định trên số cũ mà không biết. ### 2.3.3 Data contract — schema nguồn | Trường nguồn | Kiểu | Có thể null | Nghĩa nghiệp vụ | Giá trị hợp lệ | Ghi chú | |---|---|---|---|---|---| ### 2.3.4 Ánh xạ trường | Trường đích | Từ trường nguồn | Phép biến đổi | Khi nguồn null | Khi nguồn sai định dạng | BR | |---|---|---|---|---|---| | `store_code` | `shop.id` | upper(trim(x)) | → `UNKNOWN` | → quarantine | BR-0nn | | `amount` | `total` | chia 100 (nguồn lưu đơn vị nhỏ nhất) | → 0 | → quarantine | BR-0nn | 🔴 **Ba cột cuối là phần thay thế cho "validation + message lỗi" của biến thể `screen`.** Bỏ trống ⇒ kỹ sư dữ liệu tự quyết, và mỗi luồng một kiểu. ### 2.3.5 Khoá và trùng lặp | | | |---|---| | **Khoá nghiệp vụ** | *(cái gì xác định một bản ghi là duy nhất)* | | **Nguồn có gửi trùng không** | | | **Trùng thì xử lý sao** | Giữ bản mới nhất / cộng dồn / báo lỗi | | **Bản ghi bị sửa ở nguồn** | Ghi đè / giữ lịch sử (SCD loại mấy) | ## 2.4 Quy tắc chất lượng dữ liệu | ID | Kiểm tra gì | Ngưỡng | Vi phạm thì làm gì | Ai được báo | |---|---|---|---|---| | DQ-01 | Số bản ghi so với trung bình 7 ngày | ±30% | ⚠️ Cảnh báo, vẫn nạp | | | DQ-02 | Tỷ lệ `store_code` không map được | > 1% | 🛑 **Dừng luồng** | | | DQ-03 | Tổng tiền âm | > 0 bản ghi | 🔴 Quarantine bản ghi đó | | **Ba hành vi khi vi phạm — chọn rõ một, không được để mơ hồ:** | Hành vi | Nghĩa | Dùng khi | |---|---|---| | `drop` | Bỏ bản ghi, ghi log | Bản ghi rác đã biết, không ảnh hưởng tổng | | `quarantine` | Tách sang bảng riêng để xử lý tay | 🔴 **Mặc định nên chọn** — giữ được dữ liệu để điều tra | | `fail` | Dừng cả luồng | Sai lệch có thể làm hỏng báo cáo tài chính | 🔴 **`drop` im lặng là chế độ hỏng tệ nhất.** Số liệu thiếu mà không ai biết. Chọn `drop` phải kèm ngưỡng cảnh báo. ## 2.5 Trạng thái tương đương "màn hình rỗng" | Tình huống | Xử lý | Người dùng thấy gì | |---|---|---| | Ngày không có giao dịch nào (chủ nhật, lễ) | Nạp 0 bản ghi — **không phải lỗi** | Báo cáo hiện 0, có nhãn "không có giao dịch" | | Nguồn không phản hồi | | | | Nguồn trả rỗng bất thường | 🔴 Phân biệt với ca trên bằng cách nào? | | Phân biệt **"không có dữ liệu"** với **"chưa lấy được dữ liệu"** là bắt buộc. Hai thứ này nhìn giống nhau trên báo cáo nhưng ý nghĩa ngược nhau. ## 2.6 Đối soát nguồn – đích 🔴 **Mục bắt buộc, không được bỏ.** Đây là thứ duy nhất chứng minh dữ liệu không bị mất giữa đường. | # | Đối chiếu gì | Nguồn | Đích | Sai lệch cho phép | Tần suất | Ai kiểm | |---|---|---|---|---|---|---| | 1 | Số bản ghi | count(pos_api) | count(fact_sales) | 0 | Mỗi lần chạy | Tự động | | 2 | Tổng tiền | sum(total) | sum(amount)×100 | ≤ 1 đơn vị (làm tròn) | Hằng ngày | Tự động | | 3 | Đối chiếu với báo cáo hệ thống cũ | | | | Hằng tháng | Kế toán | **Sai lệch vượt ngưỡng thì làm gì, ai chịu trách nhiệm xử lý:** … ## 2.7 Chạy lại, backfill, dữ liệu đến muộn | Câu hỏi | Trả lời | |---|---| | **Chạy lại cùng một ngày hai lần** → kết quả có giống không (idempotent)? | 🔴 Không idempotent ⇒ nói rõ quy trình dọn trước khi chạy lại | | **Backfill** lịch sử N ngày làm thế nào? Mất bao lâu? Ảnh hưởng báo cáo đang chạy không? | | | **Dữ liệu đến muộn** (giao dịch hôm qua tới hôm nay) | Nạp vào ngày phát sinh hay ngày nhận? | | Nạp vào ngày phát sinh ⇒ **báo cáo đã chốt có thay đổi không?** | 🔴 Nếu có, ai được báo | | **Thất bại giữa chừng** | Rollback toàn bộ / tiếp tục từ checkpoint | ## 2.8 Vận hành | | | |---|---| | Chạy tự động lúc | | | Chạy tay được không, ai được chạy | | | Cảnh báo gửi đi đâu | | | Ai trực khi luồng hỏng ban đêm | | | Hỏng bao lâu thì phải báo người dùng | |