From 13ddc7e1882ef7f198fbae3643533ac02f8bc4b0 Mon Sep 17 00:00:00 2001 From: Zarrar Date: Tue, 20 Mar 2018 12:38:43 +0530 Subject: [PATCH] [ Enhance ] Production to Work Order (#12902) * remove occurrences of Production Order * rename from report and jsons * Change Production Order to Work Order * change occurences of production order from other files * resolve minor conflict issues and reports * patch added * codacy fix * updated patches, leftover changes * rename reports, rectify patches --- erpnext/config/learn.py | 2 +- erpnext/config/manufacturing.py | 22 +-- erpnext/demo/user/manufacturing.py | 22 +-- erpnext/domains/manufacturing.py | 2 +- erpnext/hooks.py | 2 +- erpnext/hr/doctype/employee/employee.py | 2 +- .../manufacturing_settings.json | 4 +- .../production_plan/production_plan.js | 8 +- .../production_plan/production_plan.json | 40 ++++- .../production_plan/production_plan.py | 48 +++--- .../production_plan_dashboard.py | 2 +- .../production_plan/test_production_plan.py | 10 +- .../production_planning_tool.py | 46 +++--- .../{production_order => work_order}/.py | 0 .../README.md | 0 .../__init__.py | 0 .../test_records.json | 4 +- .../test_work_order.js} | 30 ++-- .../test_work_order.py} | 149 +++++++++-------- .../work_order.js} | 90 +++++------ .../work_order.json} | 14 +- .../work_order.py} | 100 ++++++------ .../work_order_calendar.js} | 6 +- .../work_order_dashboard.py} | 2 +- .../work_order_list.js} | 2 +- .../__init__.py | 0 .../work_order_item.json} | 4 +- .../work_order_item.py} | 4 +- .../__init__.py | 0 .../work_order_operation.json} | 4 +- .../work_order_operation.py} | 2 +- .../production_analytics.js | 6 +- .../completed_production_orders.json | 27 ---- .../__init__.py | 0 .../completed_work_orders.json | 27 ++++ ...issued_items_against_production_order.json | 27 ---- .../__init__.py | 0 .../issued_items_against_work_order.json | 27 ++++ .../open_production_orders.json | 27 ---- .../__init__.py | 0 .../open_work_orders/open_work_orders.json | 27 ++++ .../production_orders_in_progress.json | 27 ---- .../__init__.py | 0 .../work_order_stock_report.js} | 5 +- .../work_order_stock_report.json} | 8 +- .../work_order_stock_report.py} | 44 ++--- .../__init__.py | 0 .../work_orders_in_progress.json | 27 ++++ erpnext/patches.txt | 3 +- .../rename_production_order_to_work_order.py | 35 ++++ .../v4_0/set_naming_series_property_setter.py | 2 +- .../v4_2/seprate_manufacture_and_repack.py | 4 +- ...nned_operating_cost_in_production_order.py | 12 +- .../patches/v5_0/rename_table_fieldnames.py | 4 +- ...pdate_material_transfer_for_manufacture.py | 2 +- ..._material_transferred_for_manufacturing.py | 6 +- ...ial_transferred_for_manufacturing_again.py | 20 +-- ...e_item_description_based_on_item_master.py | 12 ++ erpnext/patches/v6_0/fix_planned_qty.py | 2 +- .../v6_20x/rename_project_name_to_project.py | 2 +- .../v7_0/convert_timelog_to_timesheet.py | 10 +- .../v7_0/convert_timelogbatch_to_timesheet.py | 2 +- ...tock_for_deleted_bins_for_merging_items.py | 8 +- .../patches/v8_0/update_production_orders.py | 32 ++-- .../add_indexes_in_transaction_doctypes.py | 2 +- .../v8_6/update_timesheet_company_from_PO.py | 4 +- .../v9_2/set_item_name_in_production_order.py | 2 +- .../doctype/timesheet/test_timesheet.js | 23 +++ .../projects/doctype/timesheet/timesheet.json | 16 +- .../projects/doctype/timesheet/timesheet.py | 32 ++-- .../timesheet_detail/timesheet_detail.json | 96 ++++++++++- erpnext/public/js/help_links.js | 4 +- .../doctype/sales_order/sales_order.js | 20 +-- .../doctype/sales_order/sales_order.py | 26 +-- .../sales_order/sales_order_dashboard.py | 2 +- .../doctype/sales_order/test_sales_order.py | 16 +- .../company/tests/test_company_production.js | 2 +- erpnext/startup/notifications.py | 2 +- erpnext/startup/report_data_map.py | 4 +- erpnext/stock/doctype/batch/test_batch.py | 2 +- erpnext/stock/doctype/bin/bin.py | 4 +- erpnext/stock/doctype/item/item_dashboard.py | 4 +- .../material_request/material_request.js | 10 +- .../material_request/material_request.py | 50 +++--- .../material_request_dashboard.py | 2 +- .../material_request/test_material_request.py | 6 +- .../stock/doctype/stock_entry/stock_entry.js | 30 ++-- .../doctype/stock_entry/stock_entry.json | 8 +- .../stock/doctype/stock_entry/stock_entry.py | 153 +++++++++--------- .../doctype/stock_entry/stock_entry_list.js | 2 +- .../doctype/stock_entry/test_stock_entry.py | 30 ++-- erpnext/stock/stock_balance.py | 2 +- erpnext/tests/ui/tests.txt | 2 +- 93 files changed, 902 insertions(+), 710 deletions(-) rename erpnext/manufacturing/doctype/{production_order => work_order}/.py (100%) rename erpnext/manufacturing/doctype/{production_order => work_order}/README.md (100%) rename erpnext/manufacturing/doctype/{production_order => work_order}/__init__.py (100%) rename erpnext/manufacturing/doctype/{production_order => work_order}/test_records.json (87%) rename erpnext/manufacturing/doctype/{production_order/test_production_order.js => work_order/test_work_order.js} (84%) rename erpnext/manufacturing/doctype/{production_order/test_production_order.py => work_order/test_work_order.py} (62%) rename erpnext/manufacturing/doctype/{production_order/production_order.js => work_order/work_order.js} (79%) rename erpnext/manufacturing/doctype/{production_order/production_order.json => work_order/work_order.json} (99%) rename erpnext/manufacturing/doctype/{production_order/production_order.py => work_order/work_order.py} (88%) rename erpnext/manufacturing/doctype/{production_order/production_order_calendar.js => work_order/work_order_calendar.js} (83%) rename erpnext/manufacturing/doctype/{production_order/production_order_dashboard.py => work_order/work_order_dashboard.py} (77%) rename erpnext/manufacturing/doctype/{production_order/production_order_list.js => work_order/work_order_list.js} (91%) rename erpnext/manufacturing/doctype/{production_order_item => work_order_item}/__init__.py (100%) rename erpnext/manufacturing/doctype/{production_order_item/production_order_item.json => work_order_item/work_order_item.json} (99%) rename erpnext/manufacturing/doctype/{production_order_item/production_order_item.py => work_order_item/work_order_item.py} (70%) rename erpnext/manufacturing/doctype/{production_order_operation => work_order_operation}/__init__.py (100%) rename erpnext/manufacturing/doctype/{production_order_operation/production_order_operation.json => work_order_operation/work_order_operation.json} (99%) rename erpnext/manufacturing/doctype/{production_order_operation/production_order_operation.py => work_order_operation/work_order_operation.py} (85%) delete mode 100644 erpnext/manufacturing/report/completed_production_orders/completed_production_orders.json rename erpnext/manufacturing/report/{completed_production_orders => completed_work_orders}/__init__.py (100%) create mode 100644 erpnext/manufacturing/report/completed_work_orders/completed_work_orders.json delete mode 100644 erpnext/manufacturing/report/issued_items_against_production_order/issued_items_against_production_order.json rename erpnext/manufacturing/report/{issued_items_against_production_order => issued_items_against_work_order}/__init__.py (100%) create mode 100644 erpnext/manufacturing/report/issued_items_against_work_order/issued_items_against_work_order.json delete mode 100644 erpnext/manufacturing/report/open_production_orders/open_production_orders.json rename erpnext/manufacturing/report/{open_production_orders => open_work_orders}/__init__.py (100%) create mode 100644 erpnext/manufacturing/report/open_work_orders/open_work_orders.json delete mode 100644 erpnext/manufacturing/report/production_orders_in_progress/production_orders_in_progress.json rename erpnext/manufacturing/report/{production_order_stock_report => work_order_stock_report}/__init__.py (100%) rename erpnext/manufacturing/report/{production_order_stock_report/production_order_stock_report.js => work_order_stock_report/work_order_stock_report.js} (56%) rename erpnext/manufacturing/report/{production_order_stock_report/production_order_stock_report.json => work_order_stock_report/work_order_stock_report.json} (70%) rename erpnext/manufacturing/report/{production_order_stock_report/production_order_stock_report.py => work_order_stock_report/work_order_stock_report.py} (69%) rename erpnext/manufacturing/report/{production_orders_in_progress => work_orders_in_progress}/__init__.py (100%) create mode 100644 erpnext/manufacturing/report/work_orders_in_progress/work_orders_in_progress.json create mode 100644 erpnext/patches/v11_0/rename_production_order_to_work_order.py create mode 100644 erpnext/patches/v5_7/update_item_description_based_on_item_master.py create mode 100644 erpnext/projects/doctype/timesheet/test_timesheet.js diff --git a/erpnext/config/learn.py b/erpnext/config/learn.py index edd785a6c18..9095ab6b64e 100644 --- a/erpnext/config/learn.py +++ b/erpnext/config/learn.py @@ -219,7 +219,7 @@ def get_data(): }, { "type": "help", - "label": _("Production Order"), + "label": _("Work Order"), "youtube_id": "ZotgLyp2YFY" }, diff --git a/erpnext/config/manufacturing.py b/erpnext/config/manufacturing.py index d0fc39eda6d..16ca9145b4a 100644 --- a/erpnext/config/manufacturing.py +++ b/erpnext/config/manufacturing.py @@ -9,13 +9,13 @@ def get_data(): "items": [ { "type": "doctype", - "name": "Production Order", + "name": "Work Order", "description": _("Orders released for production."), }, { "type": "doctype", "name": "Production Plan", - "description": _("Generate Material Requests (MRP) and Production Orders."), + "description": _("Generate Material Requests (MRP) and Work Orders."), }, { "type": "doctype", @@ -92,26 +92,26 @@ def get_data(): { "type": "report", "is_query_report": True, - "name": "Open Production Orders", - "doctype": "Production Order" + "name": "Open Work Orders", + "doctype": "Work Order" }, { "type": "report", "is_query_report": True, - "name": "Production Orders in Progress", - "doctype": "Production Order" + "name": "Work Orders in Progress", + "doctype": "Work Order" }, { "type": "report", "is_query_report": True, - "name": "Issued Items Against Production Order", - "doctype": "Production Order" + "name": "Issued Items Against Work Order", + "doctype": "Work Order" }, { "type": "report", "is_query_report": True, - "name": "Completed Production Orders", - "doctype": "Production Order" + "name": "Completed Work Orders", + "doctype": "Work Order" },{ "type": "page", "name": "production-analytics", @@ -143,7 +143,7 @@ def get_data(): }, { "type": "help", - "label": _("Production Order"), + "label": _("Work Order"), "youtube_id": "ZotgLyp2YFY" }, ] diff --git a/erpnext/demo/user/manufacturing.py b/erpnext/demo/user/manufacturing.py index 80d140af74a..496b011ec1f 100644 --- a/erpnext/demo/user/manufacturing.py +++ b/erpnext/demo/user/manufacturing.py @@ -7,7 +7,7 @@ import frappe, random, erpnext from frappe.utils.make_random import how_many from frappe.desk import query_report from erpnext.manufacturing.doctype.workstation.workstation import WorkstationHolidayError -from erpnext.manufacturing.doctype.production_order.test_production_order import make_prod_order_test_record +from erpnext.manufacturing.doctype.work_order.test_work_order import make_prod_order_test_record def work(): frappe.set_user(frappe.db.get_global('demo_manufacturing_user')) @@ -21,13 +21,13 @@ def work(): ppt.purchase_request_for_warehouse = "Stores - WPL" ppt.run_method("get_open_sales_orders") ppt.run_method("get_items") - ppt.run_method("raise_production_orders") + ppt.run_method("raise_work_orders") ppt.run_method("raise_material_requests") frappe.db.commit() - # submit production orders - for pro in frappe.db.get_values("Production Order", {"docstatus": 0}, "name"): - b = frappe.get_doc("Production Order", pro[0]) + # submit work orders + for pro in frappe.db.get_values("Work Order", {"docstatus": 0}, "name"): + b = frappe.get_doc("Work Order", pro[0]) b.wip_warehouse = "Work in Progress - WPL" b.submit() frappe.db.commit() @@ -40,12 +40,12 @@ def work(): # stores -> wip if random.random() < 0.3: - for pro in query_report.run("Open Production Orders")["result"][:how_many("Stock Entry for WIP")]: + for pro in query_report.run("Open Work Orders")["result"][:how_many("Stock Entry for WIP")]: make_stock_entry_from_pro(pro[0], "Material Transfer for Manufacture") # wip -> fg if random.random() < 0.3: - for pro in query_report.run("Production Orders in Progress")["result"][:how_many("Stock Entry for FG")]: + for pro in query_report.run("Work Orders in Progress")["result"][:how_many("Stock Entry for FG")]: make_stock_entry_from_pro(pro[0], "Manufacture") for bom in frappe.get_all('BOM', fields=['item'], filters = {'with_operations': 1}): @@ -57,7 +57,7 @@ def work(): # submit time logs for timesheet in frappe.get_all("Timesheet", ["name"], {"docstatus": 0, - "production_order": ("!=", ""), "to_time": ("<", frappe.flags.current_date)}): + "work_order": ("!=", ""), "to_time": ("<", frappe.flags.current_date)}): timesheet = frappe.get_doc("Timesheet", timesheet.name) try: timesheet.submit() @@ -68,10 +68,10 @@ def work(): pass def make_stock_entry_from_pro(pro_id, purpose): - from erpnext.manufacturing.doctype.production_order.production_order import make_stock_entry + from erpnext.manufacturing.doctype.work_order.work_order import make_stock_entry from erpnext.stock.stock_ledger import NegativeStockError from erpnext.stock.doctype.stock_entry.stock_entry import IncorrectValuationRateError, \ - DuplicateEntryForProductionOrderError, OperationsNotCompleteError + DuplicateEntryForWorkOrderError, OperationsNotCompleteError try: st = frappe.get_doc(make_stock_entry(pro_id, purpose)) @@ -83,6 +83,6 @@ def make_stock_entry_from_pro(pro_id, purpose): frappe.db.commit() st.submit() frappe.db.commit() - except (NegativeStockError, IncorrectValuationRateError, DuplicateEntryForProductionOrderError, + except (NegativeStockError, IncorrectValuationRateError, DuplicateEntryForWorkOrderError, OperationsNotCompleteError): frappe.db.rollback() diff --git a/erpnext/domains/manufacturing.py b/erpnext/domains/manufacturing.py index 8c911a311d4..7f328b1d95a 100644 --- a/erpnext/domains/manufacturing.py +++ b/erpnext/domains/manufacturing.py @@ -6,7 +6,7 @@ data = { 'Supplier', 'Sales Order', 'Purchase Order', - 'Production Order', + 'Work Order', 'Task', 'Accounts', 'HR', diff --git a/erpnext/hooks.py b/erpnext/hooks.py index a97f80fddc4..72007fc05a7 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -49,7 +49,7 @@ my_account_context = "erpnext.shopping_cart.utils.update_my_account_context" email_append_to = ["Job Applicant", "Lead", "Opportunity", "Issue"] -calendars = ["Task", "Production Order", "Leave Application", "Sales Order", "Holiday List", "Course Schedule"] +calendars = ["Task", "Work Order", "Leave Application", "Sales Order", "Holiday List", "Course Schedule"] diff --git a/erpnext/hr/doctype/employee/employee.py b/erpnext/hr/doctype/employee/employee.py index 5446a6e4a81..bb12231f33c 100755 --- a/erpnext/hr/doctype/employee/employee.py +++ b/erpnext/hr/doctype/employee/employee.py @@ -72,7 +72,7 @@ class Employee(NestedSet): user.flags.ignore_permissions = True if "Employee" not in user.get("roles"): - user.add_roles("Employee") + user.append_roles("Employee") # copy details like Fullname, DOB and Image to User if self.employee_name and not (user.first_name and user.last_name): diff --git a/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.json b/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.json index 455a983e76f..1fb2bf5a666 100644 --- a/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.json +++ b/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.json @@ -48,7 +48,7 @@ "bold": 0, "collapsible": 0, "columns": 0, - "description": "Disables creation of time logs against Production Orders. Operations shall not be tracked against Production Order", + "description": "Disables creation of time logs against Work Orders. Operations shall not be tracked against Work Order", "fieldname": "disable_capacity_planning", "fieldtype": "Check", "hidden": 0, @@ -454,7 +454,7 @@ "istable": 0, "max_attachments": 0, "menu_index": 0, - "modified": "2017-07-31 19:25:04.242693", + "modified": "2018-02-16 13:18:17.964103", "modified_by": "Administrator", "module": "Manufacturing", "name": "Manufacturing Settings", diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.js b/erpnext/manufacturing/doctype/production_plan/production_plan.js index 953c124cbc1..e74a3755577 100644 --- a/erpnext/manufacturing/doctype/production_plan/production_plan.js +++ b/erpnext/manufacturing/doctype/production_plan/production_plan.js @@ -37,8 +37,8 @@ frappe.ui.form.on('Production Plan', { if (frm.doc.docstatus === 1 && frm.doc.po_items && frm.doc.status != 'Completed') { - frm.add_custom_button(__("Production Order"), ()=> { - frm.trigger("make_production_order"); + frm.add_custom_button(__("Work Order"), ()=> { + frm.trigger("make_work_order"); }, __("Make")); } @@ -52,9 +52,9 @@ frappe.ui.form.on('Production Plan', { frm.trigger("material_requirement"); }, - make_production_order: function(frm) { + make_work_order: function(frm) { frappe.call({ - method: "make_production_order", + method: "make_work_order", freeze: true, doc: frm.doc, callback: function() { diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.json b/erpnext/manufacturing/doctype/production_plan/production_plan.json index 06301d70ad9..f982c54876e 100644 --- a/erpnext/manufacturing/doctype/production_plan/production_plan.json +++ b/erpnext/manufacturing/doctype/production_plan/production_plan.json @@ -44,6 +44,7 @@ "reqd": 1, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -76,6 +77,7 @@ "reqd": 1, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -108,6 +110,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -137,6 +140,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -168,6 +172,7 @@ "reqd": 1, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -201,6 +206,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -232,6 +238,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -264,6 +271,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -296,6 +304,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -328,6 +337,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -357,6 +367,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0, "width": "50%" }, @@ -388,6 +399,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -418,6 +430,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -451,6 +464,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -483,6 +497,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -514,6 +529,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -546,6 +562,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -578,6 +595,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -609,6 +627,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -640,6 +659,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -658,7 +678,7 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Get Items For Production Order", + "label": "Get Items For Work Order", "length": 0, "no_copy": 0, "options": "", @@ -672,6 +692,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -703,6 +724,7 @@ "reqd": 1, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -734,6 +756,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -765,6 +788,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -795,6 +819,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -824,6 +849,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -855,6 +881,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -885,6 +912,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -915,6 +943,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -946,6 +975,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -976,6 +1006,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -1007,6 +1038,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -1038,6 +1070,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -1067,6 +1100,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -1099,6 +1133,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -1129,6 +1164,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 } ], @@ -1143,7 +1179,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-02-15 13:18:59.092921", + "modified": "2018-03-05 01:36:45.048493", "modified_by": "Administrator", "module": "Manufacturing", "name": "Production Plan", diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py index 2a767ccd50d..1d3104238a4 100644 --- a/erpnext/manufacturing/doctype/production_plan/production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py @@ -8,7 +8,7 @@ from frappe import msgprint, _ from frappe.model.document import Document from erpnext.manufacturing.doctype.bom.bom import validate_bom_no from frappe.utils import cstr, flt, cint, nowdate, add_days, comma_and, now_datetime -from erpnext.manufacturing.doctype.production_order.production_order import get_item_details +from erpnext.manufacturing.doctype.work_order.work_order import get_item_details from six import string_types class ProductionPlan(Document): @@ -229,12 +229,12 @@ class ProductionPlan(Document): def on_cancel(self): self.db_set('status', 'Cancelled') - self.delete_draft_production_order() + self.delete_draft_work_order() - def delete_draft_production_order(self): - for d in frappe.get_all('Production Order', fields = ["name"], + def delete_draft_work_order(self): + for d in frappe.get_all('Work Order', fields = ["name"], filters = {'docstatus': 0, 'production_plan': ("=", self.name)}): - frappe.delete_doc('Production Order', d.name) + frappe.delete_doc('Work Order', d.name) def set_status(self): self.status = { @@ -392,37 +392,37 @@ class ProductionPlan(Document): 'sales_order': data.sales_order }) - def make_production_order(self): - pro_list = [] + def make_work_order(self): + wo_list = [] self.validate_data() items_data = self.get_production_items() for key, item in items_data.items(): - production_order = self.create_production_order(item) - if production_order: - pro_list.append(production_order) + work_order = self.create_work_order(item) + if work_order: + wo_list.append(work_order) frappe.flags.mute_messages = False - if pro_list: - pro_list = ["""%s""" % \ - (p, p) for p in pro_list] - msgprint(_("{0} created").format(comma_and(pro_list))) + if wo_list: + wo_list = ["""%s""" % \ + (p, p) for p in wo_list] + msgprint(_("{0} created").format(comma_and(wo_list))) else : - msgprint(_("No Production Orders created")) + msgprint(_("No Work Orders created")) - def create_production_order(self, item): - from erpnext.manufacturing.doctype.production_order.production_order import OverProductionError, get_default_warehouse + def create_work_order(self, item): + from erpnext.manufacturing.doctype.work_order.work_order import OverProductionError, get_default_warehouse warehouse = get_default_warehouse() - pro = frappe.new_doc("Production Order") - pro.update(item) - pro.set_production_order_operations() + wo = frappe.new_doc("Work Order") + wo.update(item) + wo.set_work_order_operations() - if not pro.fg_warehouse: - pro.fg_warehouse = warehouse.get('fg_warehouse') + if not wo.fg_warehouse: + wo.fg_warehouse = warehouse.get('fg_warehouse') try: - pro.insert() - return pro.name + wo.insert() + return wo.name except OverProductionError: pass diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan_dashboard.py b/erpnext/manufacturing/doctype/production_plan/production_plan_dashboard.py index 5be6b2232f0..8611372dfc4 100644 --- a/erpnext/manufacturing/doctype/production_plan/production_plan_dashboard.py +++ b/erpnext/manufacturing/doctype/production_plan/production_plan_dashboard.py @@ -6,7 +6,7 @@ def get_data(): 'transactions': [ { 'label': _('Related'), - 'items': ['Production Order', 'Material Request'] + 'items': ['Work Order', 'Material Request'] }, ] } \ No newline at end of file diff --git a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py index 15fff7d491d..0a17708fbe0 100644 --- a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py @@ -41,18 +41,18 @@ class TestProductionPlan(unittest.TestCase): self.assertTrue(len(material_requests), 2) - pln.make_production_order() - production_orders = frappe.get_all('Production Order', fields = ['name'], + pln.make_work_order() + work_orders = frappe.get_all('Work Order', fields = ['name'], filters = {'production_plan': pln.name}, as_list=1) - self.assertTrue(len(production_orders), len(pln.po_items)) + self.assertTrue(len(work_orders), len(pln.po_items)) for name in material_requests: mr = frappe.get_doc('Material Request', name[0]) mr.cancel() - for name in production_orders: - mr = frappe.delete_doc('Production Order', name[0]) + for name in work_orders: + mr = frappe.delete_doc('Work Order', name[0]) pln = frappe.get_doc('Production Plan', pln.name) pln.cancel() diff --git a/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.py b/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.py index 16a30230c0f..323aaf9d626 100644 --- a/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.py +++ b/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.py @@ -9,7 +9,7 @@ from frappe import msgprint, _ from frappe.model.document import Document from erpnext.manufacturing.doctype.bom.bom import validate_bom_no -from erpnext.manufacturing.doctype.production_order.production_order import get_item_details +from erpnext.manufacturing.doctype.work_order.work_order import get_item_details class ProductionPlanningTool(Document): def clear_table(self, table_name): @@ -204,8 +204,8 @@ class ProductionPlanningTool(Document): 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_orders(self): - """It will raise production order (Draft) for all distinct FG items""" + def raise_work_orders(self): + """It will raise work order (Draft) for all distinct FG items""" self.validate_data() from erpnext.utilities.transaction_base import validate_uom_is_integer @@ -213,22 +213,22 @@ class ProductionPlanningTool(Document): items = self.get_production_items() - pro_list = [] + wo_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) + work_order = self.create_work_order(items[key]) + if work_order: + wo_list.append(work_order) frappe.flags.mute_messages = False - if pro_list: - pro_list = ["""%s""" % \ - (p, p) for p in pro_list] - msgprint(_("{0} created").format(comma_and(pro_list))) + if wo_list: + wo_list = ["""%s""" % \ + (p, p) for p in wo_list] + msgprint(_("{0} created").format(comma_and(wo_list))) else : - msgprint(_("No Production Orders created")) + msgprint(_("No Work Orders created")) def get_production_items(self): item_dict = {} @@ -264,21 +264,21 @@ class ProductionPlanningTool(Document): 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 + def create_work_order(self, item_dict): + """Create work order. Called from Production Planning Tool""" + from erpnext.manufacturing.doctype.work_order.work_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() + wo = frappe.new_doc("Work Order") + wo.update(item_dict) + wo.set_work_order_operations() if warehouse: - pro.wip_warehouse = warehouse.get('wip_warehouse') - if not pro.fg_warehouse: - pro.fg_warehouse = warehouse.get('fg_warehouse') + wo.wip_warehouse = warehouse.get('wip_warehouse') + if not wo.fg_warehouse: + wo.fg_warehouse = warehouse.get('fg_warehouse') try: - pro.insert() - return pro.name + wo.insert() + return wo.name except OverProductionError: pass diff --git a/erpnext/manufacturing/doctype/production_order/.py b/erpnext/manufacturing/doctype/work_order/.py similarity index 100% rename from erpnext/manufacturing/doctype/production_order/.py rename to erpnext/manufacturing/doctype/work_order/.py diff --git a/erpnext/manufacturing/doctype/production_order/README.md b/erpnext/manufacturing/doctype/work_order/README.md similarity index 100% rename from erpnext/manufacturing/doctype/production_order/README.md rename to erpnext/manufacturing/doctype/work_order/README.md diff --git a/erpnext/manufacturing/doctype/production_order/__init__.py b/erpnext/manufacturing/doctype/work_order/__init__.py similarity index 100% rename from erpnext/manufacturing/doctype/production_order/__init__.py rename to erpnext/manufacturing/doctype/work_order/__init__.py diff --git a/erpnext/manufacturing/doctype/production_order/test_records.json b/erpnext/manufacturing/doctype/work_order/test_records.json similarity index 87% rename from erpnext/manufacturing/doctype/production_order/test_records.json rename to erpnext/manufacturing/doctype/work_order/test_records.json index 81141037acc..e7c7039ed43 100644 --- a/erpnext/manufacturing/doctype/production_order/test_records.json +++ b/erpnext/manufacturing/doctype/work_order/test_records.json @@ -2,11 +2,11 @@ { "bom_no": "BOM-_Test FG Item-001", "company": "_Test Company", - "doctype": "Production Order", + "doctype": "Work Order", "fg_warehouse": "_Test Warehouse 1 - _TC", "production_item": "_Test FG Item", "qty": 10.0, "stock_uom": "_Test UOM", "wip_warehouse": "_Test Warehouse - _TC" } -] +] \ No newline at end of file diff --git a/erpnext/manufacturing/doctype/production_order/test_production_order.js b/erpnext/manufacturing/doctype/work_order/test_work_order.js similarity index 84% rename from erpnext/manufacturing/doctype/production_order/test_production_order.js rename to erpnext/manufacturing/doctype/work_order/test_work_order.js index 3a2e5cea85f..1e224eb468c 100644 --- a/erpnext/manufacturing/doctype/production_order/test_production_order.js +++ b/erpnext/manufacturing/doctype/work_order/test_work_order.js @@ -1,4 +1,4 @@ -QUnit.test("test: production order", function (assert) { +QUnit.test("test: work order", function (assert) { assert.expect(25); let done = assert.async(); let laptop_quantity = 5; @@ -14,13 +14,13 @@ QUnit.test("test: production order", function (assert) { }; frappe.run_serially([ - // test production order - () => frappe.set_route("List", "Production Order", "List"), + // test work order + () => frappe.set_route("List", "Work Order", "List"), () => frappe.timeout(3), - // Create a laptop production order + // Create a laptop work order () => { - return frappe.tests.make('Production Order', [ + return frappe.tests.make('Work Order', [ {production_item: 'Laptop'}, {company: 'For Testing'}, {qty: laptop_quantity}, @@ -50,13 +50,13 @@ QUnit.test("test: production order", function (assert) { }); }, - // Submit the production order + // Submit the work order () => cur_frm.savesubmit(), () => frappe.timeout(1), () => frappe.click_button('Yes'), () => frappe.timeout(2.5), - // Confirm the production order timesheet, save and submit it + // Confirm the work order timesheet, save and submit it () => frappe.click_link("TS-00"), () => frappe.timeout(1), () => frappe.click_button("Submit"), @@ -64,8 +64,8 @@ QUnit.test("test: production order", function (assert) { () => frappe.click_button("Yes"), () => frappe.timeout(2.5), - // Start the production order process - () => frappe.set_route("List", "Production Order", "List"), + // Start the work order process + () => frappe.set_route("List", "Work Order", "List"), () => frappe.timeout(2), () => frappe.click_link("Laptop"), () => frappe.timeout(1), @@ -82,20 +82,20 @@ QUnit.test("test: production order", function (assert) { assert.equal(cur_frm.doc.total_outgoing_value, "99000", "Outgoing cost is correct"); // Price of each item x5 }, - // Submit for production + // Submit for work () => frappe.click_button("Submit"), () => frappe.timeout(0.5), () => frappe.click_button("Yes"), () => frappe.timeout(0.5), - // Finish the production order by sending for manufacturing - () => frappe.set_route("List", "Production Order"), + // Finish the work order by sending for manufacturing + () => frappe.set_route("List", "Work Order"), () => frappe.timeout(1), () => frappe.click_link("Laptop"), () => frappe.timeout(1), () => { - assert.ok(frappe.tests.is_visible("5 items in progress", 'p'), "Production order initiated"); + assert.ok(frappe.tests.is_visible("5 items in progress", 'p'), "Work order initiated"); assert.ok(frappe.tests.is_visible("Finish"), "Finish button visible"); }, @@ -118,12 +118,12 @@ QUnit.test("test: production order", function (assert) { () => frappe.timeout(1), // Manufacturing finished - () => frappe.set_route("List", "Production Order", "List"), + () => frappe.set_route("List", "Work Order", "List"), () => frappe.timeout(1), () => frappe.click_link("Laptop"), () => frappe.timeout(1), - () => assert.ok(frappe.tests.is_visible("5 items produced", 'p'), "Production order completed"), + () => assert.ok(frappe.tests.is_visible("5 items produced", 'p'), "Work order completed"), () => done() ]); diff --git a/erpnext/manufacturing/doctype/production_order/test_production_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py similarity index 62% rename from erpnext/manufacturing/doctype/production_order/test_production_order.py rename to erpnext/manufacturing/doctype/work_order/test_work_order.py index 76124615357..6b43c637997 100644 --- a/erpnext/manufacturing/doctype/production_order/test_production_order.py +++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py @@ -7,13 +7,13 @@ import unittest import frappe from frappe.utils import flt, time_diff_in_hours, now, add_days, cint from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory -from erpnext.manufacturing.doctype.production_order.production_order \ +from erpnext.manufacturing.doctype.work_order.work_order \ import make_stock_entry, ItemHasVariantError, stop_unstop from erpnext.stock.doctype.stock_entry import test_stock_entry from erpnext.stock.utils import get_bin from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order -class TestProductionOrder(unittest.TestCase): +class TestWorkOrder(unittest.TestCase): def setUp(self): self.warehouse = '_Test Warehouse 2 - _TC' self.item = '_Test Item' @@ -24,7 +24,7 @@ class TestProductionOrder(unittest.TestCase): planned0 = frappe.db.get_value("Bin", {"item_code": "_Test FG Item", "warehouse": "_Test Warehouse 1 - _TC"}, "planned_qty") or 0 - pro_order = make_prod_order_test_record() + wo_order = make_wo_order_test_record() planned1 = frappe.db.get_value("Bin", {"item_code": "_Test FG Item", "warehouse": "_Test Warehouse 1 - _TC"}, "planned_qty") @@ -38,60 +38,59 @@ class TestProductionOrder(unittest.TestCase): target="Stores - _TC", qty=100, basic_rate=100) # from stores to wip - s = frappe.get_doc(make_stock_entry(pro_order.name, "Material Transfer for Manufacture", 4)) + s = frappe.get_doc(make_stock_entry(wo_order.name, "Material Transfer for Manufacture", 4)) for d in s.get("items"): d.s_warehouse = "Stores - _TC" s.insert() s.submit() # from wip to fg - s = frappe.get_doc(make_stock_entry(pro_order.name, "Manufacture", 4)) + s = frappe.get_doc(make_stock_entry(wo_order.name, "Manufacture", 4)) s.insert() s.submit() - self.assertEqual(frappe.db.get_value("Production Order", pro_order.name, "produced_qty"), 4) + self.assertEqual(frappe.db.get_value("Work Order", wo_order.name, "produced_qty"), 4) planned2 = frappe.db.get_value("Bin", {"item_code": "_Test FG Item", "warehouse": "_Test Warehouse 1 - _TC"}, "planned_qty") self.assertEqual(planned2, planned0 + 6) - return pro_order + return wo_order def test_over_production(self): - from erpnext.manufacturing.doctype.production_order.production_order import StockOverProductionError - pro_doc = self.check_planned_qty() + from erpnext.manufacturing.doctype.work_order.work_order import StockOverProductionError + wo_doc = self.check_planned_qty() test_stock_entry.make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=100, basic_rate=100) test_stock_entry.make_stock_entry(item_code="_Test Item Home Desktop 100", target="_Test Warehouse - _TC", qty=100, basic_rate=100) - s = frappe.get_doc(make_stock_entry(pro_doc.name, "Manufacture", 7)) + s = frappe.get_doc(make_stock_entry(wo_doc.name, "Manufacture", 7)) s.insert() self.assertRaises(StockOverProductionError, s.submit) def test_make_time_sheet(self): - from erpnext.manufacturing.doctype.production_order.production_order import make_timesheet - prod_order = make_prod_order_test_record(item="_Test FG Item 2", + from erpnext.manufacturing.doctype.work_order.work_order import make_timesheet + wo_order = make_wo_order_test_record(item="_Test FG Item 2", planned_start_date=now(), qty=1, do_not_save=True) - prod_order.set_production_order_operations() - prod_order.insert() - prod_order.submit() + wo_order.set_work_order_operations() + wo_order.insert() + wo_order.submit() - d = prod_order.operations[0] + d = wo_order.operations[0] d.completed_qty = flt(d.completed_qty) - name = frappe.db.get_value('Timesheet', {'production_order': prod_order.name}, 'name') + name = frappe.db.get_value('Timesheet', {'work_order': wo_order.name}, 'name') time_sheet_doc = frappe.get_doc('Timesheet', name) - self.assertEqual(prod_order.company, time_sheet_doc.company) + self.assertEqual(wo_order.company, time_sheet_doc.company) time_sheet_doc.submit() - - self.assertEqual(prod_order.name, time_sheet_doc.production_order) - self.assertEqual((prod_order.qty - d.completed_qty), + self.assertEqual(wo_order.name, time_sheet_doc.work_order) + self.assertEqual((wo_order.qty - d.completed_qty), sum([d.completed_qty for d in time_sheet_doc.time_logs])) manufacturing_settings = frappe.get_doc({ @@ -101,49 +100,49 @@ class TestProductionOrder(unittest.TestCase): manufacturing_settings.save() - prod_order.load_from_db() - self.assertEqual(prod_order.operations[0].status, "Completed") - self.assertEqual(prod_order.operations[0].completed_qty, prod_order.qty) + wo_order.load_from_db() + self.assertEqual(wo_order.operations[0].status, "Completed") + self.assertEqual(wo_order.operations[0].completed_qty, wo_order.qty) - self.assertEqual(prod_order.operations[0].actual_operation_time, 60) - self.assertEqual(prod_order.operations[0].actual_operating_cost, 6000) + self.assertEqual(wo_order.operations[0].actual_operation_time, 60) + self.assertEqual(wo_order.operations[0].actual_operating_cost, 6000) - time_sheet_doc1 = make_timesheet(prod_order.name, prod_order.company) + time_sheet_doc1 = make_timesheet(wo_order.name, wo_order.company) self.assertEqual(len(time_sheet_doc1.get('time_logs')), 0) time_sheet_doc.cancel() - prod_order.load_from_db() - self.assertEqual(prod_order.operations[0].status, "Pending") - self.assertEqual(flt(prod_order.operations[0].completed_qty), 0) + wo_order.load_from_db() + self.assertEqual(wo_order.operations[0].status, "Pending") + self.assertEqual(flt(wo_order.operations[0].completed_qty), 0) - self.assertEqual(flt(prod_order.operations[0].actual_operation_time), 0) - self.assertEqual(flt(prod_order.operations[0].actual_operating_cost), 0) + self.assertEqual(flt(wo_order.operations[0].actual_operation_time), 0) + self.assertEqual(flt(wo_order.operations[0].actual_operating_cost), 0) def test_planned_operating_cost(self): - prod_order = make_prod_order_test_record(item="_Test FG Item 2", + wo_order = make_wo_order_test_record(item="_Test FG Item 2", planned_start_date=now(), qty=1, do_not_save=True) - prod_order.set_production_order_operations() - cost = prod_order.planned_operating_cost - prod_order.qty = 2 - prod_order.set_production_order_operations() - self.assertEqual(prod_order.planned_operating_cost, cost*2) + wo_order.set_work_order_operations() + cost = wo_order.planned_operating_cost + wo_order.qty = 2 + wo_order.set_work_order_operations() + self.assertEqual(wo_order.planned_operating_cost, cost*2) def test_production_item(self): - prod_order = make_prod_order_test_record(item="_Test FG Item", qty=1, do_not_save=True) + wo_order = make_wo_order_test_record(item="_Test FG Item", qty=1, do_not_save=True) frappe.db.set_value("Item", "_Test FG Item", "end_of_life", "2000-1-1") - self.assertRaises(frappe.ValidationError, prod_order.save) + self.assertRaises(frappe.ValidationError, wo_order.save) frappe.db.set_value("Item", "_Test FG Item", "end_of_life", None) frappe.db.set_value("Item", "_Test FG Item", "disabled", 1) - self.assertRaises(frappe.ValidationError, prod_order.save) + self.assertRaises(frappe.ValidationError, wo_order.save) frappe.db.set_value("Item", "_Test FG Item", "disabled", 0) - prod_order = make_prod_order_test_record(item="_Test Variant Item", qty=1, do_not_save=True) - self.assertRaises(ItemHasVariantError, prod_order.save) + wo_order = make_wo_order_test_record(item="_Test Variant Item", qty=1, do_not_save=True) + self.assertRaises(ItemHasVariantError, wo_order.save) def test_reserved_qty_for_production_submit(self): self.bin1_at_start = get_bin(self.item, self.warehouse) @@ -151,7 +150,7 @@ class TestProductionOrder(unittest.TestCase): # reset to correct value self.bin1_at_start.update_reserved_qty_for_production() - self.pro_order = make_prod_order_test_record(item="_Test FG Item", qty=2, + self.wo_order = make_wo_order_test_record(item="_Test FG Item", qty=2, source_warehouse=self.warehouse) self.bin1_on_submit = get_bin(self.item, self.warehouse) @@ -165,7 +164,7 @@ class TestProductionOrder(unittest.TestCase): def test_reserved_qty_for_production_cancel(self): self.test_reserved_qty_for_production_submit() - self.pro_order.cancel() + self.wo_order.cancel() bin1_on_cancel = get_bin(self.item, self.warehouse) @@ -183,7 +182,7 @@ class TestProductionOrder(unittest.TestCase): self.test_reserved_qty_for_production_submit() - s = frappe.get_doc(make_stock_entry(self.pro_order.name, + s = frappe.get_doc(make_stock_entry(self.wo_order.name, "Material Transfer for Manufacture", 2)) s.submit() @@ -198,7 +197,7 @@ class TestProductionOrder(unittest.TestCase): self.assertEqual(cint(self.bin1_at_start.projected_qty), cint(bin1_on_start_production.projected_qty) + 2) - s = frappe.get_doc(make_stock_entry(self.pro_order.name, "Manufacture", 2)) + s = frappe.get_doc(make_stock_entry(self.wo_order.name, "Manufacture", 2)) bin1_on_end_production = get_bin(self.item, self.warehouse) @@ -220,7 +219,7 @@ class TestProductionOrder(unittest.TestCase): #2 0 -2 - s = frappe.get_doc(make_stock_entry(self.pro_order.name, + s = frappe.get_doc(make_stock_entry(self.wo_order.name, "Material Transfer for Manufacture", 1)) s.submit() @@ -238,7 +237,7 @@ class TestProductionOrder(unittest.TestCase): cint(bin1_on_start_production.projected_qty) + 2) # STOP - stop_unstop(self.pro_order.name, "Stopped") + stop_unstop(self.wo_order.name, "Stopped") bin1_on_stop_production = get_bin(self.item, self.warehouse) @@ -249,7 +248,7 @@ class TestProductionOrder(unittest.TestCase): cint(self.bin1_at_start.projected_qty)) def test_scrap_material_qty(self): - prod_order = make_prod_order_test_record(planned_start_date=now(), qty=2) + wo_order = make_wo_order_test_record(planned_start_date=now(), qty=2) # add raw materials to stores test_stock_entry.make_stock_entry(item_code="_Test Item", @@ -257,27 +256,27 @@ class TestProductionOrder(unittest.TestCase): test_stock_entry.make_stock_entry(item_code="_Test Item Home Desktop 100", target="Stores - _TC", qty=10, basic_rate=1000.0) - s = frappe.get_doc(make_stock_entry(prod_order.name, "Material Transfer for Manufacture", 2)) + s = frappe.get_doc(make_stock_entry(wo_order.name, "Material Transfer for Manufacture", 2)) for d in s.get("items"): d.s_warehouse = "Stores - _TC" s.insert() s.submit() - s = frappe.get_doc(make_stock_entry(prod_order.name, "Manufacture", 2)) + s = frappe.get_doc(make_stock_entry(wo_order.name, "Manufacture", 2)) s.insert() s.submit() - prod_order_details = frappe.db.get_value("Production Order", prod_order.name, + wo_order_details = frappe.db.get_value("Work Order", wo_order.name, ["scrap_warehouse", "qty", "produced_qty", "bom_no"], as_dict=1) - scrap_item_details = get_scrap_item_details(prod_order_details.bom_no) + scrap_item_details = get_scrap_item_details(wo_order_details.bom_no) - self.assertEqual(prod_order_details.produced_qty, 2) + self.assertEqual(wo_order_details.produced_qty, 2) for item in s.items: if item.bom_no and item.item_code in scrap_item_details: - self.assertEqual(prod_order_details.scrap_warehouse, item.t_warehouse) - self.assertEqual(flt(prod_order_details.qty)*flt(scrap_item_details[item.item_code]), item.qty) + self.assertEqual(wo_order_details.scrap_warehouse, item.t_warehouse) + self.assertEqual(flt(wo_order_details.qty)*flt(scrap_item_details[item.item_code]), item.qty) def get_scrap_item_details(bom_no): scrap_items = {} @@ -287,34 +286,34 @@ def get_scrap_item_details(bom_no): return scrap_items -def make_prod_order_test_record(**args): +def make_wo_order_test_record(**args): args = frappe._dict(args) - pro_order = frappe.new_doc("Production Order") - pro_order.production_item = args.production_item or args.item or args.item_code or "_Test FG Item" - pro_order.bom_no = frappe.db.get_value("BOM", {"item": pro_order.production_item, + wo_order = frappe.new_doc("Work Order") + wo_order.production_item = args.production_item or args.item or args.item_code or "_Test FG Item" + wo_order.bom_no = frappe.db.get_value("BOM", {"item": wo_order.production_item, "is_active": 1, "is_default": 1}) - pro_order.qty = args.qty or 10 - pro_order.wip_warehouse = args.wip_warehouse or "_Test Warehouse - _TC" - pro_order.fg_warehouse = args.fg_warehouse or "_Test Warehouse 1 - _TC" - pro_order.scrap_warehouse = args.fg_warehouse or "_Test Scrap Warehouse - _TC" - pro_order.company = args.company or "_Test Company" - pro_order.stock_uom = args.stock_uom or "_Test UOM" - pro_order.use_multi_level_bom=0 - pro_order.get_items_and_operations_from_bom() + wo_order.qty = args.qty or 10 + wo_order.wip_warehouse = args.wip_warehouse or "_Test Warehouse - _TC" + wo_order.fg_warehouse = args.fg_warehouse or "_Test Warehouse 1 - _TC" + wo_order.scrap_warehouse = args.fg_warehouse or "_Test Scrap Warehouse - _TC" + wo_order.company = args.company or "_Test Company" + wo_order.stock_uom = args.stock_uom or "_Test UOM" + wo_order.use_multi_level_bom=0 + wo_order.get_items_and_operations_from_bom() if args.source_warehouse: - for item in pro_order.get("required_items"): + for item in wo_order.get("required_items"): item.source_warehouse = args.source_warehouse if args.planned_start_date: - pro_order.planned_start_date = args.planned_start_date + wo_order.planned_start_date = args.planned_start_date if not args.do_not_save: - pro_order.insert() + wo_order.insert() if not args.do_not_submit: - pro_order.submit() - return pro_order + wo_order.submit() + return wo_order -test_records = frappe.get_test_records('Production Order') +test_records = frappe.get_test_records('Work Order') diff --git a/erpnext/manufacturing/doctype/production_order/production_order.js b/erpnext/manufacturing/doctype/work_order/work_order.js similarity index 79% rename from erpnext/manufacturing/doctype/production_order/production_order.js rename to erpnext/manufacturing/doctype/work_order/work_order.js index bba3e1ed6d5..7d50416d20b 100644 --- a/erpnext/manufacturing/doctype/production_order/production_order.js +++ b/erpnext/manufacturing/doctype/work_order/work_order.js @@ -1,7 +1,7 @@ -// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -// License: GNU General Public License v3. See license.txt +// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt -frappe.ui.form.on("Production Order", { +frappe.ui.form.on("Work Order", { setup: function(frm) { frm.custom_make_buttons = { 'Timesheet': 'Make Timesheet', @@ -80,7 +80,7 @@ frappe.ui.form.on("Production Order", { } }); - // formatter for production order operation + // formatter for work order operation frm.set_indicator_formatter('operation', function(doc) { return (frm.doc.qty==doc.completed_qty) ? "green" : "orange" }); }, @@ -96,17 +96,17 @@ frappe.ui.form.on("Production Order", { "actual_start_date": "", "actual_end_date": "" }); - erpnext.production_order.set_default_warehouse(frm); + erpnext.work_order.set_default_warehouse(frm); } }, refresh: function(frm) { erpnext.toggle_naming_series(); - erpnext.production_order.set_custom_buttons(frm); + erpnext.work_order.set_custom_buttons(frm); frm.set_intro(""); if (frm.doc.docstatus === 0 && !frm.doc.__islocal) { - frm.set_intro(__("Submit this Production Order for further processing.")); + frm.set_intro(__("Submit this Work Order for further processing.")); } if (frm.doc.docstatus===1) { @@ -116,7 +116,7 @@ frappe.ui.form.on("Production Order", { if(frm.doc.docstatus == 1 && frm.doc.status != 'Stopped'){ frm.add_custom_button(__('Make Timesheet'), function(){ frappe.model.open_mapped_doc({ - method: "erpnext.manufacturing.doctype.production_order.production_order.make_new_timesheet", + method: "erpnext.manufacturing.doctype.work_order.work_order.make_new_timesheet", frm: cur_frm }) }) @@ -160,7 +160,7 @@ frappe.ui.form.on("Production Order", { production_item: function(frm) { if (frm.doc.production_item) { frappe.call({ - method: "erpnext.manufacturing.doctype.production_order.production_order.get_item_details", + method: "erpnext.manufacturing.doctype.work_order.work_order.get_item_details", args: { item: frm.doc.production_item, project: frm.doc.project @@ -222,7 +222,7 @@ frappe.ui.form.on("Production Order", { set_sales_order: function(frm) { if(frm.doc.production_item) { frappe.call({ - method: "erpnext.manufacturing.doctype.production_order.production_order.query_sales_order", + method: "erpnext.manufacturing.doctype.work_order.work_order.query_sales_order", args: { production_item: frm.doc.production_item }, callback: function(r) { frm.set_query("sales_order", function() { @@ -239,7 +239,7 @@ frappe.ui.form.on("Production Order", { } }); -frappe.ui.form.on("Production Order Item", { +frappe.ui.form.on("Work Order Item", { source_warehouse: function(frm, cdt, cdn) { var row = locals[cdt][cdn]; if(!row.item_code) { @@ -260,7 +260,7 @@ frappe.ui.form.on("Production Order Item", { } }) -frappe.ui.form.on("Production Order Operation", { +frappe.ui.form.on("Work Order Operation", { workstation: function(frm, cdt, cdn) { var d = locals[cdt][cdn]; if (d.workstation) { @@ -272,29 +272,29 @@ frappe.ui.form.on("Production Order Operation", { }, callback: function (data) { frappe.model.set_value(d.doctype, d.name, "hour_rate", data.message.hour_rate); - erpnext.production_order.calculate_cost(frm.doc); - erpnext.production_order.calculate_total_cost(frm); + erpnext.work_order.calculate_cost(frm.doc); + erpnext.work_order.calculate_total_cost(frm); } }) } }, time_in_mins: function(frm, cdt, cdn) { - erpnext.production_order.calculate_cost(frm.doc); - erpnext.production_order.calculate_total_cost(frm); + erpnext.work_order.calculate_cost(frm.doc); + erpnext.work_order.calculate_total_cost(frm); }, }); -erpnext.production_order = { +erpnext.work_order = { set_custom_buttons: function(frm) { var doc = frm.doc; if (doc.docstatus === 1) { if (doc.status != 'Stopped' && doc.status != 'Completed') { frm.add_custom_button(__('Stop'), function() { - erpnext.production_order.stop_production_order(frm, "Stopped"); + erpnext.wokr_order.stop_work_order(frm, "Stopped"); }, __("Status")); } else if (doc.status == 'Stopped') { frm.add_custom_button(__('Re-open'), function() { - erpnext.production_order.stop_production_order(frm, "Resumed"); + erpnext.work_order.stop_work_order(frm, "Resumed"); }, __("Status")); } @@ -303,7 +303,7 @@ erpnext.production_order = { && frm.doc.status != 'Stopped') { frm.has_start_btn = true; var start_btn = frm.add_custom_button(__('Start'), function() { - erpnext.production_order.make_se(frm, 'Material Transfer for Manufacture'); + erpnext.work_order.make_se(frm, 'Material Transfer for Manufacture'); }); start_btn.addClass('btn-primary'); } @@ -314,7 +314,7 @@ erpnext.production_order = { && frm.doc.status != 'Stopped') { frm.has_finish_btn = true; var finish_btn = frm.add_custom_button(__('Finish'), function() { - erpnext.production_order.make_se(frm, 'Manufacture'); + erpnext.work_order.make_se(frm, 'Manufacture'); }); if(doc.material_transferred_for_manufacturing==doc.qty) { @@ -326,7 +326,7 @@ erpnext.production_order = { if ((flt(doc.produced_qty) < flt(doc.qty)) && frm.doc.status != 'Stopped') { frm.has_finish_btn = true; var finish_btn = frm.add_custom_button(__('Finish'), function() { - erpnext.production_order.make_se(frm, 'Manufacture'); + erpnext.work_order.make_se(frm, 'Manufacture'); }); finish_btn.addClass('btn-primary'); } @@ -340,7 +340,7 @@ erpnext.production_order = { doc.planned_operating_cost = 0.0; for(var i=0;i max) { - frappe.msgprint(__("Quantity must not be more than {0}", [max])); - return; + description: __("Max: {0}", [max]), 'default': max }, function(data) + { + if(data.qty > max) { + frappe.msgprint(__("Quantity must not be more than {0}", [max])); + return; + } + frappe.call({ + method:"erpnext.manufacturing.doctype.work_order.work_order.make_stock_entry", + args: { + "work_order_id": frm.doc.name, + "purpose": purpose, + "qty": data.qty + }, + callback: function(r) { + var doclist = frappe.model.sync(r.message); + frappe.set_route("Form", doclist[0].doctype, doclist[0].name); } - frappe.call({ - method:"erpnext.manufacturing.doctype.production_order.production_order.make_stock_entry", - args: { - "production_order_id": frm.doc.name, - "purpose": purpose, - "qty": data.qty - }, - callback: function(r) { - var doclist = frappe.model.sync(r.message); - frappe.set_route("Form", doclist[0].doctype, doclist[0].name); - } - }); - }, __("Select Quantity"), __("Make")); + }); + }, __("Select Quantity"), __("Make")); }, - stop_production_order: function(frm, status) { + stop_work_order: function(frm, status) { frappe.call({ - method: "erpnext.manufacturing.doctype.production_order.production_order.stop_unstop", + method: "erpnext.manufacturing.doctype.work_order.work_order.stop_unstop", args: { - production_order: frm.doc.name, + work_order: frm.doc.name, status: status }, callback: function(r) { diff --git a/erpnext/manufacturing/doctype/production_order/production_order.json b/erpnext/manufacturing/doctype/work_order/work_order.json similarity index 99% rename from erpnext/manufacturing/doctype/production_order/production_order.json rename to erpnext/manufacturing/doctype/work_order/work_order.json index 4399d32c883..6f6c4e42fb3 100644 --- a/erpnext/manufacturing/doctype/production_order/production_order.json +++ b/erpnext/manufacturing/doctype/work_order/work_order.json @@ -48,7 +48,7 @@ "bold": 0, "collapsible": 0, "columns": 0, - "default": "PRO-", + "default": "WO-", "fieldname": "naming_series", "fieldtype": "Select", "hidden": 0, @@ -61,7 +61,7 @@ "label": "Series", "length": 0, "no_copy": 0, - "options": "PRO-", + "options": "WO-", "permlevel": 0, "print_hide": 1, "print_hide_if_no_value": 0, @@ -626,7 +626,7 @@ "label": "Required Items", "length": 0, "no_copy": 1, - "options": "Production Order Item", + "options": "Work Order Item", "permlevel": 0, "precision": "", "print_hide": 1, @@ -901,7 +901,7 @@ "label": "Operations", "length": 0, "no_copy": 0, - "options": "Production Order Operation", + "options": "Work Order Operation", "permlevel": 0, "precision": "", "print_hide": 0, @@ -1425,7 +1425,7 @@ "no_copy": 1, "oldfieldname": "amended_from", "oldfieldtype": "Data", - "options": "Production Order", + "options": "Work Order", "permlevel": 0, "print_hide": 0, "print_hide_if_no_value": 0, @@ -1449,10 +1449,10 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2017-12-20 05:31:56.636724", + "modified": "2018-02-13 02:58:11.328693", "modified_by": "Administrator", "module": "Manufacturing", - "name": "Production Order", + "name": "Work Order", "owner": "Administrator", "permissions": [ { diff --git a/erpnext/manufacturing/doctype/production_order/production_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py similarity index 88% rename from erpnext/manufacturing/doctype/production_order/production_order.py rename to erpnext/manufacturing/doctype/work_order/work_order.py index c41260fa762..6c632a5a032 100644 --- a/erpnext/manufacturing/doctype/production_order/production_order.py +++ b/erpnext/manufacturing/doctype/work_order/work_order.py @@ -25,10 +25,10 @@ class OperationTooLongError(frappe.ValidationError): pass class ItemHasVariantError(frappe.ValidationError): pass form_grid_templates = { - "operations": "templates/form_grid/production_order_grid.html" + "operations": "templates/form_grid/work_order_grid.html" } -class ProductionOrder(Document): +class WorkOrder(Document): def validate(self): self.validate_production_item() if self.bom_no: @@ -79,7 +79,7 @@ class ProductionOrder(Document): self.project = so[0].project if not self.material_request: - self.validate_production_order_against_so() + self.validate_work_order_against_so() else: frappe.throw(_("Sales Order {0} is not valid").format(self.sales_order)) @@ -111,9 +111,9 @@ class ProductionOrder(Document): else self.planned_operating_cost self.total_operating_cost = flt(self.additional_operating_cost) + flt(variable_cost) - def validate_production_order_against_so(self): + def validate_work_order_against_so(self): # already ordered qty - ordered_qty_against_so = frappe.db.sql("""select sum(qty) from `tabProduction Order` + ordered_qty_against_so = frappe.db.sql("""select sum(qty) from `tabWork Order` where production_item = %s and sales_order = %s and docstatus < 2 and name != %s""", (self.production_item, self.sales_order, self.name))[0][0] @@ -138,7 +138,7 @@ class ProductionOrder(Document): .format(self.production_item, so_qty), OverProductionError) def update_status(self, status=None): - '''Update status of production order if unknown''' + '''Update status of work order if unknown''' if status != "Stopped": status = self.get_status(status) @@ -150,7 +150,7 @@ class ProductionOrder(Document): return status def get_status(self, status=None): - '''Return the status based on stock entries against this production order''' + '''Return the status based on stock entries against this work order''' if not status: status = self.status @@ -159,7 +159,7 @@ class ProductionOrder(Document): elif self.docstatus==1: if status != 'Stopped': stock_entries = frappe._dict(frappe.db.sql("""select purpose, sum(fg_completed_qty) - from `tabStock Entry` where production_order=%s and docstatus=1 + from `tabStock Entry` where work_order=%s and docstatus=1 group by purpose""", self.name)) status = "Not Started" @@ -173,18 +173,18 @@ class ProductionOrder(Document): return status - def update_production_order_qty(self): - """Update **Manufactured Qty** and **Material Transferred for Qty** in Production Order + def update_work_order_qty(self): + """Update **Manufactured Qty** and **Material Transferred for Qty** in Work Order based on Stock Entry""" for purpose, fieldname in (("Manufacture", "produced_qty"), ("Material Transfer for Manufacture", "material_transferred_for_manufacturing")): qty = flt(frappe.db.sql("""select sum(fg_completed_qty) - from `tabStock Entry` where production_order=%s and docstatus=1 + from `tabStock Entry` where work_order=%s and docstatus=1 and purpose=%s""", (self.name, purpose))[0][0]) if qty > self.qty: - frappe.throw(_("{0} ({1}) cannot be greater than planned quanitity ({2}) in Production Order {3}").format(\ + frappe.throw(_("{0} ({1}) cannot be greater than planned quanitity ({2}) in Work Order {3}").format(\ self.meta.get_label(fieldname), qty, self.qty, self.name), StockOverProductionError) self.db_set(fieldname, qty) @@ -222,11 +222,11 @@ class ProductionOrder(Document): def validate_cancel(self): if self.status == "Stopped": - frappe.throw(_("Stopped Production Order cannot be cancelled, Unstop it first to cancel")) + frappe.throw(_("Stopped Work Order cannot be cancelled, Unstop it first to cancel")) - # Check whether any stock entry exists against this Production Order + # Check whether any stock entry exists against this Work Order stock_entry = frappe.db.sql("""select name from `tabStock Entry` - where production_order = %s and docstatus = 1""", self.name) + where work_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])) @@ -253,8 +253,8 @@ class ProductionOrder(Document): if self.material_request: frappe.get_doc("Material Request", self.material_request).update_completed_qty([self.material_request_item]) - def set_production_order_operations(self): - """Fetch operations from BOM and set in 'Production Order'""" + def set_work_order_operations(self): + """Fetch operations from BOM and set in 'Work Order'""" self.set('operations', []) if not self.bom_no \ @@ -330,10 +330,10 @@ class ProductionOrder(Document): timesheet.validate_time_logs() except OverlapError: if frappe.message_log: frappe.message_log.pop() - timesheet.schedule_for_production_order(d.idx) + timesheet.schedule_for_work_order(d.idx) except WorkstationHolidayError: if frappe.message_log: frappe.message_log.pop() - timesheet.schedule_for_production_order(d.idx) + timesheet.schedule_for_work_order(d.idx) from_time, to_time = self.get_start_end_time(timesheet, d.name) @@ -418,12 +418,12 @@ class ProductionOrder(Document): self.actual_end_date = max(actual_end_dates) def delete_timesheet(self): - for timesheet in frappe.get_all("Timesheet", ["name"], {"production_order": self.name}): + for timesheet in frappe.get_all("Timesheet", ["name"], {"work_order": self.name}): frappe.delete_doc("Timesheet", timesheet.name) def validate_production_item(self): if frappe.db.get_value("Item", self.production_item, "has_variants"): - frappe.throw(_("Production Order cannot be raised against a Item Template"), ItemHasVariantError) + frappe.throw(_("Work Order cannot be raised against a Item Template"), ItemHasVariantError) if self.production_item: validate_end_of_life(self.production_item) @@ -458,7 +458,7 @@ class ProductionOrder(Document): def get_items_and_operations_from_bom(self): self.set_required_items() - self.set_production_order_operations() + self.set_work_order_operations() return check_if_scrap_warehouse_mandatory(self.bom_no) @@ -497,13 +497,13 @@ class ProductionOrder(Document): def update_transaferred_qty_for_required_items(self): '''update transferred qty from submitted stock entries for that item against - the production order''' + the work order''' for d in self.required_items: transferred_qty = frappe.db.sql('''select sum(qty) from `tabStock Entry` entry, `tabStock Entry Detail` detail where - entry.production_order = %s + entry.work_order = %s and entry.purpose = "Material Transfer for Manufacture" and entry.docstatus = 1 and detail.parent = entry.name @@ -564,50 +564,50 @@ def check_if_scrap_warehouse_mandatory(bom_no): return res @frappe.whitelist() -def set_production_order_ops(name): - po = frappe.get_doc('Production Order', name) - po.set_production_order_operations() +def set_work_order_ops(name): + po = frappe.get_doc('Work Order', name) + po.set_work_order_operations() po.save() @frappe.whitelist() -def make_stock_entry(production_order_id, purpose, qty=None): - production_order = frappe.get_doc("Production Order", production_order_id) - if not frappe.db.get_value("Warehouse", production_order.wip_warehouse, "is_group") \ - and not production_order.skip_transfer: - wip_warehouse = production_order.wip_warehouse +def make_stock_entry(work_order_id, purpose, qty=None): + work_order = frappe.get_doc("Work Order", work_order_id) + if not frappe.db.get_value("Warehouse", work_order.wip_warehouse, "is_group") \ + and not work_order.skip_transfer: + wip_warehouse = work_order.wip_warehouse else: wip_warehouse = None stock_entry = frappe.new_doc("Stock Entry") stock_entry.purpose = purpose - stock_entry.production_order = production_order_id - stock_entry.company = production_order.company + stock_entry.work_order = work_order_id + stock_entry.company = work_order.company stock_entry.from_bom = 1 - stock_entry.bom_no = production_order.bom_no - stock_entry.use_multi_level_bom = production_order.use_multi_level_bom - stock_entry.fg_completed_qty = qty or (flt(production_order.qty) - flt(production_order.produced_qty)) - if production_order.bom_no: + stock_entry.bom_no = work_order.bom_no + stock_entry.use_multi_level_bom = work_order.use_multi_level_bom + stock_entry.fg_completed_qty = qty or (flt(work_order.qty) - flt(work_order.produced_qty)) + if work_order.bom_no: stock_entry.inspection_required = frappe.db.get_value('BOM', - production_order.bom_no, 'inspection_required') + work_order.bom_no, 'inspection_required') if purpose=="Material Transfer for Manufacture": stock_entry.to_warehouse = wip_warehouse - stock_entry.project = production_order.project + stock_entry.project = work_order.project else: stock_entry.from_warehouse = wip_warehouse - stock_entry.to_warehouse = production_order.fg_warehouse - additional_costs = get_additional_costs(production_order, fg_qty=stock_entry.fg_completed_qty) - stock_entry.project = production_order.project + stock_entry.to_warehouse = work_order.fg_warehouse + additional_costs = get_additional_costs(work_order, fg_qty=stock_entry.fg_completed_qty) + stock_entry.project = work_order.project stock_entry.set("additional_costs", additional_costs) stock_entry.get_items() return stock_entry.as_dict() @frappe.whitelist() -def make_timesheet(production_order, company): +def make_timesheet(work_order, company): timesheet = frappe.new_doc("Timesheet") timesheet.employee = "" - timesheet.production_order = production_order + timesheet.work_order = work_order timesheet.company = company return timesheet @@ -632,7 +632,7 @@ def get_default_warehouse(): @frappe.whitelist() def make_new_timesheet(source_name, target_doc=None): - po = frappe.get_doc('Production Order', source_name) + po = frappe.get_doc('Work Order', source_name) ts = po.make_time_logs(open_new=True) if not ts or not ts.get('time_logs'): @@ -641,16 +641,16 @@ def make_new_timesheet(source_name, target_doc=None): return ts @frappe.whitelist() -def stop_unstop(production_order, status): +def stop_unstop(work_order, status): """ Called from client side on Stop/Unstop event""" - if not frappe.has_permission("Production Order", "write"): + if not frappe.has_permission("Work Order", "write"): frappe.throw(_("Not permitted"), frappe.PermissionError) - pro_order = frappe.get_doc("Production Order", production_order) + pro_order = frappe.get_doc("Work Order", work_order) pro_order.update_status(status) pro_order.update_planned_qty() - frappe.msgprint(_("Production Order has been {0}").format(status)) + frappe.msgprint(_("Work Order has been {0}").format(status)) pro_order.notify_update() return pro_order.status diff --git a/erpnext/manufacturing/doctype/production_order/production_order_calendar.js b/erpnext/manufacturing/doctype/work_order/work_order_calendar.js similarity index 83% rename from erpnext/manufacturing/doctype/production_order/production_order_calendar.js rename to erpnext/manufacturing/doctype/work_order/work_order_calendar.js index ce2600aea1e..c44b1e2700d 100644 --- a/erpnext/manufacturing/doctype/production_order/production_order_calendar.js +++ b/erpnext/manufacturing/doctype/work_order/work_order_calendar.js @@ -1,7 +1,7 @@ -// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -// License: GNU General Public License v3. See license.txt +// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt -frappe.views.calendar["Production Order"] = { +frappe.views.calendar["Work Order"] = { field_map: { "start": "planned_start_date", "end": "planned_end_date", diff --git a/erpnext/manufacturing/doctype/production_order/production_order_dashboard.py b/erpnext/manufacturing/doctype/work_order/work_order_dashboard.py similarity index 77% rename from erpnext/manufacturing/doctype/production_order/production_order_dashboard.py rename to erpnext/manufacturing/doctype/work_order/work_order_dashboard.py index 7c8c8c64b96..9b7c9a3de0f 100644 --- a/erpnext/manufacturing/doctype/production_order/production_order_dashboard.py +++ b/erpnext/manufacturing/doctype/work_order/work_order_dashboard.py @@ -2,7 +2,7 @@ from frappe import _ def get_data(): return { - 'fieldname': 'production_order', + 'fieldname': 'work_order', 'transactions': [ { 'items': ['Stock Entry', 'Timesheet'] diff --git a/erpnext/manufacturing/doctype/production_order/production_order_list.js b/erpnext/manufacturing/doctype/work_order/work_order_list.js similarity index 91% rename from erpnext/manufacturing/doctype/production_order/production_order_list.js rename to erpnext/manufacturing/doctype/work_order/work_order_list.js index 762beb0e7c1..8d18395acd4 100644 --- a/erpnext/manufacturing/doctype/production_order/production_order_list.js +++ b/erpnext/manufacturing/doctype/work_order/work_order_list.js @@ -1,4 +1,4 @@ -frappe.listview_settings['Production Order'] = { +frappe.listview_settings['Work Order'] = { add_fields: ["bom_no", "status", "sales_order", "qty", "produced_qty", "expected_delivery_date", "planned_start_date", "planned_end_date"], filters: [["status", "!=", "Stopped"]], diff --git a/erpnext/manufacturing/doctype/production_order_item/__init__.py b/erpnext/manufacturing/doctype/work_order_item/__init__.py similarity index 100% rename from erpnext/manufacturing/doctype/production_order_item/__init__.py rename to erpnext/manufacturing/doctype/work_order_item/__init__.py diff --git a/erpnext/manufacturing/doctype/production_order_item/production_order_item.json b/erpnext/manufacturing/doctype/work_order_item/work_order_item.json similarity index 99% rename from erpnext/manufacturing/doctype/production_order_item/production_order_item.json rename to erpnext/manufacturing/doctype/work_order_item/work_order_item.json index c0b1d009ba1..1ac6b66047d 100644 --- a/erpnext/manufacturing/doctype/production_order_item/production_order_item.json +++ b/erpnext/manufacturing/doctype/work_order_item/work_order_item.json @@ -354,10 +354,10 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2017-08-18 18:11:10.311736", + "modified": "2018-02-13 02:58:11.328693", "modified_by": "Administrator", "module": "Manufacturing", - "name": "Production Order Item", + "name": "Work Order Item", "name_case": "", "owner": "Administrator", "permissions": [], diff --git a/erpnext/manufacturing/doctype/production_order_item/production_order_item.py b/erpnext/manufacturing/doctype/work_order_item/work_order_item.py similarity index 70% rename from erpnext/manufacturing/doctype/production_order_item/production_order_item.py rename to erpnext/manufacturing/doctype/work_order_item/work_order_item.py index e52ccc2e0f1..d18f028fc6e 100644 --- a/erpnext/manufacturing/doctype/production_order_item/production_order_item.py +++ b/erpnext/manufacturing/doctype/work_order_item/work_order_item.py @@ -6,8 +6,8 @@ from __future__ import unicode_literals import frappe from frappe.model.document import Document -class ProductionOrderItem(Document): +class WorkOrderItem(Document): pass def on_doctype_update(): - frappe.db.add_index("Production Order Item", ["item_code", "source_warehouse"]) \ No newline at end of file + frappe.db.add_index("Work Order Item", ["item_code", "source_warehouse"]) \ No newline at end of file diff --git a/erpnext/manufacturing/doctype/production_order_operation/__init__.py b/erpnext/manufacturing/doctype/work_order_operation/__init__.py similarity index 100% rename from erpnext/manufacturing/doctype/production_order_operation/__init__.py rename to erpnext/manufacturing/doctype/work_order_operation/__init__.py diff --git a/erpnext/manufacturing/doctype/production_order_operation/production_order_operation.json b/erpnext/manufacturing/doctype/work_order_operation/work_order_operation.json similarity index 99% rename from erpnext/manufacturing/doctype/production_order_operation/production_order_operation.json rename to erpnext/manufacturing/doctype/work_order_operation/work_order_operation.json index 89306c47b21..9c1c95383bb 100644 --- a/erpnext/manufacturing/doctype/production_order_operation/production_order_operation.json +++ b/erpnext/manufacturing/doctype/work_order_operation/work_order_operation.json @@ -672,10 +672,10 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2017-05-29 18:02:04.252419", + "modified": "2018-02-13 02:58:11.328693", "modified_by": "Administrator", "module": "Manufacturing", - "name": "Production Order Operation", + "name": "Work Order Operation", "name_case": "", "owner": "Administrator", "permissions": [], diff --git a/erpnext/manufacturing/doctype/production_order_operation/production_order_operation.py b/erpnext/manufacturing/doctype/work_order_operation/work_order_operation.py similarity index 85% rename from erpnext/manufacturing/doctype/production_order_operation/production_order_operation.py rename to erpnext/manufacturing/doctype/work_order_operation/work_order_operation.py index c425a6eb3ce..3c20d8e88a0 100644 --- a/erpnext/manufacturing/doctype/production_order_operation/production_order_operation.py +++ b/erpnext/manufacturing/doctype/work_order_operation/work_order_operation.py @@ -5,5 +5,5 @@ from __future__ import unicode_literals import frappe from frappe.model.document import Document -class ProductionOrderOperation(Document): +class WorkOrderOperation(Document): pass diff --git a/erpnext/manufacturing/page/production_analytics/production_analytics.js b/erpnext/manufacturing/page/production_analytics/production_analytics.js index a40177c7f25..f75bccf705c 100644 --- a/erpnext/manufacturing/page/production_analytics/production_analytics.js +++ b/erpnext/manufacturing/page/production_analytics/production_analytics.js @@ -19,7 +19,7 @@ erpnext.ProductionAnalytics = frappe.views.GridReportWithPlot.extend({ title: __("Production Analytics"), parent: $(wrapper).find('.layout-main'), page: wrapper.page, - doctypes: ["Item", "Company", "Fiscal Year", "Production Order"] + doctypes: ["Item", "Company", "Fiscal Year", "Work Order"] }); }, @@ -86,7 +86,7 @@ erpnext.ProductionAnalytics = frappe.views.GridReportWithPlot.extend({ // add Opening, Closing, Totals rows // if filtered by account and / or voucher var me = this; - var all_open_orders = {name:"All Production Orders", "id": "all-open-pos", + var all_open_orders = {name:"All Work Orders", "id": "all-open-pos", checked:true}; var not_started = {name:"Not Started", "id":"not-started-pos", checked:true}; @@ -97,7 +97,7 @@ erpnext.ProductionAnalytics = frappe.views.GridReportWithPlot.extend({ var completed = {name:"Completed", "id":"completed-pos", checked:true}; - $.each(frappe.report_dump.data["Production Order"], function(i, d) { + $.each(frappe.report_dump.data["Work Order"], function(i, d) { var dateobj = frappe.datetime.str_to_obj(d.creation); var date = frappe.datetime.str_to_user(d.creation.split(" ")[0]); diff --git a/erpnext/manufacturing/report/completed_production_orders/completed_production_orders.json b/erpnext/manufacturing/report/completed_production_orders/completed_production_orders.json deleted file mode 100644 index d36e52e478b..00000000000 --- a/erpnext/manufacturing/report/completed_production_orders/completed_production_orders.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "add_total_row": 0, - "apply_user_permissions": 1, - "creation": "2013-08-12 12:44:27", - "disabled": 0, - "docstatus": 0, - "doctype": "Report", - "idx": 3, - "is_standard": "Yes", - "modified": "2017-02-24 20:10:32.460097", - "modified_by": "Administrator", - "module": "Manufacturing", - "name": "Completed Production Orders", - "owner": "Administrator", - "query": "SELECT\n `tabProduction Order`.name as \"Production Order:Link/Production Order:200\",\n `tabProduction Order`.creation as \"Date:Date:120\",\n `tabProduction Order`.production_item as \"Item:Link/Item:150\",\n `tabProduction Order`.qty as \"To Produce:Int:100\",\n `tabProduction Order`.produced_qty as \"Produced:Int:100\",\n `tabProduction Order`.company as \"Company:Link/Company:\"\nFROM\n `tabProduction Order`\nWHERE\n `tabProduction Order`.docstatus=1\n AND ifnull(`tabProduction Order`.produced_qty,0) = `tabProduction Order`.qty", - "ref_doctype": "Production Order", - "report_name": "Completed Production Orders", - "report_type": "Query Report", - "roles": [ - { - "role": "Manufacturing User" - }, - { - "role": "Stock User" - } - ] -} \ No newline at end of file diff --git a/erpnext/manufacturing/report/completed_production_orders/__init__.py b/erpnext/manufacturing/report/completed_work_orders/__init__.py similarity index 100% rename from erpnext/manufacturing/report/completed_production_orders/__init__.py rename to erpnext/manufacturing/report/completed_work_orders/__init__.py diff --git a/erpnext/manufacturing/report/completed_work_orders/completed_work_orders.json b/erpnext/manufacturing/report/completed_work_orders/completed_work_orders.json new file mode 100644 index 00000000000..be50e93f1ba --- /dev/null +++ b/erpnext/manufacturing/report/completed_work_orders/completed_work_orders.json @@ -0,0 +1,27 @@ +{ + "add_total_row": 0, + "apply_user_permissions": 1, + "creation": "2013-08-12 12:44:27", + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "idx": 3, + "is_standard": "Yes", + "modified": "2018-02-13 04:58:51.549413", + "modified_by": "Administrator", + "module": "Manufacturing", + "name": "Completed Work Orders", + "owner": "Administrator", + "query": "SELECT\n `tabWork Order`.name as \"Work Order:Link/Work Order:200\",\n `tabWork Order`.creation as \"Date:Date:120\",\n `tabWork Order`.production_item as \"Item:Link/Item:150\",\n `tabWork Order`.qty as \"To Produce:Int:100\",\n `tabWork Order`.produced_qty as \"Produced:Int:100\",\n `tabWork Order`.company as \"Company:Link/Company:\"\nFROM\n `tabWork Order`\nWHERE\n `tabWork Order`.docstatus=1\n AND ifnull(`tabWork Order`.produced_qty,0) = `tabWork Order`.qty", + "ref_doctype": "Work Order", + "report_name": "Completed Work Orders", + "report_type": "Query Report", + "roles": [ + { + "role": "Manufacturing User" + }, + { + "role": "Stock User" + } + ] +} \ No newline at end of file diff --git a/erpnext/manufacturing/report/issued_items_against_production_order/issued_items_against_production_order.json b/erpnext/manufacturing/report/issued_items_against_production_order/issued_items_against_production_order.json deleted file mode 100644 index 388ab8c327a..00000000000 --- a/erpnext/manufacturing/report/issued_items_against_production_order/issued_items_against_production_order.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "add_total_row": 0, - "apply_user_permissions": 1, - "creation": "2013-05-03 17:48:46", - "disabled": 0, - "docstatus": 0, - "doctype": "Report", - "idx": 3, - "is_standard": "Yes", - "modified": "2017-02-24 20:00:38.101588", - "modified_by": "Administrator", - "module": "Manufacturing", - "name": "Issued Items Against Production Order", - "owner": "Administrator", - "query": "select\n ste.production_order as \"Production Order:Link/Production Order:120\",\n ste.posting_date as \"Issue Date:Date:140\",\n ste_item.item_code as \"Item Code:Link/Item:120\",\n\tste_item.description as \"Description::150\",\n\tste_item.transfer_qty as \"Qty:Float:100\",\n\tste_item.stock_uom as \"UOM:Link/UOM:80\",\n\tste_item.amount as \"Amount:Currency:120\",\n\tste_item.serial_no as \"Serial No:Link/Serial No:80\",\n\tste_item.s_warehouse as \"Source Warehouse:Link/Warehouse:120\",\n\tste_item.t_warehouse as \"Target Warehouse:Link/Warehouse:120\",\n\tpro.production_item as \"Finished Goods:Link/Item:120\", \n\tste.name as \"Stock Entry:Link/Stock Entry:120\",\n\tste.company as \"Company:Link/Company:\",\n\t(select bin.projected_qty from `tabBin` bin \n\t\t\twhere bin.item_code= ste_item.item_code and bin.warehouse= ste_item.s_warehouse) as \"Projected Quantity as Source:Float:200\"\nfrom\t`tabStock Entry` ste, `tabStock Entry Detail` ste_item, `tabProduction Order` pro\nwhere\n\tifnull(ste.production_order, '') != '' and ste.name = ste_item.parent \n\tand ste.production_order = pro.name and ste.docstatus = 1\n\tand ste.purpose = 'Material Transfer for Manufacture'\norder by ste.posting_date, ste.production_order, ste_item.item_code", - "ref_doctype": "Production Order", - "report_name": "Issued Items Against Production Order", - "report_type": "Query Report", - "roles": [ - { - "role": "Manufacturing User" - }, - { - "role": "Stock User" - } - ] -} \ No newline at end of file diff --git a/erpnext/manufacturing/report/issued_items_against_production_order/__init__.py b/erpnext/manufacturing/report/issued_items_against_work_order/__init__.py similarity index 100% rename from erpnext/manufacturing/report/issued_items_against_production_order/__init__.py rename to erpnext/manufacturing/report/issued_items_against_work_order/__init__.py diff --git a/erpnext/manufacturing/report/issued_items_against_work_order/issued_items_against_work_order.json b/erpnext/manufacturing/report/issued_items_against_work_order/issued_items_against_work_order.json new file mode 100644 index 00000000000..430f116d826 --- /dev/null +++ b/erpnext/manufacturing/report/issued_items_against_work_order/issued_items_against_work_order.json @@ -0,0 +1,27 @@ +{ + "add_total_row": 0, + "apply_user_permissions": 1, + "creation": "2013-05-03 17:48:46", + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "idx": 3, + "is_standard": "Yes", + "modified": "2018-02-13 04:56:57.040163", + "modified_by": "Administrator", + "module": "Manufacturing", + "name": "Issued Items Against Work Order", + "owner": "Administrator", + "query": "select\n ste.work_order as \"Work Order:Link/Work Order:120\",\n ste.posting_date as \"Issue Date:Date:140\",\n ste_item.item_code as \"Item Code:Link/Item:120\",\n\tste_item.description as \"Description::150\",\n\tste_item.transfer_qty as \"Qty:Float:100\",\n\tste_item.stock_uom as \"UOM:Link/UOM:80\",\n\tste_item.amount as \"Amount:Currency:120\",\n\tste_item.serial_no as \"Serial No:Link/Serial No:80\",\n\tste_item.s_warehouse as \"Source Warehouse:Link/Warehouse:120\",\n\tste_item.t_warehouse as \"Target Warehouse:Link/Warehouse:120\",\n\two.production_item as \"Finished Goods:Link/Item:120\", \n\tste.name as \"Stock Entry:Link/Stock Entry:120\",\n\tste.company as \"Company:Link/Company:\",\n\t(select bin.projected_qty from `tabBin` bin \n\t\t\twhere bin.item_code= ste_item.item_code and bin.warehouse= ste_item.s_warehouse) as \"Projected Quantity as Source:Float:200\"\nfrom\t`tabStock Entry` ste, `tabStock Entry Detail` ste_item, `tabWork Order` wo\nwhere\n\tifnull(ste.work_order, '') != '' and ste.name = ste_item.parent \n\tand ste.work_order = wo.name and ste.docstatus = 1\n\tand ste.purpose = 'Material Transfer for Manufacture'\norder by ste.posting_date, ste.work_order, ste_item.item_code", + "ref_doctype": "Work Order", + "report_name": "Issued Items Against Work Order", + "report_type": "Query Report", + "roles": [ + { + "role": "Manufacturing User" + }, + { + "role": "Stock User" + } + ] +} \ No newline at end of file diff --git a/erpnext/manufacturing/report/open_production_orders/open_production_orders.json b/erpnext/manufacturing/report/open_production_orders/open_production_orders.json deleted file mode 100644 index 5d0b7111209..00000000000 --- a/erpnext/manufacturing/report/open_production_orders/open_production_orders.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "add_total_row": 0, - "apply_user_permissions": 1, - "creation": "2013-08-12 12:32:30", - "disabled": 0, - "docstatus": 0, - "doctype": "Report", - "idx": 3, - "is_standard": "Yes", - "modified": "2017-02-24 20:10:23.179130", - "modified_by": "Administrator", - "module": "Manufacturing", - "name": "Open Production Orders", - "owner": "Administrator", - "query": "SELECT\n `tabProduction Order`.name as \"Production Order:Link/Production Order:200\",\n `tabProduction Order`.creation as \"Date:Date:120\",\n `tabProduction Order`.production_item as \"Item:Link/Item:150\",\n `tabProduction Order`.qty as \"To Produce:Int:100\",\n `tabProduction Order`.produced_qty as \"Produced:Int:100\",\n `tabProduction Order`.company as \"Company:Link/Company:\"\nFROM\n `tabProduction Order`\nWHERE\n `tabProduction Order`.docstatus=1\n AND ifnull(`tabProduction Order`.produced_qty,0) < `tabProduction Order`.qty\n AND NOT EXISTS (SELECT name from `tabStock Entry` where production_order =`tabProduction Order`.name) ", - "ref_doctype": "Production Order", - "report_name": "Open Production Orders", - "report_type": "Query Report", - "roles": [ - { - "role": "Manufacturing User" - }, - { - "role": "Stock User" - } - ] -} \ No newline at end of file diff --git a/erpnext/manufacturing/report/open_production_orders/__init__.py b/erpnext/manufacturing/report/open_work_orders/__init__.py similarity index 100% rename from erpnext/manufacturing/report/open_production_orders/__init__.py rename to erpnext/manufacturing/report/open_work_orders/__init__.py diff --git a/erpnext/manufacturing/report/open_work_orders/open_work_orders.json b/erpnext/manufacturing/report/open_work_orders/open_work_orders.json new file mode 100644 index 00000000000..479c65b312a --- /dev/null +++ b/erpnext/manufacturing/report/open_work_orders/open_work_orders.json @@ -0,0 +1,27 @@ +{ + "add_total_row": 0, + "apply_user_permissions": 1, + "creation": "2013-08-12 12:32:30", + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "idx": 3, + "is_standard": "Yes", + "modified": "2018-02-13 04:58:29.780472", + "modified_by": "Administrator", + "module": "Manufacturing", + "name": "Open Work Orders", + "owner": "Administrator", + "query": "SELECT\n `tabWork Order`.name as \"Work Order:Link/Work Order:200\",\n `tabWork Order`.creation as \"Date:Date:120\",\n `tabWork Order`.production_item as \"Item:Link/Item:150\",\n `tabWork Order`.qty as \"To Produce:Int:100\",\n `tabWork Order`.produced_qty as \"Produced:Int:100\",\n `tabWork Order`.company as \"Company:Link/Company:\"\nFROM\n `tabWork Order`\nWHERE\n `tabWork Order`.docstatus=1\n AND ifnull(`tabWork Order`.produced_qty,0) < `tabWork Order`.qty\n AND NOT EXISTS (SELECT name from `tabStock Entry` where work_order =`tabWork Order`.name) ", + "ref_doctype": "Work Order", + "report_name": "Open Work Orders", + "report_type": "Query Report", + "roles": [ + { + "role": "Manufacturing User" + }, + { + "role": "Stock User" + } + ] +} \ No newline at end of file diff --git a/erpnext/manufacturing/report/production_orders_in_progress/production_orders_in_progress.json b/erpnext/manufacturing/report/production_orders_in_progress/production_orders_in_progress.json deleted file mode 100644 index 5867aedf5c2..00000000000 --- a/erpnext/manufacturing/report/production_orders_in_progress/production_orders_in_progress.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "add_total_row": 0, - "apply_user_permissions": 1, - "creation": "2013-08-12 12:43:47", - "disabled": 0, - "docstatus": 0, - "doctype": "Report", - "idx": 3, - "is_standard": "Yes", - "modified": "2017-02-24 20:10:40.304828", - "modified_by": "Administrator", - "module": "Manufacturing", - "name": "Production Orders in Progress", - "owner": "Administrator", - "query": "SELECT\n `tabProduction Order`.name as \"Production Order:Link/Production Order:200\",\n `tabProduction Order`.creation as \"Date:Date:120\",\n `tabProduction Order`.production_item as \"Item:Link/Item:150\",\n `tabProduction Order`.qty as \"To Produce:Int:100\",\n `tabProduction Order`.produced_qty as \"Produced:Int:100\",\n `tabProduction Order`.company as \"Company:Link/Company:\"\nFROM\n `tabProduction Order`\nWHERE\n `tabProduction Order`.docstatus=1\n AND ifnull(`tabProduction Order`.produced_qty,0) < `tabProduction Order`.qty\n AND EXISTS (SELECT name from `tabStock Entry` where production_order =`tabProduction Order`.name) ", - "ref_doctype": "Production Order", - "report_name": "Production Orders in Progress", - "report_type": "Query Report", - "roles": [ - { - "role": "Manufacturing User" - }, - { - "role": "Stock User" - } - ] -} \ No newline at end of file diff --git a/erpnext/manufacturing/report/production_order_stock_report/__init__.py b/erpnext/manufacturing/report/work_order_stock_report/__init__.py similarity index 100% rename from erpnext/manufacturing/report/production_order_stock_report/__init__.py rename to erpnext/manufacturing/report/work_order_stock_report/__init__.py diff --git a/erpnext/manufacturing/report/production_order_stock_report/production_order_stock_report.js b/erpnext/manufacturing/report/work_order_stock_report/work_order_stock_report.js similarity index 56% rename from erpnext/manufacturing/report/production_order_stock_report/production_order_stock_report.js rename to erpnext/manufacturing/report/work_order_stock_report/work_order_stock_report.js index 94e326d7c12..dbb7c234101 100644 --- a/erpnext/manufacturing/report/production_order_stock_report/production_order_stock_report.js +++ b/erpnext/manufacturing/report/work_order_stock_report/work_order_stock_report.js @@ -1,7 +1,8 @@ -// Copyright (c) 2016, Velometro Mobility Inc and contributors +// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors // For license information, please see license.txt +/* eslint-disable */ -frappe.query_reports["Production Order Stock Report"] = { +frappe.query_reports["Work Order Stock Report"] = { "filters": [ { "fieldname": "warehouse", diff --git a/erpnext/manufacturing/report/production_order_stock_report/production_order_stock_report.json b/erpnext/manufacturing/report/work_order_stock_report/work_order_stock_report.json similarity index 70% rename from erpnext/manufacturing/report/production_order_stock_report/production_order_stock_report.json rename to erpnext/manufacturing/report/work_order_stock_report/work_order_stock_report.json index 0cb8982b155..7e027dab716 100644 --- a/erpnext/manufacturing/report/production_order_stock_report/production_order_stock_report.json +++ b/erpnext/manufacturing/report/work_order_stock_report/work_order_stock_report.json @@ -8,13 +8,13 @@ "idx": 0, "is_standard": "Yes", "letter_head": "", - "modified": "2017-02-24 19:59:07.792058", + "modified": "2018-02-13 04:47:04.158213", "modified_by": "Administrator", "module": "Manufacturing", - "name": "Production Order Stock Report", + "name": "Work Order Stock Report", "owner": "Administrator", - "ref_doctype": "Production Order", - "report_name": "Production Order Stock Report", + "ref_doctype": "Work Order", + "report_name": "Work Order Stock Report", "report_type": "Script Report", "roles": [ { diff --git a/erpnext/manufacturing/report/production_order_stock_report/production_order_stock_report.py b/erpnext/manufacturing/report/work_order_stock_report/work_order_stock_report.py similarity index 69% rename from erpnext/manufacturing/report/production_order_stock_report/production_order_stock_report.py rename to erpnext/manufacturing/report/work_order_stock_report/work_order_stock_report.py index f99632359a7..97553e699d8 100644 --- a/erpnext/manufacturing/report/production_order_stock_report/production_order_stock_report.py +++ b/erpnext/manufacturing/report/work_order_stock_report/work_order_stock_report.py @@ -6,20 +6,20 @@ from frappe.utils import cint import frappe def execute(filters=None): - prod_list = get_production_orders() - data = get_item_list(prod_list, filters) + wo_list = get_work_orders() + data = get_item_list(wo_list, filters) columns = get_columns() return columns, data -def get_item_list(prod_list, filters): +def get_item_list(wo_list, filters): out = [] #Add a row for each item/qty - for prod_details in prod_list: - desc = frappe.db.get_value("BOM", prod_details.bom_no, "description") + for wo_details in wo_list: + desc = frappe.db.get_value("BOM", wo_details.bom_no, "description") - for prod_item_details in frappe.db.get_values("Production Order Item", - {"parent": prod_details.name}, ["item_code", "source_warehouse"], as_dict=1): + for wo_item_details in frappe.db.get_values("Work Order Item", + {"parent": wo_details.name}, ["item_code", "source_warehouse"], as_dict=1): item_list = frappe.db.sql("""SELECT bom_item.item_code as item_code, @@ -35,15 +35,15 @@ def get_item_list(prod_list, filters): and bom.name = %(bom)s GROUP BY bom_item.item_code""", - {"bom": prod_details.bom_no, "warehouse": prod_item_details.source_warehouse, - "filterhouse": filters.warehouse, "item_code": prod_item_details.item_code}, as_dict=1) + {"bom": wo_details.bom_no, "warehouse": wo_item_details.source_warehouse, + "filterhouse": filters.warehouse, "item_code": wo_item_details.item_code}, as_dict=1) stock_qty = 0 count = 0 - buildable_qty = prod_details.qty + buildable_qty = wo_details.qty for item in item_list: count = count + 1 - if item.build_qty >= (prod_details.qty - prod_details.produced_qty): + if item.build_qty >= (wo_details.qty - wo_details.produced_qty): stock_qty = stock_qty + 1 elif buildable_qty >= item.build_qty: buildable_qty = item.build_qty @@ -54,15 +54,15 @@ def get_item_list(prod_list, filters): build = "N" row = frappe._dict({ - "production_order": prod_details.name, - "status": prod_details.status, + "work_order": wo_details.name, + "status": wo_details.status, "req_items": cint(count), "instock": stock_qty, "description": desc, - "source_warehouse": prod_item_details.source_warehouse, - "item_code": prod_item_details.item_code, - "bom_no": prod_details.bom_no, - "qty": prod_details.qty, + "source_warehouse": wo_item_details.source_warehouse, + "item_code": wo_item_details.item_code, + "bom_no": wo_details.bom_no, + "qty": wo_details.qty, "buildable_qty": buildable_qty, "ready_to_build": build }) @@ -71,18 +71,18 @@ def get_item_list(prod_list, filters): return out -def get_production_orders(): - out = frappe.get_all("Production Order", filters={"docstatus": 1, "status": ( "!=","Completed")}, +def get_work_orders(): + out = frappe.get_all("Work Order", filters={"docstatus": 1, "status": ( "!=","Completed")}, fields=["name","status", "bom_no", "qty", "produced_qty"], order_by='name') return out def get_columns(): columns = [{ - "fieldname": "production_order", - "label": "Production Order", + "fieldname": "work_order", + "label": "Work Order", "fieldtype": "Link", - "options": "Production Order", + "options": "Work Order", "width": 110 }, { "fieldname": "bom_no", diff --git a/erpnext/manufacturing/report/production_orders_in_progress/__init__.py b/erpnext/manufacturing/report/work_orders_in_progress/__init__.py similarity index 100% rename from erpnext/manufacturing/report/production_orders_in_progress/__init__.py rename to erpnext/manufacturing/report/work_orders_in_progress/__init__.py diff --git a/erpnext/manufacturing/report/work_orders_in_progress/work_orders_in_progress.json b/erpnext/manufacturing/report/work_orders_in_progress/work_orders_in_progress.json new file mode 100644 index 00000000000..db94fe8071a --- /dev/null +++ b/erpnext/manufacturing/report/work_orders_in_progress/work_orders_in_progress.json @@ -0,0 +1,27 @@ +{ + "add_total_row": 0, + "apply_user_permissions": 1, + "creation": "2013-08-12 12:43:47", + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "idx": 3, + "is_standard": "Yes", + "modified": "2018-02-13 04:56:02.206353", + "modified_by": "Administrator", + "module": "Manufacturing", + "name": "Work Orders in Progress", + "owner": "Administrator", + "query": "SELECT\n `tabWork Order`.name as \"Work Order:Link/Work Order:200\",\n `tabWork Order`.creation as \"Date:Date:120\",\n `tabWork Order`.production_item as \"Item:Link/Item:150\",\n `tabWork Order`.qty as \"To Produce:Int:100\",\n `tabWork Order`.produced_qty as \"Produced:Int:100\",\n `tabWork Order`.company as \"Company:Link/Company:\"\nFROM\n `tabWork Order`\nWHERE\n `tabWork Order`.docstatus=1\n AND ifnull(`tabWork Order`.produced_qty,0) < `tabWork Order`.qty\n AND EXISTS (SELECT name from `tabStock Entry` where work_order =`tabWork Order`.name) ", + "ref_doctype": "Work Order", + "report_name": "Work Orders in Progress", + "report_type": "Query Report", + "roles": [ + { + "role": "Manufacturing User" + }, + { + "role": "Stock User" + } + ] +} \ No newline at end of file diff --git a/erpnext/patches.txt b/erpnext/patches.txt index e049a81d298..328a7e45823 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -1,6 +1,7 @@ execute:import unidecode # new requirement erpnext.patches.v8_0.move_perpetual_inventory_setting erpnext.patches.v10_0.rename_schools_to_education +erpnext.patches.v11_0.rename_production_order_to_work_order erpnext.patches.v4_0.validate_v3_patch erpnext.patches.v4_0.fix_employee_user_id erpnext.patches.v4_0.remove_employee_role_if_no_employee @@ -198,7 +199,7 @@ execute:frappe.db.sql("update `tabStock Ledger Entry` set stock_queue = '[]' whe erpnext.patches.v5_4.fix_missing_item_images erpnext.patches.v5_4.stock_entry_additional_costs erpnext.patches.v5_4.cleanup_journal_entry #2015-08-14 -execute:frappe.db.sql("update `tabProduction Order` pro set description = (select description from tabItem where name=pro.production_item) where ifnull(description, '') = ''") +erpnext.patches.v5_7.update_item_description_based_on_item_master erpnext.patches.v5_7.item_template_attributes execute:frappe.delete_doc_if_exists("DocType", "Manage Variants") execute:frappe.delete_doc_if_exists("DocType", "Manage Variants Item") diff --git a/erpnext/patches/v11_0/rename_production_order_to_work_order.py b/erpnext/patches/v11_0/rename_production_order_to_work_order.py new file mode 100644 index 00000000000..72bdb68daf9 --- /dev/null +++ b/erpnext/patches/v11_0/rename_production_order_to_work_order.py @@ -0,0 +1,35 @@ +# Copyright (c) 2018, Frappe and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +from frappe.model.rename_doc import rename_doc +from frappe.model.utils.rename_field import rename_field +import frappe + +def execute(): + rename_doc('DocType', 'Production Order', 'Work Order', force=True) + frappe.reload_doc('manufacturing', 'doctype', 'work_order') + + rename_doc('DocType', 'Production Order Item', 'Work Order Item', force=True) + frappe.reload_doc('manufacturing', 'doctype', 'work_order_item') + + rename_doc('DocType', 'Production Order Operation', 'Work Order Operation', force=True) + frappe.reload_doc('manufacturing', 'doctype', 'work_order_operation') + + frappe.reload_doc('projects', 'doctype', 'timesheet') + frappe.reload_doc('stock', 'doctype', 'stock_entry') + rename_field("Timesheet", "production_order", "work_order") + rename_field("Stock Entry", "production_order", "work_order") + + frappe.rename_doc("Report", "Production Orders in Progress", "Work Orders in Progress", force=True) + frappe.rename_doc("Report", "Completed Production Orders", "Completed Work Orders", force=True) + frappe.rename_doc("Report", "Open Production Orders", "Open Work Orders", force=True) + frappe.rename_doc("Report", "Issued Items Against Production Order", "Issued Items Against Work Order", force=True) + frappe.rename_doc("Report", "Production Order Stock Report", "Work Order Stock Report", force=True) + + frappe.db.sql("""update `tabDesktop Icon` \ + set label='Work Order', module_name='Work Order' \ + where label='Production Order'""") + frappe.db.sql("""update `tabDesktop Icon` \ + set link='List/Work Order' \ + where link='List/Production Order'""") diff --git a/erpnext/patches/v4_0/set_naming_series_property_setter.py b/erpnext/patches/v4_0/set_naming_series_property_setter.py index e61a5968fe2..4cf3bb224c4 100644 --- a/erpnext/patches/v4_0/set_naming_series_property_setter.py +++ b/erpnext/patches/v4_0/set_naming_series_property_setter.py @@ -18,7 +18,7 @@ doctype_series_map = { 'Lead': 'LEAD-', 'Opportunity': 'OPTY-', 'Packing Slip': 'PS-', - 'Production Order': 'PRO-', + 'Work Order': 'WO-', 'Purchase Invoice': 'PINV-', 'Purchase Order': 'PO-', 'Purchase Receipt': 'PREC-', diff --git a/erpnext/patches/v4_2/seprate_manufacture_and_repack.py b/erpnext/patches/v4_2/seprate_manufacture_and_repack.py index 56373e20e2e..2c935436a2c 100644 --- a/erpnext/patches/v4_2/seprate_manufacture_and_repack.py +++ b/erpnext/patches/v4_2/seprate_manufacture_and_repack.py @@ -5,5 +5,5 @@ from __future__ import unicode_literals import frappe def execute(): - frappe.db.sql("""update `tabStock Entry` set purpose='Manufacture' where purpose='Manufacture/Repack' and ifnull(production_order,"")!="" """) - frappe.db.sql("""update `tabStock Entry` set purpose='Repack' where purpose='Manufacture/Repack' and ifnull(production_order,"")="" """) \ No newline at end of file + frappe.db.sql("""update `tabStock Entry` set purpose='Manufacture' where purpose='Manufacture/Repack' and ifnull(work_order,"")!="" """) + frappe.db.sql("""update `tabStock Entry` set purpose='Repack' where purpose='Manufacture/Repack' and ifnull(work_order,"")="" """) \ No newline at end of file diff --git a/erpnext/patches/v5_0/reclculate_planned_operating_cost_in_production_order.py b/erpnext/patches/v5_0/reclculate_planned_operating_cost_in_production_order.py index a943c062bc4..6d392831b40 100644 --- a/erpnext/patches/v5_0/reclculate_planned_operating_cost_in_production_order.py +++ b/erpnext/patches/v5_0/reclculate_planned_operating_cost_in_production_order.py @@ -5,9 +5,9 @@ from __future__ import unicode_literals import frappe def execute(): - for po in frappe.db.sql("""select name from `tabProduction Order` where docstatus < 2""", as_dict=1): - prod_order = frappe.get_doc("Production Order", po.name) - if prod_order.operations: - prod_order.flags.ignore_validate_update_after_submit = True - prod_order.calculate_time() - prod_order.save() \ No newline at end of file + for wo in frappe.db.sql("""select name from `tabWork Order` where docstatus < 2""", as_dict=1): + work_order = frappe.get_doc("Work Order", wo.name) + if work_order.operations: + work_order.flags.ignore_validate_update_after_submit = True + work_order.calculate_time() + work_order.save() \ No newline at end of file diff --git a/erpnext/patches/v5_0/rename_table_fieldnames.py b/erpnext/patches/v5_0/rename_table_fieldnames.py index e6667deb77f..e93070f9501 100644 --- a/erpnext/patches/v5_0/rename_table_fieldnames.py +++ b/erpnext/patches/v5_0/rename_table_fieldnames.py @@ -51,7 +51,7 @@ rename_map = { ["other_charges", "taxes"], ["advance_allocation_details", "advances"] ], - "Production Order": [ + "Work Order": [ ["production_order_operations", "operations"] ], "BOM": [ @@ -216,7 +216,7 @@ def execute(): frappe.rename_doc("DocType", old_dt, new_dt, force=True) # reload new child doctypes - frappe.reload_doc("manufacturing", "doctype", "production_order_operation") + frappe.reload_doc("manufacturing", "doctype", "work_order_operation") frappe.reload_doc("manufacturing", "doctype", "workstation_working_hour") frappe.reload_doc("stock", "doctype", "item_variant") frappe.reload_doc("hr", "doctype", "salary_detail") diff --git a/erpnext/patches/v5_0/update_material_transfer_for_manufacture.py b/erpnext/patches/v5_0/update_material_transfer_for_manufacture.py index d862ad3d753..b858bd8074f 100644 --- a/erpnext/patches/v5_0/update_material_transfer_for_manufacture.py +++ b/erpnext/patches/v5_0/update_material_transfer_for_manufacture.py @@ -2,4 +2,4 @@ import frappe def execute(): frappe.db.sql("""update `tabStock Entry` set purpose='Material Transfer for Manufacture' - where ifnull(production_order, '')!='' and purpose='Material Transfer'""") + where ifnull(work_order, '')!='' and purpose='Material Transfer'""") diff --git a/erpnext/patches/v5_0/update_material_transferred_for_manufacturing.py b/erpnext/patches/v5_0/update_material_transferred_for_manufacturing.py index f377e232325..2133d1c0504 100644 --- a/erpnext/patches/v5_0/update_material_transferred_for_manufacturing.py +++ b/erpnext/patches/v5_0/update_material_transferred_for_manufacturing.py @@ -1,9 +1,9 @@ import frappe def execute(): - frappe.reload_doctype("Production Order") - frappe.db.sql("""update `tabProduction Order` set material_transferred_for_manufacturing= + frappe.reload_doctype("Work Order") + frappe.db.sql("""update `tabWork Order` set material_transferred_for_manufacturing= (select sum(fg_completed_qty) from `tabStock Entry` where docstatus=1 - and production_order=`tabProduction Order`.name + and work_order=`tabWork Order`.name and purpose = "Material Transfer for Manufacture")""") diff --git a/erpnext/patches/v5_0/update_material_transferred_for_manufacturing_again.py b/erpnext/patches/v5_0/update_material_transferred_for_manufacturing_again.py index a74b4bd7769..187f4ea0bd0 100644 --- a/erpnext/patches/v5_0/update_material_transferred_for_manufacturing_again.py +++ b/erpnext/patches/v5_0/update_material_transferred_for_manufacturing_again.py @@ -1,18 +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 + wo_order_qty_transferred = frappe._dict() + for se in frappe.db.sql("""select work_order, sum(fg_completed_qty) as transferred_qty from `tabStock Entry` - where docstatus=1 and ifnull(production_order, '') != '' + where docstatus=1 and ifnull(work_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) + group by work_order""", as_dict=1): + wo_order_qty_transferred.setdefault(se.work_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 + for d in frappe.get_all("Work Order", filters={"docstatus": 1}, fields=["name", "qty"]): + if d.name in wo_order_qty_transferred: + material_transferred_for_manufacturing = wo_order_qty_transferred.get(d.name) \ + if wo_order_qty_transferred.get(d.name) <= d.qty else d.qty - frappe.db.sql("""update `tabProduction Order` set material_transferred_for_manufacturing=%s + frappe.db.sql("""update `tabWork Order` set material_transferred_for_manufacturing=%s where name=%s""", (material_transferred_for_manufacturing, d.name)) \ No newline at end of file diff --git a/erpnext/patches/v5_7/update_item_description_based_on_item_master.py b/erpnext/patches/v5_7/update_item_description_based_on_item_master.py new file mode 100644 index 00000000000..6851e67475f --- /dev/null +++ b/erpnext/patches/v5_7/update_item_description_based_on_item_master.py @@ -0,0 +1,12 @@ +import frappe + +def execute(): + name = frappe.db.sql(""" select name from `tabPatch Log` \ + where \ + patch like 'execute:frappe.db.sql("update `tabProduction Order` pro set description%' """) + if not name: + frappe.db.sql("update `tabProduction Order` pro \ + set \ + description = (select description from tabItem where name=pro.production_item) \ + where \ + ifnull(description, '') = ''") diff --git a/erpnext/patches/v6_0/fix_planned_qty.py b/erpnext/patches/v6_0/fix_planned_qty.py index e8ed1d05302..cf7b429249d 100644 --- a/erpnext/patches/v6_0/fix_planned_qty.py +++ b/erpnext/patches/v6_0/fix_planned_qty.py @@ -7,7 +7,7 @@ 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`"""): + from `tabWork Order`"""): if frappe.db.exists("Item", item_code) and frappe.db.exists("Warehouse", warehouse): update_bin_qty(item_code, warehouse, { "planned_qty": get_planned_qty(item_code, warehouse) diff --git a/erpnext/patches/v6_20x/rename_project_name_to_project.py b/erpnext/patches/v6_20x/rename_project_name_to_project.py index b420ce90131..49ec9d22bc0 100644 --- a/erpnext/patches/v6_20x/rename_project_name_to_project.py +++ b/erpnext/patches/v6_20x/rename_project_name_to_project.py @@ -7,7 +7,7 @@ from frappe.model.utils.rename_field import rename_field def execute(): - doc_list = ["Production Order", "BOM", "Purchase Invoice Item", "Sales Invoice", + doc_list = ["Work Order", "BOM", "Purchase Invoice Item", "Sales Invoice", "Purchase Order Item", "Stock Entry", "Delivery Note", "Sales Order", "Purchase Receipt Item", "Supplier Quotation Item"] diff --git a/erpnext/patches/v7_0/convert_timelog_to_timesheet.py b/erpnext/patches/v7_0/convert_timelog_to_timesheet.py index 4b6cf745359..d21758d031c 100644 --- a/erpnext/patches/v7_0/convert_timelog_to_timesheet.py +++ b/erpnext/patches/v7_0/convert_timelog_to_timesheet.py @@ -1,5 +1,5 @@ import frappe -from erpnext.manufacturing.doctype.production_order.production_order \ +from erpnext.manufacturing.doctype.work_order.work_order \ import make_timesheet, add_timesheet_detail def execute(): @@ -11,12 +11,12 @@ def execute(): for data in frappe.db.sql("select * from `tabTime Log`", as_dict=1): if data.task: company = frappe.db.get_value("Task", data.task, "company") - elif data.production_order: - company = frappe.db.get_value("Prodction Order", data.production_order, "company") + elif data.work_order: + company = frappe.db.get_value("Work Order", data.work_order, "company") else: company = frappe.db.get_single_value('Global Defaults', 'default_company') - time_sheet = make_timesheet(data.production_order, company) + time_sheet = make_timesheet(data.work_order, company) args = get_timelog_data(data) add_timesheet_detail(time_sheet, args) if data.docstatus == 2: @@ -40,7 +40,7 @@ def execute(): time_sheet.db_set("docstatus", 1) for d in time_sheet.get("time_logs"): d.db_set("docstatus", 1) - time_sheet.update_production_order(time_sheet.name) + time_sheet.update_work_order(time_sheet.name) time_sheet.update_task_and_project() if data.docstatus == 2: time_sheet.db_set("docstatus", 2) diff --git a/erpnext/patches/v7_0/convert_timelogbatch_to_timesheet.py b/erpnext/patches/v7_0/convert_timelogbatch_to_timesheet.py index a7cb0d74ce1..e23669b0f23 100644 --- a/erpnext/patches/v7_0/convert_timelogbatch_to_timesheet.py +++ b/erpnext/patches/v7_0/convert_timelogbatch_to_timesheet.py @@ -1,6 +1,6 @@ import frappe from frappe.utils import cint -from erpnext.manufacturing.doctype.production_order.production_order import add_timesheet_detail +from erpnext.manufacturing.doctype.work_order.work_order import add_timesheet_detail from erpnext.patches.v7_0.convert_timelog_to_timesheet import get_timelog_data def execute(): diff --git a/erpnext/patches/v7_1/repost_stock_for_deleted_bins_for_merging_items.py b/erpnext/patches/v7_1/repost_stock_for_deleted_bins_for_merging_items.py index 39b7f6ce91e..aca21085cc1 100644 --- a/erpnext/patches/v7_1/repost_stock_for_deleted_bins_for_merging_items.py +++ b/erpnext/patches/v7_1/repost_stock_for_deleted_bins_for_merging_items.py @@ -3,8 +3,8 @@ import frappe from erpnext.stock.stock_balance import repost_stock def execute(): - frappe.reload_doc('manufacturing', 'doctype', 'production_order_item') - frappe.reload_doc('manufacturing', 'doctype', 'production_order') + frappe.reload_doc('manufacturing', 'doctype', 'work_order_item') + frappe.reload_doc('manufacturing', 'doctype', 'work_order') modified_items = frappe.db.sql_list(""" select name from `tabItem` @@ -26,12 +26,12 @@ def execute(): item_warehouses_with_transactions += list(frappe.db.sql(""" select distinct production_item, fg_warehouse - from `tabProduction Order` where docstatus=1 and production_item in ({0})""" + from `tabWork Order` where docstatus=1 and production_item in ({0})""" .format(', '.join(['%s']*len(modified_items))), tuple(modified_items))) item_warehouses_with_transactions += list(frappe.db.sql(""" select distinct pr_item.item_code, pr_item.source_warehouse - from `tabProduction Order` pr, `tabProduction Order Item` pr_item + from `tabWork Order` pr, `tabWork Order Item` pr_item where pr_item.parent and pr.name and pr.docstatus=1 and pr_item.item_code in ({0})""" .format(', '.join(['%s']*len(modified_items))), tuple(modified_items))) diff --git a/erpnext/patches/v8_0/update_production_orders.py b/erpnext/patches/v8_0/update_production_orders.py index 06b8ce74c12..7d87d683195 100644 --- a/erpnext/patches/v8_0/update_production_orders.py +++ b/erpnext/patches/v8_0/update_production_orders.py @@ -6,41 +6,41 @@ import frappe def execute(): # reload schema - for doctype in ("Production Order", "Production Order Item", "Production Order Operation", + for doctype in ("Work Order", "Work Order Item", "Work Order Operation", "BOM Item", "BOM Explosion Item", "BOM"): frappe.reload_doctype(doctype) - # fetch all draft and submitted production orders + # fetch all draft and submitted work orders fields = ["name"] - if "source_warehouse" in frappe.db.get_table_columns("Production Order"): + if "source_warehouse" in frappe.db.get_table_columns("Work Order"): fields.append("source_warehouse") - pro_orders = frappe.get_all("Production Order", filters={"docstatus": ["!=", 2]}, fields=fields) + wo_orders = frappe.get_all("Work Order", filters={"docstatus": ["!=", 2]}, fields=fields) count = 0 - for p in pro_orders: - pro_order = frappe.get_doc("Production Order", p.name) + for p in wo_orders: + wo_order = frappe.get_doc("Work Order", p.name) count += 1 # set required items table - pro_order.set_required_items() + wo_order.set_required_items() - for item in pro_order.get("required_items"): + for item in wo_order.get("required_items"): # set source warehouse based on parent if not item.source_warehouse and "source_warehouse" in fields: - item.source_warehouse = pro_order.get("source_warehouse") + item.source_warehouse = wo_order.get("source_warehouse") item.db_update() - if pro_order.docstatus == 1: + if wo_order.docstatus == 1: # update transferred qty based on Stock Entry, it also updates db - pro_order.update_transaferred_qty_for_required_items() + wo_order.update_transaferred_qty_for_required_items() # Set status where it was 'Unstopped', as it is deprecated - if pro_order.status == "Unstopped": - status = pro_order.get_status() - pro_order.db_set("status", status) - elif pro_order.status == "Stopped": - pro_order.update_reserved_qty_for_production() + if wo_order.status == "Unstopped": + status = wo_order.get_status() + wo_order.db_set("status", status) + elif wo_order.status == "Stopped": + wo_order.update_reserved_qty_for_production() if count % 200 == 0: frappe.db.commit() \ No newline at end of file diff --git a/erpnext/patches/v8_1/add_indexes_in_transaction_doctypes.py b/erpnext/patches/v8_1/add_indexes_in_transaction_doctypes.py index 21a47fbc605..2fa0221ed71 100644 --- a/erpnext/patches/v8_1/add_indexes_in_transaction_doctypes.py +++ b/erpnext/patches/v8_1/add_indexes_in_transaction_doctypes.py @@ -5,5 +5,5 @@ import frappe def execute(): for dt in ("Sales Order Item", "Purchase Order Item", - "Material Request Item", "Production Order Item", "Packed Item"): + "Material Request Item", "Work Order Item", "Packed Item"): frappe.get_doc("DocType", dt).run_module_method("on_doctype_update") \ No newline at end of file diff --git a/erpnext/patches/v8_6/update_timesheet_company_from_PO.py b/erpnext/patches/v8_6/update_timesheet_company_from_PO.py index 5bab961c041..2d46bee7caa 100644 --- a/erpnext/patches/v8_6/update_timesheet_company_from_PO.py +++ b/erpnext/patches/v8_6/update_timesheet_company_from_PO.py @@ -11,5 +11,5 @@ def execute(): #Check more than one company exists if len(company) > 1: frappe.db.sql(""" update `tabTimesheet` set `tabTimesheet`.company = - (select company from `tabProduction Order` where name = `tabTimesheet`.production_order) - where production_order is not null and production_order !=''""") \ No newline at end of file + (select company from `tabWork Order` where name = `tabTimesheet`.work_order) + where workn_order is not null and work_order !=''""") \ No newline at end of file diff --git a/erpnext/patches/v9_2/set_item_name_in_production_order.py b/erpnext/patches/v9_2/set_item_name_in_production_order.py index e0e422b3076..18b5b8cdc6c 100644 --- a/erpnext/patches/v9_2/set_item_name_in_production_order.py +++ b/erpnext/patches/v9_2/set_item_name_in_production_order.py @@ -3,7 +3,7 @@ import frappe def execute(): frappe.db.sql(""" - update `tabBOM Item` bom, `tabProduction Order Item` po_item + update `tabBOM Item` bom, `tabWork Order Item` po_item set po_item.item_name = bom.item_name, po_item.description = bom.description where po_item.item_code = bom.item_code diff --git a/erpnext/projects/doctype/timesheet/test_timesheet.js b/erpnext/projects/doctype/timesheet/test_timesheet.js new file mode 100644 index 00000000000..c081d6f8ea4 --- /dev/null +++ b/erpnext/projects/doctype/timesheet/test_timesheet.js @@ -0,0 +1,23 @@ +/* eslint-disable */ +// rename this file from _test_[name] to test_[name] to activate +// and remove above this line + +QUnit.test("test: Timesheet", function (assert) { + let done = assert.async(); + + // number of asserts + assert.expect(1); + + frappe.run_serially([ + // insert a new Timesheet + () => frappe.tests.make('Timesheet', [ + // values to be set + {key: 'value'} + ]), + () => { + assert.equal(cur_frm.doc.key, 'value'); + }, + () => done() + ]); + +}); diff --git a/erpnext/projects/doctype/timesheet/timesheet.json b/erpnext/projects/doctype/timesheet/timesheet.json index 239bd62c9ba..0ef789c2656 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.json +++ b/erpnext/projects/doctype/timesheet/timesheet.json @@ -204,7 +204,7 @@ "collapsible": 0, "collapsible_depends_on": "", "columns": 0, - "depends_on": "eval:!doc.production_order || doc.docstatus == 1", + "depends_on": "eval:!doc.work_order || doc.docstatus == 1", "fieldname": "employee_detail", "fieldtype": "Section Break", "hidden": 0, @@ -421,8 +421,8 @@ "collapsible": 0, "collapsible_depends_on": "", "columns": 0, - "depends_on": "production_order", - "fieldname": "production_detail", + "depends_on": "work_order", + "fieldname": "work_detail", "fieldtype": "Section Break", "hidden": 0, "ignore_user_permissions": 0, @@ -431,7 +431,7 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Production Detail", + "label": "Work Detail", "length": 0, "no_copy": 0, "permlevel": 0, @@ -452,7 +452,7 @@ "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "production_order", + "fieldname": "work_order", "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, @@ -461,10 +461,10 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Production Order", + "label": "Work Order", "length": 0, "no_copy": 1, - "options": "Production Order", + "options": "Work Order", "permlevel": 0, "precision": "", "print_hide": 0, @@ -938,7 +938,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2017-06-13 14:28:51.838769", + "modified": "2018-01-07 11:44:09.573900", "modified_by": "Administrator", "module": "Projects", "name": "Timesheet", diff --git a/erpnext/projects/doctype/timesheet/timesheet.py b/erpnext/projects/doctype/timesheet/timesheet.py index 82494b0fcf2..c358a542879 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.py +++ b/erpnext/projects/doctype/timesheet/timesheet.py @@ -16,7 +16,7 @@ from erpnext.manufacturing.doctype.workstation.workstation import (check_if_with from erpnext.manufacturing.doctype.manufacturing_settings.manufacturing_settings import get_mins_between_operations class OverlapError(frappe.ValidationError): pass -class OverProductionLoggedError(frappe.ValidationError): pass +class OverWorkLoggedError(frappe.ValidationError): pass class Timesheet(Document): def onload(self): @@ -97,18 +97,18 @@ class Timesheet(Document): self.set_status() def on_cancel(self): - self.update_production_order(None) + self.update_work_order(None) self.update_task_and_project() def on_submit(self): self.validate_mandatory_fields() - self.update_production_order(self.name) + self.update_work_order(self.name) self.update_task_and_project() def validate_mandatory_fields(self): - if self.production_order: - production_order = frappe.get_doc("Production Order", self.production_order) - pending_qty = flt(production_order.qty) - flt(production_order.produced_qty) + if self.work_order: + work_order = frappe.get_doc("Work Order", self.work_order) + pending_qty = flt(work_order.qty) - flt(work_order.produced_qty) for data in self.time_logs: if not data.from_time and not data.to_time: @@ -120,16 +120,16 @@ class Timesheet(Document): if flt(data.hours) == 0.0: frappe.throw(_("Row {0}: Hours value must be greater than zero.").format(data.idx)) - if self.production_order and flt(data.completed_qty) == 0: + if self.work_order and flt(data.completed_qty) == 0: frappe.throw(_("Row {0}: Completed Qty must be greater than zero.").format(data.idx)) - if self.production_order and flt(pending_qty) < flt(data.completed_qty) and flt(pending_qty) > 0: + if self.work_order and flt(pending_qty) < flt(data.completed_qty) and flt(pending_qty) > 0: frappe.throw(_("Row {0}: Completed Qty cannot be more than {1} for operation {2}").format(data.idx, pending_qty, data.operation), - OverProductionLoggedError) + OverWorkLoggedError) - def update_production_order(self, time_sheet): - if self.production_order: - pro = frappe.get_doc('Production Order', self.production_order) + def update_work_order(self, time_sheet): + if self.work_order: + pro = frappe.get_doc('Work Order', self.work_order) for timesheet in self.time_logs: for data in pro.operations: @@ -152,8 +152,8 @@ class Timesheet(Document): return frappe.db.sql("""select sum(tsd.hours*60) as mins, sum(tsd.completed_qty) as completed_qty, min(tsd.from_time) as from_time, max(tsd.to_time) as to_time from `tabTimesheet Detail` as tsd, `tabTimesheet` as ts where - ts.production_order = %s and tsd.operation_id = %s and ts.docstatus=1 and ts.name = tsd.parent""", - (self.production_order, operation_id), as_dict=1)[0] + ts.work_order = %s and tsd.operation_id = %s and ts.docstatus=1 and ts.name = tsd.parent""", + (self.work_order, operation_id), as_dict=1)[0] def update_task_and_project(self): tasks, projects = [], [] @@ -181,7 +181,7 @@ class Timesheet(Document): def validate_overlap(self, data): settings = frappe.get_single('Projects Settings') - if self.production_order: + if self.work_order: self.validate_overlap_for("workstation", data, data.workstation, settings.ignore_workstation_time_overlap) else: self.validate_overlap_for("user", data, self.user, settings.ignore_user_time_overlap) @@ -232,7 +232,7 @@ class Timesheet(Document): if args.workstation and args.from_time and args.to_time: check_if_within_operating_hours(args.workstation, args.operation, args.from_time, args.to_time) - def schedule_for_production_order(self, index): + def schedule_for_work_order(self, index): for data in self.time_logs: if data.idx == index: self.move_to_next_day(data) #check for workstation holiday diff --git a/erpnext/projects/doctype/timesheet_detail/timesheet_detail.json b/erpnext/projects/doctype/timesheet_detail/timesheet_detail.json index fdeb16c8a5f..d82e79d3ede 100644 --- a/erpnext/projects/doctype/timesheet_detail/timesheet_detail.json +++ b/erpnext/projects/doctype/timesheet_detail/timesheet_detail.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_guest_to_view": 0, "allow_import": 0, "allow_rename": 0, "beta": 0, @@ -11,6 +12,7 @@ "editable_grid": 1, "fields": [ { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -21,7 +23,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 1, + "in_standard_filter": 0, "label": "Activity Type", "length": 0, "no_copy": 0, @@ -38,6 +42,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -48,7 +53,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 1, + "in_standard_filter": 0, "label": "From Time", "length": 0, "no_copy": 0, @@ -65,6 +72,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -75,7 +83,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "length": 0, "no_copy": 0, "permlevel": 0, @@ -91,6 +101,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -101,7 +112,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 1, + "in_standard_filter": 0, "label": "Hrs", "length": 0, "no_copy": 0, @@ -117,6 +130,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -127,7 +141,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "To Time", "length": 0, "no_copy": 0, @@ -144,6 +160,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -154,7 +171,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "length": 0, "no_copy": 0, "permlevel": 0, @@ -170,18 +189,21 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, - "depends_on": "eval:parent.production_order", + "depends_on": "eval:parent.work_order", "fieldname": "completed_qty", "fieldtype": "Float", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Completed Qty", "length": 0, "no_copy": 0, @@ -198,18 +220,21 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, - "depends_on": "eval:parent.production_order", + "depends_on": "eval:parent.work_order", "fieldname": "workstation", "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Workstation", "length": 0, "no_copy": 0, @@ -227,6 +252,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -237,7 +263,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "length": 0, "no_copy": 0, "permlevel": 0, @@ -253,18 +281,21 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, - "depends_on": "eval:parent.production_order", + "depends_on": "eval:parent.work_order", "fieldname": "operation", "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Operation", "length": 0, "no_copy": 0, @@ -282,18 +313,21 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, - "depends_on": "eval:parent.production_order", + "depends_on": "eval:parent.work_order", "fieldname": "operation_id", "fieldtype": "Data", "hidden": 1, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Operation Id", "length": 0, "no_copy": 0, @@ -310,6 +344,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -320,7 +355,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "length": 0, "no_copy": 0, "permlevel": 0, @@ -336,6 +373,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -346,7 +384,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 1, + "in_standard_filter": 0, "label": "Project", "length": 0, "no_copy": 0, @@ -364,6 +404,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -374,7 +415,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "length": 0, "no_copy": 0, "permlevel": 0, @@ -390,6 +433,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -401,7 +445,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Task", "length": 0, "no_copy": 0, @@ -419,6 +465,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -429,7 +476,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "length": 0, "no_copy": 0, "permlevel": 0, @@ -445,6 +494,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 1, "bold": 0, "collapsible": 0, @@ -456,7 +506,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 1, + "in_standard_filter": 0, "label": "Bill", "length": 0, "no_copy": 0, @@ -473,6 +525,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -483,7 +536,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "length": 0, "no_copy": 0, "permlevel": 0, @@ -499,6 +554,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 1, "bold": 0, "collapsible": 0, @@ -510,7 +566,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Billing Hours", "length": 0, "no_copy": 0, @@ -527,6 +585,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -538,7 +597,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "length": 0, "no_copy": 0, "permlevel": 0, @@ -554,6 +615,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -565,7 +627,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Billing Rate", "length": 0, "no_copy": 0, @@ -582,6 +646,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 1, "bold": 0, "collapsible": 0, @@ -595,7 +660,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Billing Amount", "length": 0, "no_copy": 0, @@ -612,6 +679,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -622,7 +690,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "length": 0, "no_copy": 0, "permlevel": 0, @@ -638,6 +708,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -648,7 +719,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Costing Rate", "length": 0, "no_copy": 0, @@ -665,6 +738,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 1, "bold": 0, "collapsible": 0, @@ -677,7 +751,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Costing Amount", "length": 0, "no_copy": 0, @@ -694,6 +770,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -704,7 +781,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Reference", "length": 0, "no_copy": 0, @@ -721,6 +800,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 1, "bold": 0, "collapsible": 0, @@ -731,7 +811,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Sales Invoice", "length": 0, "no_copy": 1, @@ -749,17 +831,17 @@ "unique": 0 } ], + "has_web_view": 0, "hide_heading": 0, "hide_toolbar": 0, "idx": 1, "image_view": 0, "in_create": 0, - "in_dialog": 0, "is_submittable": 0, "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2016-11-03 16:01:10.519549", + "modified": "2018-01-07 11:46:04.045313", "modified_by": "Administrator", "module": "Projects", "name": "Timesheet Detail", @@ -768,6 +850,8 @@ "quick_entry": 1, "read_only": 0, "read_only_onload": 0, + "show_name_in_global_search": 0, "sort_order": "ASC", + "track_changes": 0, "track_seen": 0 } \ No newline at end of file diff --git a/erpnext/public/js/help_links.js b/erpnext/public/js/help_links.js index d8af0e516d3..21d02dbc3d8 100644 --- a/erpnext/public/js/help_links.js +++ b/erpnext/public/js/help_links.js @@ -492,8 +492,8 @@ frappe.help.help_links['Form/BOM'] = [ { label: 'Nested BOM Structure', url: 'https://frappe.github.io/erpnext/user/manual/en/manufacturing/articles/nested-bom-structure' }, ] -frappe.help.help_links['Form/Production Order'] = [ - { label: 'Production Order', url: 'https://frappe.github.io/erpnext/user/manual/en/manufacturing/production-order' }, +frappe.help.help_links['Form/Work Order'] = [ + { label: 'Work Order', url: 'https://frappe.github.io/erpnext/user/manual/en/manufacturing/production-order' }, ] frappe.help.help_links['Form/Workstation'] = [ diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js index 0657f9fab27..0aa4cf444b0 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.js +++ b/erpnext/selling/doctype/sales_order/sales_order.js @@ -106,8 +106,8 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend( if(flt(doc.per_delivered, 2) < 100 && ["Sales", "Shopping Cart"].indexOf(doc.order_type)!==-1 && allow_delivery) { this.frm.add_custom_button(__('Delivery'), function() { me.make_delivery_note_based_on_delivery_date(); }, __("Make")); - this.frm.add_custom_button(__('Production Order'), - function() { me.make_production_order() }, __("Make")); + this.frm.add_custom_button(__('Work Order'), + function() { me.make_work_order() }, __("Make")); this.frm.page.set_inner_btn_group_as_primary(__("Make")); } @@ -192,15 +192,15 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend( this.order_type(doc); }, - make_production_order() { + make_work_order() { var me = this; this.frm.call({ doc: this.frm.doc, - method: 'get_production_order_items', + method: 'get_work_order_items', callback: function(r) { if(!r.message) { frappe.msgprint({ - title: __('Production Order not created'), + title: __('Work Order not created'), message: __('No Items with Bill of Materials to Manufacture'), indicator: 'orange' }); @@ -208,8 +208,8 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend( } else if(!r.message) { frappe.msgprint({ - title: __('Production Order not created'), - message: __('Production Order already created for all items with BOM'), + title: __('Work Order not created'), + message: __('Work Order already created for all items with BOM'), indicator: 'orange' }); return; @@ -240,7 +240,7 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend( primary_action: function() { var data = d.get_values(); me.frm.call({ - method: 'make_production_orders', + method: 'make_work_orders', args: { items: data, company: me.frm.doc.company, @@ -251,9 +251,9 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend( callback: function(r) { if(r.message) { frappe.msgprint({ - message: __('Production Orders Created: {0}', + message: __('Work Orders Created: {0}', [r.message.map(function(d) { - return repl('%(name)s', {name:d}) + return repl('%(name)s', {name:d}) }).join(', ')]), indicator: 'green' }) diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index 54595b6da93..34272b211a8 100755 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -242,14 +242,14 @@ class SalesOrder(SellingController): frappe.throw(_("Maintenance Visit {0} must be cancelled before cancelling this Sales Order") .format(comma_and(submit_mv))) - # check production order + # check work order pro_order = frappe.db.sql_list(""" select name - from `tabProduction Order` + from `tabWork Order` where sales_order = %s and docstatus = 1""", self.name) if pro_order: - frappe.throw(_("Production Order {0} must be cancelled before cancelling this Sales Order") + frappe.throw(_("Work Order {0} must be cancelled before cancelling this Sales Order") .format(comma_and(pro_order))) def check_modified_date(self): @@ -347,8 +347,8 @@ class SalesOrder(SellingController): self.indicator_color = "green" self.indicator_title = _("Paid") - def get_production_order_items(self): - '''Returns items with BOM that already do not have a linked production order''' + def get_work_order_items(self): + '''Returns items with BOM that already do not have a linked work order''' items = [] for table in [self.items, self.packed_items]: @@ -356,7 +356,7 @@ class SalesOrder(SellingController): bom = get_default_bom_item(i.item_code) if bom: stock_qty = i.qty if i.doctype == 'Packed Item' else i.stock_qty - pending_qty= stock_qty - flt(frappe.db.sql('''select sum(qty) from `tabProduction Order` + pending_qty= stock_qty - flt(frappe.db.sql('''select sum(qty) from `tabWork Order` where production_item=%s and sales_order=%s and sales_order_item = %s and docstatus<2''', (i.item_code, self.name, i.name))[0][0]) if pending_qty: items.append(dict( @@ -776,8 +776,8 @@ def get_supplier(doctype, txt, searchfield, start, page_len, filters): }) @frappe.whitelist() -def make_production_orders(items, sales_order, company, project=None): - '''Make Production Orders against the given Sales Order for the given `items`''' +def make_work_orders(items, sales_order, company, project=None): + '''Make Work Orders against the given Sales Order for the given `items`''' items = json.loads(items).get('items') out = [] @@ -787,8 +787,8 @@ def make_production_orders(items, sales_order, company, project=None): if not i.get("pending_qty"): frappe.throw(_("Please select Qty against item {0}").format(i.get("item_code"))) - production_order = frappe.get_doc(dict( - doctype='Production Order', + work_order = frappe.get_doc(dict( + doctype='Work Order', production_item=i['item_code'], bom_no=i.get('bom'), qty=i['pending_qty'], @@ -798,9 +798,9 @@ def make_production_orders(items, sales_order, company, project=None): project=project, fg_warehouse=i['warehouse'] )).insert() - production_order.set_production_order_operations() - production_order.save() - out.append(production_order) + work_order.set_work_order_operations() + work_order.save() + out.append(work_order) return [p.name for p in out] diff --git a/erpnext/selling/doctype/sales_order/sales_order_dashboard.py b/erpnext/selling/doctype/sales_order/sales_order_dashboard.py index ffce7ce102d..34ed6bce571 100644 --- a/erpnext/selling/doctype/sales_order/sales_order_dashboard.py +++ b/erpnext/selling/doctype/sales_order/sales_order_dashboard.py @@ -28,7 +28,7 @@ def get_data(): }, { 'label': _('Manufacturing'), - 'items': ['Production Order'] + 'items': ['Work Order'] }, { 'label': _('Reference'), diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py index a1acb215bf6..63376d9c1fe 100644 --- a/erpnext/selling/doctype/sales_order/test_sales_order.py +++ b/erpnext/selling/doctype/sales_order/test_sales_order.py @@ -9,7 +9,7 @@ from erpnext.selling.doctype.sales_order.sales_order \ import make_material_request, make_delivery_note, make_sales_invoice, WarehouseRequired from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry from frappe.tests.test_permissions import set_user_permission_doctypes -from erpnext.selling.doctype.sales_order.sales_order import make_production_orders +from erpnext.selling.doctype.sales_order.sales_order import make_work_orders import json @@ -530,7 +530,7 @@ class TestSalesOrder(unittest.TestCase): si.insert() self.assertTrue(si.get('payment_schedule')) - def test_make_production_order(self): + def test_make_work_order(self): # Make a new Sales Order so = make_sales_order(**{ "item_list": [{ @@ -545,10 +545,10 @@ class TestSalesOrder(unittest.TestCase): }] }) - # Raise Production Orders + # Raise Work Orders po_items= [] so_item_name= {} - for item in so.get_production_order_items(): + for item in so.get_work_order_items(): po_items.append({ "warehouse": item.get("warehouse"), "item_code": item.get("item_code"), @@ -557,12 +557,12 @@ class TestSalesOrder(unittest.TestCase): "bom": item.get("bom") }) so_item_name[item.get("sales_order_item")]= item.get("pending_qty") - make_production_orders(json.dumps({"items":po_items}), so.name, so.company) + make_work_orders(json.dumps({"items":po_items}), so.name, so.company) - # Check if Production Orders were raised + # Check if Work Orders were raised for item in so_item_name: - po_qty = frappe.db.sql("select sum(qty) from `tabProduction Order` where sales_order=%s and sales_order_item=%s", (so.name, item)) - self.assertEqual(po_qty[0][0], so_item_name.get(item)) + wo_qty = frappe.db.sql("select sum(qty) from `tabWork Order` where sales_order=%s and sales_order_item=%s", (so.name, item)) + self.assertEquals(wo_qty[0][0], so_item_name.get(item)) def make_sales_order(**args): so = frappe.new_doc("Sales Order") diff --git a/erpnext/setup/doctype/company/tests/test_company_production.js b/erpnext/setup/doctype/company/tests/test_company_production.js index 37a3d744d06..bf6e5405b42 100644 --- a/erpnext/setup/doctype/company/tests/test_company_production.js +++ b/erpnext/setup/doctype/company/tests/test_company_production.js @@ -4,7 +4,7 @@ QUnit.test("Test: Company", function (assert) { let done = assert.async(); frappe.run_serially([ - // Added company for Production Order testing + // Added company for Work Order testing () => frappe.set_route("List", "Company"), () => frappe.new_doc("Company"), () => frappe.timeout(1), diff --git a/erpnext/startup/notifications.py b/erpnext/startup/notifications.py index 3ab2be4adee..49b770bc46d 100644 --- a/erpnext/startup/notifications.py +++ b/erpnext/startup/notifications.py @@ -52,7 +52,7 @@ def get_notification_config(): "status": ("not in", ("Completed", "Closed")), "docstatus": ("<", 2) }, - "Production Order": { "status": ("in", ("Draft", "Not Started", "In Process")) }, + "Work Order": { "status": ("in", ("Draft", "Not Started", "In Process")) }, "BOM": {"docstatus": 0}, "Timesheet": {"status": "Draft"}, diff --git a/erpnext/startup/report_data_map.py b/erpnext/startup/report_data_map.py index 3d5a6740214..d127065f66f 100644 --- a/erpnext/startup/report_data_map.py +++ b/erpnext/startup/report_data_map.py @@ -97,7 +97,7 @@ data_map = { "conditions": ["docstatus=1"], "order_by": "posting_date, posting_time, name", }, - "Production Order": { + "Work Order": { "columns": ["name", "production_item as item_code", "(qty - produced_qty) as qty", "fg_warehouse as warehouse"], @@ -293,7 +293,7 @@ data_map = { }, # Manufacturing - "Production Order": { + "Work Order": { "columns": ["name","status","creation","planned_start_date","planned_end_date","status","actual_start_date","actual_end_date", "modified"], "conditions": ["docstatus = 1"], "order_by": "creation" diff --git a/erpnext/stock/doctype/batch/test_batch.py b/erpnext/stock/doctype/batch/test_batch.py index b545ee4f384..a2c7802686c 100644 --- a/erpnext/stock/doctype/batch/test_batch.py +++ b/erpnext/stock/doctype/batch/test_batch.py @@ -49,7 +49,7 @@ class TestBatch(unittest.TestCase): return receipt def test_stock_entry_incoming(self): - '''Test batch creation via Stock Entry (Production Order)''' + '''Test batch creation via Stock Entry (Work Order)''' self.make_batch_item('ITEM-BATCH-1') diff --git a/erpnext/stock/doctype/bin/bin.py b/erpnext/stock/doctype/bin/bin.py index 430d9fb4043..d8ed37ea50b 100644 --- a/erpnext/stock/doctype/bin/bin.py +++ b/erpnext/stock/doctype/bin/bin.py @@ -75,9 +75,9 @@ class Bin(Document): def update_reserved_qty_for_production(self): '''Update qty reserved for production from Production Item tables - in open production orders''' + in open work orders''' self.reserved_qty_for_production = frappe.db.sql('''select sum(required_qty - transferred_qty) - from `tabProduction Order` pro, `tabProduction Order Item` item + from `tabWork Order` pro, `tabWork Order Item` item where item.item_code = %s and item.parent = pro.name diff --git a/erpnext/stock/doctype/item/item_dashboard.py b/erpnext/stock/doctype/item/item_dashboard.py index c7210864c5b..21608a6d97a 100644 --- a/erpnext/stock/doctype/item/item_dashboard.py +++ b/erpnext/stock/doctype/item/item_dashboard.py @@ -7,7 +7,7 @@ def get_data(): .format('' + _('Stock Ledger') + ''), 'fieldname': 'item_code', 'non_standard_fieldnames': { - 'Production Order': 'production_item', + 'Work Order': 'production_item', 'Product Bundle': 'new_item_code', 'BOM': 'item', 'Batch': 'item' @@ -40,7 +40,7 @@ def get_data(): }, { 'label': _('Manufacture'), - 'items': ['Production Order'] + 'items': ['Work Order'] } ] } \ No newline at end of file diff --git a/erpnext/stock/doctype/material_request/material_request.js b/erpnext/stock/doctype/material_request/material_request.js index 709c2c7d192..caf4e498ab9 100644 --- a/erpnext/stock/doctype/material_request/material_request.js +++ b/erpnext/stock/doctype/material_request/material_request.js @@ -10,7 +10,7 @@ frappe.ui.form.on('Material Request', { 'Purchase Order': 'Purchase Order', 'Request for Quotation': 'Request for Quotation', 'Supplier Quotation': 'Supplier Quotation', - 'Production Order': 'Production Order' + 'Work Order': 'Work Order' } // formatter for material request item @@ -98,8 +98,8 @@ erpnext.buying.MaterialRequestController = erpnext.buying.BuyingController.exten this.make_supplier_quotation, __("Make")); if(doc.material_request_type === "Manufacture") - cur_frm.add_custom_button(__("Production Order"), - function() { me.raise_production_orders() }, __("Make")); + cur_frm.add_custom_button(__("Work Order"), + function() { me.raise_work_orders() }, __("Make")); cur_frm.page.set_inner_btn_group_as_primary(__("Make")); @@ -224,10 +224,10 @@ erpnext.buying.MaterialRequestController = erpnext.buying.BuyingController.exten }); }, - raise_production_orders: function() { + raise_work_orders: function() { var me = this; frappe.call({ - method:"erpnext.stock.doctype.material_request.material_request.raise_production_orders", + method:"erpnext.stock.doctype.material_request.material_request.raise_work_orders", args: { "material_request": me.frm.doc.name }, diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py index 7ddea715059..d4dc5233565 100644 --- a/erpnext/stock/doctype/material_request/material_request.py +++ b/erpnext/stock/doctype/material_request/material_request.py @@ -12,7 +12,7 @@ from frappe import msgprint, _ from frappe.model.mapper import get_mapped_doc from erpnext.stock.stock_balance import update_bin_qty, get_indented_qty from erpnext.controllers.buying_controller import BuyingController -from erpnext.manufacturing.doctype.production_order.production_order import get_item_details +from erpnext.manufacturing.doctype.work_order.work_order import get_item_details from erpnext.buying.utils import check_for_closed_status, validate_for_items from six import string_types @@ -168,7 +168,7 @@ class MaterialRequest(BuyingController): elif self.material_request_type == "Manufacture": d.ordered_qty = flt(frappe.db.sql("""select sum(qty) - from `tabProduction Order` where material_request = %s + from `tabWork Order` where material_request = %s and material_request_item = %s and docstatus = 1""", (self.name, d.name))[0][0]) @@ -415,36 +415,36 @@ def make_stock_entry(source_name, target_doc=None): return doclist @frappe.whitelist() -def raise_production_orders(material_request): +def raise_work_orders(material_request): mr= frappe.get_doc("Material Request", material_request) errors =[] - production_orders = [] + work_orders = [] default_wip_warehouse = frappe.db.get_single_value("Manufacturing Settings", "default_wip_warehouse") for d in mr.items: if (d.qty - d.ordered_qty) >0: if frappe.db.get_value("BOM", {"item": d.item_code, "is_default": 1}): - prod_order = frappe.new_doc("Production Order") - prod_order.production_item = d.item_code - prod_order.qty = d.qty - d.ordered_qty - prod_order.fg_warehouse = d.warehouse - prod_order.wip_warehouse = default_wip_warehouse - prod_order.description = d.description - prod_order.stock_uom = d.stock_uom - prod_order.expected_delivery_date = d.schedule_date - prod_order.sales_order = d.sales_order - prod_order.bom_no = get_item_details(d.item_code).bom_no - prod_order.material_request = mr.name - prod_order.material_request_item = d.name - prod_order.planned_start_date = mr.transaction_date - prod_order.company = mr.company - prod_order.save() - production_orders.append(prod_order.name) + wo_order = frappe.new_doc("Work Order") + wo_order.production_item = d.item_code + wo_order.qty = d.qty - d.ordered_qty + wo_order.fg_warehouse = d.warehouse + wo_order.wip_warehouse = default_wip_warehouse + wo_order.description = d.description + wo_order.stock_uom = d.stock_uom + wo_order.expected_delivery_date = d.schedule_date + wo_order.sales_order = d.sales_order + wo_order.bom_no = get_item_details(d.item_code).bom_no + wo_order.material_request = mr.name + wo_order.material_request_item = d.name + wo_order.planned_start_date = mr.transaction_date + wo_order.company = mr.company + wo_order.save() + work_orders.append(wo_order.name) else: errors.append(_("Row {0}: Bill of Materials not found for the Item {1}").format(d.idx, d.item_code)) - if production_orders: - message = ["""%s""" % \ - (p, p) for p in production_orders] - msgprint(_("The following Production Orders were created:") + '\n' + new_line_sep(message)) + if work_orders: + message = ["""%s""" % \ + (p, p) for p in work_orders] + msgprint(_("The following Work Orders were created:") + '\n' + new_line_sep(message)) if errors: frappe.throw(_("Productions Orders cannot be raised for:") + '\n' + new_line_sep(errors)) - return production_orders + return work_orders diff --git a/erpnext/stock/doctype/material_request/material_request_dashboard.py b/erpnext/stock/doctype/material_request/material_request_dashboard.py index 751c7237303..c3fe8f3222e 100644 --- a/erpnext/stock/doctype/material_request/material_request_dashboard.py +++ b/erpnext/stock/doctype/material_request/material_request_dashboard.py @@ -11,7 +11,7 @@ def get_data(): }, { 'label': _('Manufacturing'), - 'items': ['Production Order'] + 'items': ['Work Order'] } ] } \ No newline at end of file diff --git a/erpnext/stock/doctype/material_request/test_material_request.py b/erpnext/stock/doctype/material_request/test_material_request.py index 3c5012ca4a3..6b0b7bb4861 100644 --- a/erpnext/stock/doctype/material_request/test_material_request.py +++ b/erpnext/stock/doctype/material_request/test_material_request.py @@ -7,7 +7,7 @@ from __future__ import unicode_literals import frappe, unittest, erpnext from frappe.utils import flt, today -from erpnext.stock.doctype.material_request.material_request import raise_production_orders +from erpnext.stock.doctype.material_request.material_request import raise_work_orders class TestMaterialRequest(unittest.TestCase): def setUp(self): @@ -536,8 +536,8 @@ class TestMaterialRequest(unittest.TestCase): requested_qty = frappe.db.sql("""select indented_qty from `tabBin` where \ item_code= %s and warehouse= %s """, (mr.items[0].item_code, mr.items[0].warehouse))[0][0] - prod_order = raise_production_orders(mr.name) - po = frappe.get_doc("Production Order", prod_order[0]) + prod_order = raise_work_orders(mr.name) + po = frappe.get_doc("Work Order", prod_order[0]) po.wip_warehouse = "_Test Warehouse 1 - _TC" po.submit() diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js index b4d8e1500be..c9d50f6d757 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.js +++ b/erpnext/stock/doctype/stock_entry/stock_entry.js @@ -4,12 +4,12 @@ frappe.provide("erpnext.stock"); frappe.ui.form.on('Stock Entry', { setup: function(frm) { - frm.set_query('production_order', function() { + frm.set_query('work_order', function() { return { filters: [ - ['Production Order', 'docstatus', '=', 1], - ['Production Order', 'qty', '>','`tabProduction Order`.produced_qty'], - ['Production Order', 'company', '=', frm.doc.company] + ['Work Order', 'docstatus', '=', 1], + ['Work Order', 'qty', '>','`tabWork Order`.produced_qty'], + ['Work Order', 'company', '=', frm.doc.company] ] } }); @@ -565,11 +565,11 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({ }, clean_up: function() { - // Clear Production Order record from locals, because it is updated via Stock Entry - if(this.frm.doc.production_order && + // Clear Work Order record from locals, because it is updated via Stock Entry + if(this.frm.doc.work_order && in_list(["Manufacture", "Material Transfer for Manufacture"], this.frm.doc.purpose)) { - frappe.model.remove_from_locals("Production Order", - this.frm.doc.production_order); + frappe.model.remove_from_locals("Work Order", + this.frm.doc.work_order); } }, @@ -578,8 +578,8 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({ if(!this.frm.doc.fg_completed_qty || !this.frm.doc.bom_no) frappe.throw(__("BOM and Manufacturing Quantity are required")); - if(this.frm.doc.production_order || this.frm.doc.bom_no) { - // if production order / bom is mentioned, get items + if(this.frm.doc.work_order || this.frm.doc.bom_no) { + // if work order / bom is mentioned, get items return this.frm.call({ doc: me.frm.doc, method: "get_items", @@ -590,17 +590,17 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({ } }, - production_order: function() { + work_order: function() { var me = this; this.toggle_enable_bom(); - if(!me.frm.doc.production_order) { + if(!me.frm.doc.work_order) { return; } return frappe.call({ - method: "erpnext.stock.doctype.stock_entry.stock_entry.get_production_order_details", + method: "erpnext.stock.doctype.stock_entry.stock_entry.get_work_order_details", args: { - production_order: me.frm.doc.production_order + work_order: me.frm.doc.work_order }, callback: function(r) { if (!r.exc) { @@ -630,7 +630,7 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({ }, toggle_enable_bom: function() { - this.frm.toggle_enable("bom_no", !!!this.frm.doc.production_order); + this.frm.toggle_enable("bom_no", !!!this.frm.doc.work_order); }, add_excise_button: function() { diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.json b/erpnext/stock/doctype/stock_entry/stock_entry.json index b6ad6dae4e2..9107bcddb91 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.json +++ b/erpnext/stock/doctype/stock_entry/stock_entry.json @@ -178,7 +178,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:in_list([\"Material Transfer for Manufacture\", \"Manufacture\"], doc.purpose)", - "fieldname": "production_order", + "fieldname": "work_order", "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, @@ -187,12 +187,12 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Production Order", + "label": "Work Order", "length": 0, "no_copy": 0, "oldfieldname": "production_order", "oldfieldtype": "Link", - "options": "Production Order", + "options": "Work Order", "permlevel": 0, "print_hide": 1, "print_hide_if_no_value": 0, @@ -1894,7 +1894,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-03-01 12:27:12.884611", + "modified": "2018-03-13 12:27:12.884611", "modified_by": "Administrator", "module": "Stock", "name": "Stock Entry", diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 6cb81d8773a..9da35aae05b 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -17,7 +17,7 @@ import json from six import string_types class IncorrectValuationRateError(frappe.ValidationError): pass -class DuplicateEntryForProductionOrderError(frappe.ValidationError): pass +class DuplicateEntryForWorkOrderError(frappe.ValidationError): pass class OperationsNotCompleteError(frappe.ValidationError): pass class MaxSampleAlreadyRetainedError(frappe.ValidationError): pass @@ -37,8 +37,8 @@ class StockEntry(StockController): def validate(self): self.pro_doc = frappe._dict() - if self.production_order: - self.pro_doc = frappe.get_doc('Production Order', self.production_order) + if self.work_order: + self.pro_doc = frappe.get_doc('Work Order', self.work_order) self.validate_posting_time() self.validate_purpose() @@ -47,7 +47,7 @@ class StockEntry(StockController): self.validate_uom_is_integer("uom", "qty") self.validate_uom_is_integer("stock_uom", "transfer_qty") self.validate_warehouse() - self.validate_production_order() + self.validate_work_order() self.validate_bom() self.validate_finished_goods() self.validate_with_material_request() @@ -72,7 +72,7 @@ class StockEntry(StockController): from erpnext.stock.doctype.serial_no.serial_no import update_serial_nos_after_submit update_serial_nos_after_submit(self, "items") - self.update_production_order() + self.update_work_order() self.validate_purchase_order() if self.purchase_order and self.purpose == "Subcontract": self.update_purchase_order_supplied_items() @@ -80,7 +80,7 @@ class StockEntry(StockController): def on_cancel(self): self.update_stock_ledger() - self.update_production_order() + self.update_work_order() if self.purchase_order and self.purpose == "Subcontract": self.update_purchase_order_supplied_items() self.make_gl_entries_on_cancel() @@ -172,7 +172,7 @@ class StockEntry(StockController): frappe.throw(_("Target warehouse is mandatory for row {0}").format(d.idx)) elif self.pro_doc and (cstr(d.t_warehouse) != self.pro_doc.fg_warehouse and cstr(d.t_warehouse) != self.pro_doc.scrap_warehouse): - frappe.throw(_("Target warehouse in row {0} must be same as Production Order").format(d.idx)) + frappe.throw(_("Target warehouse in row {0} must be same as Work Order").format(d.idx)) else: d.t_warehouse = None @@ -182,39 +182,39 @@ class StockEntry(StockController): if cstr(d.s_warehouse) == cstr(d.t_warehouse) and not self.purpose == "Material Transfer for Manufacture": frappe.throw(_("Source and target warehouse cannot be same for row {0}").format(d.idx)) - def validate_production_order(self): + def validate_work_order(self): if self.purpose in ("Manufacture", "Material Transfer for Manufacture"): - # check if production order is entered + # check if work order is entered - if self.purpose=="Manufacture" and self.production_order: + if self.purpose=="Manufacture" and self.work_order: if not self.fg_completed_qty: frappe.throw(_("For Quantity (Manufactured Qty) is mandatory")) self.check_if_operations_completed() - self.check_duplicate_entry_for_production_order() + self.check_duplicate_entry_for_work_order() elif self.purpose != "Material Transfer": - self.production_order = None + self.work_order = None def check_if_operations_completed(self): """Check if Time Sheets are completed against before manufacturing to capture operating costs.""" - prod_order = frappe.get_doc("Production Order", self.production_order) + prod_order = frappe.get_doc("Work Order", self.work_order) for d in prod_order.get("operations"): total_completed_qty = flt(self.fg_completed_qty) + flt(prod_order.produced_qty) if total_completed_qty > flt(d.completed_qty): - frappe.throw(_("Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Production Order # {3}. Please update operation status via Time Logs") - .format(d.idx, d.operation, total_completed_qty, self.production_order), OperationsNotCompleteError) + frappe.throw(_("Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order # {3}. Please update operation status via Time Logs") + .format(d.idx, d.operation, total_completed_qty, self.work_order), OperationsNotCompleteError) - def check_duplicate_entry_for_production_order(self): + def check_duplicate_entry_for_work_order(self): other_ste = [t[0] for t in frappe.db.get_values("Stock Entry", { - "production_order": self.production_order, + "work_order": self.work_order, "purpose": self.purpose, "docstatus": ["!=", 2], "name": ["!=", self.name] }, "name")] if other_ste: - production_item, qty = frappe.db.get_value("Production Order", - self.production_order, ["production_item", "qty"]) + production_item, qty = frappe.db.get_value("Work Order", + self.work_order, ["production_item", "qty"]) args = other_ste + [production_item] fg_qty_already_entered = frappe.db.sql("""select sum(transfer_qty) from `tabStock Entry Detail` @@ -223,8 +223,8 @@ class StockEntry(StockController): and ifnull(s_warehouse,'')='' """ % (", ".join(["%s" * len(other_ste)]), "%s"), args)[0][0] if fg_qty_already_entered >= qty: - frappe.throw(_("Stock Entries already created for Production Order ") - + self.production_order + ":" + ", ".join(other_ste), DuplicateEntryForProductionOrderError) + frappe.throw(_("Stock Entries already created for Work Order ") + + self.work_order + ":" + ", ".join(other_ste), DuplicateEntryForWorkOrderError) def set_incoming_rate(self): for d in self.items: @@ -261,8 +261,8 @@ class StockEntry(StockController): frappe.bold(d.transfer_qty)), NegativeStockError, title=_('Insufficient Stock')) - def set_serial_nos(self, production_order): - previous_se = frappe.db.get_value("Stock Entry", {"production_order": production_order, + def set_serial_nos(self, work_order): + previous_se = frappe.db.get_value("Stock Entry", {"work_order": work_order, "purpose": "Material Transfer for Manufacture"}, "name") for d in self.get('items'): @@ -273,7 +273,7 @@ class StockEntry(StockController): d.serial_no = transferred_serial_no def get_stock_and_rate(self): - self.set_production_order_details() + self.set_work_order_details() self.set_transfer_qty() self.set_actual_qty() self.calculate_rate_and_amount() @@ -418,12 +418,12 @@ class StockEntry(StockController): frappe.throw(_("Quantity in row {0} ({1}) must be same as manufactured quantity {2}"). \ format(d.idx, d.transfer_qty, self.fg_completed_qty)) - if self.production_order and self.purpose == "Manufacture" and d.t_warehouse: + if self.work_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 self.work_order and self.purpose == "Manufacture": + production_item = frappe.db.get_value("Work Order", + self.work_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)) @@ -489,20 +489,20 @@ class StockEntry(StockController): return gl_entries - def update_production_order(self): - def _validate_production_order(pro_doc): + def update_work_order(self): + def _validate_work_order(pro_doc): if flt(pro_doc.docstatus) != 1: - frappe.throw(_("Production Order {0} must be submitted").format(self.production_order)) + frappe.throw(_("Work Order {0} must be submitted").format(self.work_order)) if pro_doc.status == 'Stopped': - frappe.throw(_("Transaction not allowed against stopped Production Order {0}").format(self.production_order)) + frappe.throw(_("Transaction not allowed against stopped Work Order {0}").format(self.work_order)) - if self.production_order: - pro_doc = frappe.get_doc("Production Order", self.production_order) - _validate_production_order(pro_doc) + if self.work_order: + pro_doc = frappe.get_doc("Work Order", self.work_order) + _validate_work_order(pro_doc) pro_doc.run_method("update_status") if self.fg_completed_qty: - pro_doc.run_method("update_production_order_qty") + pro_doc.run_method("update_work_order_qty") if self.purpose == "Manufacture": pro_doc.run_method("update_planned_qty") @@ -567,24 +567,24 @@ class StockEntry(StockController): def get_items(self): self.set('items', []) - self.validate_production_order() + self.validate_work_order() if not self.posting_date or not self.posting_time: frappe.throw(_("Posting date and posting time is mandatory")) - self.set_production_order_details() + self.set_work_order_details() if self.bom_no: if self.purpose in ["Material Issue", "Material Transfer", "Manufacture", "Repack", "Subcontract", "Material Transfer for Manufacture"]: - if self.production_order and self.purpose == "Material Transfer for Manufacture": + if self.work_order and self.purpose == "Material Transfer for Manufacture": item_dict = self.get_pending_raw_materials() if self.to_warehouse and self.pro_doc: for item in item_dict.values(): item["to_warehouse"] = self.pro_doc.wip_warehouse self.add_to_stock_entry_detail(item_dict) - elif self.production_order and self.purpose == "Manufacture" and \ + elif self.work_order and self.purpose == "Manufacture" and \ frappe.db.get_single_value("Manufacturing Settings", "backflush_raw_materials_based_on")== "Material Transferred for Manufacture": self.get_transfered_raw_materials() @@ -595,6 +595,7 @@ class StockEntry(StockController): item_dict = self.get_bom_raw_materials(self.fg_completed_qty) #Get PO Supplied Items Details + print('Purchase Order', self.purchase_order, self.purpose) if self.purchase_order and self.purpose == "Subcontract": #Get PO Supplied Items Details item_wh = frappe._dict(frappe.db.sql(""" @@ -621,8 +622,8 @@ class StockEntry(StockController): self.add_to_stock_entry_detail(scrap_item_dict, bom_no=self.bom_no) # fetch the serial_no of the first stock entry for the second stock entry - if self.production_order and self.purpose == "Manufacture": - self.set_serial_nos(self.production_order) + if self.work_order and self.purpose == "Manufacture": + self.set_serial_nos(self.work_order) # add finished goods item if self.purpose in ("Manufacture", "Repack"): @@ -631,23 +632,23 @@ class StockEntry(StockController): self.set_actual_qty() self.calculate_rate_and_amount(raise_error_if_no_rate=False) - def set_production_order_details(self): + def set_work_order_details(self): if not getattr(self, "pro_doc", None): self.pro_doc = frappe._dict() - if self.production_order: + if self.work_order: # common validations if not self.pro_doc: - self.pro_doc = frappe.get_doc('Production Order', self.production_order) + self.pro_doc = frappe.get_doc('Work Order', self.work_order) if self.pro_doc: self.bom_no = self.pro_doc.bom_no else: - # invalid production order - self.production_order = None + # invalid work order + self.work_order = None def load_items_from_bom(self): - if self.production_order: + if self.work_order: item_code = self.pro_doc.production_item to_warehouse = self.pro_doc.fg_warehouse else: @@ -657,7 +658,7 @@ class StockEntry(StockController): item = frappe.db.get_value("Item", item_code, ["item_name", "description", "stock_uom", "expense_account", "buying_cost_center", "name", "default_warehouse"], as_dict=1) - if not self.production_order and not to_warehouse: + if not self.work_order and not to_warehouse: # in case of BOM to_warehouse = item.default_warehouse @@ -705,9 +706,9 @@ class StockEntry(StockController): from `tabStock Entry` se,`tabStock Entry Detail` sed where se.name = sed.parent and se.docstatus=1 and se.purpose='Material Transfer for Manufacture' - and se.production_order= %s and ifnull(sed.t_warehouse, '') != '' + and se.work_order= %s and ifnull(sed.t_warehouse, '') != '' group by sed.item_code, sed.t_warehouse - """, self.production_order, as_dict=1) + """, self.work_order, as_dict=1) materials_already_backflushed = frappe.db.sql(""" select @@ -716,16 +717,16 @@ class StockEntry(StockController): `tabStock Entry` se, `tabStock Entry Detail` sed where se.name = sed.parent and se.docstatus=1 and se.purpose='Manufacture' - and se.production_order= %s and ifnull(sed.s_warehouse, '') != '' + and se.work_order= %s and ifnull(sed.s_warehouse, '') != '' group by sed.item_code, sed.s_warehouse - """, self.production_order, as_dict=1) + """, self.work_order, as_dict=1) backflushed_materials= {} for d in materials_already_backflushed: backflushed_materials.setdefault(d.item_code,[]).append({d.warehouse: d.qty}) po_qty = frappe.db.sql("""select qty, produced_qty, material_transferred_for_manufacturing from - `tabProduction Order` where name=%s""", self.production_order, as_dict=1)[0] + `tabWork Order` where name=%s""", self.work_order, as_dict=1)[0] manufacturing_qty = flt(po_qty.qty) produced_qty = flt(po_qty.produced_qty) trans_qty = flt(po_qty.material_transferred_for_manufacturing) @@ -780,13 +781,13 @@ class StockEntry(StockController): # show some message 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 Work Order.""")) return item_dict def get_pro_order_required_items(self): item_dict = frappe._dict() - pro_order = frappe.get_doc("Production Order", self.production_order) + pro_order = frappe.get_doc("Work Order", self.work_order) if not frappe.db.get_value("Warehouse", pro_order.wip_warehouse, "is_group"): wip_warehouse = pro_order.wip_warehouse else: @@ -908,32 +909,32 @@ def move_sample_to_retention_warehouse(company, items): return stock_entry.as_dict() @frappe.whitelist() -def get_production_order_details(production_order): - production_order = frappe.get_doc("Production Order", production_order) - pending_qty_to_produce = flt(production_order.qty) - flt(production_order.produced_qty) +def get_work_order_details(work_order): + work_order = frappe.get_doc("Work Order", work_order) + pending_qty_to_produce = flt(work_order.qty) - flt(work_order.produced_qty) return { "from_bom": 1, - "bom_no": production_order.bom_no, - "use_multi_level_bom": production_order.use_multi_level_bom, - "wip_warehouse": production_order.wip_warehouse, - "fg_warehouse": production_order.fg_warehouse, + "bom_no": work_order.bom_no, + "use_multi_level_bom": work_order.use_multi_level_bom, + "wip_warehouse": work_order.wip_warehouse, + "fg_warehouse": work_order.fg_warehouse, "fg_completed_qty": pending_qty_to_produce, - "additional_costs": get_additional_costs(production_order, fg_qty=pending_qty_to_produce) + "additional_costs": get_additional_costs(work_order, fg_qty=pending_qty_to_produce) } -def get_additional_costs(production_order=None, bom_no=None, fg_qty=None): +def get_additional_costs(work_order=None, bom_no=None, fg_qty=None): additional_costs = [] - operating_cost_per_unit = get_operating_cost_per_unit(production_order, bom_no) + operating_cost_per_unit = get_operating_cost_per_unit(work_order, bom_no) if operating_cost_per_unit: additional_costs.append({ - "description": "Operating Cost as per Production Order / BOM", + "description": "Operating Cost as per Work Order / BOM", "amount": operating_cost_per_unit * flt(fg_qty) }) - if production_order and production_order.additional_operating_cost and production_order.qty: + if work_order and work_order.additional_operating_cost and work_order.qty: additional_operating_cost_per_unit = \ - flt(production_order.additional_operating_cost) / flt(production_order.qty) + flt(work_order.additional_operating_cost) / flt(work_order.qty) additional_costs.append({ "description": "Additional Operating Cost", @@ -942,19 +943,19 @@ def get_additional_costs(production_order=None, bom_no=None, fg_qty=None): return additional_costs -def get_operating_cost_per_unit(production_order=None, bom_no=None): +def get_operating_cost_per_unit(work_order=None, bom_no=None): operating_cost_per_unit = 0 - if production_order: + if work_order: if not bom_no: - bom_no = production_order.bom_no + bom_no = work_order.bom_no - for d in production_order.get("operations"): + for d in work_order.get("operations"): if flt(d.completed_qty): operating_cost_per_unit += flt(d.actual_operating_cost) / flt(d.completed_qty) - elif production_order.qty: - operating_cost_per_unit += flt(d.planned_operating_cost) / flt(production_order.qty) + elif work_order.qty: + operating_cost_per_unit += flt(d.planned_operating_cost) / flt(work_order.qty) - # Get operating cost from BOM if not found in production_order. + # Get operating cost from BOM if not found in work_order. if not operating_cost_per_unit and bom_no: bom = frappe.db.get_value("BOM", bom_no, ["operating_cost", "quantity"], as_dict=1) if bom.quantity: diff --git a/erpnext/stock/doctype/stock_entry/stock_entry_list.js b/erpnext/stock/doctype/stock_entry/stock_entry_list.js index db0620968d6..0f84b6da8d7 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry_list.js +++ b/erpnext/stock/doctype/stock_entry/stock_entry_list.js @@ -1,6 +1,6 @@ frappe.listview_settings['Stock Entry'] = { add_fields: ["`tabStock Entry`.`from_warehouse`", "`tabStock Entry`.`to_warehouse`", - "`tabStock Entry`.`purpose`", "`tabStock Entry`.`production_order`", "`tabStock Entry`.`bom_no`"], + "`tabStock Entry`.`purpose`", "`tabStock Entry`.`work_order`", "`tabStock Entry`.`bom_no`"], column_render: { "from_warehouse": function(doc) { var html = ""; diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py index d4b015a9f69..7f98a0c943d 100644 --- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py @@ -538,14 +538,14 @@ class TestStockEntry(unittest.TestCase): self.assertRaises(StockFreezeError, se.submit) frappe.db.set_value("Stock Settings", None, "stock_frozen_upto_days", 0) - def test_production_order(self): - from erpnext.manufacturing.doctype.production_order.production_order \ + def test_work_order(self): + from erpnext.manufacturing.doctype.work_order.work_order \ import make_stock_entry as _make_stock_entry bom_no, bom_operation_cost = frappe.db.get_value("BOM", {"item": "_Test FG Item 2", "is_default": 1, "docstatus": 1}, ["name", "operating_cost"]) - production_order = frappe.new_doc("Production Order") - production_order.update({ + work_order = frappe.new_doc("Work Order") + work_order.update({ "company": "_Test Company", "fg_warehouse": "_Test Warehouse 1 - _TC", "production_item": "_Test FG Item 2", @@ -555,13 +555,13 @@ class TestStockEntry(unittest.TestCase): "wip_warehouse": "_Test Warehouse - _TC", "additional_operating_cost": 1000 }) - production_order.insert() - production_order.submit() + work_order.insert() + work_order.submit() make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, basic_rate=100) make_stock_entry(item_code="_Test Item 2", target="_Test Warehouse - _TC", qty=50, basic_rate=20) - stock_entry = _make_stock_entry(production_order.name, "Manufacture", 1) + stock_entry = _make_stock_entry(work_order.name, "Manufacture", 1) rm_cost = 0 for d in stock_entry.get("items"): @@ -569,15 +569,15 @@ class TestStockEntry(unittest.TestCase): rm_cost += flt(d.amount) fg_cost = filter(lambda x: x.item_code=="_Test FG Item 2", stock_entry.get("items"))[0].amount self.assertEqual(fg_cost, - flt(rm_cost + bom_operation_cost + production_order.additional_operating_cost, 2)) + flt(rm_cost + bom_operation_cost + work_order.additional_operating_cost, 2)) - def test_variant_production_order(self): + def test_variant_work_order(self): bom_no = frappe.db.get_value("BOM", {"item": "_Test Variant Item", "is_default": 1, "docstatus": 1}) - production_order = frappe.new_doc("Production Order") - production_order.update({ + work_order = frappe.new_doc("Work Order") + work_order.update({ "company": "_Test Company", "fg_warehouse": "_Test Warehouse 1 - _TC", "production_item": "_Test Variant Item-S", @@ -586,12 +586,12 @@ class TestStockEntry(unittest.TestCase): "stock_uom": "_Test UOM", "wip_warehouse": "_Test Warehouse - _TC" }) - production_order.insert() - production_order.submit() + work_order.insert() + work_order.submit() - from erpnext.manufacturing.doctype.production_order.production_order import make_stock_entry + from erpnext.manufacturing.doctype.work_order.work_order import make_stock_entry - stock_entry = frappe.get_doc(make_stock_entry(production_order.name, "Manufacture", 1)) + stock_entry = frappe.get_doc(make_stock_entry(work_order.name, "Manufacture", 1)) stock_entry.insert() self.assertTrue("_Test Variant Item-S" in [d.item_code for d in stock_entry.items]) diff --git a/erpnext/stock/stock_balance.py b/erpnext/stock/stock_balance.py index 49909d9c56f..90c82c43c3e 100644 --- a/erpnext/stock/stock_balance.py +++ b/erpnext/stock/stock_balance.py @@ -131,7 +131,7 @@ def get_ordered_qty(item_code, warehouse): def get_planned_qty(item_code, warehouse): planned_qty = frappe.db.sql(""" - select sum(qty - produced_qty) from `tabProduction Order` + select sum(qty - produced_qty) from `tabWork Order` where production_item = %s and fg_warehouse = %s and status not in ("Stopped", "Completed") and docstatus=1 and qty > produced_qty""", (item_code, warehouse)) diff --git a/erpnext/tests/ui/tests.txt b/erpnext/tests/ui/tests.txt index 37885f34822..e13795ccec3 100644 --- a/erpnext/tests/ui/tests.txt +++ b/erpnext/tests/ui/tests.txt @@ -40,7 +40,7 @@ erpnext/hr/doctype/leave_control_panel/test_leave_control_panel.js erpnext/hr/doctype/leave_allocation/test_leave_allocation.js erpnext/hr/doctype/leave_application/test_leave_application.js erpnext/stock/doctype/warehouse/test_warehouse.js -erpnext/manufacturing/doctype/production_order/test_production_order.js #long +erpnext/manufacturing/doctype/work_order/test_work_order.js #long erpnext/accounts/page/pos/test_pos.js erpnext/selling/page/point_of_sale/tests/test_point_of_sale.js erpnext/selling/doctype/product_bundle/test_product_bundle.js