From 7a6f0489284d0dc739fb3458ec0dbb3d682d10e5 Mon Sep 17 00:00:00 2001 From: Neil Trini Lasrado Date: Mon, 24 Aug 2015 14:37:17 +0530 Subject: [PATCH 1/3] Fixed issue while creating item variants with decimal values (precision error) --- erpnext/stock/doctype/item/item.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index f9b41f1657..379da18934 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -516,9 +516,6 @@ def validate_item_variant_attributes(item, args): numeric_attributes = frappe._dict((t.name, t) for t in frappe.get_list("Item Attribute", filters={"numeric_values":1, "name": ["in", args.keys()]}, fields=["name", "from_range", "to_range", "increment"])) - template_item = frappe.get_doc("Item", item) - template_item_attributes = frappe._dict((d.attribute, d) for d in template_item.attributes) - for attribute, value in args.items(): if attribute in numeric_attributes: @@ -531,10 +528,17 @@ def validate_item_variant_attributes(item, args): if increment == 0: # defensive validation to prevent ZeroDivisionError frappe.throw(_("Increment for Attribute {0} cannot be 0").format(attribute)) + + is_in_range = from_range <= flt(value) <= to_range + precision = len(cstr(increment).split(".")[-1].rstrip("0")) + #avoid precision error by rounding the remainder + remainder = flt((flt(value) - from_range) % increment, precision) + is_incremental = remainder==0 or remainder==0 or remainder==increment - if not ( (from_range <= flt(value) <= to_range) and (flt(value) - from_range) % increment == 0 ): - frappe.throw(_("Value for Attribute {0} must be within the range of {1} to {2} in the increments of {3}").format(attribute, from_range, to_range, increment), InvalidItemAttributeValueError) + if not (is_in_range and is_incremental): + frappe.throw(_("Value for Attribute {0} must be within the range of {1} to {2} in the increments of {3}")\ + .format(attribute, from_range, to_range, increment), InvalidItemAttributeValueError) elif value not in attribute_values[attribute]: frappe.throw(_("Value {0} for Attribute {1} does not exist in the list of valid Item Attribute Values").format( From 4c614bd59a6f34743545004d6ff49e9098adbc7f Mon Sep 17 00:00:00 2001 From: Neil Trini Lasrado Date: Mon, 24 Aug 2015 15:12:34 +0530 Subject: [PATCH 2/3] Fixed validation for numeric variants to check with values from template instead of master --- erpnext/stock/doctype/item/item.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index 379da18934..659fb1b5f5 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -513,9 +513,10 @@ def validate_item_variant_attributes(item, args): filters={"parent": ["in", args.keys()]}): (attribute_values.setdefault(t.parent, [])).append(t.attribute_value) - numeric_attributes = frappe._dict((t.name, t) for t in frappe.get_list("Item Attribute", filters={"numeric_values":1, - "name": ["in", args.keys()]}, fields=["name", "from_range", "to_range", "increment"])) - + numeric_attributes = frappe._dict((t.attribute, t) for t in \ + frappe.db.sql("""select attribute, from_range, to_range, increment from `tabItem Variant Attribute` + where parent = %s and numeric_values=1""", (item), as_dict=1)) + for attribute, value in args.items(): if attribute in numeric_attributes: From db189d7f19272723dcdcc277c327c19a75482470 Mon Sep 17 00:00:00 2001 From: Neil Trini Lasrado Date: Mon, 24 Aug 2015 16:59:24 +0530 Subject: [PATCH 3/3] Fixed test case for Item Variants --- erpnext/stock/doctype/item/test_item.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/erpnext/stock/doctype/item/test_item.py b/erpnext/stock/doctype/item/test_item.py index f7c0f40efa..916101516f 100644 --- a/erpnext/stock/doctype/item/test_item.py +++ b/erpnext/stock/doctype/item/test_item.py @@ -6,9 +6,8 @@ import unittest import frappe from frappe.test_runner import make_test_records -from erpnext.stock.doctype.item.item import (WarehouseNotSet, ItemTemplateCannotHaveStock, create_variant, +from erpnext.stock.doctype.item.item import (WarehouseNotSet, create_variant, ItemVariantExistsError, InvalidItemAttributeValueError) -from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry test_ignore = ["BOM"] test_dependencies = ["Warehouse"] @@ -129,8 +128,16 @@ class TestItem(unittest.TestCase): # make template item make_item("_Test Numeric Template Item", { "attributes": [ - {"attribute": "Test Size"}, - {"attribute": "Test Item Length"} + { + "attribute": "Test Size" + }, + { + "attribute": "Test Item Length", + "numeric_values": 1, + "from_range": 0.0, + "to_range": 100.0, + "increment": 0.5 + } ], "default_warehouse": "_Test Warehouse - _TC" })