Sơ đồ luồng dữ liệu & hướng dẫn tích hợp

VuaNem Forecasting Pipeline

2026-07-29 11:09
Báo cáosơ đồ luồng dữ liệu & hướng dẫn tích hợp
Dùng đểMô tả toàn bộ luồng dữ liệu — nguồn đầu vào hiện tại, cách thêm sản phẩm/cửa hàng/kênh, và cách tích hợp hệ thống ngoài (NetSuite, BigQuery, PostgreSQL/MariaDB, Google Sheets) để có dữ liệu thật quy mô lớn.
Câu hỏi trả lờiDF
Tạo lúc2026-07-29 11:09
Dữ liệu đến ngày2026-07-29
Phương pháp tính (kỹ thuật)
Đọc toàn bộ cấu hình siêu dữ liệu, đối chiếu trạng thái file thực tế (tồn tại, số dòng, độ mới, lệch schema), quét tham chiếu bước pipeline và lệnh load_master trong code để dựng báo cáo HTML — luồng dữ liệu, từ điển dữ liệu, hướng dẫn thêm dữ liệu, hướng dẫn tích hợp theo loại nguồn, checklist onboard công ty mới.
sources.yamlsource_field_mapping.yamlmaster_data_schema.yamltrạng thái file thật→ Hướng dẫn tích hợp

Luồng dữ liệu tổng quan

Nguồn thô (file/API)m0 chuẩn hóaMaster CSV (data/{company}/temporary)Các bước phân tích (q1-q25, dp*, fp1)Báo cáo HTML + đẩy ERP/CRM
Nguyên tắc tầng siêu dữ liệu
Mọi bước pipeline chỉ đọc master CSV đã chuẩn hóa — không bước nào đọc nguồn thô trực tiếp. Muốn đổi nguồn dữ liệu (file → API → database) chỉ sửa 3 file metadata: config/sources.yaml (nguồn ở đâu), config/source_field_mapping.yaml (cột nguồn → cột chuẩn), {CODE}config/master_data_schema.yaml (hợp đồng dữ liệu chuẩn). Code không đổi.
Thực thể master
15
trong master_data_schema.yaml
Nguồn khai báo
8
trong sources.yaml
Chế độ mặc định
file
file | api (override theo nguồn)
Company namespace
vuanem_fresh
env ABN_COMPANY
TầngVai tròCấu hình tại
1. Nguồn thôFile CSV/Excel export hoặc API/DB bên ngoài (PowerBI, NetSuite, Google Sheets, BigQuery, SQL...)config/sources.yaml
2. Ánh xạ cộtTên cột nguồn → tên cột chuẩn (nhiều biến thể ngôn ngữ)config/source_field_mapping.yaml
3. Master dataCSV chuẩn hóa sau bước m0 — hợp đồng dữ liệu của toàn hệ thốngconfig/master_data_schema.yaml
4. Phân tíchCác bước q1-q25/dp/fp đọc master qua load_master(), không biết nguồn thôconfig/pipeline.yaml
5. Phân phốiBáo cáo HTML trong data/{company}/outputs + đẩy Frappe ERP/CRM (q15)config/pipeline.yaml

Tình trạng dữ liệu hiện tại (readiness)

Sẵn sàng
13
Thiếu file
1
chạy bước m0 / nguồn chưa có
Dữ liệu cũ (>7 ngày)
0
nên cập nhật định kỳ
Thực thểFileSố dòngDung lượngCập nhậtĐộ mớiTrạng thái
sales_transactionssales_transactions.csv18012.5 KB2026-07-29 11:09MớiOK
sales_history_monthlysales_history_monthly.csv723.4 KB2026-07-29 11:09MớiOK
inventory_snapshotsinventory_snapshots.csv11393 B2026-07-29 11:09MớiOK
leadtime_moqleadtime_moq.csv12492 B2026-07-29 11:09MớiOK
sku_catalogsku_catalog.csv6324 B2026-07-29 11:09MớiOK
sales_targetssales_targets.csv18650 B2026-07-29 11:09MớiOK
customer_profilescustomer_profiles.csv61.4 KB2026-07-29 11:09MớiOK
customer_matched_productscustomer_matched_products.csv6481 B2026-07-29 11:09MớiOK
crm_interactionscrm_interactions.csv0154 B2026-07-29 11:09MớiRỗng
customer_segmentscustomer_segments.csv6128 B2026-07-29 11:09MớiOK
customer_criteria_tagscustomer_criteria_tags.csv6858 B2026-07-29 11:09MớiOK
customer_purchasescustomer_purchases.csvThiếu file
purchase_segmentspurchase_segments.csv30126.8 KB2026-07-29 11:09MớiOK
campaign_recommendationscampaign_recommendations.csv94.8 KB2026-07-29 11:09MớiOK
product_affinityproduct_affinity.csv232.0 KB2026-07-29 11:09MớiOK
Tại sao độ mới quan trọng
Cảnh báo tồn kho (q2/q13), đặt hàng lại (q3) và PO (q20) chỉ đúng khi tồn kho + bán hàng được cập nhật hằng ngày. Dự báo (q1/q4/q8) cần lịch sử bán hàng cập nhật hằng tháng. Cron mặc định chạy 3h sáng hằng ngày — xem config/pipeline.yaml → schedule.

