Merge pull request #3422 from nabinhait/develop
Manufactured qty in Stock Entry
This commit is contained in:
commit
de1f934e22
@ -164,4 +164,5 @@ erpnext.patches.v5_0.update_item_and_description_again
|
|||||||
erpnext.patches.v5_0.repost_gle_for_jv_with_multiple_party
|
erpnext.patches.v5_0.repost_gle_for_jv_with_multiple_party
|
||||||
erpnext.patches.v5_0.portal_fixes
|
erpnext.patches.v5_0.portal_fixes
|
||||||
erpnext.patches.v5_0.reset_values_in_tools
|
erpnext.patches.v5_0.reset_values_in_tools
|
||||||
execute:frappe.delete_doc("Page", "users")
|
execute:frappe.delete_doc("Page", "users")
|
||||||
|
erpnext.patches.v5_0.update_material_transferred_for_manufacturing_again
|
@ -0,0 +1,18 @@
|
|||||||
|
import frappe
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
pro_order_qty_transferred = frappe._dict()
|
||||||
|
for se in frappe.db.sql("""select production_order, sum(fg_completed_qty) as transferred_qty
|
||||||
|
from `tabStock Entry`
|
||||||
|
where docstatus=1 and ifnull(production_order, '') != ''
|
||||||
|
and purpose = 'Material Transfer for Manufacture'
|
||||||
|
group by production_order""", as_dict=1):
|
||||||
|
pro_order_qty_transferred.setdefault(se.production_order, se.transferred_qty)
|
||||||
|
|
||||||
|
for d in frappe.get_all("Production Order", filters={"docstatus": 1}, fields=["name", "qty"]):
|
||||||
|
if d.name in pro_order_qty_transferred:
|
||||||
|
material_transferred_for_manufacturing = pro_order_qty_transferred.get(d.name) \
|
||||||
|
if pro_order_qty_transferred.get(d.name) <= d.qty else d.qty
|
||||||
|
|
||||||
|
frappe.db.sql("""update `tabProduction Order` set material_transferred_for_manufacturing=%s
|
||||||
|
where name=%s""", (material_transferred_for_manufacturing, d.name))
|
@ -5,7 +5,7 @@ from __future__ import unicode_literals
|
|||||||
import frappe
|
import frappe
|
||||||
import frappe.defaults
|
import frappe.defaults
|
||||||
|
|
||||||
from frappe.utils import cstr, cint, flt, comma_or, nowdate, get_datetime
|
from frappe.utils import cstr, cint, flt, comma_or, get_datetime
|
||||||
|
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from erpnext.stock.utils import get_incoming_rate
|
from erpnext.stock.utils import get_incoming_rate
|
||||||
@ -185,11 +185,16 @@ class StockEntry(StockController):
|
|||||||
|
|
||||||
def validate_production_order(self):
|
def validate_production_order(self):
|
||||||
if self.purpose in ("Manufacture", "Material Transfer for Manufacture"):
|
if self.purpose in ("Manufacture", "Material Transfer for Manufacture"):
|
||||||
|
if not self.bom_no:
|
||||||
|
frappe.throw(_("BOM No is mandatory"))
|
||||||
|
|
||||||
# check if production order is entered
|
# check if production order is entered
|
||||||
if not self.production_order:
|
if not self.production_order:
|
||||||
frappe.throw(_("Production order number is mandatory for stock entry purpose manufacture"))
|
frappe.throw(_("Production order number is mandatory for stock entry purpose manufacture"))
|
||||||
# check for double entry
|
# check for double entry
|
||||||
if self.purpose=="Manufacture":
|
if self.purpose=="Manufacture":
|
||||||
|
if not self.fg_completed_qty:
|
||||||
|
frappe.throw(_("For Quantity (Manufactured Qty) is mandatory"))
|
||||||
self.check_if_operations_completed()
|
self.check_if_operations_completed()
|
||||||
self.check_duplicate_entry_for_production_order()
|
self.check_duplicate_entry_for_production_order()
|
||||||
elif self.purpose != "Material Transfer":
|
elif self.purpose != "Material Transfer":
|
||||||
@ -378,10 +383,21 @@ class StockEntry(StockController):
|
|||||||
|
|
||||||
def validate_finished_goods(self):
|
def validate_finished_goods(self):
|
||||||
"""validation: finished good quantity should be same as manufacturing quantity"""
|
"""validation: finished good quantity should be same as manufacturing quantity"""
|
||||||
|
items_with_target_warehouse = []
|
||||||
for d in self.get('items'):
|
for d in self.get('items'):
|
||||||
if d.bom_no and flt(d.transfer_qty) != flt(self.fg_completed_qty):
|
if d.bom_no and flt(d.transfer_qty) != flt(self.fg_completed_qty):
|
||||||
frappe.throw(_("Quantity in row {0} ({1}) must be same as manufactured quantity {2}"). \
|
frappe.throw(_("Quantity in row {0} ({1}) must be same as manufactured quantity {2}"). \
|
||||||
format(d.idx, d.transfer_qty, self.fg_completed_qty))
|
format(d.idx, d.transfer_qty, self.fg_completed_qty))
|
||||||
|
|
||||||
|
if self.production_order and self.purpose == "Manufacture" and d.t_warehouse:
|
||||||
|
items_with_target_warehouse.append(d.item_code)
|
||||||
|
|
||||||
|
if self.production_order and self.purpose == "Manufacture":
|
||||||
|
production_item = frappe.db.get_value("Production Order",
|
||||||
|
self.production_order, "production_item")
|
||||||
|
if production_item not in items_with_target_warehouse:
|
||||||
|
frappe.throw(_("Finished Item {0} must be entered for Manufacture type entry")
|
||||||
|
.format(production_item))
|
||||||
|
|
||||||
def validate_return_reference_doc(self):
|
def validate_return_reference_doc(self):
|
||||||
"""validate item with reference doc"""
|
"""validate item with reference doc"""
|
||||||
@ -399,7 +415,6 @@ class StockEntry(StockController):
|
|||||||
|
|
||||||
# posting date check
|
# posting date check
|
||||||
ref_posting_datetime = "%s %s" % (ref.doc.posting_date, ref.doc.posting_time or "00:00:00")
|
ref_posting_datetime = "%s %s" % (ref.doc.posting_date, ref.doc.posting_time or "00:00:00")
|
||||||
this_posting_datetime = "%s %s" % (self.posting_date, self.posting_time)
|
|
||||||
|
|
||||||
if get_datetime(ref_posting_datetime) < get_datetime(ref_posting_datetime):
|
if get_datetime(ref_posting_datetime) < get_datetime(ref_posting_datetime):
|
||||||
from frappe.utils.dateutils import datetime_in_user_format
|
from frappe.utils.dateutils import datetime_in_user_format
|
||||||
@ -474,9 +489,10 @@ class StockEntry(StockController):
|
|||||||
pro_doc = frappe.get_doc("Production Order", self.production_order)
|
pro_doc = frappe.get_doc("Production Order", self.production_order)
|
||||||
_validate_production_order(pro_doc)
|
_validate_production_order(pro_doc)
|
||||||
pro_doc.run_method("update_status")
|
pro_doc.run_method("update_status")
|
||||||
pro_doc.run_method("update_production_order_qty")
|
if self.fg_completed_qty:
|
||||||
if self.purpose == "Manufacture":
|
pro_doc.run_method("update_production_order_qty")
|
||||||
self.update_planned_qty(pro_doc)
|
if self.purpose == "Manufacture":
|
||||||
|
self.update_planned_qty(pro_doc)
|
||||||
|
|
||||||
def update_planned_qty(self, pro_doc):
|
def update_planned_qty(self, pro_doc):
|
||||||
from erpnext.stock.utils import update_bin
|
from erpnext.stock.utils import update_bin
|
||||||
@ -546,9 +562,6 @@ class StockEntry(StockController):
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
def get_items(self):
|
def get_items(self):
|
||||||
if not self.fg_completed_qty or not self.bom_no:
|
|
||||||
frappe.throw(_("BOM and Manufacturing Quantity are required"))
|
|
||||||
|
|
||||||
self.set('items', [])
|
self.set('items', [])
|
||||||
self.validate_production_order()
|
self.validate_production_order()
|
||||||
|
|
||||||
@ -638,17 +651,16 @@ class StockEntry(StockController):
|
|||||||
issued_item_qty = self.get_issued_qty()
|
issued_item_qty = self.get_issued_qty()
|
||||||
|
|
||||||
max_qty = flt(self.pro_doc.qty)
|
max_qty = flt(self.pro_doc.qty)
|
||||||
only_pending_fetched = []
|
|
||||||
|
|
||||||
for item in item_dict:
|
for item in item_dict:
|
||||||
pending_to_issue = (max_qty * item_dict[item]["qty"]) - issued_item_qty.get(item, 0)
|
pending_to_issue = (max_qty * item_dict[item]["qty"]) - issued_item_qty.get(item, 0)
|
||||||
desire_to_transfer = flt(self.fg_completed_qty) * item_dict[item]["qty"]
|
desire_to_transfer = flt(self.fg_completed_qty) * item_dict[item]["qty"]
|
||||||
|
|
||||||
if desire_to_transfer <= pending_to_issue:
|
if desire_to_transfer <= pending_to_issue:
|
||||||
item_dict[item]["qty"] = desire_to_transfer
|
item_dict[item]["qty"] = desire_to_transfer
|
||||||
else:
|
elif pending_to_issue > 0:
|
||||||
item_dict[item]["qty"] = pending_to_issue
|
item_dict[item]["qty"] = pending_to_issue
|
||||||
if pending_to_issue:
|
else:
|
||||||
only_pending_fetched.append(item)
|
item_dict[item]["qty"] = 0
|
||||||
|
|
||||||
# delete items with 0 qty
|
# delete items with 0 qty
|
||||||
for item in item_dict.keys():
|
for item in item_dict.keys():
|
||||||
@ -659,9 +671,6 @@ class StockEntry(StockController):
|
|||||||
if not len(item_dict):
|
if not len(item_dict):
|
||||||
frappe.msgprint(_("""All items have already been transferred for this Production Order."""))
|
frappe.msgprint(_("""All items have already been transferred for this Production Order."""))
|
||||||
|
|
||||||
elif only_pending_fetched:
|
|
||||||
frappe.msgprint(_("Pending Items {0} updated").format(only_pending_fetched))
|
|
||||||
|
|
||||||
return item_dict
|
return item_dict
|
||||||
|
|
||||||
def get_issued_qty(self):
|
def get_issued_qty(self):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user