Chic Data · Báo cáo tuần

Onboard 6 nhà, một đơn đặt trùng, và bản thiết kế để nó không lặp lại

15/09 – 21/09/2026 · onboard đợt 17/09 · đồng bộ lịch · thiết kế lại sync phòng · hai bộ thu mới
13 commit chicdata_dashboard 21 phòng mới lên ChicStay (ẩn) 219 ảnh lên R2 chicdata: 109 cơ sở · 511 phòng Số đo lúc 16:30 ngày 21/09

Tổng quan tuần

6
nhà mới lên production
21 phòng · 69 gói giá
219
ảnh lên R2
18 phòng · 500MB → 19,5MB
1
đơn đặt trùng production
đã tìm ra nguyên nhân gốc
305
phòng đã nối PMS
+29 trong tuần
94,2%
161.121 lượt đồng bộ
9.308 PARTIAL · 72 FAILED

Tuần này có ba việc lớn. Một: onboard đợt 17/09 — 6 nhà, 21 phòng, 219 ảnh lên production ở trạng thái ẩn, kèm hai lỗi importer làm rơi dữ liệu trong im lặng. Hai: một đơn đặt trùng thật (CS-A9DG) và miếng vá đệm dọn hai đầu — vá xong thì vận hành báo ngược lại rằng miếng vá đang ăn mất khung bán. Ba: thiết kế lại phần sync phòng để đưa hẳn vào ChicStay backend, mới là thiết kế, chưa apply code.

Phần việc của mình ở repo chicstay-backend tuần này chỉ là sync phòng. 29 commit tính năng của repo đó (engine bán thêm giờ, quy trình xác nhận booking, Control Tower) là của đội dev ChicStay; mình ở phía review và gộp 4 PR — ghi ở mục D.

A. Onboard đợt 17/09 — 6 nhà, 21 phòng chicdata → ChicStay, tất cả ẩn

A1. Hai lỗi importer làm rơi dữ liệu mà không báo gì

Dry-run in ra “8 cơ sở · 0 phòng” trong khi sheet có 78 dòng phòng đã tick. Bộ nhập đọc mã cơ sở ở cột Mã cơ sở của tab 02_Phòng, nhưng tiêu đề cột đó đang bị gõ đè thành zZZ. Mọi dòng ra undefined rồi rơi vào một lệnh continue câm — gói giá, album và tiện ích đều treo vào phòng nên biến mất theo.

Dry-runTrướcSau khi vá
Phòng021
Gói giá069
Price rule0141
Media / tiện ích phòng0 / 018 / 81

Nay mã cơ sở được suy theo tên cột đã cắt khoảng trắng, rồi theo tiền tố CS#### của Mã phòng, và bỏ dòng nào thì ghi vào skipped thay vì im lặng. Lỗi thứ hai: ô “Chỉ Thứ 2 - Thứ 8” của Kat House vi phạm CHECK constraint và rollback cả lượt nạp 8 cơ sở — giá trị ngoài từ vựng nay về “Khác (ghi rõ ở Ghi chú)” kèm cảnh báo. Không đoán đó là Thứ 5 hay Thứ 6, vì đoán sai là bán sai giá.

A2. Nạp vào chicdata — chỉ thêm, không sửa, không xoá

BảngTrướcSau
Merchant4250 (+8)
Cơ sở101109 (+8)
Phòng490511 (+21)
Gói giá2.0912.160 (+69)
Đã publish00

Cơ sở và phòng để DRAFT, merchant để portal_enabled=false. Kiểm cả 4 bảng: số dòng cũ bị sửa bằng 0. Sao lưu trước khi nạp bằng Neon branch backup-prod-before-onboard-20260917.

A3. Ảnh — 219 ảnh cho 18 phòng, kiểm tới từng tấm

Chạy lại push_room_albums_to_r2.py đúng chuẩn nén cũ (WebP q80, cạnh dài ≤1600px): 500 MB ảnh gốc còn 19,5 MB, bảng media 6.239 → 6.458, không dòng cũ nào bị sửa. Ảnh mỗi phòng: Demo 10–19, Chạm 2–9, Kat House 9–13, Biko 18–30.

Không chỉ tin script chạy xanh: quét trước 18 album (không thư mục con, video, HEIC, file >20MB); tải lại cả 219 ảnh từ R2 đối chiếu checksum/dung lượng/kích thước với DB; so nội dung từng ảnh R2 với ảnh gốc trên Drive — lệch tối đa 5/256, tức mọi ảnh đều gắn đúng phòng; mỗi phòng đúng 1 ảnh bìa.