Chất lượng dữ liệu (m0 validation)

✅ Không có vấn đề
Lần chạy m0 gần nhất không phát hiện lỗi nào theo hợp đồng master_data_schema.yaml (khóa chính, trường bắt buộc, ngày, giá trị âm, trùng dòng).

Nguồn dữ liệu đầu vào hiện tại

Cơ chế fallback an toàn
Khi một nguồn ở chế độ api nhưng thiếu credential (env chưa đặt) hoặc connector chưa implement, pipeline tự động dùng file fallback kèm cảnh báo — không bao giờ chết giữa chừng. Chuyển đổi file → API chỉ cần đổi mode: api trong sources.yaml.
NguồnMô tảChế độFile (fallback)APIBiến môi trường
actual_salesDaily sales actuals (Unit Sale Order + Sales) by class x channelfile{company}/inputs/sample/daily_sales.csv
180 dòng · 8.0 KB
powerbi✗ POWERBI_TENANT_ID ✗ POWERBI_CLIENT_ID ✗ POWERBI_CLIENT_SECRET
sales_targetsMonthly sales scenario per class x channel (Kich ban ban hang)file{company}/inputs/sample/sales_targets.csv
18 dòng · 650 B
gsheet✗ GOOGLE_SERVICE_ACCOUNT_JSON
inventoryRealtime available stock, KC + TM warehouses onlyfile{company}/inputs/sample/inventory.csv
14 dòng · 487 B
netsuite✗ NETSUITE_ACCOUNT ✗ NETSUITE_TOKEN_ID ✗ NETSUITE_TOKEN_SECRET ✗ NETSUITE_CONSUMER_KEY ✗ NETSUITE_CONSUMER_SECRET
leadtimeSupplier leadtime + safety stock days per SKU x regionfile{company}/inputs/sample/leadtime_moq.csv
12 dòng · 492 B
lark✗ LARK_APP_ID ✗ LARK_APP_SECRET
sku_metadataSKU -> class/brand/category mappingfile{company}/inputs/sample/sku_metadata.csv
6 dòng · 324 B
netsuite✗ NETSUITE_ACCOUNT ✗ NETSUITE_TOKEN_ID ✗ NETSUITE_TOKEN_SECRET ✗ NETSUITE_CONSUMER_KEY ✗ NETSUITE_CONSUMER_SECRET
sales_historyLong-run monthly sales history for forecasting modelsfile{company}/inputs/sample/sales_history.csv
72 dòng · 3.4 KB
bigquery✗ GOOGLE_APPLICATION_CREDENTIALS
chat_messagesRaw customer chat/call messages (Pancake, Caresoft, Zalo)file{company}/inputs/customer360/raw_messages.csv
không có file
pancake✗ PANCAKE_API_KEY ✗ PANCAKE_PAGE_IDS
crm_interactionsCRM leads/deals pulled from Frappefile{company}/temporary/crm_interactions.csv
0 dòng · 154 B
frappe✗ FRAPPE_SITE_URL ✗ FRAPPE_API_KEY ✗ FRAPPE_API_SECRET

Thêm dữ liệu mới: sản phẩm, cửa hàng, kênh…

