Đến nội dung chính
ERP Thực Chiến
Thư viện
Menu

Lỗi làm tròn đơn vị tính Business Central: base là thùng, bán theo hộp

Lỗi làm tròn đơn vị tính Business Central khi base là thùng, bán theo hộp 1/60, 1/105: vì sao ra 1,100.02 và cách sửa hệ số mà Config Package không làm được.

Lỗi làm tròn đơn vị tính trong Business Central khi base là thùng, bán theo hộp, nằm ở hệ số Qty. per Unit of Measure: hộp 1/105 lưu 0.009524 nên 115,500 hộp ra 1,100.02 thùng. Sửa tận gốc bằng cách ghi hệ số 1/N đủ 18 chữ số, đưa precision của thùng về 0, và không ghi số đó qua Configuration Package.

Tôi gặp lỗi này ở một khách hàng ngành thực phẩm và đồ uống. Mặt hàng khai base là thùng, vì kho, kế hoạch sản xuất và mua nguyên vật liệu đều chạy theo thùng. Hàng luôn xuất tròn thùng, nhưng khách muốn hóa đơn ghi theo hộp, nên Sales Order chọn đơn vị HOP. Cách sửa trong bài tôi đã chạy trên một sandbox BC 28 ngày 03/10/2026: tạo Sales Order, Warehouse Shipment, Transfer Order rồi post. Số viết theo định dạng BC: dấu phẩy ngăn hàng nghìn, dấu chấm thập phân.

Vì sao 115,500 hộp ra 1,100.02 thùng#

BC tính số lượng cơ sở bằng số lượng trên dòng nhân Qty. per Unit of Measure của đơn vị đó, rồi làm tròn theo Qty. Rounding Precision của đơn vị cơ sở. Trên màn hình, field hệ số chỉ hiện 5 chữ số, nên người khai master data thường gõ 0.00952 hoặc 0.009524 cho hộp 1/105, 0.01667 cho hộp 1/60. Sai số của hệ số nhân lên theo số hộp:

Số lượng trên dòngHệ số đang lưuNhân raPrecision thùngQuantity (Base)
115,500 hộp (105 hộp/thùng)0.0095241,100.0220.011,100.02
46,725 hộp (105 hộp/thùng)0.00952444.8220.01444.82
21,000 hộp (60 hộp/thùng)0.01667350.070.1350.1
105 hộp, dòng Assembly0.009520.999600.9996
1,170 hộp (60 hộp/thùng)0.0166719.50390.119.5

Dòng cuối là số lẻ thật: 1,170 hộp đúng là 19.5 thùng. Mọi cách sửa phải giữ nguyên những dòng như vậy, chỉ sửa dòng mà base đúng ra phải là số nguyên.

Số lẻ còn làm FactBox hiện số lạ, xem công thức Item Availability trên Sales Order. Và số lẻ không dừng ở dòng bán. Warehouse Shipment tạo từ Sales Order mang nguyên 1,100.02, người kho gán lô theo số đó, lô bị cắt vụn kiểu 24 + 0.9 + 0.09, và sau vài lần post thì tồn của một lô còn 9.99 thùng. Từ đây phát sinh thêm lỗi khi post: tổng Qty. to Handle (Base) của các lô không bằng Qty. to Ship (Base) của dòng. Lô đã lẻ thì sửa theo cách trong bài sửa lô sau khi xuất kho, phải có lô chịu phần 0.01 đó bằng một bút toán điều chỉnh, sửa tracking không thôi thì không đủ.

Vì sao tăng Qty. Rounding Precision không xử lý hết#

Cách hay được thử đầu tiên là đặt Qty. Rounding Precision của thùng thành 0.01, import bằng Configuration Package có tắt Validate Field. Nó che được 1,100.022 nhưng không che được 444.822, vì sai số đã lên tới 0.18 thùng. Muốn làm tròn 444.822 về 445 thì precision phải là 1, và khi đó bán 1 hộp (0.0095 thùng) bị làm tròn về 0.

Precision của dòng cũng gây lỗi theo hướng ngược lại. Tôi gặp trường hợp sửa tay Quantity (Base) của dòng Transfer Order về 5 trong khi precision của dòng là 0. Lúc post, BC tính lại 300 hộp × 0.01667 = 5.001, không khớp 5 đang lưu, và báo out of balance. Sales Order cùng mặt hàng thì post được, vì dòng bán không chạy bước kiểm này, còn dòng chuyển kho và Warehouse Shipment thì có.