Trong lúc kiểm tìm ra một lỗi thật: ảnh chụp dọc lên R2 thành nằm ngang — WebP không mang EXIF theo nên 2 ảnh của Chạm Dịch Vọng Hậu ra 1600×720 thay vì 720×1600. Đã vá script, 4 test tái hiện, đẩy lại 2 ảnh. Ghi thêm một chuyện tự gây ra: lúc quét album tôi tải hàng loạt ảnh gốc nên bị Google trả 403 tạm; đã dừng và chuyển sang đọc metadata Drive. Key này dùng chung với phần sync Google Sheet.

A4. Nạp lên ChicStay production

Hai chỗ Claude Code bị guard quyền chặn nên phải chuyển sang người chạy tay: bước push main để deploy sync, và bước ẩn 6 host sau import. Hệ quả còn lại: 6 host mới vẫn is_listed=True (blue-diamond-apartment, demo-innine, cham-cine-cafe-giang-vo, cham-cine-cafe-vong-hau, kat-house, biko-apartment) — phòng thì ẩn nhưng host thì chưa. Nếu team muốn giấu hẳn trong lúc review thì cần ẩn tay 6 host này.

A5. Không nhà mới nào tự đồng bộ lịch được

Trả lời câu hỏi của Thu Phương: cả 8 nhà đợt này không nhà nào nối lịch tự động được — Chạm dùng AppSheet, Ora là link booking.com, Biko là link agoda (thiếu https:// nên còn không dựng nổi availability_config), Blue Diamond / Kat House / AN25 đều “đóng mở trực tiếp”. Riêng DEMO Inn&Ine có sổ Google nên đã nối được (mục C2). Blue Diamond vẫn 3 phòng 0 ảnh, BD sẽ bổ sung.

A6. Tích luỹ: sheet onboarding đã đẩy được bao nhiêu lên ChicStay

Đợt exportHostPhòngGói giáGhi chú
07/09830113đợt đầu, bản export staging
08/09 (prod)72693bản thật nạp production
13/09830132export lại kèm dữ liệu vá trong tuần
17/0962169đợt tuần này, nạp prod ở trạng thái ẩn

Đếm trên chính chicdata theo dấu nguồn chicstay-data-sheet — tức toàn bộ những gì sheet onboarding đã sinh ra từ trước tới nay: 31 merchant · 84 cơ sở · 423 phòng · 1.893 gói giá. Trong đó 305 phòng đã nối được PMS (mục E); phần còn lại là nhà không có nguồn lịch tự động, đúng như tình trạng của cả 8 nhà đợt này (mục A5).

B. Đơn đặt trùng CS-A9DG — và miếng vá hai đầu 18/09 → 21/09

B1. Nguyên nhân gốc: ChicStay quên đệm dọn của chính mình

Ngày 18/09 một khách đặt được phòng 19:00–21:00 trong khi phòng đó đã có khách Gohost nhận lúc 21:00 (đặt từ 15/09, trước đơn ChicStay ba ngày). Dựng lại mốc hôm đó:

00:00 – 01:30   CSR08910 (khách đêm trước ra 00:30 + dọn)
06:30 – 18:00   CSR08888 ở
18:00 – 19:00   dọn phòng
19:00 – 21:00   CS-A9DG  ← khách ChicStay đặt lúc 10:59 ngày 18/09
21:00 – 22:00   cần dọn phòng   ✗ nhưng 21:00 khách CSR08727 đã nhận

ChicStay hỏi chicdata “19:00–21:00 có bận không?” và chicdata trả lời đúng: trống — chicdata đã cộng đủ 1 giờ dọn sau mỗi khách Gohost. Chỗ hụt là ChicStay không hỏi thêm 1 giờ dọn sau đơn của chính nó; nếu hỏi “19:00–22:00” thì đơn đã bị chặn. Không phải lỗi của Bum, cũng không phải lỗi dữ liệu chicdata.

B2. Miếng vá: khoá thêm 1 giờ ở CẢ HAI ĐẦU

Yêu cầu vận hành 18/09 — “phòng 2–3h thì bận 1–4h” — áp cho mọi phòng của mọi nhà, thay vì chỉ cộng sau giờ trả theo cấu hình từng nhà (trước đó 281/511 phòng để 0 phút).

Đo ngay sau khi bật (18/09): lượt ChicStay kéo lịch lúc 16:20 nhận 459 khoảng bận của 292 phòng; 55/55 nhà đã nối lịch đang bật công tắc chặn bán. Ví dụ thật: 602 – 85A CL khách 18:30–22:30 thì ChicStay bận tới 23:30; 201 – 13 Đại Đồng khách nhận 19:00 thì khoá từ 18:00. Không đặt thử đơn thật vì bước kiểm lúc tạo đơn có ghi vào DB ChicStay — chỉ đọc để xác nhận.

B3. Sáng 21/09, vận hành báo ngược lại — và họ đúng

CS báo: lịch hiện khoá từ 12:00 nhưng mở PMS ra không thấy gì ở 12:00. Kiểm trên dữ liệu thật, độ dài khoá luôn bằng gói + 2 tiếng:

PhòngKhoá trên ChicStayĐơn PMS suy ra
Oasis Blanc 23/0912:00–18:00 (6h)13:00–17:00 = gói 4 giờ
Oasis Blanc 24/0914:00–20:00 (6h)15:00–19:00 = gói 4 giờ
602CL 22–23/0911:00 → 13:00 hôm sau (26h)12:00–12:00 = gói fullday 24h

Đệm trước giờ nhận ăn mất khung bán và không ai tra ngược ra được, vì con số đó không tồn tại bên PMS. Luật áp cho toàn bộ 511 phòng nên không riêng Thanh Xuân — chỉ là Thanh Xuân nhiều đơn chiều nên lộ rõ. Cần đội chốt một trong ba: (1) giữ nguyên và phổ biến quy ước “tra PMS phải cộng/trừ 1h”; (2) bỏ đệm trước, giữ đệm sau như trước 18/09; (3) hiện lý do khoá cho ops — dữ liệu đã có sẵn trong payload (checkin_at, cleaning_before_minutes), chỉ chưa hiển thị ở đâu.

C. Đồng bộ lịch — hai kiểu sổ mới, ba lỗi hạ tầng 13 commit · 673 test

C1. Gohost chỉ giữ MỘT phiên cho mỗi người đăng nhập

Hai lỗi chồng nhau: phiên cache không mang cookie sang client của lượt sau nên lời gọi đầu luôn 419 rồi đăng nhập lại; và Lela mượn credential của Bum nhưng phiên giữ theo tài khoản nên hai bên đá phiên nhau mỗi phút. Số đo production 17–18/09: 1436/1441 lượt của Bum và 1437/1441 của Taphouse đều là session_renewed — gần như 100% lượt chạy phải đăng nhập lại.

Nay giữ phiên theo chủ credential, có khoá cho lượt chạy song song, chụp/nạp nguyên cookie jar. Đo lại với Gohost thật: 10 lượt Bum+Lela xen kẽ và song song → 1 lần đăng nhập, 0 session_renewed, số khoảng bận không đổi.

C2. Hai bố cục sổ mới

C3. Ba lỗi hạ tầng đo tận nơi

Chỗ hỏngHậu quả thậtĐã sửa
KiotViet chối quá nửa request suốt 43 phút ngày 17/09 (503 trả trong 270–485ms; 18 tài khoản khác cùng khung giờ vẫn bình thường) Amoureux hỏng 34/45 lượt, có chuỗi 9 lượt liền, mà 153 phòng vẫn được chào bán bằng số của lần chạy được gần nhất — ngưỡng tươi 15 phút không bao giờ chạm tới vì cứ ~10 phút lại lọt một lượt Thử lại 502/503/504 tối đa 3 lần, chỉ GET/HEAD, không thử lại khi quá hạn; hỏng ≥3 lượt liên tiếp thì hạ ảnh chụp phòng của merchant đó xuống STALE, lượt chạy được tiếp theo tự đưa lại
openpyxl chỉ nằm ở nhóm [dev], ảnh Fly chỉ cài requirements.txt Miu lên production báo “No module named openpyxl”; lượt đồng bộ an toàn (PARTIAL, không đóng khoảng nào) nhưng 402 và 601 đang có khách mà chưa được khoá Cài đủ, kèm test quét mọi import của app/ và đòi có trong requirements
Tiêu đề cột mã cơ sở bị gõ đè thành “zZZ” (mục A1) 78 phòng rơi hết mà dry-run vẫn in “8 cơ sở · 0 phòng” Suy mã cơ sở theo tên cột đã cắt khoảng trắng rồi theo tiền tố; bỏ dòng nào thì ghi skipped

Deploy bản vá sync: push đúng commit 9c6f5a0 lên main, CI room-state xanh, /health trả đúng 9c6f5a0. Lượt sync đầu trên bản mới: 16/16 tài khoản chạy, 15 OK, chỉ sun_sheet PARTIAL — nhưng nó PARTIAL ở mọi lượt kể cả trước deploy. Không nhà nào bị hạ nhầm xuống “chưa biết”.

D. ChicStay backend — thiết kế lại phần sync phòng mới là thiết kế, chưa apply code

Phần việc của mình ở repo chicstay-backend tuần này chỉ là sync phòng: đưa hẳn bộ đồng bộ lịch từ chicdata về trong backend, chạy trên một Neon dev branch. Đã viết reports/chicstay-calendar-sync-architecture.html và chốt xong thiết kế với đội — chưa viết spec vào repo, chưa apply một dòng code nào.

Điểm xuất phát là hai đơn thật: CS-A9DG (mục B) và CS-8D2R — phòng bugalow của ALÀ HOMESTAY, đặt đêm 21/09, phòng này chưa map PMS nên backend coi là not_enforced và vẫn nhận đơn. Cùng một gốc: nguồn lịch và chỗ bán phòng đang nằm ở hai hệ.

Bốn nguyên tắc

Ba luật vận hành đã chốt

Năm quyết định chờ đội chốt

Để khỏi hiểu nhầm khi đọc git log: 29 commit tính năng của chicstay-backend tuần này (engine booking thêm giờ, quy trình xác nhận check-in, Control Tower, ChicAI) là của đội dev ChicStay. Phần của mình là review và gộp 4 PR, cộng với bản thiết kế sync phòng ở trên.

E. Số đo production 21/09, lấy thẳng từ DB

Chỉ sốTuần trước21/09
Cơ sở trong chicdata101109
Phòng490511
Merchant4250
Phòng đã nối PMS (source_mapping)274305
Cơ sở có ít nhất một phòng nối PMS—57 / 109
Phòng đang có khoảng bận còn hiệu lực—199

+29 phòng nối trong tuần: 17 qua Gohost (Lela 6 phòng chạy thật sau khi vá phiên; Bum 404 Bưởi 9 và 68 CG 2 qua “mã móc lịch”) và 12 qua Google Sheet (Miu 8, DEMO Inn&Ine 4). Kiểm lại: cả 6 phòng Lela và cả 11 phòng mã móc đều đang có khoảng bận thật — hai việc treo từ tuần trước đã chạy.

Sức khoẻ lượt đồng bộ 15–21/09: 161.121 lượt · 151.740 OK (94,2%) · 9.308 PARTIAL · 72 FAILED · 1 INTERRUPTED. Gần như toàn bộ PARTIAL (9.191) đến từ một nguồn: SUN HOMESTAY — xem mục F.

F. Rủi ro đang mở

F1. SUN HOMESTAY mù lịch từ 01/09 — 7 phòng

Bảng của nhà dừng ở ngày 31/08, không có dòng nào cho hôm nay trở đi. Lượt đồng bộ báo PARTIAL mỗi phút từ 17/08 tới nay (9.191 lượt riêng tuần này) và 7 phòng không có một khoảng bận nào. Cần chủ home kéo dài bảng hoặc mở tab tháng mới — không sửa được bằng code.

F2. Đệm dọn đầu giờ đang ăn khung bán (mục B3)

Chờ đội chốt một trong ba hướng. Trong lúc chờ, vận hành cần biết quy ước “tra PMS phải cộng/trừ 1 giờ”, nếu không mỗi lần đối chiếu sẽ lại tưởng hệ thống sai.

F3. 6 host mới vẫn chưa ẩn

21 phòng đã ẩn nhưng 6 host còn is_listed=True vì lệnh ẩn bị guard quyền chặn. Cần một người ẩn tay, hoặc cấp quyền để chạy tiếp.

F4. Dayladau 502 sáng nay

12 lượt FAILED ngày 21/09, cả ba tài khoản abri / fiora / homnaykhongngu cùng lỗi GET /v1/listings → HTTP 502. Bộ thử lại mới đã chạy mà vẫn không qua, tức nguồn hỏng thật chứ không phải chớp nhoáng. Đang STALE đúng thiết kế, nhưng cần theo dõi.

F5. 6 commit chưa push

Nhánh feat/onboard-7-home-chuan-hoa còn 6 commit ngày 15/09 chưa có bản tương đương trên origin/main (báo cáo sync, ghép tay phòng, script mã móc lịch, vá tiêu đề cột onboard, vá EXIF). Cả 6 đều là script chạy tay nên production không bị ảnh hưởng — nhưng chúng đang tồn tại ở đúng một máy và chưa ai review. Lúc deploy đã cố ý chỉ push một commit sync thay vì cả nhánh.

F6. Việc còn treo từ tuần trước

  • Đã xong: deploy room-state (Lela 6/6 phòng có lịch thật), 11 phòng mã móc của Bum đang chảy lịch.
  • Chưa động: Fiora vẫn 3.0★ từ đúng 2 review; 13 phòng Lela/Miu vẫn thiếu ảnh; 69 gói ghi “Chỉ T2–T5” vẫn bán cả 7 ngày theo giá cuối tuần; Lela Trường Chinh vẫn thiếu toạ độ; Blue Diamond 3 phòng 0 ảnh.
  • chicgo_data không có commit nào từ 24/08 — tuần thứ tư đứng im.
  • Suite test chicdata: 424 pass, vẫn 46 test đỏ có sẵn (server/api/events/*, phụ thuộc DB) — có trước và sau thay đổi tuần này, đang che tín hiệu CI.

G. Việc khác trong tuần

Việc tuần tới