diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index 88bb4b29a84..b2e8a73d065 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -467,7 +467,7 @@ class BuyingController(SubcontractingController): self.precision("item_tax_amount", item), ) - self.round_floats_in(item) + self.round_floats_in(item, do_not_round_fields=["conversion_factor"]) if flt(item.conversion_factor) == 0.0: item.conversion_factor = ( get_conversion_factor(item.item_code, item.uom).get("conversion_factor") or 1.0 diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py index fcf10b019d8..bd8db461524 100644 --- a/erpnext/controllers/taxes_and_totals.py +++ b/erpnext/controllers/taxes_and_totals.py @@ -227,7 +227,12 @@ class calculate_taxes_and_totals: if self.doc.get("is_consolidated") or self.discount_amount_applied: return - do_not_round_fields = ["valuation_rate", "incoming_rate", "sales_incoming_rate"] + do_not_round_fields = [ + "valuation_rate", + "incoming_rate", + "sales_incoming_rate", + "conversion_factor", + ] for item in self.doc.items: self.doc.round_floats_in(item, do_not_round_fields=do_not_round_fields) self.calculate_item_rate(item) diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js index 8a0719c6d3f..af993a6a082 100644 --- a/erpnext/public/js/controllers/taxes_and_totals.js +++ b/erpnext/public/js/controllers/taxes_and_totals.js @@ -138,11 +138,26 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments { } } + get_item_fields_to_round() { + const [item] = this.frm.doc.items || []; + if (!item) { + return []; + } + + const do_not_round_fields = ["conversion_factor"]; + return frappe.meta + .get_fieldnames(item.doctype, item.parent, { + fieldtype: ["in", ["Currency", "Float"]], + }) + .filter((fieldname) => !do_not_round_fields.includes(fieldname)); + } + calculate_item_values() { var me = this; if (!this.discount_amount_applied) { + const fields_to_round = this.get_item_fields_to_round(); for (const item of this.frm.doc.items || []) { - frappe.model.round_floats_in(item); + frappe.model.round_floats_in(item, fields_to_round); item.net_rate = item.rate; item.qty = item.qty === undefined ? (me.frm.doc.is_return ? -1 : 1) : item.qty; diff --git a/erpnext/stock/doctype/material_request/test_material_request.py b/erpnext/stock/doctype/material_request/test_material_request.py index b23118f524c..51ad01517a4 100644 --- a/erpnext/stock/doctype/material_request/test_material_request.py +++ b/erpnext/stock/doctype/material_request/test_material_request.py @@ -847,6 +847,28 @@ class TestMaterialRequest(ERPNextTestSuite): mr = frappe.get_doc("Material Request", mr.name) self.assertEqual(mr.per_ordered, 100) + def test_fractional_conversion_factor_for_purchase(self): + item = create_item("_Test Fractional Conversion Item", stock_uom="Kg", is_purchase_item=1) + conversion_factor = 0.453592292 + + mr = make_material_request( + item_code=item.name, + qty=1000, + uom="Pound", + conversion_factor=conversion_factor, + ) + mr.reload() + + self.assertEqual(mr.items[0].conversion_factor, conversion_factor) + + po = make_purchase_order(mr.name) + po.supplier = "_Test Supplier" + po.insert() + po.reload() + + self.assertEqual(po.items[0].conversion_factor, conversion_factor) + self.assertEqual(po.items[0].stock_qty, mr.items[0].stock_qty) + def test_customer_provided_parts_mr(self): create_item("CUST-0987", is_customer_provided_item=1, customer="_Test Customer", is_purchase_item=0) existing_requested_qty = self._get_requested_qty("_Test Customer", "_Test Warehouse - _TC")