Estimator Tools

Odoo là bộ não, mọi thứ khác là biên.

Kiến trúc cho Casa Estimate, viết để tái dùng cho JC, Hirsh và các web app sau. Bốn hình, ít chữ.

Anthony · 15 Sep 2026 · nguồn: họp 7/9, 14/9, demo của Sky, API staging của Phillip
  1. Tiền và sự thật ở Odoo. Giá, folio, invoice chỉ tính và ghi trong Odoo. Không ai viết lại pricing lần thứ tư.
  2. Nháp không vào Odoo. 5 đến 10 vòng sửa sống ở tầng biên, có TTL. Odoo chỉ nhận một cú submit do người bấm.
  3. Chốt hợp đồng, không chốt chỗ đặt UI. OpenAPI v1 là giao diện duy nhất. UI ở đâu đổi sau được.
  4. Anthony lead dự án và tầng biên. Phillip làm chủ tầng Odoo. Gặp nhau tại một file OpenAPI.
  5. Fresher không chạm Odoo. TypeScript trên client sinh từ spec, mock server từ spec.

Hình 1Kiến trúc Core & Edge

Kiến trúc Casa Core & Edge Sơ đồ kiến trúc ba vùng tin cậy: người dùng đi qua tầng biên TypeScript, tầng biên gọi Odoo qua hợp đồng OpenAPI v1 bằng compute chỉ đọc và submit do người bấm, còn trình duyệt đi thẳng Odoo và AI gọi submit đều bị chặn tại ranh giới. NGƯỜI DÙNG EDGE · TEAM ANTHONY · TYPESCRIPT · VERCEL CORE · PHILLIP · ODOO 19 · ODOO.SH OPENAPI V1 · HỢP ĐỒNG DUY NHẤT DIVER LOGIN TIN NHẮN TRIP NHÁP COMPUTE·SUBMIT SNAPSHOT COMPUTE · ĐỌC SUBMIT · BẤM CẤM ĐI TẮT AI ≠ SUBMIT USER Staff Casa · Agent · Khách lẻ · Diver trình duyệt · WhatsApp (giai đoạn 2) UI Estimator UI trang HTML hiện tại AI AI Extractor tin nhắn → Trip GATE BFF auth · vai→key · rate limit DB Draft store Postgres + RLS · TTL 90 ngày API Engine + FastAPI compute_estimate · rate card ERP Folio → SO → Invoice chỉ ghi qua submit PORTAL Dive Passport Odoo portal · diver tự login CHÚ GIẢI Cổng đặc quyền Gọi qua hợp đồng Luồng nội bộ Đường cấm, dừng ở ranh giới Ranh giới tin cậy
Ba vùng tin cậy, một ranh giới. BFF là cổng đặc quyền duy nhất; hai đường cấm dừng trước ranh giới thay vì đi xuyên qua. Diver là ngoại lệ có chủ ý: đăng nhập thẳng vào Odoo portal.

Hình 2Một báo giá đi qua hệ thống

Luồng một báo giá từ tin nhắn đến hóa đơn Luồng dữ liệu ba vai: khách nhắn, tầng biên trích xuất và tính giá qua Odoo rồi giữ bản nháp qua nhiều vòng sửa, và chỉ một lần submit do người bấm mới tạo folio trong Odoo, sau đó hóa đơn quay về khách. 01NHẮN 02TRÍCH XUẤT 03TÍNH GIÁ 04SỬA 05SUBMIT 06THU TIỀN NGƯỜIKHÁCH · STAFF EDGETEAM ANTHONY ODOOPHILLIP 1 LẦN · BẤM NG Khách nhắn WhatsApp · email · web Việt · Anh · Trung WB ED AI Extractor tin nhắn → Trip 3 trạng thái · không bịa WB TB ED BFF compute Trip → model giá kèm rates_version TB TB OD Engine tính giá Python thuần · chỉ đọc rate card = product TB TB NG Người sửa 5–10 vòng qua lại trang estimator TB TB ED Draft store revision + snapshot Postgres · TTL 90 ngày TB TB ED BFF submit contact + trip + guests Idempotency-Key TB TB OD Folio + báo giá sale order draft folio_id · order_ids TB FL OD Invoice · e-sign 100% trả trước báo kitchen · dive ops FL FL NG Khách trả tiền PDF + link thanh toán rồi mới báo bếp, tàu FL KIỂU DỮ LIỆU tin nhắn thô Trip / model giá (JSON) PDF · hóa đơn chip trái = vào · chip phải = ra LUỒNG dữ liệu đi tiếp lần ghi duy nhất vào Odoo gửi ra khách Ô XANH ô duy nhất trong Odoo được tạo bởi hệ thống ngoài, và chỉ khi người bấm
Bước 03 chỉ đọc. Bước 04 lặp bao nhiêu lần cũng nằm ở Draft store. Bước 05 là lần ghi duy nhất vào Odoo.

Chốt ở standupBa quyết định

ADR = Architecture Decision Record. Mỗi quyết định là một trang: bối cảnh, quyết định, lý do, hậu quả, ngày, người ký. Đã ký thì không sửa; đổi ý thì viết ADR mới và ghi "thay thế ADR cũ". Nhờ vậy không có chuyện dời quyết định từ họp này sang họp khác.

ADR-001

Odoo chỉ nhận submit

Nháp, hội thoại, kết quả AI, snapshot giá ở Draft store, TTL 90 ngày.
Khai tử: câu hỏi một hay hai DB, hack gộp request, nỗi lo AI ghi bậy.

ADR-002

Hợp đồng trước, host sau

OpenAPI v1 đóng băng. MVP giữ trang Evane đã UAT, thay calc() bằng compute sau flag. Dive Passport dùng Odoo portal.
Khai tử: tranh luận Odoo website hay standalone.

