diff --git a/erpnext/buying/doctype/purchase_order/test_purchase_order.py b/erpnext/buying/doctype/purchase_order/test_purchase_order.py index 05c6542939d..a9da89a8306 100644 --- a/erpnext/buying/doctype/purchase_order/test_purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/test_purchase_order.py @@ -724,6 +724,25 @@ class TestPurchaseOrder(ERPNextTestSuite): below_minimum.items[0].conversion_factor = 0.6 self.assertRaises(frappe.ValidationError, below_minimum.insert) + def test_uom_integer_check_tolerates_conversion_dust(self): + from erpnext.utilities.transaction_base import UOMMustBeIntegerError + + item_doc = make_item(properties={"stock_uom": "Nos"}) + item_doc.append("uoms", {"uom": "Kg", "conversion_factor": 0.6}) + item_doc.save() + item = item_doc.name + + precision = frappe.get_precision("Purchase Order Item", "stock_qty") + po = create_purchase_order(item_code=item, qty=flt(2000 / 0.6, precision), do_not_save=1) + po.items[0].uom = "Kg" + po.items[0].conversion_factor = 0.6 + po.insert() + + fractional = create_purchase_order(item_code=item, qty=3333.9, do_not_save=1) + fractional.items[0].uom = "Kg" + fractional.items[0].conversion_factor = 0.6 + self.assertRaises(UOMMustBeIntegerError, fractional.insert) + def test_ordered_qty_for_closing_po(self): bin = frappe.get_all( "Bin", diff --git a/erpnext/utilities/transaction_base.py b/erpnext/utilities/transaction_base.py index e49660f33c0..07e9c40ebd7 100644 --- a/erpnext/utilities/transaction_base.py +++ b/erpnext/utilities/transaction_base.py @@ -618,13 +618,13 @@ def validate_uom_is_integer(doc, uom_field, qty_fields, child_dt=None): for f in qty_fields: qty = d.get(f) if qty: - precision = d.precision(f) - if abs(cint(qty) - flt(qty, precision)) > 0.0000001: + qty = flt(qty, d.precision(f)) + if qty != cint(qty): frappe.throw( _( "Row {1}: Quantity ({0}) cannot be a fraction. To allow this, disable '{2}' in UOM {3}." ).format( - flt(qty, precision), + qty, d.idx, frappe.bold(_("Must be Whole Number")), frappe.bold(d.get(uom_field)),