Muốn thêm…Làm gìThay đổi
Sản phẩm / SKU mớiThêm dòng vào nguồn sku_metadata (sku_id, class, brand, price_tier, category) + dữ liệu bán/tồn tương ứngChỉ dữ liệu — không sửa config, không sửa code
Nhóm hàng (class) mớiXuất hiện tự nhiên trong sku_metadata + sales; thêm mục tiêu vào sales_targets nếu cần cảnh báoChỉ dữ liệu
Cửa hàng / kho mớiThêm mã kho vào nguồn inventory; nếu kho cần đưa vào phân tích, bổ sung pattern vào warehouses.include_patternsconfig/demand_planning.yaml (metadata)
Kênh bán hàng mới (Shopee, TikTok…)Thêm alias kênh (vd. shopee → Ecom hoặc kênh chuẩn mới) vào channel_aliases; nếu là kênh chuẩn mới, thêm vào target_vs_actual.channels + sales_targetsconfig/demand_planning.yaml (metadata)
Cột/chỉ số mới (vd. chi phí ads)Khai báo field trong master_data_schema.yaml + alias nguồn trong source_field_mapping.yaml2 file metadata
Thực thể mới (vd. giá vốn, công nợ)Khai báo entity trong schema + nguồn trong sources.yaml + mapping; thêm hàm migrate_ (m0)metadata + 1 hàm nhỏ ở m0
Công ty mới (multi-tenant)Đặt ABN_COMPANY=, tạo data//inputs + bộ config riêng (sources/mapping/schema)Chỉ metadata — xem mục Onboard công ty mới

Kết nối với hệ thống bên ngoài

Thêm connector mới ở đâu?
Mọi connector là một hàm _fetch_(spec) -> DataFrame trong libs/api_sources.py, đăng ký trong dict FETCHERS. Credential chỉ lấy từ biến môi trường khai báo trong api.env — không hardcode secret. Thiếu credential → tự động fallback về file, pipeline không chết.
File drop (CSV/Excel/Parquet) — mặc định Sẵn sàng
Đặt file export vào đúng đường dẫn file: trong sources.yaml (hoặc đổi path). Loader hỗ trợ .csv/.xlsx/.parquet tự động.
sources.yaml
  actual_sales:
    file: { path: {company}/inputs/sample/daily_sales.csv }
BigQuery Đã implement
Đặt mode: api, type: bigquery, table: dataset.table. Xác thực bằng service account. Cũng có thể dùng trực tiếp bq://dataset.table ở mọi tham số input của tools.
✗ GOOGLE_APPLICATION_CREDENTIALS
  sales_history:
    mode: api
    api:
      type: bigquery
      table: vuanem.sales_history
      env: [GOOGLE_APPLICATION_CREDENTIALS]
PostgreSQL / MariaDB / MySQL Đã implement
Đặt type: sql với table hoặc query tùy ý. DSN để trong biến môi trường (SQLAlchemy URL). Cần cài sqlalchemy + psycopg2-binary (PG) hoặc pymysql (MariaDB).
✗ ABN_PG_DSN ✗ ABN_MYSQL_DSN
  actual_sales:
    mode: api
    api:
      type: sql
      driver: postgresql        # hoặc mariadb
      table: public.daily_sales # hoặc query: "SELECT ..."
      env: [ABN_PG_DSN]
# ABN_PG_DSN=postgresql+psycopg2://user:pass@host:5432/db
# ABN_MYSQL_DSN=mysql+pymysql://user:pass@host:3306/db
NetSuite (ERP) Đã implement — cần credential
SuiteTalk REST saved search + Token-Based Auth (OAuth1 HMAC-SHA256), phân trang 1000 dòng. Tồn kho dùng saved search id=77 theo tài liệu hiện tại. Đặt đủ 5 biến môi trường rồi chuyển mode: api.
✗ NETSUITE_ACCOUNT ✗ NETSUITE_TOKEN_ID ✗ NETSUITE_TOKEN_SECRET ✗ NETSUITE_CONSUMER_KEY ✗ NETSUITE_CONSUMER_SECRET
  inventory:
    mode: api
    api:
      type: netsuite
      saved_search_id: "77"
      env: [NETSUITE_ACCOUNT, NETSUITE_TOKEN_ID, NETSUITE_TOKEN_SECRET,
            NETSUITE_CONSUMER_KEY, NETSUITE_CONSUMER_SECRET]