ADR-003

Biên = TypeScript + Postgres RLS

Vercel, client sinh từ spec, Supabase project mới dưới TechNext, RLS đóng từ đầu. Browser chỉ nói với BFF; BFF giữ key Odoo theo vai.
Khai tử: key trong trang tĩnh, admin/admin, n8n.

Số nào lên hóa đơn thì đến từ Odoo. Chưa lên hóa đơn thì là nháp, không vào Odoo.

Dữ liệuỞ đâuSống bao lâu
Rate card, promo 5+1, điều khoản cọcOdoo product + enginevĩnh viễn
Folio, quotation, sale order, invoiceOdoo, chỉ qua submitvĩnh viễn
Scenario nháp, các vòng sửa, snapshot giáDraft store (Edge)90 ngày
Tin nhắn gốc, kết quả trích xuấtDraft store, cột riêng30 ngày, che PII khi làm eval
Hồ sơ diverOdoo portal (Dive Passport)theo chính sách Casa

Hình 3Vì sao hai cuộc họp chưa chốt được

Xương cá: vì sao kiến trúc chưa chốt Sơ đồ xương cá với năm nhóm nguyên nhân dẫn đến việc kiến trúc bị dời quyết định qua hai cuộc họp; nhóm Vai trò là nguyên nhân gốc vì không có solutions architect và người lead không phải người giữ code. không có solutions architect lead ≠ người giữ code quyền quyết định chưa ghi chưa có trang capability agent login bỏ, diver giữ MVP ≠ sản phẩm dài hạn 4 stack, 3 bản giá 2 database không sync website Kasa HTML rời sợ theo số của Hirsh Casa chưa có p95 DB bloat chưa lượng hóa không có ADR dev không dự họp staging vừa mới có Vai trò Yêu cầu Stack Số đo Quy trình Kiến trúc chưa chốt 2 họp · dời sang standup thứ 3 CHÚ GIẢI nguyên nhân gốc: sửa cái này, bốn nhóm kia tự nhỏ lại nhóm nguyên nhân bằng chứng trong transcript 7/9 và 14/9
Sky tự gọi mình là "half-broken solutions architect". Mọi thứ khác là hệ quả.

Hình 4Ai lead, ai support

Sơ đồ trách nhiệm dự án Casa Sky là sponsor ký quyết định; Anthony lead dự án và tầng biên với ba pod fresher; Phillip làm chủ tầng Odoo; Jett giữ yêu cầu; hai tầng nối nhau bằng hợp đồng OpenAPI; ghế solutions architect còn trống. OPENAPI V1 CEO Sky · sponsor ký 3 ADR · ưu tiên · tiền GAP Solutions architect chưa có · Anthony kiêm cho Casa LEAD Anthony · lead + Edge quyết stack biên · backlog · DoD CO-LEAD Phillip · co-lead, chủ Odoo quyết Odoo · góp ý product, latency BA Jett · yêu cầu capability · acceptance POD Contract & Test diff calc vs compute POD Extractor Trip đúng schema · eval POD Edge UI & BFF flag compute · role→key CHÚ GIẢI quyền quyết định · bất đồng thì Sky phân xử chủ một tầng pod fresher ghế còn trống hợp đồng
Anthony không quyết bên trong Odoo, Phillip không quyết stack bên ngoài, nhưng cả hai đều có tiếng nói về sản phẩm, latency và security; bất đồng thì Sky phân xử. ADR (Architecture Decision Record) là một trang ghi quyết định, lý do, hậu quả, ngày và người ký; không sửa ADR cũ, chỉ viết ADR mới thay thế.

Gửi PhillipSáu việc cho API v1

  1. Khai báo securitySchemes: API key theo vai. Spec hiện nói về 401 nhưng không nói xác thực bằng gì.
  2. rates_version trong response compute, để snapshot chứng minh được giá cũ.
  3. Idempotency-Key cho submit. Thay cho hack "một khách một request mở", vốn gộp hai đoàn của cùng agency.
  4. Guest và diver trong submit, kèm external_ref mỗi guest và mỗi line.
  5. GET /v1/booking/{folio_id} trả draft, sent, paid.
  6. Rate limit ở tầng biên. compute ẩn danh đang mở, mỗi request chiếm một worker Odoo.
Ba bản giá đang lệchFile Sky (₱)Odoo staging (₱)
Boat dive, 1 diver / ngày4.50010.000hơn gấp đôi
Boat dive, 4+ diver, mỗi người2.9003.60024%
Deluxe, 3–4 pax / đêm14.50016.40013%
Van khứ hồi sân bay14.00013.000ngược chiều
Full board / người / ngày1.5001.500khớp

Odoo thắng, sau khi Eloa xác nhận. Differential test của pod Contract sẽ lộ hết các dòng còn lại.

Kế hoạchHai tuần đầu

Tuần 1 · chốt và đo

  • Ký ba ADR ở standup. Ghi file.
  • Jett viết trang capability một mặt giấy.
  • Gửi Phillip sáu việc, thống nhất ngày freeze v1.
  • Differential test + mock server. Supabase mới, RLS đóng.
  • Eloa xác nhận rate card, cho 30 tin nhắn thật đã che tên.

Tuần 2 · nối và cho Evane xem

  • BFF trên Vercel preview gọi compute staging.
  • Trang estimator có flag "tính từ Odoo", hai số cạnh nhau.
  • Extractor xuất Trip đúng schema, đổ vào form.
  • Demo 20 phút với Evane.
  • Báo p50 / p95 thật của compute. Hết sợ theo số của Hirsh.

Minh bạchĐã và chưa kiểm chứng