Kiểm tra bản fix extension Business Central trước khi nghiệm thu
Cách tôi dùng AI kiểm tra bản fix extension Business Central trước khi đưa khách nghiệm thu: đúng bản build, đọc code đổi, test hồi quy, kiểm số sau post.
Tôi kiểm tra bản fix extension Business Central trước khi đưa khách nghiệm thu theo thứ tự: chắc đang cầm đúng bản build, nhờ AI đọc phần code đã đổi, chạy lại test hồi quy của ticket cũ, rồi mở bảng dữ liệu sau khi post xem số có đổi đúng không. "Post không còn báo lỗi" chưa phải là đã sửa.
Lần tôi kể dưới đây, tháng 07/2026 ở một dự án kho dùng Tasklet, đi qua ba bản build mới có một bản sửa đúng lỗi gốc. Nếu chỉ test bằng cách xem còn báo lỗi hay không, bản đầu tiên đã được nghiệm thu.
Tôi là functional consultant, không đọc AL thành thạo, nên phần đọc code tôi giao cho AI (Claude Code chạy trên máy). Bài này để có một quy trình tự kiểm, không để chấm điểm ai: hai bản đầu nằm ở hai nhánh code chạy song song, còn hai trong ba lần đọc nhầm bản là lỗi phía tôi.
Lỗi gốc: hai lot trên một dòng thì báo thiếu tồn pallet#
Extension của dự án giữ tồn theo pallet trong MOB License Plate Content, bảng tồn pallet của Tasklet, và trừ tồn này khi post Warehouse Shipment. Lỗi xảy ra ở kho không bật Require Pick, chứng từ nguồn là Transfer Order, Item Tracking của dòng có 2 lot: 380 và 120, tổng 500.
Vòng kiểm tra chạy theo từng lot, nhưng đem tồn của lot so với Qty. to Ship (Base) của cả dòng:
| Con số | Đúng ra | Hệ thống đang làm |
|---|---|---|
| Số đem kiểm tra cho lot 1 | 380 | 500 |
| Số đem kiểm tra cho lot 2 | 120 | 500 |
| Tổng trừ nếu cả hai lot đều còn từ 500 trở lên | 500 | 1.000 |
Lot 2 còn đúng 120 vẫn bị báo thiếu tồn. Dòng cuối mới đáng lo: cả hai lot đều còn từ 500 trở lên thì lọt qua kiểm tra, phiếu xuất 500 trừ mất 1.000 trong bảng tồn pallet mà không ai thấy.
Vì sao sửa lỗi này lại sinh lỗi kia#
Bản sửa trước đó ở chính chỗ này đã đổi từ "trừ theo số của từng lot" sang "trừ theo số của cả dòng", để chữa một lỗi khác: phiếu có nhiều dòng cùng lot khác pallet, hoặc xuất một phần nhiều lần, thì pallet bị trừ trùng. Hai lỗi kéo ngược nhau. Chọn một trong hai con số thì sửa lỗi này sẽ mở lại lỗi kia.
Quy tắc nghiệm thu tôi viết cho dev dùng cả hai con số cùng lúc:
Kiểm tra và trừ tồn theo từng lot trên Item Tracking, nhưng tổng trừ của mỗi dòng phải đúng bằng
Qty. to Ship (Base)của dòng đó, không hơn, không kém.
Spec gắn nhãn từng bước [KHÔNG ĐỔI], [SỬA], [MỚI] để dev biết chỗ nào phải đụng. Kèm 7 test hồi quy, trong đó test 3 và 4 chép nguyên văn kịch bản đã nghiệm thu của ticket cũ:
| # | Kịch bản | Kỳ vọng |
|---|---|---|
| 1 | 1 dòng, 1 lot, 1 pallet | Trừ đúng |
| 2 | 1 dòng, 2 lot (380 và 120) | Post được, trừ 380 và 120 theo từng lot |
| 3 | Nhiều dòng cùng lot, khác pallet (50, 60, 70) | Mỗi pallet trừ đúng phần của nó, không pallet nào bị trừ hai lần |
| 4 | Xuất một phần nhiều lần (100 rồi 200) | Mỗi lần trừ đúng số đã xuất |
| 5 | Bắt buộc trừ đúng pallet chỉ định | Trừ đúng pallet đó |
| 6 | Kho có Require Pick, nguồn Sales Order, Purchase Return Order | Không đổi so với trước |
| 7 | Mặt hàng có đơn vị tính khác đơn vị cơ sở | Trừ đúng theo Base |
Spec và comment do AI soạn, tôi sửa hai chỗ. Comment bản đầu trích số dòng code và tên hàm. Tôi không phải dev, đem số dòng ra thì dev hỏi lại một câu là tôi không trả lời được. Comment chỉ nói hệ thống làm gì sai, nghiệp vụ cần gì, kiểm chứng bằng dữ liệu nào. Spec bản đầu có câu "giữ nguyên máy móc trừ hiện tại", kiểu câu tôi gặp nhiều trong tài liệu FDD do AI viết: đọc xong không ai biết hiện tại là gì. Phải tả ra: hệ thống lấy pallet ghi trên Item Tracking trước, không đủ thì vét sang pallet khác cùng lot trong bin, pallet nhập sau vét trước. Cách viết mỗi bước logic thành một câu đủ ý có ví dụ ở bài lấy diễn giải khuyến mãi lên hóa đơn điện tử LS Central.
Ba bản build và test nào bắt được#
| Bản | Thay đổi | Hậu quả | Test bắt được |
|---|---|---|---|
| A | Bỏ phép tính số lượng cần trừ, số này thành 0. Thêm một query tính tổng tồn | Hết báo lỗi nhưng tồn pallet không giảm. Kho có Require Pick vốn đúng cũng ngừng trừ tồn | Mọi test, nếu mở bảng tồn pallet sau khi post. Chỉ nhìn thông báo lỗi thì không test nào bắt được |
| B | Số version cao hơn bản A nhưng là nhánh cũ. Tắt mấy subscriber của Sales-Post và Purch.-Post | Vẫn báo lỗi gốc. Giao hàng bán không còn trừ tồn pallet | Test 2 và test 6 |
| C | Viết lại, lấy số theo từng lot từ Reservation Entry | Lỗi gốc hết. Còn bốn chỗ phải test hoặc hỏi lại | Test 3 và 4 phải chạy thật mới biết |
Bản A là loại khó bắt nhất. Lỗi biến mất vì phép kiểm tra không còn gì để kiểm, không phải vì hệ thống tính đúng lên. Trước đó lỗi còn chặn post nên dữ liệu sạch, bản này post lọt và tồn pallet sai âm thầm. Phần code bị đổi nhìn gọn, phần chạy sai lại là phần không ai đụng tới, nên đọc lướt cũng dễ lọt. AI còn thấy query tính tổng tồn mới viết đúng, nhưng dòng kiểm tra ngay dưới vẫn dùng biến cũ chưa được tính. Đặt lại phép tính số lượng là lỗi này lộ ra, mọi phiếu báo thiếu tồn ngay lot đầu tiên.
Bản B số version cao hơn nên tôi tưởng mới hơn. Thật ra đó là nhánh khác, phép tính vẫn như bản gốc.
Bản C sửa đúng hướng. Bốn chỗ còn hở tôi ghi vào ticket:
- Với mỗi dòng chứng từ nguồn, hệ thống vẫn chỉ xử lý dòng Warehouse Shipment đầu tiên, nên phiếu tách nhiều dòng theo pallet phải chạy test 3.
- Bản này quay lại lấy số theo Item Tracking, đúng thứ bản sửa trước từng đổi đi, nên phải chạy test 4 xem lỗi trừ trùng có quay lại không.
- Bước lọc theo kết quả QC chỉ áp cho Sales Order. Phải hỏi dev đây là chủ ý hay bỏ sót.
- Chưa chặn khi Item Tracking khai thiếu so với số xuất.
Người dùng test bản C và gặp Quantity must be positive#
Người dùng test bản C: post được. Nhưng chọn một lot trên Item Tracking Lines, đổi sang lot khác rồi đóng trang thì báo:
Quantity must be positive
AI tìm câu này trong toàn bộ source của extension, không có. Đây là chặn chuẩn của BC khi còn một dòng tracking số lượng 0. Phần custom trên trang Item Tracking Lines có đổi 76 dòng giữa bản gốc và bản C, nhưng không đụng logic lot. Cách làm tạm cho người dùng: xóa hẳn dòng lot cũ rồi thêm dòng mới, không gõ đè. Tôi tách thành ticket riêng để ticket post đóng được.
Kết luận này từ đọc code tĩnh, chưa tái hiện trên hệ thống. Muốn chốt thì đổi lot y như vậy trên bản cũ: bản cũ cũng báo thì không phải do bản fix.
AI làm phần nào, tôi làm phần nào#
| Việc | Ai làm |
|---|---|
| Tìm file .app mới trên máy, kể cả khi nó nằm ở thư mục project khác với chỗ tôi đang mở | AI |
| Giải nén, so nội dung giữa hai bản | AI |
| Đọc phần code đổi, lần theo biến số lượng cần trừ | AI |
| Đối chiếu từng bước trong spec, chấm đạt hay chưa | AI |
| Chọn giọng comment gửi dev, quyết định trả bản build hay nhận | Tôi |
| Test trên sandbox | Người dùng |
Kiểm đúng bản build: đừng tin ngày sửa file#
Ba lần tôi suýt review nhầm bản. Lần đầu, dev báo đã fix, file bản A trên máy mang ngày sửa mới nhưng cùng số version và cùng dung lượng với lần trước. AI giải nén và so từng byte: nội dung y hệt, chỉ là OneDrive đồng bộ lại. Hai lần sau là lỗi của tôi: một lần tải về mà chưa giải nén, một lần tải nhầm bản.
Quy tắc: nhìn số version, không nhìn ngày sửa file. Trùng số version thì so nội dung. Số version cao hơn cũng chưa chắc mới hơn, bản B là ví dụ.
File .app có source code không#
AI đọc được code vì file .app của chính extension dự án có kèm source. File .app là container NAVX: 40 byte header rồi tới một file zip chuẩn, cắt header là giải nén được.
Gói chỉ có symbol thì không đọc được thân hàm, ví dụ một gói 39 KB tôi gặp chỉ có NavxManifest, SymbolReference, DocComments. Nếu app.json của extension bật allowDownloadingSource thì tải source ở trang Extension Management, chọn Download Source. Các cờ này nằm trong resourceExposurePolicy, xem Resource exposure policy setting trên Microsoft Learn.
Chỉ giải nén .app của extension do công ty mình sở hữu, hoặc khách cho phép xem source. Symbol của Microsoft (Base Application, System Application và các gói đi kèm bản 28.4 giải nén ra 9.875 file .al) thì để ở thư mục ngoài project. Để trong project, AL compiler quét luôn số file đó và báo trùng object ID hàng loạt.
Checklist kiểm bản fix trước khi đưa khách nghiệm thu#
- Đúng bản: số version khớp bản dev báo. Trùng số thì so nội dung, không tin ngày sửa file.
- Đọc phần code đổi so với bản trước, và cả phần không đổi nhưng nhận số liệu khác.
- Chạy lại nguyên văn test đã nghiệm thu của các ticket cũ ở cùng chỗ.
- Sau khi post, mở bảng dữ liệu bị tác động, ở đây là MOB License Plate Content, xem số có đổi đúng từng lot không.
- Chạy một phiếu ở luồng ngoài phạm vi sửa, ở đây là kho có
Require Pickvà giao hàng bán. - Lỗi mới không thuộc ticket thì tách ticket riêng, ghi rõ đã tái hiện hay mới đọc code.