Nói gọn: sửa số base bằng tay hay đổi precision chỉ chữa từng chứng từ. Lúc post, BC luôn tính lại base từ số lượng nhân hệ số, nên hệ số sai thì số sai quay lại.

Sửa tận gốc: ghi lại hệ số 1/N đủ 18 chữ số#

1/60 không phải số vô tỷ, nó là số thập phân vô hạn tuần hoàn 0.016666… Máy chỉ lưu được một số chữ số hữu hạn. Trên sandbox, BC lưu field Qty. per Unit of Measure tới 18 chữ số sau dấu phẩy, và với giá trị đó thì phép nhân ra số tròn:

Hộp mỗi thùngGhi vào Qty. per Unit of Measure của HOP
60.166666666666666667
240.041666666666666667
300.033333333333333333
600.016666666666666667
1050.009523809523809524

Quy cách chia ra số thập phân hữu hạn (5, 10, 20 hộp mỗi thùng) đã đúng sẵn, không cần sửa.

Thứ tự làm trên bảng Item Unit of Measure:

  1. Dòng đơn vị cơ sở (THUNG): Qty. Rounding Precision = 0. Làm trước, vì BC kiểm hệ số của các đơn vị khác phải chia hết cho precision của đơn vị cơ sở, mà 0.009523809523809524 không chia hết cho 0.01.
  2. Dòng HOP: Qty. per Unit of Measure = giá trị trong bảng trên.
  3. Tạo thử một Sales Order 115,500 hộp. Ra 1,100 là xong.

Kết quả trên sandbox sau khi sửa master data, không cài extension nào:

Số lượngTrước khi sửaSau khi sửa
115,500 hộp (1/105)1,100.021,100
46,725 hộp (1/105, hệ số cũ 0.009524)445.01445
21,000 hộp (1/60)350.1350
1,170 hộp (1/60)19.519.5

Tôi post tiếp hai chứng từ. Sales Order 525 hộp mã 1/105 cùng 300 và 90 hộp mã 1/60 cho Warehouse Shipment 5, 5 và 1.5 thùng. Gán lô rồi post, Item Ledger Entry ghi đúng -5, -5, -1.5. Transfer Order 300 hộp mã 1/60 ra 5 thùng, post shipment không còn báo out of balance.

Còn một chỗ master data không sửa được: bán lẻ từng hộp. 1 hộp vẫn là 0.00952 thùng, bán 105 lần mỗi lần 1 hộp thì cộng lại không đúng 1 thùng. Khách này luôn xuất tròn thùng nên không vướng. Nếu doanh nghiệp bán lẻ hộp thường xuyên thì phải xem tới cách cuối bài.

Đừng ghi hệ số bằng Configuration Package#

Đây là chỗ tôi đã sai một lần. Configuration Package cắt Qty. per Unit of Measure còn 5 chữ số khi import: tôi import file có 0.009523809523809524 lên sandbox, BC lưu 0.00952. Export cũng chỉ ra 5 chữ số, nên mở file export ra kiểm thì không thấy gì bất thường. Một khi precision của thùng đã về 0 mà hệ số bị cắt còn 0.00952, số còn lệch hơn trước:

Số lượngHệ số 0.009524, precision 0.01Hệ số 0.00952, precision 0
115,500 hộp1,100.021,099.56
21,000 hộp350.1350.07

Phải ghi thẳng vào bảng, không qua Configuration Package. Tôi dùng công cụ import/export bảng của Insight Works, xuất bảng 5404 ra file .txt, sửa hệ số, rồi import lại với thiết lập: cho phép cập nhật bản ghi, không cho thêm bản ghi, không chạy trigger OnModify. Công cụ này validate field khóa (Item No., Code), còn hai field số lượng thì không. Sau khi import, mở Page Inspection trên dòng HOP: field hiện đúng 0.009523809523809524. Cột trên danh sách vẫn hiện 0.00952, vì màn hình chỉ hiển thị 5 chữ số, giá trị lưu trong bảng đã đúng.

Kiểm bằng một Sales Order thử, không kiểm bằng file export. Ra 1,100 là hệ số đủ chữ số, ra 1,100.02 hoặc 1,099.56 là đã bị cắt. Data Editor và các công cụ sửa bảng khác tôi chưa thử, cứ làm một mã rồi tạo đơn thử trước khi làm cả danh sách.

