refactor code in Production Planning Tool

This commit is contained in:
Neil Trini Lasrado 2016-02-12 14:32:23 +05:30
parent 877e2ebff8
commit fd9dc5e9f5
6 changed files with 173 additions and 155 deletions

View File

@ -116,6 +116,54 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "column_break_6",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"description": "Reserved Warehouse in Sales Order / Finished Goods Warehouse",
"fieldname": "warehouse",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Warehouse",
"length": 0,
"no_copy": 0,
"options": "Warehouse",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
@ -160,7 +208,7 @@
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@ -194,31 +242,6 @@
"unique": 0,
"width": "100px"
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"description": "Reserved Warehouse in Sales Order / Finished Goods Warehouse",
"fieldname": "warehouse",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Warehouse",
"length": 0,
"no_copy": 0,
"options": "Warehouse",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
@ -308,7 +331,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2016-02-10 07:08:38.461787",
"modified": "2016-02-11 05:08:19.492712",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "Production Plan Item",

View File

@ -66,7 +66,7 @@
"bold": 0,
"collapsible": 0,
"fieldname": "material_request_date",
"fieldtype": "Date",
"fieldtype": "Read Only",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
@ -76,6 +76,7 @@
"no_copy": 0,
"oldfieldname": "document_date",
"oldfieldtype": "Date",
"options": "material_request.transaction_date",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@ -99,7 +100,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2016-02-10 05:13:07.529068",
"modified": "2016-02-11 04:21:34.372317",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "Production Plan Material Request",

View File

@ -41,7 +41,7 @@
"bold": 0,
"collapsible": 0,
"fieldname": "sales_order_date",
"fieldtype": "Date",
"fieldtype": "Read Only",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
@ -51,11 +51,12 @@
"no_copy": 0,
"oldfieldname": "document_date",
"oldfieldtype": "Date",
"options": "sales_order.transaction_date",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": "120px",
"read_only": 1,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@ -91,7 +92,7 @@
"bold": 0,
"collapsible": 0,
"fieldname": "customer",
"fieldtype": "Link",
"fieldtype": "Read Only",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
@ -99,7 +100,7 @@
"label": "Customer",
"length": 0,
"no_copy": 0,
"options": "Customer",
"options": "sales_order.customer",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
@ -116,8 +117,9 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"default": "",
"fieldname": "grand_total",
"fieldtype": "Currency",
"fieldtype": "Read Only",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
@ -125,7 +127,7 @@
"label": "Grand Total",
"length": 0,
"no_copy": 0,
"options": "Company:company:default_currency",
"options": "sales_order.base_grand_total",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
@ -148,7 +150,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2016-02-10 05:13:30.301297",
"modified": "2016-02-11 04:17:42.849873",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "Production Plan Sales Order",

View File

@ -5,24 +5,25 @@ frappe.require("assets/erpnext/js/utils.js");
cur_frm.cscript.onload = function(doc, cdt, cdn) {
cur_frm.set_value("company", frappe.defaults.get_user_default("Company"))
cur_frm.set_value("use_multi_level_bom", 1)
}
cur_frm.cscript.refresh = function(doc) {
cur_frm.disable_save();
}
cur_frm.cscript.sales_order = function(doc,cdt,cdn) {
var d = locals[cdt][cdn];
if (d.sales_order) {
return get_server_fields('get_so_details', d.sales_order, 'sales_orders', doc, cdt, cdn, 1);
}
}
cur_frm.cscript.item_code = function(doc,cdt,cdn) {
var d = locals[cdt][cdn];
if (d.item_code) {
return get_server_fields('get_item_details', d.item_code, 'items', doc, cdt, cdn, 1);
frappe.call({
method: "erpnext.manufacturing.doctype.production_order.production_order.get_item_details",
args: {
"item" : d.item_code
},
callback: function(r) {
$.extend(d, r.message);
refresh_field("items");
}
});
}
}

View File

@ -510,7 +510,7 @@
"label": "Create Production Orders",
"length": 0,
"no_copy": 0,
"options": "raise_production_order",
"options": "raise_production_orders",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
@ -629,7 +629,7 @@
"issingle": 1,
"istable": 0,
"max_attachments": 0,
"modified": "2016-02-10 07:28:50.298538",
"modified": "2016-02-11 06:18:45.077263",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "Production Planning Tool",

View File

