Punch list — Trung tâm điều hành

Phiên rà soát hub ngày 15/06/2026 · 12 mục + 1 ghi chú · cập nhật 16/06/2026 · DRAFT — INTERNAL · không phân phối

I3 · I5 · I7 · I9 · I10 — XONG & ĐÃ TRIỂN KHAI (hub sống). I6 — đã xây công cụ + áp 25-26 (chờ cấp quyền ghi DB). I11 — đã rà (Trao gửi yêu thương). I12 — chờ xác nhận điều phối viên.

Kết quả phiên 16/06:
  • Đã triển khai (hub sống): I5 (kiểm tra + test luồng đổi trạng thái), I7 (phúc lợi trong kỳ + lũy kế, năm học 1/8–31/7), I9 (số HS theo lứa), I10 (lớp + số lượng trong báo cáo trường), I3 (gộp thỏa thuận theo nguồn), + sửa FLAG 4 (nguồn tài trợ không cộng trùng) + làm gọn CSV danh sách HS. PR #61 + #64 đã gộp + deploy.
  • I6 — gần xong: thỏa thuận = gốc, Excel = công thức phân bổ; phân bổ theo biên bản (dòng phủ Track K) khớp 25-26 (đủ 6 trường). Công cụ allocation_apply.py + ghi chú đối chiếu đã đăng. Áp 25-26 đã kiểm trên bản sao + sao lưu DB; chờ cấp quyền ghi bucket sống. 23-24/24-25 cần học bạ theo năm (I12).
  • I11 — đã rà: "Chia sẻ yêu thương" = chương trình Trao gửi yêu thương (hỗ trợ hàng tháng trẻ mồ côi/khó khăn): 88 em được cấp 25-26 (86 mới), 866tr/năm. Công cụ dry-run đã xây; nạp sống chờ sao lưu + go-ahead.
  • Còn chờ bạn: I12 (xác nhận BCKQ Đại An 24-25 + Vĩnh Hào 25-26, 24 em chưa có học bạ, SE 4 trường, TDTT) · cấp quyền ghi DB cho I6 25-26 · sao lưu + go-ahead cho I11.

Mỗi mục là một nhận xét khi xem hub sống, kèm chẩn đoán, cách sửa, quyết định và trạng thái. Tên học sinh, mã hồ sơ và email đã được ẩn (trang này công khai).

Tổng hợp

ViệcTrạng thái
I1Tài khoản nhân viên (1 khu vực) vẫn thấy tab/khu vực không được cấp quyền — rà soát phân quyền chéo khu vựcXONG
I2Tạo tài khoản: "Chưa cấu hình gửi email" — đặt mật khẩu qua liên kết sao chépKHÔNG SỬA
I3"Phúc lợi theo nguồn tài trợ": Quỹ Thành Nhân hiển thị Tổng = 0 dù có thỏa thuậnXONG · TRIỂN KHAI
I4Thêm 2 biểu mẫu Google (Phiếu hoạt động + Khảo sát học sinh) vào tab Trợ giúpXONG
I5Kiểm tra luồng đổi trạng thái học sinh + rà các hàm ít dùng có chạy đúng khôngXONG · TRIỂN KHAI
I6Nạp bảng phân bổ học bổng theo học sinh (lớp/trường/năm) vào Drive + tính số tiền mỗi em25-26 SẴN SÀNG · chờ ghi DB
I7Phúc lợi: hiển thị 2 giá trị — trong kỳ (năm học hiện tại) + lũy kếXONG · TRIỂN KHAI
I8Phúc lợi theo trường: vì sao các trường THCS số tiền nhỏ? (đã giải thích; cùng gốc I3, sửa qua I6)ĐÃ TRẢ LỜI
I9BC phân tích: bổ sung số lượng học sinh theo lứaXONG · TRIỂN KHAI
I10Danh sách em theo chương trình: thêm cột lớp + số lượng mỗi nhómXONG · TRIỂN KHAI
I11Xem xét bảng "chương trình khác" (Trao gửi yêu thương) và cách đưa vào hệ thốngĐÃ RÀ · chờ nạp
I12Rà soát dữ liệu CETB: 85/317 tài liệu Drive chưa nạp (27 phiếu PDF của LTV, học bạ thiếu năm ở Đại An/Vĩnh Hào, SE chỉ có 2/6 trường, TDTT chưa mô hình hoá)CHƯA LÀM
N1Ghi chú quyết định: Google Forms là cổng tải lên (sign-in OK) — không sửa code, có 2 thiết lập cần xác minhGHI NHẬN