Google Sheets (kịch bản bán hàng) Đã implement — cần credential
Service account (JWT RS256) + Sheets API v4. Đọc sheet theo pattern 'Chi tiết class T{month}', tự suy ra cột month (YYYY-MM) từ tên sheet; sheet dạng wide (Unit/Sale Order theo kênh) được m0 melt về dạng long tự động.
✗ GOOGLE_SERVICE_ACCOUNT_JSON
  sales_targets:
    mode: api
    api:
      type: gsheet
      spreadsheet: 1txcM32K...
      sheet_pattern: "Chi tiết class T{month}"
      env: [GOOGLE_SERVICE_ACCOUNT_JSON]  # inline JSON hoặc đường dẫn key file
PowerBI Đã implement — cần credential
Service principal (client credentials) + executeQueries DAX trên dataset. Thực tế nên ưu tiên đọc trực tiếp từ DB nguồn của PowerBI (qua type: sql/bigquery) để tránh giới hạn API.
✗ POWERBI_TENANT_ID ✗ POWERBI_CLIENT_ID ✗ POWERBI_CLIENT_SECRET
  actual_sales:
    mode: api
    api:
      type: powerbi
      dataset_id: ""
      # group_id: ""
      table: sales_daily        # -> EVALUATE 'sales_daily' (hoặc query: )
      env: [POWERBI_TENANT_ID, POWERBI_CLIENT_ID, POWERBI_CLIENT_SECRET]
Lark Base/Sheet (leadtime NCC) Đã implement — cần credential
Lark Open API: tenant_access_token → wiki node → Bitable app → bảng 'Leadtime', phân trang 500 dòng.
✗ LARK_APP_ID ✗ LARK_APP_SECRET
  leadtime:
    mode: api
    api:
      type: lark
      wiki: Olgjw9yO...
      sheet: Leadtime
      env: [LARK_APP_ID, LARK_APP_SECRET]
Frappe ERP/CRM Một phần (pull_crm.py)
CRM interactions đã kéo qua tools/frappe_sync/pull_crm.py (bước q0). Chiều đẩy dữ liệu lên ERP dùng q15 push_to_frappe qua Science Bridge ingest API.
✗ FRAPPE_SITE_URL ✗ FRAPPE_API_KEY ✗ FRAPPE_API_SECRET
  crm_interactions:
    api:
      type: frappe
      env: [FRAPPE_SITE_URL, FRAPPE_API_KEY, FRAPPE_API_SECRET]

Từ điển dữ liệu chuẩn (data dictionary)