Bảng Item Unit of Measure còn có bút toán và đơn đang mở nên BC chặn đổi hệ số. Sửa thẳng vào bảng là bỏ qua bước chặn đó. Phần chênh với dữ liệu cũ rất nhỏ, nhưng vẫn phải làm trên sandbox trước.

Đơn tạo trước khi sửa thì sao#

Mỗi dòng chứng từ giữ Qty. per Unit of Measure của lúc tạo dòng. Sửa master data xong, chỉ đơn mới mới sạch. Với đơn cũ còn mở:

  • Dòng chưa giao, chưa nhận: ghi lại hệ số 1/N lên chính dòng đó rồi tính lại các cột Base từ cột số lượng. Một file Purchase Line 720 dòng chưa nhận hàng sau khi ghi lại hệ số chỉ có 1 dòng phải đổi Base, các dòng khác vốn đã tròn.
  • Dòng đã nhận hoặc đã giao một phần mà chưa xuất hóa đơn: để nguyên. Bút toán nhận hàng đã ghi theo hệ số cũ, đổi dòng thành số tròn thì lúc post hóa đơn số không khớp với phần đã nhận. Phần lệch nằm trong tồn kho, sửa bằng bút toán điều chỉnh nếu cần.
  • Dòng có lô: mở Item Tracking Lines kiểm lại cho khớp với Base mới.

Để nhận ra dòng nào lẻ do hệ số, dòng nào lẻ thật, tôi viết một script đọc file Configuration Package xuất ra và tái hiện phép tính của BC: lấy base nguyên, nhân ngược ra số hộp, nhân lại với hệ số trên dòng, làm tròn theo precision. Ra đúng số đang lưu (ví dụ 445 × 105 = 46,725 hộp, × 0.00952 = 444.822, làm tròn 0.01 ra 444.82) thì dòng đó lẻ do hệ số. Dòng 19.5 không tái hiện ra được nên được giữ nguyên. Lần đầu tôi dùng ngưỡng lệch dưới 0.15 thùng và đã bỏ sót đúng dòng 444.82, nên đừng lọc theo độ lệch.

Dòng Assembly và BOM: chỗ hệ số không đi qua đơn vị tính#

Assembly Order và lệnh sản xuất tính số lượng linh kiện bằng Quantity per trên BOM nhân số lượng đầu phiếu, không đi qua hệ số đơn vị tính. BOM khai linh kiện là 0.00952 thùng thì 105 × 0.00952 vẫn ra 0.9996, dù Item Unit of Measure đã sửa. Với nhóm này, khai linh kiện theo đơn vị HOP với Quantity per = 1 thay vì 1/105 thùng.

Trên một Assembly Order khác, tôi gặp câu lỗi này khi Rounding Precision trên thẻ Item đặt là 1:

mã
Qty. Rounding Precision on Item-<mã hàng> causes the Quantity to Consume and Quantity to Consume (Base) to be out of balance. Rounding of the field Quantity to Consume (Base) results to 0.

Dòng linh kiện cần 1.2, base bị làm tròn thành 1, tiêu hao 0.98 xong thì phần còn lại 0.02 bị làm tròn về 0. Hướng đã đưa là đổi Rounding Precision trên thẻ Item từ 1 thành 0.01 rồi gõ lại Quantity per trên dòng linh kiện để BC tính lại. Cách này tôi chưa có xác nhận đã post được.

Khi nào nên đổi base sang hộp#

Khai đơn vị cơ sở là đơn vị nhỏ nhất (HOP), thùng là 60 hoặc 105 hộp, thì mọi hệ số là số nguyên và không còn làm tròn ở đâu. Kế hoạch mua và sản xuất vẫn chạy theo thùng nhờ Purch. Unit of Measure và đơn vị trên BOM, lệnh sản xuất. Đây là cách duy nhất xử lý cả trường hợp bán lẻ từng hộp.

Cái giá là BC không cho đổi base khi mặt hàng đã có bút toán. Muốn đổi phải tạo mã mới rồi chuyển tồn, BOM, bảng giá, khuyến mãi sang. Nên chốt từ lúc dựng master data, trước khi import tồn đầu kỳ. Lúc import tồn đầu kỳ cũng có một bẫy cùng gốc: thiếu cột Unit of Measure Code thì số lượng bị quy đổi sai mà BC không báo.

Microsoft mô tả Qty. Rounding Precision và Qty. per Unit of Measure trong Set up units of measure. Ví dụ trong đó là hộp 6 cái nhận về 5 cái ra 4.99998, cùng một gốc với bài này.

Đọc tiếp