From f0b3014a232fccadfebbc6f0c6be4e07a065f307 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Wed, 9 Sep 2015 11:04:05 +0530 Subject: [PATCH] Planned Qty logic fixed and reposted for existing --- .../production_order/production_order.py | 38 +++++++++---------- erpnext/patches.txt | 1 + erpnext/patches/v6_0/fix_planned_qty.py | 13 +++++++ .../stock/doctype/stock_entry/stock_entry.py | 11 +----- 4 files changed, 34 insertions(+), 29 deletions(-) create mode 100644 erpnext/patches/v6_0/fix_planned_qty.py diff --git a/erpnext/manufacturing/doctype/production_order/production_order.py b/erpnext/manufacturing/doctype/production_order/production_order.py index 19746fc304..3e380a54eb 100644 --- a/erpnext/manufacturing/doctype/production_order/production_order.py +++ b/erpnext/manufacturing/doctype/production_order/production_order.py @@ -2,9 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe, json +import frappe -from frappe.utils import flt, nowdate, get_datetime, getdate, date_diff, cint +from frappe.utils import flt, get_datetime, getdate, date_diff, cint from frappe import _ from frappe.model.document import Document from erpnext.manufacturing.doctype.bom.bom import validate_bom_no @@ -14,6 +14,7 @@ from erpnext.manufacturing.doctype.workstation.workstation import WorkstationHol from erpnext.projects.doctype.time_log.time_log import OverlapError from erpnext.stock.doctype.stock_entry.stock_entry import get_additional_costs from erpnext.manufacturing.doctype.manufacturing_settings.manufacturing_settings import get_mins_between_operations +from erpnext.stock.stock_balance import get_planned_qty, update_bin_qty class OverProductionError(frappe.ValidationError): pass class StockOverProductionError(frappe.ValidationError): pass @@ -106,8 +107,7 @@ class ProductionOrder(Document): def stop_unstop(self, status): """ Called from client side on Stop/Unstop event""" self.update_status(status) - qty = (flt(self.qty)-flt(self.produced_qty)) * ((status == 'Stopped') and -1 or 1) - self.update_planned_qty(qty) + self.update_planned_qty() frappe.msgprint(_("Production Order status is {0}").format(status)) self.notify_modified() @@ -154,30 +154,30 @@ class ProductionOrder(Document): frappe.throw(_("For Warehouse is required before Submit")) frappe.db.set(self,'status', 'Submitted') self.make_time_logs() - self.update_planned_qty(self.qty) + self.update_planned_qty() def on_cancel(self): + self.validate_cancel() + + frappe.db.set(self,'status', 'Cancelled') + self.update_planned_qty() + self.delete_time_logs() + + def validate_cancel(self): + if self.status == "Stopped": + frappe.throw(_("Stopped Production Order cannot be cancelled, Unstop it first to cancel")) + # Check whether any stock entry exists against this Production Order stock_entry = frappe.db.sql("""select name from `tabStock Entry` where production_order = %s and docstatus = 1""", self.name) if stock_entry: frappe.throw(_("Cannot cancel because submitted Stock Entry {0} exists").format(stock_entry[0][0])) - frappe.db.set(self,'status', 'Cancelled') - self.update_planned_qty(-self.qty) - self.delete_time_logs() - - def update_planned_qty(self, qty): - """update planned qty in bin""" - args = { - "item_code": self.production_item, - "warehouse": self.fg_warehouse, - "posting_date": nowdate(), - "planned_qty": flt(qty) - } - from erpnext.stock.utils import update_bin - update_bin(args) + def update_planned_qty(self): + update_bin_qty(self.production_item, self.fg_warehouse, { + "planned_qty": get_planned_qty(self.production_item, self.fg_warehouse) + }) def set_production_order_operations(self): """Fetch operations from BOM and set in 'Production Order'""" diff --git a/erpnext/patches.txt b/erpnext/patches.txt index b5fa71bd16..2b4a017138 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -205,3 +205,4 @@ erpnext.patches.v6_0.default_activity_rate execute:frappe.db.set_value("Stock Settings", None, "automatically_set_serial_nos_based_on_fifo", 1) execute:frappe.db.sql("""update `tabProject` set percent_complete=round(percent_complete, 2) where percent_complete is not null""") erpnext.patches.v6_0.fix_outstanding_amount +erpnext.patches.v6_0.fix_planned_qty \ No newline at end of file diff --git a/erpnext/patches/v6_0/fix_planned_qty.py b/erpnext/patches/v6_0/fix_planned_qty.py new file mode 100644 index 0000000000..b523350e8d --- /dev/null +++ b/erpnext/patches/v6_0/fix_planned_qty.py @@ -0,0 +1,13 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import frappe +from erpnext.stock.stock_balance import get_planned_qty, update_bin_qty + +def execute(): + for item_code, warehouse in frappe.db.sql("""select distinct production_item, fg_warehouse + from `tabProduction Order`"""): + update_bin_qty(item_code, warehouse, { + "planned_qty": get_planned_qty(item_code, warehouse) + }) \ No newline at end of file diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index cdfdc78725..5f85ef91a8 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -441,16 +441,7 @@ class StockEntry(StockController): if self.fg_completed_qty: pro_doc.run_method("update_production_order_qty") if self.purpose == "Manufacture": - self.update_planned_qty(pro_doc) - - def update_planned_qty(self, pro_doc): - from erpnext.stock.utils import update_bin - update_bin({ - "item_code": pro_doc.production_item, - "warehouse": pro_doc.fg_warehouse, - "posting_date": self.posting_date, - "planned_qty": (self.docstatus==1 and -1 or 1 ) * flt(self.fg_completed_qty) - }) + pro_doc.run_method("update_planned_qty") def get_item_details(self, args=None, for_update=False): item = frappe.db.sql("""select stock_uom, description, image, item_name,