refactor code in Production Planning Tool
This commit is contained in:
parent
877e2ebff8
commit
fd9dc5e9f5
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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",
|
||||
|
@ -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"))
|
||||
|
Loading…
x
Reference in New Issue
Block a user