Hợp đồng dữ liệu (common data dictionary)
config/master_data_schema.yaml là nơi duy nhất định nghĩa thực thể + trường chuẩn. Mọi hệ thống ngoài (NetSuite, BigQuery, POS, CRM...) chỉ cần xuất ra các cột khớp với alias trong config/source_field_mapping.yaml là pipeline chạy được — không cần đổi code.
sales_transactions — Daily sales actuals at SKU × channel × date granularity (sales_transactions.csv)
Dùng bởi: steps: dp1, fp1, q12, q13, q2, q3, q6 · tools: _loader, overstock_understock, price_elasticity, reorder, run_shap, shortage
TrườngKiểuBắt buộcMô tảAlias cột nguồn
datedateTransaction date (YYYY-MM-DD)date, Date, Ngày
sku_idstringStock Keeping Unit identifiersku_id, SKU ID, Item, Mã hàng
classstringProduct class/group (e.g. Gummi, Comfy, Amando, Tempur)class, Class, Product Group, Ngành hàng
channelstringSales channel: Ecom, Online, Offlinechannel, Channel, Chanel, Kênh
unit_sale_orderfloatQuantity sold — Unit Sale Order (canonical from PowerBI/adapter)unit_sale_order, unit_sale, Unit SO, Unit Sale Order
unit_salefloatQuantity sold — alias for unit_sale_order (backward compat)unit_sale, unit_sale_order, Unit SO, Unit Sale Order
salesfloatTotal revenue for this row (VND). Canonical from adapter.sales, sales_amount, Sales, Doanh số
sales_amountfloatTotal revenue — alias for sales (backward compat)sales_amount, sales, Sales, Doanh số
pricefloatUnit price at time of sale (VND)price, Unit Price, Đơn giá
promo_flagintegerPromotion active: 0=regular, 1=promopromo_flag, Promo, Khuyến mãi
return_qtyfloatQuantity returned in this row (>= 0). Retail reality: returns/trial-period send-backs — keep separate from unit_sale so demand math stays honest; net demand = unit_sale - return_qty.return_qty, Return Qty, Returns, Số lượng trả
exchange_flagintegerExchange transaction (e.g. 100-night trial swap): 0=normal sale, 1=exchange. Exchanges move stock between SKUs without new demand.exchange_flag, Exchange, Đổi hàng, Đổi trả
store_trafficfloatFoot traffic count (when available)store_traffic, Traffic, Lượt khách
is_holidayintegerHoliday indicator: 0=working day, 1=holidayis_holiday, Holiday
sales_history_monthly — Monthly aggregated sales history at SKU × class × channel × month granularity (sales_history_monthly.csv)
Dùng bởi: steps: q1, q10, q14, q16, q17, q18, q21, q22, q23, q24, q25, q7, q8a, q8b, q9 · tools: _loader, cash_flow_forecast, category_forecast, executive_dashboard, inventory_turnover, location_forecast
TrườngKiểuBắt buộcMô tảAlias cột nguồn
datedateFirst day of the month (YYYY-MM-DD)date, Date, Tháng
sku_idstringStock Keeping Unit identifiersku_id, SKU ID, Item
classstringProduct class/groupclass, Class, Product Group, Ngành hàng
channelstringSales channel: Ecom, Online, Offlinechannel, Channel, Chanel, Kênh
unit_salefloatTotal units sold in the monthunit_sale, unit_sale_order, Unit, Quantity
sales_amountfloatTotal revenue (VND) for the monthsales, sales_amount, Sales, Doanh số
inventory_snapshots — Current inventory positions per SKU × warehouse (KC+TM only) (inventory_snapshots.csv)
Dùng bởi: steps: q10, q13, q14, q2, q22, q23, q24, q3 · tools: _loader, cash_flow_forecast, inventory_turnover, location_forecast, overstock_understock, reorder
TrườngKiểuBắt buộcMô tảAlias cột nguồn
sku_idstringStock Keeping Unit identifiersku_id, SKU ID, Item, Mã hàng
warehousestringWarehouse code (e.g. BDI01-KC, HMIKT-TM)warehouse, Location, Kho
on_handfloatPhysical stock on handon_hand, On Hand, Tồn
committedfloatStock reserved/committed to orderscommitted, Committed, Đã giữ
availablefloatStock available for new orders (on_hand - committed)available, Available, Có thể bán
regionstringRegion: MB (North), MN (South), MT (Central)region, Region, Khu vực
leadtime_moq — Supplier leadtime, safety stock, and minimum order quantity per SKU × region (leadtime_moq.csv)
Dùng bởi: steps: q13, q2, q20, q23, q3 · tools: _loader, overstock_understock, reorder, shortage, supplier_scorecard
TrườngKiểuBắt buộcMô tảAlias cột nguồn
sku_idstringStock Keeping Unit identifiersku_id, SKU ID, Item, Mã hàng
supplierstringSupplier/vendor namesupplier, Supplier, Vendor, Tên NCC
leadtime_daysfloatLead time in days from order to deliveryleadtime_days, Leadtime Days, Lead Time
safety_stock_daysfloatRecommended safety stock in days of demandsafety_stock_days, Safety Stock Days
moq_qtyfloatMinimum order quantity (units)moq_qty, MOQ, MOQ Qty
moq_unitstringMOQ unit of measure (e.g. pcs, carton)moq_unit, MOQ Unit, Đơn vị MOQ
regionstringRegion: MB (North), MN (South)region, Region, Khu vực
sku_catalog — Product/SKU metadata — class, brand, price tier, category (sku_catalog.csv)
Dùng bởi: steps: dp1, fp1, q14, q17, q20, q23, q24, q5 · tools: _loader, inventory_turnover, supplier_scorecard
TrườngKiểuBắt buộcMô tảAlias cột nguồn
sku_idstringStock Keeping Unit identifiersku_id, SKU ID, Item, Mã hàng
classstringProduct class/group (e.g. Gummi, Comfy, Amando, Tempur, Bedgear, Saffron)class, Class, Product Group, Nhóm hàng
brandstringBrand name (e.g. Vuanem, Saffron, Tempur, Bedgear)brand, Brand, Thương hiệu
price_tierstringPrice tier: budget, mid, premium, luxuryprice_tier, Price Tier, Phân khúc giá
categorystringProduct category: mattress, accessory, etc.category, Category, Danh mục
region_casestringRegional applicability: MB, MN, MT, bothregion_case, Region Case
sales_targets — Monthly sales targets per class × channel (sales_targets.csv)
Dùng bởi: steps: dp1, q21, q25 · tools: _loader, revenue_summary, target_vs_actual
TrườngKiểuBắt buộcMô tảAlias cột nguồn
monthstringTarget month (YYYY-MM)month, Month, Tháng
classstringProduct class/groupclass, Class, Nhóm hàng, Ngành hàng
channelstringSales channel: Ecom, Online, Offlinechannel, Channel, Kênh, Channel
target_unitfloatTarget quantity (units)target_unit, Target Unit, Unit
target_sale_orderfloatTarget sales order value (VND)target_sale_order, Target Sales Order, Sale Order, Target Sales
customer_profiles — Per-customer 360 profiles with sentiment, price sensitivity, and product affinities (customer_profiles.csv)
Dùng bởi: steps: c4, c5, q11, q14, q15, q16, q17 · tools: _loader
TrườngKiểuBắt buộcMô tảAlias cột nguồn
customer_idstringUnique customer identifiercustomer_id, user_id, phone
phonestringPhone number (contact key)
total_sessionsintegerTotal conversation sessions analyzedtotal_sessions, sessions
first_sessiondateDate of first analyzed session
last_sessiondateDate of most recent analyzed sessionlast_session, last_session_date
avg_sentimentfloatAverage sentiment score across sessions (-1 to 1)
weighted_sentimentfloatRecency-weighted sentiment score (-1 to 1)weighted_sentiment, sentiment_score
sentiment_trendstringSentiment trend: improving, stable, degrading
sentiment_volatilityfloatStd-dev of sentiment across sessions
negative_session_countintegerNumber of sessions with negative sentiment
price_sensitivity_scorefloatNumeric price sensitivity score (0-1)
price_sensitivity_labelstringPrice sensitivity category (rất_nhạy, hơi_nhạy, không_nhạy, không_rõ)price_sensitivity_label, price_sensitivity
quality_focusedbooleanCustomer cares about product qualityquality_focused, quality_focus
brand_focusedbooleanCustomer has brand preferencebrand_focused, brand_focus
top_productsstringProducts the customer mentions most
channels_usedstringChannels the customer has interacted throughchannels_used
customer_needsstringDetected customer needs/intents (muốn_mua, hỏi_giá, ...)customer_needs, purchase_intent, intent
purchase_reasonsstringPurchase reasons (health_pain, life_event, replacement, gift, ...)
last_urgencystringLatest purchase urgency: urgent, soon, flexible
avg_conversion_likelihoodfloatEstimated probability of conversion (0.0-1.0)avg_conversion_likelihood, conversion_likelihood, conversion_probability
profile_versionstringProfile builder version
profile_updated_atdateWhen the profile was last updated
customer_matched_products — Products matched from customer conversations to catalog SKUs (customer_matched_products.csv)
Dùng bởi: tools: _loader
TrườngKiểuBắt buộcMô tảAlias cột nguồn
user_idstringUser/customer identifieruser_id, customer_id
canonical_namestringCanonical product name from the catalogcanonical_name, product_name
mentioned_namestringProduct name as mentioned by the customermentioned_name, mentioned_product
intentstringCustomer intent (muốn_mua, hỏi_giá, trả_giá, etc.)intent, purchase_intent
matchedbooleanWhether the product was successfully matched to catalogmatched, is_matched
crm_interactions — CRM leads and deals pulled from Frappe (crm_interactions.csv)
Dùng bởi: steps: q0, q14 · tools: _loader
TrườngKiểuBắt buộcMô tảAlias cột nguồn
customer_keystringCustomer key for matching to customer_profilescustomer_key, customer_id
crm_leadstringCRM Lead doc namecrm_lead, lead_name
crm_dealstringCRM Deal doc namecrm_deal, deal_name
full_namestringFull name of the lead/contactfull_name, name, lead_name
emailstringEmail addressemail
phonestringPhone numberphone, mobile_no
lead_statusstringLead status (Open, Qualified, Converted, etc.)lead_status, status
deal_statusstringDeal status (Open, Won, Lost, etc.)deal_status, status
productstringProduct name from dealproduct, product_name
deal_valuefloatDeal value (VND)deal_value, value
probabilityfloatWin probability (0-100)probability, win_probability
expected_closure_datedateExpected deal closure dateexpected_closure_date, closed_date
interaction_datedateDate of interactioninteraction_date, date
sourcestringLead source (e.g. website, referral, walk-in)source, lead_source
customer_segments — Per-customer segment assignment from multi-criteria analysis (Q11) (customer_segments.csv)
Dùng bởi: steps: q11, q14, q15, q16, q21
TrườngKiểuBắt buộcMô tảAlias cột nguồn
customer_idstringUnique customer identifier (foreign key to customer_profiles)
segmentstringAssigned segment label (premium_enthusiast, deal_hunter, health_seeker, brand_loyalist, new_starter, gift_shopper, value_seeker, at_risk, general)
customer_criteria_tags — Full multi-criteria tags per customer — 10 segmentation dimensions + assigned segment (customer_criteria_tags.csv)
Dùng bởi: steps: q11, q16
TrườngKiểuBắt buộcMô tảAlias cột nguồn
customer_idstringUnique customer identifier
price_sensitivity_tierstringPrice sensitivity tier: rất_nhạy, hơi_nhạy, ít_quan_tâm
quality_focusedbooleanCustomer cares about product quality
brand_focusedbooleanCustomer has brand preference
conversion_scorefloatConversion likelihood score (0.0-1.0)
purchase_intent_tierstringBucketed purchase intent: Cao, Trung bình, Thấp
sentiment_scorefloatWeighted sentiment score (-1.0 to 1.0)
sentiment_tierstringSentiment tier: delighted, satisfied, neutral, at_risk
sentiment_trendstringSentiment trend: improving, stable, degrading
total_sessionsintegerTotal customer sessions
lifecycle_stagestringLifecycle stage: new, active, engaged, power
channel_affinitystringPreferred channel: ecom, offline, multi_channel, unknown
purchase_reason_primarystringPrimary purchase reason: health_pain, life_event, replacement, gift, children, upgrade, general
urgency_tierstringPurchase urgency: urgent, soon, flexible
segmentstringAssigned segment label
customer_purchases — Per-customer purchase transactions with SKU, price, channel, and date (customer_purchases.csv)
Dùng bởi: steps: q17
TrườngKiểuBắt buộcMô tảAlias cột nguồn
purchase_idstringUnique purchase transaction identifier
customer_idstringForeign key to customer_profiles
purchase_datedateDate of purchase (YYYY-MM-DD)
sku_idstringStock Keeping Unit identifier
product_classstringProduct class/group
brandstringBrand name
price_tierstringPrice tier: mid, premium, luxury
categorystringProduct category: mattress, accessory
unit_pricefloatUnit price at time of purchase (VND)
quantityintegerQuantity purchased
total_amountfloatTotal purchase amount (VND)
channelstringPurchase channel: Ecom, Online, Offline
promo_flagintegerPurchase during promotion: 0=regular, 1=promo
purchase_segments — Per-customer RFM scores and purchase-based segment assignment (Q17) (purchase_segments.csv)
Dùng bởi: steps: q17
TrườngKiểuBắt buộcMô tảAlias cột nguồn
customer_idstringUnique customer identifier
purchase_segmentstringPurchase segment: Champions, Loyal Customers, Potential Loyalist, New Customers, At Risk, Hibernating, Lost, Big Spenders, Price-Sensitive Loyal
recency_daysintegerDays since last purchase
frequencyintegerTotal number of purchases
monetaryfloatTotal amount spent (VND)
r_scoreintegerRecency score (1-5, 5=most recent)
f_scoreintegerFrequency score (1-5, 5=most frequent)
m_scoreintegerMonetary score (1-5, 5=highest spend)
rfm_scoreintegerComposite RFM score (R*100 + F*10 + M)
avg_order_valuefloatAverage order value (VND)
preferred_categorystringMost purchased product category
preferred_tierstringMost purchased price tier
promo_ratefloatFraction of purchases during promotions
last_purchasedateDate of most recent purchase
campaign_recommendations — Per-segment marketing campaign briefs with target products, offers, timing, and KPIs (campaign_recommendations.csv)
Dùng bởi: steps: q17
TrườngKiểuBắt buộcMô tảAlias cột nguồn
segmentstringTarget purchase segment
segment_vistringVietnamese segment name
strategystringHigh-level strategy: Retention & Advocacy, Upsell & Cross-sell, Re-engagement, etc.
campaign_namestringCampaign name
descriptionstringCampaign description and rationale
target_productsstringComma-separated SKU IDs to target
offerstringOffer/mechanic description
channelsstringComma-separated distribution channels
timingstringRecommended timing/cadence
kpistringExpected KPI and target
segment_sizeintegerNumber of customers in this segment
top_products_boughtstringTop products historically bought by this segment
affinity_productsstringCross-sell product pairs for this segment
product_affinity — Product-pair cross-sell affinities — customers who bought A also bought B (product_affinity.csv)
Dùng bởi: steps: q17
TrườngKiểuBắt buộcMô tảAlias cột nguồn
sku_astringSource product SKU (the one the customer bought)
sku_bstringTarget product SKU (recommended cross-sell)
co_occurrenceintegerNumber of customers who bought both
affinity_scorefloatAffinity score (0.0-1.0)
liftfloatLift over random baseline
recommendation_reasonstringHuman-readable recommendation reason (Vietnamese)