@ -16,28 +16,8 @@ class ProductionPlanningTool(Document):
super(ProductionPlanningTool, self).__init__(arg1, arg2)
self.item_dict = {}
def get_so_details(self, so):
"""Pull other details from so"""
so = frappe.db.sql("""select transaction_date, customer, base_grand_total
from `tabSales Order` where name = %s""", so, as_dict = 1)
ret = {
'sales_order_date': so and so[0]['transaction_date'] or '',
'customer' : so[0]['customer'] or '',
'grand_total': so[0]['base_grand_total']
}
return ret
def get_item_details(self, item_code):
return get_item_details(item_code)
def clear_so_table(self):
self.set('sales_orders', [])
def clear_mr_table(self):
self.set('material_requests', [])
def clear_item_table(self):
self.set('items', [])
def clear_table(self, table_name):
self.set(table_name, [])
def validate_company(self):
if not self.company:
@ -81,7 +61,7 @@ class ProductionPlanningTool(Document):
def add_so_in_table(self, open_so):
""" Add sales orders in the table"""
self.clear_so_table()
self.clear_table("sales_orders")
so_list = [d.sales_order for d in self.get('sales_orders')]
for r in open_so:
@ -125,7 +105,7 @@ class ProductionPlanningTool(Document):
def add_mr_in_table(self, pending_mr):
""" Add Material Requests in the table"""
self.clear_mr_table()
self.clear_table("material_requests")
mr_list = [d.material_request for d in self.get('material_requests')]
for r in pending_mr:
@ -199,7 +179,7 @@ class ProductionPlanningTool(Document):
def add_items(self, items):
self.clear_item_table()
self.clear_table("items")
for p in items:
item_details = get_item_details(p['item_code'])
pi = self.append('items', {})
@ -220,97 +200,108 @@ class ProductionPlanningTool(Document):
def validate_data(self):
self.validate_company()
for d in self.get('items'):
validate_bom_no(d.item_code, d.bom_no)
if not d.bom_no:
frappe.throw(_("Please select BOM for Item in Row {0}".format(d.idx)))
else:
validate_bom_no(d.item_code, d.bom_no)
if not flt(d.planned_qty):
frappe.throw(_("Please enter Planned Qty for Item {0} at row {1}").format(d.item_code, d.idx))
def raise_production_order(self):
def raise_production_orders(self):
"""It will raise production order (Draft) for all distinct FG items"""
self.validate_data()
from erpnext.utilities.transaction_base import validate_uom_is_integer
validate_uom_is_integer(self, "stock_uom", "planned_qty")
items = self.get_distinct_items_and_boms()[1]
pro = self.create_production_order(items)
if pro:
pro = ["""<a href="#Form/Production Order/%s" target="_blank">%s</a>""" % \
(p, p) for p in pro]
msgprint(_("{0} created").format(comma_and(pro)))
items = self.get_production_items()
pro_list = []
frappe.flags.mute_messages = True
for key in items:
production_order = self.create_production_order(items[key])
if production_order:
pro_list.append(production_order)
frappe.flags.mute_messages = False
if pro_list:
pro_list = ["""<a href="#Form/Production Order/%s" target="_blank">%s</a>""" % \
(p, p) for p in pro_list]
msgprint(_("{0} created").format(comma_and(pro_list)))
else :
msgprint(_("No Production Orders created"))
def get_distinct_items_and_boms(self):
""" Club similar BOM and item for processing
def get_production_items(self):
item_dict = {}
for d in self.get("items"):
item_details= {
"production_item" : d.item_code,
"sales_order" : d.sales_order,
"material_request" : d.material_request,
"material_request_item" : d.material_request_item,
"bom_no" : d.bom_no,
"description" : d.description,
"stock_uom" : d.stock_uom,
"company" : self.company,
"wip_warehouse" : "",
"fg_warehouse" : d.warehouse,
"status" : "Draft",
}
""" Club similar BOM and item for processing in case of Sales Orders """
if self.plan_using == "Sales Order":
item_details.update({
"qty":flt(item_dict.get((d.item_code, d.sales_order, d.warehouse),{})
.get("qty")) + flt(d.planned_qty)
})
item_dict[(d.item_code, d.sales_order, d.warehouse)] = item_details
elif self.plan_using == "Material Request":
item_details.update({
"qty": d.planned_qty
})
item_dict[(d.item_code, d.material_request_item, d.warehouse)] = item_details
return item_dict
def create_production_order(self, item_dict):
"""Create production order. Called from Production Planning Tool"""
from erpnext.manufacturing.doctype.production_order.production_order import OverProductionError, get_default_warehouse
warehouse = get_default_warehouse()
pro = frappe.new_doc("Production Order")
pro.update(item_dict)
pro.set_production_order_operations()
if warehouse:
pro.wip_warehouse = warehouse.get('wip_warehouse')
if not pro.fg_warehouse:
pro.fg_warehouse = warehouse.get('fg_warehouse')
try:
pro.insert()
return pro.name
except OverProductionError:
pass
def get_so_wise_planned_qty(self):
"""
bom_dict {
bom_no: ['sales_order', 'qty']
}
"""
item_dict, bom_dict = {}, {}
bom_dict = {}
for d in self.get("items"):
if d.bom_no:
if self.plan_using == "Sales Order":
bom_dict.setdefault(d.bom_no, []).append([d.sales_order, flt(d.planned_qty)])
if frappe.db.get_value("Item", d.item_code, "is_pro_applicable"):
item_dict[(d.item_code, d.sales_order, d.warehouse)] = {
"production_item" : d.item_code,
"sales_order" : d.sales_order,
"qty" : flt(item_dict.get((d.item_code, d.sales_order, d.warehouse),
{}).get("qty")) + flt(d.planned_qty),
"bom_no" : d.bom_no,
"description" : d.description,
"stock_uom" : d.stock_uom,
"company" : self.company,
"wip_warehouse" : "",
"fg_warehouse" : d.warehouse,
"status" : "Draft",
}
elif self.plan_using == "Material Request":
bom_dict.setdefault(d.bom_no, []).append([d.material_request_item, flt(d.planned_qty)])
if frappe.db.get_value("Item", d.item_code, "is_pro_applicable"):
item_dict[(d.item_code, d.material_request_item, d.warehouse)] = {
"production_item" : d.item_code,
"material_request" : d.material_request,
"material_request_item" : d.material_request_item,
"qty" : d.planned_qty,
"bom_no" : d.bom_no,
"description" : d.description,
"stock_uom" : d.stock_uom,
"company" : self.company,
"wip_warehouse" : "",
"fg_warehouse" : d.warehouse,
"status" : "Draft",
}
return bom_dict, item_dict
def create_production_order(self, items):
"""Create production order. Called from Production Planning Tool"""
from erpnext.manufacturing.doctype.production_order.production_order import OverProductionError, get_default_warehouse
warehouse = get_default_warehouse()
pro_list = []
for key in items:
pro = frappe.new_doc("Production Order")
pro.update(items[key])
pro.set_production_order_operations()
if warehouse:
pro.wip_warehouse = warehouse.get('wip_warehouse')
if not pro.fg_warehouse:
pro.fg_warehouse = warehouse.get('fg_warehouse')
frappe.flags.mute_messages = True
try:
pro.insert()
pro_list.append(pro.name)
except OverProductionError:
pass
frappe.flags.mute_messages = False
return pro_list
if self.plan_using == "Sales Order":
bom_dict.setdefault(d.bom_no, []).append({d.sales_order: flt(d.planned_qty)})
elif self.plan_using == "Material Request":
bom_dict.setdefault(d.bom_no, []).append({d.material_request_item: flt(d.planned_qty)})
def download_raw_materials(self):
""" Create csv data for required raw material to produce finished goods"""
self.validate_data()
bom_dict = self.get_distinct_items_and_boms()[0]
bom_dict = self.get_so_wise_planned_qty()
self.get_raw_materials(bom_dict)
return self.get_csv()
@ -389,7 +380,7 @@ class ProductionPlanningTool(Document):
if not self.purchase_request_for_warehouse:
frappe.throw(_("Please enter Warehouse for which Material Request will be raised"))
bom_dict = self.get_distinct_items_and_boms()[0]
bom_dict = self.get_so_wise_planned_qty()
self.get_raw_materials(bom_dict)
if self.item_dict:
@ -445,12 +436,12 @@ class ProductionPlanningTool(Document):
def insert_purchase_request(self):
items_to_be_requested = self.get_requested_items()
purchase_request_list = []
material_request_list = []
if items_to_be_requested:
for item in items_to_be_requested:
item_wrapper = frappe.get_doc("Item", item)
pr_doc = frappe.new_doc("Material Request")
pr_doc.update({
material_request = frappe.new_doc("Material Request")
material_request.update({
"transaction_date": nowdate(),
"status": "Draft",
"company": self.company,
@ -458,7 +449,7 @@ class ProductionPlanningTool(Document):
"material_request_type": "Purchase"
})
for sales_order, requested_qty in items_to_be_requested[item].items():
pr_doc.append("items", {
material_request.append("items", {
"doctype": "Material Request Item",
"__islocal": 1,
"item_code": item,
@ -473,13 +464,13 @@ class ProductionPlanningTool(Document):
"sales_order": sales_order if sales_order!="No Sales Order" else None
})
pr_doc.flags.ignore_permissions = 1
pr_doc.submit()
purchase_request_list.append(pr_doc.name)
material_request.flags.ignore_permissions = 1
material_request.submit()
material_request_list.append(material_request.name)
if purchase_request_list:
pur_req = ["""<a href="#Form/Material Request/%s" target="_blank">%s</a>""" % \
(p, p) for p in purchase_request_list]
msgprint(_("Material Requests {0} created").format(comma_and(pur_req)))
if material_request_list:
message = ["""<a href="#Form/Material Request/%s" target="_blank">%s</a>""" % \
(p, p) for p in material_request_list]
msgprint(_("Material Requests {0} created").format(comma_and(message)))
else:
msgprint(_("Nothing to request"))