Changelog

Lịch sử cập nhật, lỗi đã phát hiện và các bản vá

Lỗi nghiêm trọng
Lỗi ảnh hưởng dữ liệu
Cải tiến / tính năng mới
Đã sửa
v1.1.1·2026-03-19
Bản vá Diễn giải cột D — Feedback lần 3
Cột Diễn giải (D) trong FILE ASP cần dùng cùng 1 nội dung cho cả 3 dòng cùng ngày để kế toán lọc được trên MISA, trong khi cột Diễn giải HT (E) vẫn giữ chi tiết riêng từng dòng.
BUG-010Ảnh hưởng dữ liệuĐã sửa
FILE ASP — Cột "Diễn giải" (D) hiển thị 3 nội dung khác nhau thay vì cùng 1 nội dung
Phát hiện bởi:Kế toán (Feedback lần 3 ngày 19/03/2026 — lọc trên MISA chỉ ra 1/3 dòng)
File liên quan:src/lib/converter.ts
Nguyên nhân kỹ thuật
Fix BUG-008 (Feedback lần 2) đã tách đúng 3 diễn giải riêng cho cột E dien_giai_ht, nhưng đồng thời cũng gán 3 giá trị khác nhau cho cột D dien_giai (dg1/dg2/dg3). Cột D đáng lẽ phải dùng chung 1 nội dung cho cả 3 dòng cùng ngày, cột E mới tách chi tiết.
Ảnh hưởng kế toán
Trên MISA, kế toán lọc sổ nhật ký theo cột Diễn giải (D) bằng cụm từ "Shopeefood" hoặc "Grabfood". Nếu 3 dòng cùng ngày ghi khác nhau (hoa hồng / GTGT / TNCN), kết quả lọc chỉ trả về 1/3 dòng — đối chiếu công nợ TK 131 không đầy đủ, sai tổng phát sinh.
Cách sửa
Tách thành 2 biến riêng: dg_common = "Hạch toán chi phí đơn hàng {p}" dùng cho tất cả 3 rows ở dien_giai (cột D); dg1/dg2/dg3 giữ nguyên, chỉ gán vào dien_giai_ht (cột E) để phân biệt loại hạch toán.
v1.1.0·2026-03-19
Bản vá dữ liệu kế toán — Phản hồi từ kế toán
5 lỗi ảnh hưởng trực tiếp đến độ chính xác của FILE DỮ LIỆU và FILE ASP MISA được phát hiện qua feedback kế toán và đã sửa toàn bộ.
BUG-005Ảnh hưởng dữ liệuĐã sửa
FILE DỮ LIỆU — Cột NGÀY hiển thị lệch 1 ngày so với email
Phát hiện bởi:Kế toán (đối chiếu FILE DỮ LIỆU vs email SF/GF)
File liên quan:src/lib/parsers/shopeefood.ts, src/lib/parsers/grabfood.ts
Nguyên nhân kỹ thuật
Hàm dateKeyToDate() tạo Date object bằng new Date(yyyy, mm-1, dd, 0, 0, 0, 0) — là midnight theo local timezone của Node.js process. Trên VPS chạy UTC, midnight ngày 01/03 theo giờ Việt Nam (UTC+7) = 2026-02-28T17:00:00Z. ExcelJS chuyển Date sang Excel serial number dùng UTC epoch → Excel thấy ngày 28/02 → hiển thị sai 1 ngày.
Ảnh hưởng kế toán
Cột Ngày trong FILE DỮ LIỆU hiển thị sớm hơn 1 ngày so với email SF/GF. Nếu kế toán đối chiếu theo ngày (đặc biệt cuối tháng), dữ liệu sẽ rơi sai kỳ hạch toán — ví dụ đơn hàng 31/03 ghi thành 30/03, sai tháng.
Cách sửa
Đổi sang new Date(Date.UTC(yyyy, mm-1, dd)) — date luôn là midnight UTC bất kể timezone server, ExcelJS serialize đúng ở mọi môi trường. Áp dụng cho cả SF (shopeefood.ts) và GF (grabfood.ts).
BUG-006Ảnh hưởng dữ liệuĐã sửa
FILE DỮ LIỆU — Cột GIẢM GIÁ THÊM hiển thị sai số tiền
Phát hiện bởi:Kế toán (so sánh với email SF: "Tổng khuyến mại lợi quán" = 7,500 nhưng file ghi sai)
File liên quan:src/lib/parsers/shopeefood.ts, src/lib/file-dulieu-writer.ts
Nguyên nhân kỹ thuật
Parser SF chỉ đọc 6 trong 12 cột của CSV (cột 3, 4, 5, 9, 10, 11). Cột 6 "Khuyến mại từ quán" không được đọc trực tiếp. Writer tính ngược bằng công thức: giam_gia = gia_tri_don − tien_ck − thue − thuc_nhan. Công thức này sai khi có cột 8 "Phí vận chuyển trả cho quán" ≠ 0 vì phí vận chuyển cộng thêm vào thuc_nhan khiến phép trừ cho kết quả nhỏ hơn giá trị thật.
Ảnh hưởng kế toán
Cột GIẢM GIÁ THÊM dùng để đối chiếu với email SF ("Tổng khuyến mại lợi quán") và tính Doanh thu xuất hoá đơn = Giá trị đơn − Giảm giá thêm. Nếu sai, kế toán không đối chiếu được với email, doanh thu xuất HĐ cũng sai → sai hoá đơn thuế.
Cách sửa
Thêm COL_KHUYEN_MAI = 6, đọc trực tiếp vào trường giam_gia_them trong ParsedDayData. Writer ưu tiên dùng row.giam_gia_them nếu có, chỉ fallback về công thức tính ngược cho GF (không có khái niệm này).
BUG-007Nghiêm trọngĐã sửa
FILE ASP — Cùng ngày sử dụng 2 số chứng từ NVK khác nhau
Phát hiện bởi:Kế toán (import MISA thấy 1 ngày split thành 2 bút toán riêng)
File liên quan:src/lib/converter.ts
Nguyên nhân kỹ thuật
converter.ts cấp 2 NVK mỗi ngày: ct1 = NVK_n (Row hoa hồng) và ct2 = NVK_(n+1) (Row thuế GTGT + TNCN). Counter tăng 2 mỗi ngày, khiến 3 dòng ASP của cùng 1 ngày mang 2 số chứng từ khác nhau. Nhận định sai từ ban đầu dựa trên tham chiếu file cũ.
Ảnh hưởng kế toán
Trong MISA, 1 số chứng từ NVK = 1 bút toán kế toán. Nếu 3 dòng của cùng 1 ngày dùng 2 NVK khác nhau, MISA hiểu là 2 giao dịch riêng lẻ → bút toán không cân → đối chiếu công nợ TK 131 bị sai → báo cáo sai. Đây là lỗi nghiêm trọng nhất trong nhóm feedback này.
Cách sửa
Dùng 1 NVK duy nhất cho cả 3 dòng của cùng 1 ngày+kênh. Counter tăng 1 mỗi ngày thay vì 2. Code mới: const ct = formatChungTu(counter++) — cả 3 rows đều dùng ct.
BUG-008Ảnh hưởng dữ liệuĐã sửa
FILE ASP — 3 dòng cùng ngày có diễn giải khác nhau
Phát hiện bởi:Kế toán (yêu cầu: tất cả 3 dòng cùng nội dung để dễ tìm kiếm trên MISA)
File liên quan:src/lib/converter.ts
Nội dung hiện tại (sai)
  • Row 1: "Hạch toán chi phí hoa hồng Shopeefood"
  • Row 2: "Hạch toán khấu trừ thuế GTGT đơn Shopeefood"
  • Row 3: "Hạch toán khấu trừ thuế TNCN đơn Shopeefood"