Onboard công ty mới (config-only)

1Đặt biến môi trường: ABN_COMPANY=<ten_cty> (namespace dữ liệu, vd. acme), tùy chọn ABN_DATA_ROOT / ABN_CONFIG_ROOT nếu dữ liệu/config nằm ngoài repo.
2Tạo thư mục dữ liệu data/<ten_cty>/inputs/ và đặt file export thô vào đó (hoặc cấu hình API/DB trong sources.yaml).
3Sao chép config/sources.yaml và chỉnh: đường dẫn file ({company} tự thay bằng namespace), chế độ file/api, tên bảng/sheet/saved-search của công ty đó.
4Chỉnh config/source_field_mapping.yaml: thêm alias cột theo đúng header mà hệ thống nguồn của công ty xuất ra (tiếng Việt/Anh đều được).
5Rà soát config/master_data_schema.yaml: thực thể/trường chuẩn nào công ty không có (nullable) hoặc cần thêm — chỉnh tại đây, không chỉnh code.
6Chạy kiểm tra: python run_pipeline.py --pipeline forecasting --steps m0,df — xem mục Tình trạng dữ liệu ở báo cáo này, xử lý các dòng đỏ.
7Chạy toàn bộ: python run_pipeline.py --all.
Cam kết kiến trúc
Toàn bộ khác biệt giữa các công ty nằm ở tầng metadata (config/*.yaml + biến môi trường). Code pipeline dùng chung 100%: đường dẫn dùng placeholder {company}, kênh/kho/alias cột đều qua config, connector nạp theo type. Không fork code cho từng công ty.

Lộ trình đưa dữ liệu thật vào phân tích

Ưu tiênViệcCách làmTrạng thái
P0Kết nối nguồn thật cho 4 nhóm dữ liệu lõi: bán hàng ngày, tồn kho realtime, leadtime NCC, mục tiêu thángConnector NetSuite/PowerBI/GSheet/Lark đã implement — chỉ cần đặt credential env + mode: api (hoặc đọc DB qua type: sql/bigquery)Đã implement — chờ credential
P0Dữ liệu lịch sử đủ dài (≥ 24 tháng) cho q1/q4/q8/q9Nạp sales_history từ BigQuery/DB — đã hỗ trợ bq:// và type: sqlSẵn sàng kỹ thuật
P1Data quality gate ở m0: kiểm tra null khóa chính, trùng dòng, âm số lượng, lệch schema trước khi ghi masterĐã implement trong m0 (validation.mode: warn|fail) — xem mục Chất lượng dữ liệu ở trênĐã implement
P1Tầng lưu trữ columnar (Parquet/DuckDB) khi dữ liệu lớn (> 1 triệu dòng)Đã implement: m0 tự ghi .parquet khi vượt storage.parquet_threshold_rows; load_master ưu tiên parquetĐã implement
P2Incremental ingest (theo watermark ngày) thay full reload + sizing trước khi nạpĐã implement trong Data Management: merge upsert theo khóa + watermark (state/master_watermarks.json), since-pushdown cho SQL/BQ, history windows, sizing per-source (rows/bytes/thời gian) — xem báo cáo dmĐã implement
P2Onboard thêm công ty khác lên cùng pipelineABN_COMPANY + bộ config riêng — đã smoke-test end-to-end (df chạy được với namespace khác)Đã kiểm chứng
Nguyên tắc khi đưa dữ liệu thật vào
1) Master data là hợp đồng duy nhất — mọi nguồn phải quy về schema. 2) Không bao giờ sửa tool để nhận nguồn mới — chỉ thêm alias/connector. 3) Fallback file luôn hoạt động để phát triển offline. 4) Secret chỉ qua biến môi trường.