วางแผน
Ingestion
2Warehouse
3Deploy
4Monitor
เฟส 2 เสร็จ · idempotent พิสูจน์แล้ว (รันซ้ำแถวไม่เบิ้ล)

คลังข้อมูล Postgres + quality gate + UPSERT

เฟสที่สองของ Premium — รับ JSON ที่ normalize จากเฟส 1 → ผ่าน data-quality gate (กันยอดติดลบ/SKU ซ้ำ) → idempotent UPSERT เข้า warehouse. โฟกัสเฉพาะ load — ยังไม่ deploy cloud (เฟส 3)

Postgres
3 ตาราง + 2 views
idempotent
รันซ้ำ 5→5 ✓
quality
6→5 · reject 1
9/9
เทสผ่าน
มืออาชีพ · ไม่หลุดเป้า

ขอบเขตเฟส 2 ชัดเจน

เฟสนี้คือชั้นเก็บข้อมูลให้ถูกและเชื่อถือได้ — ส่งต่อ deploy ในเฟสหน้า

✅ เฟสนี้ทำ (In Scope)

  • Postgres warehouse schema (products · orders · inventory)
  • views v_daily_sales, v_restock_watch (ป้อน Looker/alert เฟส 4)
  • data-quality gate — กันยอด/จำนวนติดลบ, SKU ว่าง, คีย์ซ้ำ
  • idempotent loader (UPSERT ON CONFLICT บน natural key)
  • พิสูจน์ idempotency จริงด้วย runnable demo

→ ส่งต่อเฟสหน้า (ยังไม่ทำตอนนี้)

  • Docker → Cloud Run + Scheduler + Secret Manager เฟส 3
  • Cloud SQL provisioning จริง เฟส 3
  • Looker dashboard + Telegram alert เฟส 4
  • Monitoring 24/7 + handover เฟส 4
01 · คลังข้อมูล

Warehouse Schema (สร้างแล้ว)

natural key เปิดทาง idempotent · views ป้อน Looker โดยตรง

products
  • sku TEXT
  • name TEXT
  • category TEXT
  • cost_price NUMERIC
  • min_stock_alert INT
orders
  • platform TEXT
  • platform_order_id TEXT
  • sku TEXT
  • order_date TIMESTAMPTZ
  • total_amount NUMERIC
  • qty INT
inventory
  • platform TEXT
  • sku TEXT
  • stock INT
  • updated_at TIMESTAMPTZ
v_daily_sales — ยอดขายรวมรายวันแยกแพลตฟอร์ม → ป้อน Looker
v_restock_watch — SKU สต็อก ≤ เกณฑ์ → ขับ low-stock alert
02 · ความถูกต้อง

Quality Gate → Idempotent Load

ข้อมูลพังถูกกันออกก่อนเข้าคลัง · รันซ้ำ window เดิมแถวไม่เบิ้ล

📥
JSON เฟส 1
orders + inventory
🚦
Quality Gate
ยอดติดลบ/ซ้ำ/ว่าง
clean
ผ่านเกณฑ์
✕ rejected (บันทึกเหตุผล ไม่ทิ้งเงียบ)
🗄️
UPSERT → Postgres
ON CONFLICT DO UPDATE
03 · โค้ดจริง

เปิดดูโค้ด คัดลอกได้

พิสูจน์ได้ด้วย python load_demo.py (รันด้วย sqlite ตรรกะเดียวกับ Postgres)

loader.py

    
04 · ผลรันจริง

พิสูจน์ ไม่ใช่อ้างลอย ๆ

output จริงจากการรัน load_demo.py

$ python load_demo.py
=== Quality Gate === {"orders_in": 6, "orders_clean": 5, "rejected": 1} rejected: ['negative total_amount'] === Idempotency === orders after run #1 = 5 | after run #2 = 5 idempotent = True === ยอดขายรายแพลตฟอร์ม === lazada orders=1 revenue=฿1,890 line orders=1 revenue=฿1,850 shopee orders=1 revenue=฿1,380 shopify orders=1 revenue=฿720 tiktok orders=1 revenue=฿870

🔒 พิสูจน์อะไรบ้าง

🚦 Quality gate ปัดยอดติดลบออก 1 แถว reject
🔁 รันโหลดซ้ำ window เดิม 5 → 5 ไม่เบิ้ล
🗄️ ข้อมูลสะอาดเข้าคลัง 5 orders + 5 inv
📊 query สรุปยอดรายแพลตฟอร์ม ถูกต้อง
platformordersrevenue
shopee1฿1,380
lazada1฿1,890
tiktok1฿870
shopify1฿720
line1฿1,850
05 · ทดสอบ

รายงานผล Warehouse & Load

9 กรณีผ่านครบ

#กรณีทดสอบผลที่คาดหวังผล
1quality: ยอดติดลบreject + เหตุผล "negative total_amount"✅ ผ่าน
2idempotency (รันซ้ำ)แถวเท่าเดิม 5→5 ไม่เบิ้ล✅ ผ่าน
3UPSERT update คีย์เดิมอัปเดตค่า ไม่สร้างแถวใหม่✅ ผ่าน
4dup natural key ใน batchreject กันซ้ำ✅ ผ่าน
5missing skureject✅ ผ่าน
6negative stockreject✅ ผ่าน
7aggregation รายแพลตฟอร์มrevenue/orders ถูกต้อง✅ ผ่าน
8โหลดข้อมูลสะอาด5/6 orders + 5 inventory เข้าคลัง✅ ผ่าน
9import โดยไม่มี depslazy import + sqlite stdlib✅ ผ่าน
สรุป: ผ่าน 9/9 · warehouse พร้อม · ข้อมูลพังถูกกัน · รันซ้ำปลอดภัย — ส่งต่อเฟส 3 (Deploy)
ไฟล์ส่งมอบเฟส 2

ดาวน์โหลด ไฟล์จริง

โฟลเดอร์ premium-delivery/phase2/

🗄️
Warehouse schema
schema.sql
↓ ดาวน์โหลด
🚦
Quality gate
quality.py
↓ ดาวน์โหลด
🔁
Loader (UPSERT)
loader.py
↓ ดาวน์โหลด
▶️
Runnable proof
load_demo.py
↓ ดาวน์โหลด
📦
Dependencies
requirements.txt
↓ ดาวน์โหลด
🧪
รายงานทดสอบ
TEST_REPORT.md
↓ ดาวน์โหลด
AICE Hub🔎 ตรวจ AI ฟรี