Chi tiết

I1 — Tài khoản 1 khu vực vẫn thấy khu vực không được cấp quyền XONG

Page: /care (Quản lý học sinh) · screenshot 2026-06-15 (tài khoản test, avatar "TT").

User comment (verbatim):

User's interface still show un-authorised tabs. Picture is a student-access only account. Double check and make sure all works consistently.

Read & root-cause:

Decision (user, 2026-06-15): Cấp quyền care = toàn bộ 4 tab khu vực học sinh (roster + phân tích + báo cáo + cảnh báo). KHÔNG ẩn các tab care. Vấn đề thực = đảm bảo các khu vực không được cấp (content / finance) không thể vào được qua URL trực tiếp và không lọt link nào.

Câu hỏi mở: ảnh chụp là phiên care-only hay phiên admin? Nếu admin thì các tab là đúng và không có lỗi. Xác minh sống sẽ chốt.

Fix đề xuất (sau xác minh):

  1. Xác minh sống với tài khoản test (care-only): xác nhận sidebar ẩn 4 khu vực kia, và truy cập trực tiếp /plan, /review, /trips, /finance đều 303 → /khong-co-quyen; /survey + /care/* đều mở được. Ghi lại link nào trong trang care trỏ chéo khu vực.
  2. Vá bất kỳ lỗ hổng phát hiện (link template chưa lọc, đường dẫn thiếu trong _PATH_MODULES, hoặc middleware chưa phủ một sub-app mount).
  3. Thêm test hồi quy: nhân viên care-only → 303 trên từng khu vực không được cấp; admin → 200 trên tất cả.

Chặn bởi: mật khẩu tài khoản test (hoặc cho phép tôi đặt mật khẩu qua luồng liên kết) để probe URL sống.

Trạng thái (user, 2026-06-15): XONG — user xác nhận đã hoàn tất phân quyền chéo khu vực.

I2 — "Chưa cấu hình gửi email" khi tạo tài khoản KHÔNG CẦN SỬA (đúng thiết kế)

Page: /quan-tri/nguoi-dung (Quản lý tài khoản) · screenshot 2026-06-15.

User comment (verbatim):

The email account notifications and password setup are not in place I believed. Just tried to create one.

Read & root-cause:

Decision (user, 2026-06-15): giữ luồng sao-chép-liên-kết (copy-link only). Không đổi code. Bật email sau này chỉ là đặt 2 secret HMT_SMTP_HOST + HMT_SMTP_FROM (+ user/pass/TLS) lên Cloud Run.

Lưu ý (flag): domain trong liên kết mời là hub-dev.hoamattroi.org — xác nhận đây là URL bạn thực sự phát cho người dùng. Nếu vẫn ở URL dev, người được mời sẽ đặt mật khẩu trên môi trường dev chứ không phải prod.

I3 — "Phúc lợi theo nguồn tài trợ": Quỹ Thành Nhân Tổng = 0 CẦN SỬA (lỗi trình bày)

Page: báo cáo "Phúc lợi theo nguồn tài trợ" (bảng Nguồn · Số mục · Tổng VND) · screenshot 2026-06-15.

User comment (verbatim):

Why don't we have amounts for Quỹ Thành Nhân. All the agreements are in place.

Read & root-cause (đã truy nguyên):

Decision (user, 2026-06-15): Gộp tổng thỏa thuận vào bảng theo nguồn — để Quỹ Thành Nhân hiển thị số tiền cam kết thật thay vì 0.

Fix:

  1. Trong tools/benefit_report.py, mở rộng tổng hợp "Theo nguồn tài trợ" sao cho mỗi nguồn = (tổng amount_vnd per-student) + (tổng amount_vnd các dòng register_entry funding khớp), khóa theo chuỗi funding_source.
  2. Tránh đếm trùng: tiền một nguồn đến từ hoặc dòng per-student hoặc tổng thỏa thuận, không cả hai — khớp đúng chuỗi funding_source (170-172 gộp với 107-126).
  3. Giữ mục "Tài trợ cấp trường/lứa (thỏa thuận)" như cũ, HOẶC thêm một dòng ghi chú rằng tổng của nó đã phản ánh ở bảng trên — chốt khi triển khai.
  4. Cập nhật fixture selftest (benefit_report.py:408-437) để khẳng định số tiền thỏa thuận xuất hiện trong bảng theo nguồn (hiện chỉ kiểm tên nguồn).
  5. Đối chiếu số thật: Quỹ Thành Nhân 2025-2026 (181 mục) phải hiển thị tổng thỏa thuận, không phải 0.

Không chặn: hoàn toàn tự chứa, không cần thông tin đăng nhập — sẵn sàng làm trước.

I4 — Thêm 2 biểu mẫu Google vào tab Trợ giúp XONG

Page: /tro-giup (Trợ giúp & công cụ).

User request (verbatim):

I also want to publish the 2 google forms to Trợ giúp tab.

Quyết định (user, 2026-06-15): hai biểu mẫu = Phiếu thông tin hoạt động (điều phối viên) + Phiếu khảo sát học sinh. (Form thứ ba — Đăng ký tài trợ — không chọn lần này.)

Đã làm:

Kiểm thử: ruff sạch · 42/42 test hub pass · render sống trả 200 với cả hai link biểu mẫu.

Lưu ý:

  1. Phiếu khảo sát hiện vẫn là placeholder (1 câu hỏi chưa đặt tên) — link mở được nhưng form rỗng cho tới khi nạp nội dung (forms_provision.py --apply, xem _system/forms/PROVISIONING.md). User chọn biết điều này.
  2. Tùy chọn: thêm HMT_SURVEY_FORM_ID vào .env để bỏ giá trị mặc định cứng trong code.
  3. Cần deploy service management-hub (deploy -Only management-hub, ~2 phút) để hiển thị trên hub sống — hành động ra ngoài, cần go-ahead theo từng lần (workspace-ethics.md §2).

I5 — Kiểm tra luồng đổi trạng thái + rà các hàm ít dùng CẦN KIỂM TRA

User comment (verbatim):

check if the status update functions works. Actually check all other functions that we havent touched on much whether they are working.

Read: phần lớn đợt rà soát vừa qua chỉnh chữ/giao diện; các hành động back-end ít được chạy thật. Cần một lượt kiểm tra hoạt động: xác nhận luồng đổi trạng thái học sinh chạy trọn vẹn (form → ghi DB → phụ tải ghi danh → ghi nhật ký profile_entry → banner/danh sách phản ánh trạng thái mới), rồi quét các hàm ít dùng khác.

Mục tiêu chính — đổi trạng thái (T17): route child_transition (app/main.py:819-916): graduate-cetb-to-nbtl, graduate-exit, graduate-continue, transfer-school, pause, withdraw, reactivate. Liên quan đổi danh mục trạng thái vừa làm (punch list 13/06 · P28) — kiểm lại các bước chuyển vẫn ra trạng thái hợp lệ.

Quét thêm (chốt khi làm): sửa lớp/trường ở trang chi tiết; nạp học bạ 1 PDF → school_doc_extract → duyệt; tạo lại sổ tay; trình tạo báo cáo /reports; xét chọn /survey; quản lý tài khoản (tạo/mời/cấp quyền); hành động donor/finance nếu vào được.

Cách kiểm (đề xuất): đọc test sẵn có trước (tests/test_app.py…), rồi chạy thử trên bản sao DB nháp — không động DB sống nếu chưa backup + quiesce (care-data.md rule 5). Ghi lại cái nào chạy / hỏng.

Trạng thái: chưa chạy lượt kiểm tra.

I6 — Nạp bảng phân bổ học bổng theo học sinh + tính số tiền mỗi em CHƯA LÀM

User comment (verbatim):

This link shows the amount of fund allocated to each student (different with grade) to each school and each year. We need to bring this document to the Drive (at the right place) and calculate the amount of each student of the relevant year — [Drive-sheet-id]

Read: một Google Sheet ngoài chứa lịch phân bổ tài trợ — số tiền mỗi em, thay đổi theo lớp, theo trường, theo năm. Hai phần:

  1. Đưa tài liệu vào Drive đúng chỗ. Tài liệu tài trợ nhóm theo trường/năm → định tuyến như doc tổng hợp (care-data.md rule 2: Truong/<trường>/<năm-học>/), nhưng bản chất là hồ sơ tài trợ = cầu bien-ban-tai-tro (toả ra dòng benefit mỗi em + nối funding_source).
  2. Tính số tiền mỗi em cho năm liên quan. Ghép (trường × lớp × năm → số tiền) với roster (trường + lớp + năm của từng em) → ghi dòng benefit mỗi em, kèm source_ref về sheet đã nạp.

Mở (chốt khi làm): link riêng tư — đọc qua đường SA (SA đã có quyền), không WebFetch; "năm" = năm học hay lứa?; lớp-của-từng-năm lấy từ lịch sử học bạ; ghi DB sống cần backup + quiesce + dry-run + provenance (care-data.md rule 5). Gắn với I8 (vì sao THCS nhỏ).

Trạng thái: chưa làm — cần xem cấu trúc sheet trước.

I7 — Phúc lợi: hiển thị 2 giá trị (trong kỳ + lũy kế) CHƯA LÀM

Page: /analytics (Phân tích).

User comment (verbatim):

Chị đang xem BC phân tích (on the hub page) mục phúc lợi em cho 2 giá trị: trong kỳ (trong năm học hiện tại) và lũy kế (từ đầu đến giờ) nhé

Read: mọi con số phúc lợi trên trang hiện chỉ là lũy kếlifetime_total (app/main.py:1586-1588) và bảng theo trường/nguồn (main.py:1528-1578) đều SUM(amount_vnd) không lọc năm. Cần hiện hai giá trị: trong kỳ (năm học hiện tại) và lũy kế, cho stat Tổng phúc lợi + (nên có) bảng theo trường/nguồn.

Mở: "trong kỳ" = năm học (vd 2025-2026); cần mỗi dòng benefit có năm/kỳ để lọc; chốt ranh giới năm học VN (~T9→T8).

Trạng thái: chưa làm.

I8 — Phúc lợi theo trường: vì sao THCS số tiền nhỏ? ĐÃ TRẢ LỜI · GỘP I6

Page: /analytics · bảng "Phúc lợi theo trường".

User comment (verbatim):

Is the per school amount for all years or just one year? how do these figures come together? why other THCS show small amount?

Trả lời (từ code, 2026-06-15):

Cùng gốc với I3 (Quỹ Thành Nhân Tổng=0): cả hai do tiền cam kết nằm trên register, không per-student. I6 (nạp sheet phân bổ → ghi số tiền per-student mỗi năm) là cái sửa triệt để để mọi trường so sánh được.

Trạng thái: đã trả lời; phần sửa dữ liệu theo I6.

I9 — BC phân tích: thêm số lượng HS theo lứa CHƯA LÀM

Page: /analytics.

User comment (verbatim):

BC phân tích bổ sung cho chị thêm SL HS theo lứa nữa nhé

Read: trang có "Số học sinh theo trường" nhưng chưa có theo lứa (lứa = năm vào chương trình, child.cohort_year; khác năm học). Thêm thẻ "Số học sinh theo lứa" tương tự thẻ theo-trường: query GROUP BY c.cohort_year + một chartcard nữa.

Trạng thái: chưa làm.

I10 — Danh sách theo chương trình: thêm lớp + số lượng CHƯA LÀM

Page: danh sách học sinh nhóm theo chương trình.

User comment (verbatim):

Chị mới xem BC theo trường, danh sách cuối cùng các em theo chương trình em bổ sung thêm lớp, và số lượng các em nhé

Read: trong danh sách nhóm theo chương trình, thêm (1) cột lớp (class_label) và (2) số lượng mỗi nhóm chương trình — đếm mỗi nhóm đã có ở nhóm theo trường (· 38 em), nhân bản sang nhóm theo chương trình. Query roster đã chọn c.class_label nên chủ yếu là template.

Mở: class_label là lớp hiện tại; xác nhận với user có muốn lớp lúc vào thay vì lớp mới nhất không.

Trạng thái: chưa làm.

I11 — Xem xét bảng "chương trình khác" + cách đưa vào hệ thống CHƯA LÀM

User comment (verbatim):

this is another program. we need review and consider how to bring it into the system — [Drive-sheet-id]

Read: một Google Sheet cho chương trình khác ngoài ba chương trình đã có (Cùng em tiến bước, Nâng bước tương lai, Trao gửi yêu thương) + track Hoa Sữa NBTL đã nạp. Cần xem + thiết kế tích hợp: hiểu sheet chứa gì (học sinh? tài trợ? mô hình khác?), rồi quyết cách ánh xạ vào care store / hub (slug chương trình mới, nạp roster, phúc lợi, sổ).

Mở (sau khi xem sheet): link riêng tư — mở qua SA, không WebFetch; là chương trình mới trong mô hình 8 cánh hay track khác cấu trúc (như Hoa Sữa HVK<k> cần parser riêng)?; nạp roster cần backup + quiesce + dry-run + provenance. Gắn với I6 (sheet phân bổ) và pattern nạp cohort Hoa Sữa.

Trạng thái: chưa làm — cần xem sheet trước khi lập kế hoạch tích hợp.

I12 — Rà soát dữ liệu CETB: tài liệu trên Drive chưa được nạp/ghi nhận CHƯA LÀM

User comment (verbatim):

review the CETB folders in this [Drive-folder-id]. Check if all documents have been sourced to Drive and if all the information/data ingested/recorded. I believe there are many documents not reflected such as PDF score cards. Also find which schools/cohorts miss out any important information that you need from users?

Cách làm (chỉ đọc): duyệt 3 thư mục CETB 20xx-20xx/<trường>/ trong Drive "Thông tin học sinh" (317 tệp) và đối chiếu từng Drive file id với care DB sống (source_docsource_fileessay_scoreschool_report.source_pdf), kèm rà phủ theo trường/lứa. DB sống copy ra scratch rồi xoá; không ghi gì lên Drive/bucket.

Kết quả: 232/317 tệp đã nạp, 85 chưa. Đã đủ: bài viết (156), phiếu cảm xúc-xã hội (60), tài trợ (13), phúc lợi (học bổng 352 dòng + thưởng 162 dòng) ở cả 6 trường. 85 tệp chưa nạp chia làm thiếu dữ liệu thậtchỉ thiếu nguồn gốc (tệp chưa vào sổ source_doc nhưng dữ liệu đã trích — cùng gốc P17 ở punch list 13/06). CETB = 230 em, 6 trường, lứa 2023/2024/2025.

I12.1 — 27 "Phiếu học tập" PDF của LTV (2024-2025) chưa nạp. Thư mục CETB 2024-2025/THPT LTV/PHIẾU HỌC TẬP CỦA 27 HỌC SINH QUỸ HMT/ có 27 phiếu điểm PDF từng em; không có trong DB. Đây chính là "PDF score cards chưa phản ánh". Xử lý: phân loại theo em → school_doc_extract (đường nạp hàng loạt P20) → duyệt → lưu source_doc kind=student vào Tai-lieu-goc/ từng em.

I12.2 — Thiếu học bạ theo năm. 24/230 em CETB chưa có học bạ nào (Vĩnh Hào 9, Đại An 7, Tam Thanh 6, LTV 1, Nguyễn Bính 1; Tân Khánh 0). Hai lỗ hổng trọn năm có nguồn đang nằm chưa nạp trên Drive: Đại An — lứa 2024 (25 em): kết quả 2024-2025 chưa nạp (DB chỉ có 2025-2026; Drive có BCKQ năm 24-25 chưa nạp); Vĩnh Hào — kết quả 2025-2026 chưa nạp (DB có 2024-2025; Drive có BCKQ năm 25-26 chưa nạp).

I12.3 — Phiếu cảm xúc-xã hội (SE) chỉ có ở 2/6 trường. SE chỉ có nguồn ở Tam Thanh + Đại An (2025-2026). Tân Khánh, Vĩnh Hào, LTV, Nguyễn Bính không có SE nào — đây là thiếu nguồn từ điều phối viên, không phải lỗi nạp.

I12.4 — TDTT (thể thao) có trên Drive nhưng chưa mô hình hoá. Hầu hết trường có sheet TDTT mỗi năm (cánh 5 — sức khỏe thể chất); chưa nạp và chưa có doc_type. Cần quyết: ghi nhận thành profile_entry (cánh 5)/phúc lợi, hay chỉ lưu nguồn.

I12.5 — ~50 sheet tổng hợp chưa vào sổ nguồn (cùng gốc P17). Sheet roster/KQ/thưởng/TDTT theo trường-năm phần lớn không có trong source_doc dù dữ liệu đã trích → mọi dòng hiện "Nguồn gốc —". Vào sổ kind=consolidated + gắn source_ref khi làm P17.

Cần từ người dùng:

Trạng thái: chưa làm — chờ dữ liệu/quyết định từ người dùng; việc nạp giá trị cao nhất kế tiếp = 27 phiếu PDF của LTV qua đường P20.

N1 — Ghi chú quyết định: Google Forms là cổng tải lên GHI NHẬN (không sửa code)

Bối cảnh: hỏi Google có cổng tải-lên an toàn cắm-sẵn không — không có (Google không có sản phẩm tải-lên có thương hiệu, không cần đăng nhập). "Hub upload (preferred)" trong care-data.md là thứ gần nhất ta sở hữu.

Quyết định (admin, 2026-06-15): chọn Google Forms làm cổng cho điều phối viên/nhà trường, chấp nhận yêu cầu đăng nhập Google. Người nộp đa số không có tài khoản tổ chức — Gmail cá nhân là được, không bắt buộc @hoamattroi.org.

Lý do giữ thiết kế tách rời (folder-link upload): ràng buộc thật của Forms file-upload là bức tường đăng nhập, không phải bất khả thi. Forms có câu hỏi tải file, nhưng (a) người trả lời phải đăng nhập, (b) SA của ta không tạo được (Forms.create() → 500; người tạo, SA --sync), (c) file rơi vào Drive của người tải, không phải care bucket. ⇒ giữ đường folder-link vì lý do tài khoản/quota/SA, không phải vì giới hạn cứng của Forms.

Hai thiết lập cần xác minh khi form lên sống (cho người nộp không tài khoản):

  1. Giới hạn tổ chức ("Limit to users in Quỹ Hoa Mặt Trời") TẮT.
  2. Thu thập email BẬT.

Thiết lập "Anyone with the link" trên form school-report (HMT_SCHOOL_REPORT_FORM_ID, khác form khảo sát ở I4) đã thỏa #1.

Cờ chuyển hội đồng quản trị: tài liệu chăm sóc đi qua một tài khoản Google ngoài Foundation trên đường nạp vào (gật đầu firewall / care-data.md §3) — cái giá của đường Forms-sign-in so với trang upload trên hub.

Không sửa code: registry, service school_report, đường upload tách rời đều không đổi. Đã lưu vào memory forms-as-upload-portal-decision.

Quỹ Hoa Mặt Trời · Trung tâm điều hành · phiên rà soát 15/06/2026 · DRAFT — INTERNAL. Trang công khai: đã ẩn tên/mã học sinh, email tài khoản và token đặt mật khẩu.