Ảnh hưởng kế toán
Cột "Diễn giải HT" hiển thị trên sổ sách MISA. Kế toán muốn lọc tất cả bút toán Shopeefood bằng 1 cụm từ duy nhất. Nếu 3 dòng ghi khác nhau, lọc theo diễn giải trả về không đủ — chỉ ra 1/3 dòng → đối chiếu không chính xác.
Cách sửa
Tất cả 3 dòng dùng cùng nội dung: "Hạch toán chi phí đơn hàng Shopeefood" / "Hạch toán chi phí đơn hàng Grabfood". Channel name được capitalize từ dien_giai_prefix trong DB, không cần thay đổi cấu trúc DB.
BUG-009Ảnh hưởng dữ liệuĐã sửa
FILE ASP — Xuất dòng ASP cho ngày có gia_tri_don = 0
Phát hiện bởi:Kế toán (file ASP có dòng tiền = 0, không có ý nghĩa kế toán)
File liên quan:src/lib/converter.ts
Nguyên nhân kỹ thuật
converter.ts không có guard check gia_tri_don === 0. GF PDF những ngày không có đơn hàng vẫn có thể tồn tại với tổng = 0 (đặc biệt khi hệ thống GrabFood gửi PDF báo cáo ngày với 0 đơn). Parser parse thành công → converter tạo 3 dòng ASP với so_tien = 0.
Ảnh hưởng kế toán
Dòng ASP tiền = 0 là bút toán trống, vô nghĩa trong MISA. Import vào sẽ tạo bút toán dư 0 trên TK 131 → khi đối chiếu công nợ xuất hiện những dòng rỗng gây khó đọc và nhầm lẫn khi kiểm tra sổ.
Cách sửa
Thêm if (row.gia_tri_don === 0) continue trước khi allocate NVK. Những ngày không có doanh thu sẽ không tạo bút toán nào.
v1.0.1·2026-03-18
Bản vá hạ tầng — Lỗi Gmail API, Google Drive, GF PDF
4 lỗi hạ tầng phát hiện trong quá trình vận hành thực tế đầu tiên (scan thật với email HP + DBP).
BUG-004Nghiêm trọngĐã sửa
GF PDF — list index out of range khi parse tổng cuối trang
Phát hiện bởi:PM2 error log (parse-gf-pdf.py crash)
File liên quan:src/scripts/parse-gf-pdf.py, src/lib/parsers/grabfood.ts
Nguyên nhân kỹ thuật
Parser v1.0 dùng hardcoded index để lấy số liệu từ dòng tổng PDF (ví dụ: row[16] = THUC_NHAN). GrabFood thỉnh thoảng xuất PDF với dòng tổng 16 cột thay vì 19 cột (những ngày không có đơn hoặc định dạng template thay đổi) → row[16] không tồn tại → IndexError: list index out of range.
Ảnh hưởng kế toán
Toàn bộ email GF của ngày đó bị skip không xử lý được. Nếu không phát hiện kịp thời, dữ liệu ngày đó bị thiếu khỏi FILE ASP → sai tổng hạch toán tháng.
Cách sửa
Viết lại parse-gf-pdf.py v2.0 với chiến lược 3 tầng: (1) String match header → map cột động theo tên thay vì index cứng; (2) AI fallback (Gemini) nếu tên cột không khớp pattern; (3) Error + Telegram alert nếu cả 2 tầng đều thất bại. Kèm sanity check zero-tolerance: thuc_nhan == gia_tri_don − tong_ck − thue_gtgt − thue_tncn.
BUG-003Nghiêm trọngĐã sửa
Google Drive — Service Accounts do not have storage quota
Phát hiện bởi:API error khi upload file XLSX sau convert
File liên quan:src/lib/drive.ts, src/app/api/auth/gmail/authorize/route.ts
Nguyên nhân kỹ thuật
Service Account Google là tài khoản robot — không có Google Drive quota riêng. Không thể tạo file trong Personal Drive của user bằng SA. Giải pháp đúng: dùng OAuth2 user credentials (refresh token của Gmail đã kết nối) để upload — tài khoản người dùng có quota Drive thật.
Ảnh hưởng kế toán
File XLSX không được upload lên Drive → kế toán không nhận được file qua Drive link → phải download thủ công từng file một, mất tính tự động.
Cách sửa
Thêm scope drive.file vào Gmail OAuth flow.drive.ts ưu tiên dùng user refresh token (từ GmailToken table) thay vì Service Account khi upload. SA vẫn giữ làm fallback. Yêu cầu user kết nối lại Gmail trên /setup để lấy token mới có scope drive.file.
BUG-002Nghiêm trọngĐã sửa
Google Drive — invalid_grant: Invalid JWT Signature
Phát hiện bởi:API error khi hệ thống thử dùng Service Account để upload Drive
File liên quan:.env (VPS)
Nguyên nhân kỹ thuật
File .env trên VPS chứa key ID cũ của Service Account (011350392c...) đã bị xóa khỏi Google Cloud Console. Key active hiện tại là 432467bef4... trong file che-lien-agents-432467bef4ab.json. JWT được ký bằng private key không còn tồn tại → Google từ chối xác thực.
Cách sửa
Tìm file JSON đúng (432467bef4), copy lên VPS, cập nhật GOOGLE_SERVICE_ACCOUNT_JSON trong .env. Tuy nhiên sau đó phát hiện BUG-003 (SA không có quota) → chuyển hẳn sang OAuth user credentials.
BUG-001Ảnh hưởng dữ liệuĐã sửa
Gmail API — 429 Too Many Requests khi xóa label DBP (50+ email)
Phát hiện bởi:Scan log: DBP branch báo lỗi xóa label SFGF_Processed
File liên quan:src/app/api/reset/route.ts
Nguyên nhân kỹ thuật
Code cũ dùng Promise.all(messages.map(id => gmail.modify(...))) — gửi 50 request đồng thời lên Gmail API. Gmail API có rate limit ~10 req/s per user → 50 concurrent calls bị reject 429. HP (ít email hơn) không bị, DBP (nhiều email hơn) bị lỗi.
Ảnh hưởng kế toán
Label SFGF_Processed không được gỡ → lần scan tiếp theo bỏ qua toàn bộ email đã từng scan → mất dữ liệu mới nếu user nhấn Reset rồi scan lại mà không xử lý lỗi này.
Cách sửa
Thay bằng gmail.users.messages.batchModify() — 1 API call duy nhất xử lý tối đa 1000 message IDs → không còn concurrent calls, không bị rate limit.
v1.0.0·2026-03-17
Phát hành lần đầu — Phase 1 Internal Tool
Ra mắt hệ thống tự động hạch toán SF/GF cho 2 chi nhánh HP và ĐBP.
Không có bug ghi nhận tại thời điểm ra mắt. Tính năng: Gmail OAuth, SF CSV parser, GF PDF parser, ASP converter, Drive upload, Telegram notify, /convert UI.