Merge pull request #3822 from neilLasrado/item-uom
Changed UOM validation for Item Master
This commit is contained in:
commit
cb4784c940
@ -48,7 +48,7 @@ class Item(WebsiteGenerator):
|
||||
self.website_image = self.image
|
||||
|
||||
self.check_warehouse_is_set_for_stock_item()
|
||||
self.check_stock_uom_with_bin()
|
||||
self.validate_uom()
|
||||
self.add_default_uom_in_conversion_factor_table()
|
||||
self.validate_conversion_factor()
|
||||
self.validate_item_type()
|
||||
@ -105,35 +105,6 @@ class Item(WebsiteGenerator):
|
||||
|
||||
[self.remove(d) for d in to_remove]
|
||||
|
||||
|
||||
def check_stock_uom_with_bin(self):
|
||||
if not self.get("__islocal"):
|
||||
if self.stock_uom == frappe.db.get_value("Item", self.name, "stock_uom"):
|
||||
return
|
||||
|
||||
matched=True
|
||||
ref_uom = frappe.db.get_value("Stock Ledger Entry",
|
||||
{"item_code": self.name}, "stock_uom")
|
||||
|
||||
if ref_uom:
|
||||
if cstr(ref_uom) != cstr(self.stock_uom):
|
||||
matched = False
|
||||
else:
|
||||
bin_list = frappe.db.sql("select * from tabBin where item_code=%s",
|
||||
self.item_code, as_dict=1)
|
||||
for bin in bin_list:
|
||||
if (bin.reserved_qty > 0 or bin.ordered_qty > 0 or bin.indented_qty > 0 \
|
||||
or bin.planned_qty > 0) and cstr(bin.stock_uom) != cstr(self.stock_uom):
|
||||
matched = False
|
||||
break
|
||||
|
||||
if matched and bin_list:
|
||||
frappe.db.sql("""update tabBin set stock_uom=%s where item_code=%s""",
|
||||
(self.stock_uom, self.name))
|
||||
|
||||
if not matched:
|
||||
frappe.throw(_("Default Unit of Measure for Item {0} cannot be changed directly because you have already made some transaction(s) with another UOM. To change default UOM, use 'UOM Replace Utility' tool under Stock module.").format(self.name))
|
||||
|
||||
def update_template_tables(self):
|
||||
template = frappe.get_doc("Item", self.variant_of)
|
||||
|
||||
@ -344,6 +315,17 @@ class Item(WebsiteGenerator):
|
||||
or ifnull(reserved_qty, 0) > 0 or ifnull(indented_qty, 0) > 0 or ifnull(planned_qty, 0) > 0)""", self.name)
|
||||
if stock_in:
|
||||
frappe.throw(_("Item Template cannot have stock or Open Sales/Purchase/Production Orders."), ItemTemplateCannotHaveStock)
|
||||
|
||||
def validate_uom(self):
|
||||
if not self.get("__islocal"):
|
||||
check_stock_uom_with_bin(self.name, self.stock_uom)
|
||||
if self.has_variants:
|
||||
for d in frappe.db.get_all("Item", filters= {"variant_of": self.name}):
|
||||
check_stock_uom_with_bin(d.name, self.stock_uom)
|
||||
if self.variant_of:
|
||||
template_uom = frappe.db.get_value("Item", self.variant_of, "stock_uom")
|
||||
if template_uom != self.stock_uom:
|
||||
frappe.throw(_("Default Unit of Measure for Variant must be same as Template"))
|
||||
|
||||
def validate_end_of_life(item_code, end_of_life=None, verbose=1):
|
||||
if not end_of_life:
|
||||
@ -449,3 +431,30 @@ def invalidate_cache_for_item(doc):
|
||||
|
||||
if doc.get("old_item_group") and doc.get("old_item_group") != doc.item_group:
|
||||
invalidate_cache_for(doc, doc.old_item_group)
|
||||
|
||||
def check_stock_uom_with_bin(item, stock_uom):
|
||||
if stock_uom == frappe.db.get_value("Item", item, "stock_uom"):
|
||||
return
|
||||
|
||||
matched=True
|
||||
ref_uom = frappe.db.get_value("Stock Ledger Entry",
|
||||
{"item_code": item}, "stock_uom")
|
||||
|
||||
if ref_uom:
|
||||
if cstr(ref_uom) != cstr(stock_uom):
|
||||
matched = False
|
||||
else:
|
||||
bin_list = frappe.db.sql("select * from tabBin where item_code=%s", item, as_dict=1)
|
||||
for bin in bin_list:
|
||||
if (bin.reserved_qty > 0 or bin.ordered_qty > 0 or bin.indented_qty > 0 \
|
||||
or bin.planned_qty > 0) and cstr(bin.stock_uom) != cstr(stock_uom):
|
||||
matched = False
|
||||
break
|
||||
|
||||
if matched and bin_list:
|
||||
frappe.db.sql("""update tabBin set stock_uom=%s where item_code=%s""", (stock_uom, item))
|
||||
|
||||
if not matched:
|
||||
frappe.throw(_("Default Unit of Measure for Item {0} cannot be changed directly because \
|
||||
you have already made some transaction(s) with another UOM. To change default UOM, \
|
||||
use 'UOM Replace Utility' tool under Stock module.").format(item))
|
||||
|
@ -10,6 +10,28 @@ from frappe import _
|
||||
from frappe.model.document import Document
|
||||
|
||||
class StockUOMReplaceUtility(Document):
|
||||
|
||||
# Update Stock UOM
|
||||
def update_stock_uom(self):
|
||||
self.validate_item()
|
||||
self.validate_mandatory()
|
||||
self.validate_uom_integer_type()
|
||||
|
||||
update_stock_ledger_entry(self.item_code, self.new_stock_uom, self.conversion_factor)
|
||||
update_bin(self.item_code, self.new_stock_uom, self.conversion_factor)
|
||||
update_item_master(self.item_code, self.new_stock_uom, self.conversion_factor)
|
||||
|
||||
#if item is template change UOM for all associated variants
|
||||
if frappe.db.get_value("Item", self.item_code, "has_variants"):
|
||||
for d in frappe.db.get_all("Item", filters= {"variant_of": self.item_code}):
|
||||
update_stock_ledger_entry(d.name, self.new_stock_uom, self.conversion_factor)
|
||||
update_bin(d.name, self.new_stock_uom, self.conversion_factor)
|
||||
update_item_master(d.name, self.new_stock_uom, self.conversion_factor)
|
||||
|
||||
def validate_item(self):
|
||||
if frappe.db.get_value("Item", self.item_code, "variant_of"):
|
||||
frappe.throw(_("You cannot change default UOM of Variant. To change default UOM for Variant change default UOM of the Template"))
|
||||
|
||||
def validate_mandatory(self):
|
||||
if not cstr(self.item_code):
|
||||
frappe.throw(_("Item is required"))
|
||||
@ -27,72 +49,7 @@ class StockUOMReplaceUtility(Document):
|
||||
stock_uom = frappe.db.get_value("Item", self.item_code, "stock_uom")
|
||||
if cstr(self.new_stock_uom) == cstr(stock_uom):
|
||||
frappe.throw(_("Item is updated"))
|
||||
|
||||
def update_item_master(self):
|
||||
item_doc = frappe.get_doc("Item", self.item_code)
|
||||
item_doc.stock_uom = self.new_stock_uom
|
||||
item_doc.save()
|
||||
|
||||
frappe.msgprint(_("Stock UOM updated for Item {0}").format(self.item_code))
|
||||
|
||||
def update_bin(self):
|
||||
# update bin
|
||||
if flt(self.conversion_factor) != flt(1):
|
||||
frappe.db.sql("""update `tabBin`
|
||||
set stock_uom = %s,
|
||||
indented_qty = ifnull(indented_qty,0) * %s,
|
||||
ordered_qty = ifnull(ordered_qty,0) * %s,
|
||||
reserved_qty = ifnull(reserved_qty,0) * %s,
|
||||
planned_qty = ifnull(planned_qty,0) * %s,
|
||||
projected_qty = actual_qty + ordered_qty + indented_qty +
|
||||
planned_qty - reserved_qty
|
||||
where item_code = %s""", (self.new_stock_uom, self.conversion_factor,
|
||||
self.conversion_factor, self.conversion_factor,
|
||||
self.conversion_factor, self.item_code))
|
||||
else:
|
||||
frappe.db.sql("update `tabBin` set stock_uom = %s where item_code = %s",
|
||||
(self.new_stock_uom, self.item_code) )
|
||||
|
||||
# acknowledge user
|
||||
frappe.msgprint(_("Stock balances updated"))
|
||||
|
||||
def update_stock_ledger_entry(self):
|
||||
# update stock ledger entry
|
||||
from erpnext.stock.stock_ledger import update_entries_after
|
||||
|
||||
if flt(self.conversion_factor) != flt(1):
|
||||
frappe.db.sql("""update `tabStock Ledger Entry`
|
||||
set stock_uom = %s, actual_qty = ifnull(actual_qty,0) * %s
|
||||
where item_code = %s""",
|
||||
(self.new_stock_uom, self.conversion_factor, self.item_code))
|
||||
else:
|
||||
frappe.db.sql("""update `tabStock Ledger Entry` set stock_uom=%s
|
||||
where item_code=%s""", (self.new_stock_uom, self.item_code))
|
||||
|
||||
# acknowledge user
|
||||
frappe.msgprint(_("Stock Ledger entries balances updated"))
|
||||
|
||||
# update item valuation
|
||||
if flt(self.conversion_factor) != flt(1):
|
||||
wh = frappe.db.sql("select name from `tabWarehouse`")
|
||||
for w in wh:
|
||||
update_entries_after({"item_code": self.item_code, "warehouse": w[0]})
|
||||
|
||||
# acknowledge user
|
||||
frappe.msgprint(_("Item valuation updated"))
|
||||
|
||||
# Update Stock UOM
|
||||
def update_stock_uom(self):
|
||||
self.validate_mandatory()
|
||||
self.validate_uom_integer_type()
|
||||
|
||||
self.update_stock_ledger_entry()
|
||||
|
||||
self.update_bin()
|
||||
|
||||
self.update_item_master()
|
||||
|
||||
|
||||
|
||||
def validate_uom_integer_type(self):
|
||||
current_is_integer = frappe.db.get_value("UOM", self.current_stock_uom, "must_be_whole_number")
|
||||
new_is_integer = frappe.db.get_value("UOM", self.new_stock_uom, "must_be_whole_number")
|
||||
@ -103,6 +60,53 @@ class StockUOMReplaceUtility(Document):
|
||||
if current_is_integer and new_is_integer and cint(self.conversion_factor)!=self.conversion_factor:
|
||||
frappe.throw(_("Conversion factor cannot be in fractions"))
|
||||
|
||||
def update_item_master(item_code, new_stock_uom, conversion_factor):
|
||||
frappe.db.set_value("Item", item_code, "stock_uom", new_stock_uom)
|
||||
frappe.msgprint(_("Stock UOM updated for Item {0}").format(item_code))
|
||||
|
||||
def update_bin(item_code, new_stock_uom, conversion_factor):
|
||||
# update bin
|
||||
if flt(conversion_factor) != flt(1):
|
||||
frappe.db.sql("""update `tabBin`
|
||||
set stock_uom = %s,
|
||||
indented_qty = ifnull(indented_qty,0) * %s,
|
||||
ordered_qty = ifnull(ordered_qty,0) * %s,
|
||||
reserved_qty = ifnull(reserved_qty,0) * %s,
|
||||
planned_qty = ifnull(planned_qty,0) * %s,
|
||||
projected_qty = actual_qty + ordered_qty + indented_qty +
|
||||
planned_qty - reserved_qty
|
||||
where item_code = %s""", (new_stock_uom, conversion_factor,
|
||||
conversion_factor, conversion_factor,
|
||||
conversion_factor, item_code))
|
||||
else:
|
||||
frappe.db.sql("update `tabBin` set stock_uom = %s where item_code = %s",
|
||||
(new_stock_uom, item_code) )
|
||||
|
||||
def update_stock_ledger_entry(item_code, new_stock_uom, conversion_factor):
|
||||
# update stock ledger entry
|
||||
from erpnext.stock.stock_ledger import update_entries_after
|
||||
|
||||
if flt(conversion_factor) != flt(1):
|
||||
frappe.db.sql("""update `tabStock Ledger Entry`
|
||||
set stock_uom = %s, actual_qty = ifnull(actual_qty,0) * %s
|
||||
where item_code = %s""",
|
||||
(new_stock_uom, conversion_factor, item_code))
|
||||
else:
|
||||
frappe.db.sql("""update `tabStock Ledger Entry` set stock_uom=%s
|
||||
where item_code=%s""", (new_stock_uom, item_code))
|
||||
|
||||
# acknowledge user
|
||||
frappe.msgprint(_("Stock Ledger entries balances updated"))
|
||||
|
||||
# update item valuation
|
||||
if flt(conversion_factor) != flt(1):
|
||||
wh = frappe.db.sql("select name from `tabWarehouse`")
|
||||
for w in wh:
|
||||
update_entries_after({"item_code": item_code, "warehouse": w[0]})
|
||||
|
||||
# acknowledge user
|
||||
frappe.msgprint(_("Item valuation updated"))
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_stock_uom(item_code):
|
||||
return { 'current_stock_uom': cstr(frappe.db.get_value('Item', item_code, 'stock_uom')) }
|
||||
|
Loading…
x
Reference in New Issue
Block a user