[enhance] Production Plan (#12160)
* [enhance] Production plan * Test cases * Removed production planning tool * Documentation * Added actual qty in material request production item * Renamed field 'Use Multilevel BOM' to 'Include Exploded Items'
@ -217,11 +217,6 @@ def get_data():
|
|||||||
"label": _("Bill of Materials"),
|
"label": _("Bill of Materials"),
|
||||||
"youtube_id": "hDV0c1OeWLo"
|
"youtube_id": "hDV0c1OeWLo"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"type": "help",
|
|
||||||
"label": _("Production Planning Tool"),
|
|
||||||
"youtube_id": "CzatSl4zJ2Y"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "help",
|
"type": "help",
|
||||||
"label": _("Production Order"),
|
"label": _("Production Order"),
|
||||||
|
@ -14,7 +14,7 @@ def get_data():
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "doctype",
|
"type": "doctype",
|
||||||
"name": "Production Planning Tool",
|
"name": "Production Plan",
|
||||||
"description": _("Generate Material Requests (MRP) and Production Orders."),
|
"description": _("Generate Material Requests (MRP) and Production Orders."),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -141,11 +141,6 @@ def get_data():
|
|||||||
"label": _("Bill of Materials"),
|
"label": _("Bill of Materials"),
|
||||||
"youtube_id": "hDV0c1OeWLo"
|
"youtube_id": "hDV0c1OeWLo"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"type": "help",
|
|
||||||
"label": _("Production Planning Tool"),
|
|
||||||
"youtube_id": "CzatSl4zJ2Y"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "help",
|
"type": "help",
|
||||||
"label": _("Production Order"),
|
"label": _("Production Order"),
|
||||||
|
BIN
erpnext/docs/assets/img/manufacturing/make_po_mr.png
Normal file
After Width: | Height: | Size: 37 KiB |
After Width: | Height: | Size: 29 KiB |
BIN
erpnext/docs/assets/img/manufacturing/material_request_items.png
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
erpnext/docs/assets/img/manufacturing/material_request_plan.png
Normal file
After Width: | Height: | Size: 45 KiB |
BIN
erpnext/docs/assets/img/manufacturing/material_requests.png
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
erpnext/docs/assets/img/manufacturing/production_plan.png
Normal file
After Width: | Height: | Size: 102 KiB |
BIN
erpnext/docs/assets/img/manufacturing/sales_order_filter.png
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
erpnext/docs/assets/img/manufacturing/sales_order_items.png
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
erpnext/docs/assets/img/manufacturing/sales_orders.png
Normal file
After Width: | Height: | Size: 32 KiB |
53
erpnext/docs/user/manual/en/manufacturing/production-plan.md
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
# Production Plan
|
||||||
|
|
||||||
|
Production plan helps user to plan production aginst the multiple sales orders or the material requests and also plan for the purchase of the raw materials which will be used in the production.
|
||||||
|
|
||||||
|
To use the Production Plan, go to:
|
||||||
|
|
||||||
|
> Manufacturing > Production > Production Plan
|
||||||
|
|
||||||
|
<img class="screenshot" alt="Production Plan" src="/docs/assets/img/manufacturing/production_plan.png">
|
||||||
|
|
||||||
|
## Planning for Production
|
||||||
|
|
||||||
|
#### Production Against Sales Orders
|
||||||
|
|
||||||
|
* Select option as Sales Order from the drop down list of get items from. System will show the filters, using that we can pull the sales orders for the production.
|
||||||
|
|
||||||
|
<img class="screenshot" alt="Sales Order Filters" src="/docs/assets/img/manufacturing/sales_order_filter.png">
|
||||||
|
|
||||||
|
* Click on Get Sales Orders to fetch sales orders based on above filters
|
||||||
|
|
||||||
|
<img class="screenshot" alt="Sales Orders" src="/docs/assets/img/manufacturing/sales_orders.png">
|
||||||
|
|
||||||
|
* Click on Get Items for Production Order to fetch the items from the above sales orders.
|
||||||
|
|
||||||
|
<img class="screenshot" alt="Sales Order Item" src="/docs/assets/img/manufacturing/sales_order_items.png">
|
||||||
|
* Include Exploded Items :- To include subassembly items of raw materials in the production.
|
||||||
|
|
||||||
|
#### Production Against Material Requests
|
||||||
|
|
||||||
|
* Select option as Material Request from the drop down list of get items from. System will show the filters, using that we can pull the material requests for the production.
|
||||||
|
|
||||||
|
<img class="screenshot" alt="Material Request Filters" src="/docs/assets/img/manufacturing/material_request_filter.png">
|
||||||
|
|
||||||
|
* Click on Get Material Request to fetch material requests based on above filters
|
||||||
|
|
||||||
|
<img class="screenshot" alt="Material Requests" src="/docs/assets/img/manufacturing/material_requests.png">
|
||||||
|
|
||||||
|
* Click on Get Items for Production Order to fetch the items from the above material requests.
|
||||||
|
|
||||||
|
<img class="screenshot" alt="Material Request Item" src="/docs/assets/img/manufacturing/material_request_items.png">
|
||||||
|
|
||||||
|
## Planning for Material Requests
|
||||||
|
* Click on get raw materials for production button to fetech raw materials required in the production.
|
||||||
|
|
||||||
|
<img class="screenshot" alt="Material Request Plan" src="/docs/assets/img/manufacturing/material_request_plan.png">
|
||||||
|
|
||||||
|
* Include Non Stock Items :- To add non stock items in the material request planning.
|
||||||
|
* Include Subcontracted Items :- To add subcontracted item's raw materials if include exploded items is disabled
|
||||||
|
* Ignore Existing Ordered Quantity :- If enabled then system will not check the projected quantity to make material request.
|
||||||
|
|
||||||
|
# Options To Make Production Order and Material Request
|
||||||
|
|
||||||
|
<img class="screenshot" alt="Make PO or MR" src="/docs/assets/img/manufacturing/make_po_mr.png">
|
@ -0,0 +1,8 @@
|
|||||||
|
// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
// For license information, please see license.txt
|
||||||
|
|
||||||
|
frappe.ui.form.on('Material Request Plan Item', {
|
||||||
|
refresh: function() {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
@ -0,0 +1,344 @@
|
|||||||
|
{
|
||||||
|
"allow_copy": 0,
|
||||||
|
"allow_guest_to_view": 0,
|
||||||
|
"allow_import": 0,
|
||||||
|
"allow_rename": 0,
|
||||||
|
"beta": 0,
|
||||||
|
"creation": "2017-12-01 12:12:55.048691",
|
||||||
|
"custom": 0,
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "DocType",
|
||||||
|
"document_type": "",
|
||||||
|
"editable_grid": 1,
|
||||||
|
"engine": "InnoDB",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "item_code",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Item Code",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "Item",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 1,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "item_name",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"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": "Item Name",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "warehouse",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 1,
|
||||||
|
"label": "Warehouse",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "Warehouse",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 1,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "column_break_4",
|
||||||
|
"fieldtype": "Column Break",
|
||||||
|
"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,
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "quantity",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Quantity",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 1,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 1,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "actual_qty",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Actual Qty",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 1,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "min_order_qty",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Minimum Order Quantity",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 1,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "section_break_8",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"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": "Reference",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "sales_order",
|
||||||
|
"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": "Sales Order",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "Sales Order",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "requested_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": "Requested Qty",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"has_web_view": 0,
|
||||||
|
"hide_heading": 0,
|
||||||
|
"hide_toolbar": 0,
|
||||||
|
"idx": 0,
|
||||||
|
"image_view": 0,
|
||||||
|
"in_create": 0,
|
||||||
|
"is_submittable": 0,
|
||||||
|
"issingle": 0,
|
||||||
|
"istable": 1,
|
||||||
|
"max_attachments": 0,
|
||||||
|
"modified": "2018-02-15 13:08:30.535963",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Manufacturing",
|
||||||
|
"name": "Material Request Plan Item",
|
||||||
|
"name_case": "",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"permissions": [],
|
||||||
|
"quick_entry": 1,
|
||||||
|
"read_only": 0,
|
||||||
|
"read_only_onload": 0,
|
||||||
|
"show_name_in_global_search": 0,
|
||||||
|
"sort_field": "modified",
|
||||||
|
"sort_order": "DESC",
|
||||||
|
"track_changes": 1,
|
||||||
|
"track_seen": 0
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
from frappe.model.document import Document
|
||||||
|
|
||||||
|
class MaterialRequestPlanItem(Document):
|
||||||
|
pass
|
@ -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: Material Request Plan Item", function (assert) {
|
||||||
|
let done = assert.async();
|
||||||
|
|
||||||
|
// number of asserts
|
||||||
|
assert.expect(1);
|
||||||
|
|
||||||
|
frappe.run_serially([
|
||||||
|
// insert a new Material Request Plan Item
|
||||||
|
() => frappe.tests.make('Material Request Plan Item', [
|
||||||
|
// values to be set
|
||||||
|
{key: 'value'}
|
||||||
|
]),
|
||||||
|
() => {
|
||||||
|
assert.equal(cur_frm.doc.key, 'value');
|
||||||
|
},
|
||||||
|
() => done()
|
||||||
|
]);
|
||||||
|
|
||||||
|
});
|
@ -0,0 +1,9 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
|
# See license.txt
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
class TestMaterialRequestPlanItem(unittest.TestCase):
|
||||||
|
pass
|
@ -1344,6 +1344,67 @@
|
|||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "production_plan",
|
||||||
|
"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": "Production Plan",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 1,
|
||||||
|
"options": "Production Plan",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 1,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "production_plan_item",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"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": "Production Plan Item",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 1,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 1,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@ -1388,7 +1449,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2017-11-03 05:31:56.636724",
|
"modified": "2017-12-20 05:31:56.636724",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "Production Order",
|
"name": "Production Order",
|
||||||
|
@ -189,6 +189,13 @@ class ProductionOrder(Document):
|
|||||||
|
|
||||||
self.db_set(fieldname, qty)
|
self.db_set(fieldname, qty)
|
||||||
|
|
||||||
|
if self.production_plan:
|
||||||
|
self.update_production_plan_status()
|
||||||
|
|
||||||
|
def update_production_plan_status(self):
|
||||||
|
production_plan = frappe.get_doc('Production Plan', self.production_plan)
|
||||||
|
production_plan.run_method("update_produced_qty", self.produced_qty, self.production_plan_item)
|
||||||
|
|
||||||
def before_submit(self):
|
def before_submit(self):
|
||||||
self.make_time_logs()
|
self.make_time_logs()
|
||||||
|
|
||||||
@ -201,6 +208,7 @@ class ProductionOrder(Document):
|
|||||||
self.update_reserved_qty_for_production()
|
self.update_reserved_qty_for_production()
|
||||||
self.update_completed_qty_in_material_request()
|
self.update_completed_qty_in_material_request()
|
||||||
self.update_planned_qty()
|
self.update_planned_qty()
|
||||||
|
self.update_ordered_qty()
|
||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
self.validate_cancel()
|
self.validate_cancel()
|
||||||
@ -209,6 +217,7 @@ class ProductionOrder(Document):
|
|||||||
self.delete_timesheet()
|
self.delete_timesheet()
|
||||||
self.update_completed_qty_in_material_request()
|
self.update_completed_qty_in_material_request()
|
||||||
self.update_planned_qty()
|
self.update_planned_qty()
|
||||||
|
self.update_ordered_qty()
|
||||||
self.update_reserved_qty_for_production()
|
self.update_reserved_qty_for_production()
|
||||||
|
|
||||||
def validate_cancel(self):
|
def validate_cancel(self):
|
||||||
@ -230,6 +239,16 @@ class ProductionOrder(Document):
|
|||||||
mr_obj = frappe.get_doc("Material Request", self.material_request)
|
mr_obj = frappe.get_doc("Material Request", self.material_request)
|
||||||
mr_obj.update_requested_qty([self.material_request_item])
|
mr_obj.update_requested_qty([self.material_request_item])
|
||||||
|
|
||||||
|
def update_ordered_qty(self):
|
||||||
|
if self.production_plan and self.production_plan_item:
|
||||||
|
qty = self.qty if self.docstatus == 1 else 0
|
||||||
|
frappe.db.set_value('Production Plan Item',
|
||||||
|
self.production_plan_item, 'ordered_qty', qty)
|
||||||
|
|
||||||
|
doc = frappe.get_doc('Production Plan', self.production_plan)
|
||||||
|
doc.set_status()
|
||||||
|
doc.db_set('status', doc.status)
|
||||||
|
|
||||||
def update_completed_qty_in_material_request(self):
|
def update_completed_qty_in_material_request(self):
|
||||||
if self.material_request:
|
if self.material_request:
|
||||||
frappe.get_doc("Material Request", self.material_request).update_completed_qty([self.material_request_item])
|
frappe.get_doc("Material Request", self.material_request).update_completed_qty([self.material_request_item])
|
||||||
|
168
erpnext/manufacturing/doctype/production_plan/production_plan.js
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
// For license information, please see license.txt
|
||||||
|
|
||||||
|
frappe.ui.form.on('Production Plan', {
|
||||||
|
setup: function(frm) {
|
||||||
|
frm.fields_dict['po_items'].grid.get_field('warehouse').get_query = function(doc) {
|
||||||
|
return {
|
||||||
|
filters: {
|
||||||
|
company: doc.company
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
frm.fields_dict['po_items'].grid.get_field('bom_no').get_query = function(doc, cdt, cdn) {
|
||||||
|
var d = locals[cdt][cdn];
|
||||||
|
if (d.item_code) {
|
||||||
|
return {
|
||||||
|
query: "erpnext.controllers.queries.bom",
|
||||||
|
filters:{'item': cstr(d.item_code)}
|
||||||
|
}
|
||||||
|
} else frappe.msgprint(__("Please enter Item first"));
|
||||||
|
}
|
||||||
|
|
||||||
|
frm.fields_dict['mr_items'].grid.get_field('warehouse').get_query = function(doc) {
|
||||||
|
return {
|
||||||
|
filters: {
|
||||||
|
company: doc.company
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
refresh: function(frm) {
|
||||||
|
if (frm.doc.docstatus === 1) {
|
||||||
|
frm.trigger("show_progress");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frm.doc.docstatus === 1 && frm.doc.po_items
|
||||||
|
&& frm.doc.status != 'Completed') {
|
||||||
|
frm.add_custom_button(__("Production Order"), ()=> {
|
||||||
|
frm.trigger("make_production_order");
|
||||||
|
}, __("Make"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frm.doc.docstatus === 1 && frm.doc.mr_items
|
||||||
|
&& !in_list(['Material Requested', 'Completed'], frm.doc.status)) {
|
||||||
|
frm.add_custom_button(__("Material Request"), ()=> {
|
||||||
|
frm.trigger("make_material_request");
|
||||||
|
}, __("Make"));
|
||||||
|
}
|
||||||
|
|
||||||
|
frm.trigger("material_requirement");
|
||||||
|
},
|
||||||
|
|
||||||
|
make_production_order: function(frm) {
|
||||||
|
frappe.call({
|
||||||
|
method: "make_production_order",
|
||||||
|
freeze: true,
|
||||||
|
doc: frm.doc,
|
||||||
|
callback: function() {
|
||||||
|
frm.reload_doc();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
make_material_request: function(frm) {
|
||||||
|
frappe.call({
|
||||||
|
method: "make_material_request",
|
||||||
|
freeze: true,
|
||||||
|
doc: frm.doc,
|
||||||
|
callback: function(r) {
|
||||||
|
frm.reload_doc();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
get_sales_orders: function(frm) {
|
||||||
|
frappe.call({
|
||||||
|
method: "get_open_sales_orders",
|
||||||
|
doc: frm.doc,
|
||||||
|
callback: function(r) {
|
||||||
|
refresh_field("sales_orders");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
get_material_request: function(frm) {
|
||||||
|
frappe.call({
|
||||||
|
method: "get_pending_material_requests",
|
||||||
|
doc: frm.doc,
|
||||||
|
callback: function() {
|
||||||
|
refresh_field('material_requests');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
get_items: function(frm) {
|
||||||
|
frappe.call({
|
||||||
|
method: "get_items",
|
||||||
|
freeze: true,
|
||||||
|
doc: frm.doc,
|
||||||
|
callback: function() {
|
||||||
|
refresh_field('po_items');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
get_items_for_mr: function(frm) {
|
||||||
|
frappe.call({
|
||||||
|
method: "get_items_for_material_requests",
|
||||||
|
freeze: true,
|
||||||
|
doc: frm.doc,
|
||||||
|
callback: function() {
|
||||||
|
refresh_field('mr_items');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
show_progress: function(frm) {
|
||||||
|
var bars = [];
|
||||||
|
var message = '';
|
||||||
|
var title = '';
|
||||||
|
|
||||||
|
// produced qty
|
||||||
|
let item_wise_qty = {};
|
||||||
|
frm.doc.po_items.forEach((data) => {
|
||||||
|
if(!item_wise_qty[data.item_code]) {
|
||||||
|
item_wise_qty[data.item_code] = data.produced_qty;
|
||||||
|
} else {
|
||||||
|
item_wise_qty[data.item_code] += data.produced_qty;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (item_wise_qty) {
|
||||||
|
for (var key in item_wise_qty) {
|
||||||
|
title += __('Item {0}: {1} qty produced, ', [key, item_wise_qty[key]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bars.push({
|
||||||
|
'title': title,
|
||||||
|
'width': (frm.doc.total_produced_qty / frm.doc.total_planned_qty * 100) + '%',
|
||||||
|
'progress_class': 'progress-bar-success'
|
||||||
|
});
|
||||||
|
if (bars[0].width == '0%') {
|
||||||
|
bars[0].width = '0.5%';
|
||||||
|
}
|
||||||
|
message = title;
|
||||||
|
frm.dashboard.add_progress(__('Status'), bars, message);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
frappe.ui.form.on("Material Request Plan Item", {
|
||||||
|
warehouse: function(frm, cdt, cdn) {
|
||||||
|
const row = locals[cdt][cdn];
|
||||||
|
if (row.warehouse && row.item_code) {
|
||||||
|
frappe.call({
|
||||||
|
method: "erpnext.manufacturing.doctype.production_plan.production_plan.get_bin_details",
|
||||||
|
args: {
|
||||||
|
row: row
|
||||||
|
},
|
||||||
|
callback: function(r) {
|
||||||
|
frappe.model.set_value(cdt, cdn, 'actual_qty', r.message[1])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
499
erpnext/manufacturing/doctype/production_plan/production_plan.py
Normal file
@ -0,0 +1,499 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe, json
|
||||||
|
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
|
||||||
|
|
||||||
|
class ProductionPlan(Document):
|
||||||
|
def validate(self):
|
||||||
|
self.calculate_total_planned_qty()
|
||||||
|
self.set_status()
|
||||||
|
|
||||||
|
def validate_data(self):
|
||||||
|
for d in self.get('po_items'):
|
||||||
|
if not d.bom_no:
|
||||||
|
frappe.throw(_("Please select BOM for Item in Row {0}".format(d.idx)))
|
||||||
|
else:
|
||||||
|
validate_bom_no(d.item_code, d.bom_no)
|
||||||
|
|
||||||
|
if not flt(d.planned_qty):
|
||||||
|
frappe.throw(_("Please enter Planned Qty for Item {0} at row {1}").format(d.item_code, d.idx))
|
||||||
|
|
||||||
|
def get_open_sales_orders(self):
|
||||||
|
""" Pull sales orders which are pending to deliver based on criteria selected"""
|
||||||
|
so_filter = item_filter = ""
|
||||||
|
if self.from_date:
|
||||||
|
so_filter += " and so.transaction_date >= %(from_date)s"
|
||||||
|
if self.to_date:
|
||||||
|
so_filter += " and so.transaction_date <= %(to_date)s"
|
||||||
|
if self.customer:
|
||||||
|
so_filter += " and so.customer = %(customer)s"
|
||||||
|
if self.project:
|
||||||
|
so_filter += " and so.project = %(project)s"
|
||||||
|
|
||||||
|
if self.item_code:
|
||||||
|
item_filter += " and so_item.item_code = %(item)s"
|
||||||
|
|
||||||
|
open_so = frappe.db.sql("""
|
||||||
|
select distinct so.name, so.transaction_date, so.customer, so.base_grand_total
|
||||||
|
from `tabSales Order` so, `tabSales Order Item` so_item
|
||||||
|
where so_item.parent = so.name
|
||||||
|
and so.docstatus = 1 and so.status not in ("Stopped", "Closed")
|
||||||
|
and so.company = %(company)s
|
||||||
|
and so_item.qty > so_item.delivered_qty {0} {1}
|
||||||
|
and (exists (select name from `tabBOM` bom where bom.item=so_item.item_code
|
||||||
|
and bom.is_active = 1)
|
||||||
|
or exists (select name from `tabPacked Item` pi
|
||||||
|
where pi.parent = so.name and pi.parent_item = so_item.item_code
|
||||||
|
and exists (select name from `tabBOM` bom where bom.item=pi.item_code
|
||||||
|
and bom.is_active = 1)))
|
||||||
|
""".format(so_filter, item_filter), {
|
||||||
|
"from_date": self.from_date,
|
||||||
|
"to_date": self.to_date,
|
||||||
|
"customer": self.customer,
|
||||||
|
"project": self.project,
|
||||||
|
"item": self.item_code,
|
||||||
|
"company": self.company
|
||||||
|
}, as_dict=1)
|
||||||
|
|
||||||
|
self.add_so_in_table(open_so)
|
||||||
|
|
||||||
|
def add_so_in_table(self, open_so):
|
||||||
|
""" Add sales orders in the table"""
|
||||||
|
self.set('sales_orders', [])
|
||||||
|
|
||||||
|
for data in open_so:
|
||||||
|
self.append('sales_orders', {
|
||||||
|
'sales_order': data.name,
|
||||||
|
'sales_order_date': data.transaction_date,
|
||||||
|
'customer': data.customer,
|
||||||
|
'grand_total': data.grand_total
|
||||||
|
})
|
||||||
|
|
||||||
|
def get_pending_material_requests(self):
|
||||||
|
""" Pull Material Requests that are pending based on criteria selected"""
|
||||||
|
mr_filter = item_filter = ""
|
||||||
|
if self.from_date:
|
||||||
|
mr_filter += " and mr.transaction_date >= %(from_date)s"
|
||||||
|
if self.to_date:
|
||||||
|
mr_filter += " and mr.transaction_date <= %(to_date)s"
|
||||||
|
if self.warehouse:
|
||||||
|
mr_filter += " and mr_item.warehouse = %(warehouse)s"
|
||||||
|
|
||||||
|
if self.item_code:
|
||||||
|
item_filter += " and mr_item.item_code = %(item)s"
|
||||||
|
|
||||||
|
pending_mr = frappe.db.sql("""
|
||||||
|
select distinct mr.name, mr.transaction_date
|
||||||
|
from `tabMaterial Request` mr, `tabMaterial Request Item` mr_item
|
||||||
|
where mr_item.parent = mr.name
|
||||||
|
and mr.material_request_type = "Manufacture"
|
||||||
|
and mr.docstatus = 1 and mr.company = %(company)s
|
||||||
|
and mr_item.qty > ifnull(mr_item.ordered_qty,0) {0} {1}
|
||||||
|
and (exists (select name from `tabBOM` bom where bom.item=mr_item.item_code
|
||||||
|
and bom.is_active = 1))
|
||||||
|
""".format(mr_filter, item_filter), {
|
||||||
|
"from_date": self.from_date,
|
||||||
|
"to_date": self.to_date,
|
||||||
|
"warehouse": self.warehouse,
|
||||||
|
"item": self.item_code,
|
||||||
|
"company": self.company
|
||||||
|
}, as_dict=1)
|
||||||
|
|
||||||
|
self.add_mr_in_table(pending_mr)
|
||||||
|
|
||||||
|
def add_mr_in_table(self, pending_mr):
|
||||||
|
""" Add Material Requests in the table"""
|
||||||
|
self.set('material_requests', [])
|
||||||
|
|
||||||
|
for data in pending_mr:
|
||||||
|
self.append('material_requests', {
|
||||||
|
'material_request': data.name,
|
||||||
|
'material_request_date': data.transaction_date
|
||||||
|
})
|
||||||
|
|
||||||
|
def get_items(self):
|
||||||
|
if self.get_items_from == "Sales Order":
|
||||||
|
self.get_so_items()
|
||||||
|
elif self.get_items_from == "Material Request":
|
||||||
|
self.get_mr_items()
|
||||||
|
|
||||||
|
def get_so_items(self):
|
||||||
|
so_list = [d.sales_order for d in self.sales_orders if d.sales_order]
|
||||||
|
if not so_list:
|
||||||
|
msgprint(_("Please enter Sales Orders in the above table"))
|
||||||
|
return []
|
||||||
|
|
||||||
|
item_condition = ""
|
||||||
|
if self.item_code:
|
||||||
|
item_condition = ' and so_item.item_code = "{0}"'.format(frappe.db.escape(self.item_code))
|
||||||
|
|
||||||
|
items = frappe.db.sql("""select distinct parent, item_code, warehouse,
|
||||||
|
(qty - delivered_qty)*conversion_factor as pending_qty
|
||||||
|
from `tabSales Order Item` so_item
|
||||||
|
where parent in (%s) and docstatus = 1 and qty > delivered_qty
|
||||||
|
and exists (select name from `tabBOM` bom where bom.item=so_item.item_code
|
||||||
|
and bom.is_active = 1) %s""" % \
|
||||||
|
(", ".join(["%s"] * len(so_list)), item_condition), tuple(so_list), as_dict=1)
|
||||||
|
|
||||||
|
if self.item_code:
|
||||||
|
item_condition = ' and pi.item_code = "{0}"'.format(frappe.db.escape(self.item_code))
|
||||||
|
|
||||||
|
packed_items = frappe.db.sql("""select distinct pi.parent, pi.item_code, pi.warehouse as warehouse,
|
||||||
|
(((so_item.qty - so_item.delivered_qty) * pi.qty) / so_item.qty)
|
||||||
|
as pending_qty
|
||||||
|
from `tabSales Order Item` so_item, `tabPacked Item` pi
|
||||||
|
where so_item.parent = pi.parent and so_item.docstatus = 1
|
||||||
|
and pi.parent_item = so_item.item_code
|
||||||
|
and so_item.parent in (%s) and so_item.qty > so_item.delivered_qty
|
||||||
|
and exists (select name from `tabBOM` bom where bom.item=pi.item_code
|
||||||
|
and bom.is_active = 1) %s""" % \
|
||||||
|
(", ".join(["%s"] * len(so_list)), item_condition), tuple(so_list), as_dict=1)
|
||||||
|
|
||||||
|
self.add_items(items + packed_items)
|
||||||
|
self.calculate_total_planned_qty()
|
||||||
|
|
||||||
|
def get_mr_items(self):
|
||||||
|
mr_list = [d.material_request for d in self.material_requests if d.material_request]
|
||||||
|
if not mr_list:
|
||||||
|
msgprint(_("Please enter Material Requests in the above table"))
|
||||||
|
return []
|
||||||
|
|
||||||
|
item_condition = ""
|
||||||
|
if self.item_code:
|
||||||
|
item_condition = " and mr_item.item_code ='{0}'".format(frappe.db.escape(self.item_code))
|
||||||
|
|
||||||
|
items = frappe.db.sql("""select distinct parent, name, item_code, warehouse,
|
||||||
|
(qty - ordered_qty) as pending_qty
|
||||||
|
from `tabMaterial Request Item` mr_item
|
||||||
|
where parent in (%s) and docstatus = 1 and qty > ordered_qty
|
||||||
|
and exists (select name from `tabBOM` bom where bom.item=mr_item.item_code
|
||||||
|
and bom.is_active = 1) %s""" % \
|
||||||
|
(", ".join(["%s"] * len(mr_list)), item_condition), tuple(mr_list), as_dict=1)
|
||||||
|
|
||||||
|
self.add_items(items)
|
||||||
|
self.calculate_total_planned_qty()
|
||||||
|
|
||||||
|
def add_items(self, items):
|
||||||
|
self.set('po_items', [])
|
||||||
|
for data in items:
|
||||||
|
item_details = get_item_details(data.item_code)
|
||||||
|
pi = self.append('po_items', {
|
||||||
|
'include_exploded_items': 1,
|
||||||
|
'warehouse': data.warehouse,
|
||||||
|
'item_code': data.item_code,
|
||||||
|
'description': item_details and item_details.description or '',
|
||||||
|
'stock_uom': item_details and item_details.stock_uom or '',
|
||||||
|
'bom_no': item_details and item_details.bom_no or '',
|
||||||
|
'planned_qty': data.pending_qty,
|
||||||
|
'pending_qty': data.pending_qty,
|
||||||
|
'planned_start_date': now_datetime()
|
||||||
|
})
|
||||||
|
|
||||||
|
if self.get_items_from == "Sales Order":
|
||||||
|
pi.sales_order = data.parent
|
||||||
|
pi.sales_order_item = data.name
|
||||||
|
|
||||||
|
elif self.get_items_from == "Material Request":
|
||||||
|
pi.material_request = data.parent
|
||||||
|
pi.material_request_item = data.name
|
||||||
|
|
||||||
|
def calculate_total_planned_qty(self):
|
||||||
|
self.total_planned_qty = 0
|
||||||
|
for d in self.po_items:
|
||||||
|
self.total_planned_qty += flt(d.planned_qty)
|
||||||
|
|
||||||
|
def calculate_total_produced_qty(self):
|
||||||
|
self.total_produced_qty = 0
|
||||||
|
for d in self.po_items:
|
||||||
|
self.total_produced_qty += flt(d.produced_qty)
|
||||||
|
|
||||||
|
self.db_set("total_produced_qty", self.total_produced_qty, update_modified=False)
|
||||||
|
|
||||||
|
def update_produced_qty(self, produced_qty, production_plan_item):
|
||||||
|
for data in self.po_items:
|
||||||
|
if data.name == production_plan_item:
|
||||||
|
data.produced_qty = produced_qty
|
||||||
|
data.db_update()
|
||||||
|
|
||||||
|
self.calculate_total_produced_qty()
|
||||||
|
self.set_status()
|
||||||
|
self.db_set('status', self.status)
|
||||||
|
|
||||||
|
def on_cancel(self):
|
||||||
|
self.db_set('status', 'Cancelled')
|
||||||
|
self.delete_draft_production_order()
|
||||||
|
|
||||||
|
def delete_draft_production_order(self):
|
||||||
|
for d in frappe.get_all('Production Order', fields = ["name"],
|
||||||
|
filters = {'docstatus': 0, 'production_plan': ("=", self.name)}):
|
||||||
|
frappe.delete_doc('Production Order', d.name)
|
||||||
|
|
||||||
|
def set_status(self):
|
||||||
|
self.status = {
|
||||||
|
'0': 'Draft',
|
||||||
|
'1': 'Submitted'
|
||||||
|
}[cstr(self.docstatus or 0)]
|
||||||
|
|
||||||
|
if self.total_produced_qty > 0:
|
||||||
|
self.status = "In Process"
|
||||||
|
if self.total_produced_qty == self.total_planned_qty:
|
||||||
|
self.status = "Completed"
|
||||||
|
|
||||||
|
if self.status != 'Completed':
|
||||||
|
self.update_ordered_status()
|
||||||
|
self.update_requested_status()
|
||||||
|
|
||||||
|
def update_ordered_status(self):
|
||||||
|
update_status = False
|
||||||
|
for d in self.po_items:
|
||||||
|
if d.planned_qty == d.ordered_qty:
|
||||||
|
update_status = True
|
||||||
|
|
||||||
|
if update_status and self.status != 'Completed':
|
||||||
|
self.status = 'In Process'
|
||||||
|
|
||||||
|
def update_requested_status(self):
|
||||||
|
update_status = True
|
||||||
|
for d in self.mr_items:
|
||||||
|
if d.quantity != d.requested_qty:
|
||||||
|
update_status = False
|
||||||
|
|
||||||
|
if update_status:
|
||||||
|
self.status = 'Material Requested'
|
||||||
|
|
||||||
|
def get_production_items(self):
|
||||||
|
item_dict = {}
|
||||||
|
for d in self.po_items:
|
||||||
|
item_details= {
|
||||||
|
"production_item" : d.item_code,
|
||||||
|
"use_multi_level_bom" : d.include_exploded_items,
|
||||||
|
"sales_order" : d.sales_order,
|
||||||
|
"material_request" : d.material_request,
|
||||||
|
"material_request_item" : d.material_request_item,
|
||||||
|
"bom_no" : d.bom_no,
|
||||||
|
"description" : d.description,
|
||||||
|
"stock_uom" : d.stock_uom,
|
||||||
|
"company" : self.company,
|
||||||
|
"fg_warehouse" : d.warehouse,
|
||||||
|
"production_plan" : self.name,
|
||||||
|
"production_plan_item" : d.name
|
||||||
|
}
|
||||||
|
|
||||||
|
item_details.update({
|
||||||
|
"project": self.project or frappe.db.get_value("Sales Order", d.sales_order, "project")
|
||||||
|
})
|
||||||
|
|
||||||
|
if self.get_items_from == "Material Request":
|
||||||
|
item_details.update({
|
||||||
|
"qty": d.planned_qty
|
||||||
|
})
|
||||||
|
item_dict[(d.item_code, d.material_request_item, d.warehouse)] = item_details
|
||||||
|
else:
|
||||||
|
item_details.update({
|
||||||
|
"qty":flt(item_dict.get((d.item_code, d.sales_order, d.warehouse),{})
|
||||||
|
.get("qty")) + flt(d.planned_qty)
|
||||||
|
})
|
||||||
|
item_dict[(d.item_code, d.sales_order, d.warehouse)] = item_details
|
||||||
|
|
||||||
|
return item_dict
|
||||||
|
|
||||||
|
def get_items_for_material_requests(self):
|
||||||
|
self.mr_items = []
|
||||||
|
|
||||||
|
for data in self.po_items:
|
||||||
|
bom_wise_item_details = {}
|
||||||
|
if not data.planned_qty:
|
||||||
|
frappe.throw(_("For row {0}: Enter planned qty").format(data.idx))
|
||||||
|
|
||||||
|
if data.include_exploded_items and data.bom_no and self.include_subcontracted_items:
|
||||||
|
for d in frappe.db.sql("""select bei.item_code, item.default_bom as bom,
|
||||||
|
ifnull(sum(bei.stock_qty/ifnull(bom.quantity, 1)), 0) as qty, item.item_name,
|
||||||
|
bei.description, bei.stock_uom, item.min_order_qty, bei.source_warehouse,
|
||||||
|
item.default_material_request_type, item.min_order_qty, item.default_warehouse
|
||||||
|
from
|
||||||
|
`tabBOM Explosion Item` bei, `tabBOM` bom, `tabItem` item
|
||||||
|
where
|
||||||
|
bom.name = bei.parent and item.name = bei.item_code
|
||||||
|
and bei.docstatus < 2 and bom.name=%s and item.is_stock_item in (1, {0})
|
||||||
|
group by bei.item_code, bei.stock_uom""".format(self.include_non_stock_items),
|
||||||
|
data.bom_no, as_dict=1):
|
||||||
|
bom_wise_item_details.setdefault(d.item_code, d)
|
||||||
|
else:
|
||||||
|
bom_wise_item_details = self.get_subitems(data, bom_wise_item_details, data.bom_no, 1)
|
||||||
|
|
||||||
|
for item, item_details in bom_wise_item_details.items():
|
||||||
|
if item_details.qty > 0:
|
||||||
|
self.add_item_in_material_request_items(item, item_details, data)
|
||||||
|
|
||||||
|
def get_subitems(self, data, bom_wise_item_details, bom_no, parent_qty):
|
||||||
|
items = frappe.db.sql("""
|
||||||
|
SELECT
|
||||||
|
bom_item.item_code, default_material_request_type, item.item_name,
|
||||||
|
ifnull(%(parent_qty)s * sum(bom_item.stock_qty/ifnull(bom.quantity, 1)), 0) as qty,
|
||||||
|
item.is_sub_contracted_item as is_sub_contracted, bom_item.source_warehouse,
|
||||||
|
item.default_bom as default_bom, bom_item.description as description,
|
||||||
|
bom_item.stock_uom as stock_uom, item.min_order_qty as min_order_qty,
|
||||||
|
item.default_warehouse
|
||||||
|
FROM
|
||||||
|
`tabBOM Item` bom_item, `tabBOM` bom, tabItem item
|
||||||
|
where
|
||||||
|
bom.name = bom_item.parent and bom.name = %(bom)s
|
||||||
|
and bom_item.docstatus < 2 and bom_item.item_code = item.name
|
||||||
|
and item.is_stock_item in (1, {0})
|
||||||
|
group by bom_item.item_code""".format(self.include_non_stock_items),{
|
||||||
|
'bom': bom_no,
|
||||||
|
'parent_qty': parent_qty
|
||||||
|
}, as_dict=1)
|
||||||
|
|
||||||
|
for d in items:
|
||||||
|
if not data.include_exploded_items or not d.default_bom:
|
||||||
|
if d.item_code in bom_wise_item_details:
|
||||||
|
bom_wise_item_details[d.item_code].qty = bom_wise_item_details[d.item_code].qty + d.qty
|
||||||
|
else:
|
||||||
|
bom_wise_item_details[d.item_code] = d
|
||||||
|
|
||||||
|
if data.include_exploded_items and d.default_bom:
|
||||||
|
if ((d.default_material_request_type in ["Manufacture", "Purchase"] and
|
||||||
|
not d.is_sub_contracted) or (d.is_sub_contracted and self.include_subcontracted_items)):
|
||||||
|
if d.qty > 0:
|
||||||
|
self.get_subitems(data, bom_wise_item_details, d.default_bom, d.qty)
|
||||||
|
|
||||||
|
return bom_wise_item_details
|
||||||
|
|
||||||
|
def add_item_in_material_request_items(self, item, row, data):
|
||||||
|
total_qty = row.qty * data.planned_qty
|
||||||
|
projected_qty, actual_qty = get_bin_details(row)
|
||||||
|
|
||||||
|
requested_qty = 0
|
||||||
|
if self.ignore_existing_ordered_qty:
|
||||||
|
requested_qty = total_qty
|
||||||
|
elif total_qty > projected_qty:
|
||||||
|
requested_qty = total_qty - projected_qty
|
||||||
|
|
||||||
|
if requested_qty and requested_qty < row.min_order_qty:
|
||||||
|
requested_qty = row.min_order_qty
|
||||||
|
|
||||||
|
if requested_qty > 0:
|
||||||
|
self.append('mr_items', {
|
||||||
|
'item_code': item,
|
||||||
|
'item_name': row.item_name,
|
||||||
|
'quantity': requested_qty,
|
||||||
|
'warehouse': row.source_warehouse or row.default_warehouse,
|
||||||
|
'actual_qty': actual_qty,
|
||||||
|
'min_order_qty': row.min_order_qty,
|
||||||
|
'sales_order': data.sales_order
|
||||||
|
})
|
||||||
|
|
||||||
|
def make_production_order(self):
|
||||||
|
pro_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)
|
||||||
|
|
||||||
|
frappe.flags.mute_messages = False
|
||||||
|
|
||||||
|
if pro_list:
|
||||||
|
pro_list = ["""<a href="#Form/Production Order/%s" target="_blank">%s</a>""" % \
|
||||||
|
(p, p) for p in pro_list]
|
||||||
|
msgprint(_("{0} created").format(comma_and(pro_list)))
|
||||||
|
else :
|
||||||
|
msgprint(_("No Production Orders created"))
|
||||||
|
|
||||||
|
def create_production_order(self, item):
|
||||||
|
from erpnext.manufacturing.doctype.production_order.production_order import OverProductionError, get_default_warehouse
|
||||||
|
warehouse = get_default_warehouse()
|
||||||
|
pro = frappe.new_doc("Production Order")
|
||||||
|
pro.update(item)
|
||||||
|
pro.set_production_order_operations()
|
||||||
|
|
||||||
|
if not pro.fg_warehouse:
|
||||||
|
pro.fg_warehouse = warehouse.get('fg_warehouse')
|
||||||
|
try:
|
||||||
|
pro.insert()
|
||||||
|
return pro.name
|
||||||
|
except OverProductionError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def make_material_request(self):
|
||||||
|
material_request_list = []
|
||||||
|
|
||||||
|
item_details = self.get_itemwise_qty()
|
||||||
|
for item_code, rows in item_details.items():
|
||||||
|
item_doc = frappe.get_doc("Item", item_code)
|
||||||
|
schedule_date = add_days(nowdate(), cint(item_doc.lead_time_days))
|
||||||
|
|
||||||
|
material_request = frappe.new_doc("Material Request")
|
||||||
|
material_request.update({
|
||||||
|
"transaction_date": nowdate(),
|
||||||
|
"status": "Draft",
|
||||||
|
"company": self.company,
|
||||||
|
"requested_by": frappe.session.user,
|
||||||
|
"schedule_date": schedule_date,
|
||||||
|
'material_request_type': item_doc.default_material_request_type
|
||||||
|
})
|
||||||
|
|
||||||
|
for idx in rows:
|
||||||
|
child = self.mr_items[cint(idx)-1]
|
||||||
|
material_request.append("items", {
|
||||||
|
"item_code": item_code,
|
||||||
|
"qty": child.quantity,
|
||||||
|
"schedule_date": schedule_date,
|
||||||
|
"warehouse": child.warehouse,
|
||||||
|
"sales_order": child.sales_order,
|
||||||
|
'production_plan': self.name,
|
||||||
|
'material_request_plan_item': child.name,
|
||||||
|
"project": frappe.db.get_value("Sales Order", child.sales_order, "project") \
|
||||||
|
if child.sales_order else None
|
||||||
|
})
|
||||||
|
|
||||||
|
material_request.flags.ignore_permissions = 1
|
||||||
|
material_request.run_method("set_missing_values")
|
||||||
|
material_request.submit()
|
||||||
|
material_request_list.append(material_request.name)
|
||||||
|
|
||||||
|
frappe.flags.mute_messages = False
|
||||||
|
|
||||||
|
if material_request_list:
|
||||||
|
material_request_list = ["""<a href="#Form/Material Request/%s" target="_blank">%s</a>""" % \
|
||||||
|
(p, p) for p in material_request_list]
|
||||||
|
msgprint(_("{0} created").format(comma_and(material_request_list)))
|
||||||
|
else :
|
||||||
|
msgprint(_("No material request created"))
|
||||||
|
|
||||||
|
def get_itemwise_qty(self):
|
||||||
|
item_details = {}
|
||||||
|
for data in self.get('mr_items'):
|
||||||
|
if data.item_code in item_details:
|
||||||
|
item_details[data.item_code].append(data.idx)
|
||||||
|
else:
|
||||||
|
item_details.setdefault(data.item_code, [data.idx])
|
||||||
|
|
||||||
|
return item_details
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def get_bin_details(row):
|
||||||
|
if isinstance(row, basestring):
|
||||||
|
row = frappe._dict(json.loads(row))
|
||||||
|
|
||||||
|
conditions = ""
|
||||||
|
warehouse = row.source_warehouse or row.default_warehouse or row.warehouse
|
||||||
|
if warehouse:
|
||||||
|
conditions = " and warehouse='{0}'".format(frappe.db.escape(warehouse))
|
||||||
|
|
||||||
|
item_projected_qty = frappe.db.sql(""" select ifnull(sum(projected_qty),0) as projected_qty,
|
||||||
|
ifnull(sum(actual_qty),0) as actual_qty from `tabBin`
|
||||||
|
where item_code = %(item_code)s {conditions}
|
||||||
|
""".format(conditions=conditions), { "item_code": row.item_code }, as_list=1)
|
||||||
|
|
||||||
|
return item_projected_qty and item_projected_qty[0] or (0,0)
|
@ -0,0 +1,12 @@
|
|||||||
|
from frappe import _
|
||||||
|
|
||||||
|
def get_data():
|
||||||
|
return {
|
||||||
|
'fieldname': 'production_plan',
|
||||||
|
'transactions': [
|
||||||
|
{
|
||||||
|
'label': _('Related'),
|
||||||
|
'items': ['Production Order', 'Material Request']
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
frappe.listview_settings['Production Plan'] = {
|
||||||
|
add_fields: ["status"],
|
||||||
|
filters: [["status", "!=", "Stopped"]],
|
||||||
|
get_indicator: function(doc) {
|
||||||
|
if(doc.status==="Submitted") {
|
||||||
|
return [__("Not Started"), "orange", "status,=,Submitted"];
|
||||||
|
} else {
|
||||||
|
return [__(doc.status), {
|
||||||
|
"Draft": "red",
|
||||||
|
"In Process": "orange",
|
||||||
|
"Completed": "green",
|
||||||
|
"Material Requested": "darkgrey",
|
||||||
|
"Cancelled": "darkgrey"
|
||||||
|
}[doc.status], "status,=," + doc.status];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
@ -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: Production Plan", function (assert) {
|
||||||
|
let done = assert.async();
|
||||||
|
|
||||||
|
// number of asserts
|
||||||
|
assert.expect(1);
|
||||||
|
|
||||||
|
frappe.run_serially([
|
||||||
|
// insert a new Production Plan
|
||||||
|
() => frappe.tests.make('Production Plan', [
|
||||||
|
// values to be set
|
||||||
|
{key: 'value'}
|
||||||
|
]),
|
||||||
|
() => {
|
||||||
|
assert.equal(cur_frm.doc.key, 'value');
|
||||||
|
},
|
||||||
|
() => done()
|
||||||
|
]);
|
||||||
|
|
||||||
|
});
|
@ -0,0 +1,148 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
|
# See license.txt
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import frappe
|
||||||
|
import unittest
|
||||||
|
from frappe.utils import nowdate, now_datetime, flt
|
||||||
|
from erpnext.stock.doctype.item.test_item import create_item
|
||||||
|
from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import create_stock_reconciliation
|
||||||
|
|
||||||
|
class TestProductionPlan(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
for item in ['Test Production Item 1', 'Subassembly Item 1',
|
||||||
|
'Raw Material Item 1', 'Raw Material Item 2']:
|
||||||
|
create_item(item, valuation_rate=100)
|
||||||
|
|
||||||
|
sr = frappe.db.get_value('Stock Reconciliation Item',
|
||||||
|
{'item_code': item, 'docstatus': 1}, 'parent')
|
||||||
|
if sr:
|
||||||
|
sr_doc = frappe.get_doc('Stock Reconciliation', sr)
|
||||||
|
sr_doc.cancel()
|
||||||
|
|
||||||
|
create_item('Test Non Stock Raw Material', is_stock_item=0)
|
||||||
|
for item, raw_materials in {'Subassembly Item 1': ['Raw Material Item 1', 'Raw Material Item 2'],
|
||||||
|
'Test Production Item 1': ['Raw Material Item 1', 'Subassembly Item 1',
|
||||||
|
'Test Non Stock Raw Material']}.items():
|
||||||
|
if not frappe.db.get_value('BOM', {'item': item}):
|
||||||
|
print(item, raw_materials)
|
||||||
|
make_bom(item = item, raw_materials = raw_materials)
|
||||||
|
|
||||||
|
def test_production_plan(self):
|
||||||
|
pln = create_production_plan(item_code='Test Production Item 1')
|
||||||
|
self.assertTrue(len(pln.mr_items), 2)
|
||||||
|
pln.make_material_request()
|
||||||
|
|
||||||
|
pln = frappe.get_doc('Production Plan', pln.name)
|
||||||
|
self.assertTrue(pln.status, 'Material Requested')
|
||||||
|
material_requests = frappe.get_all('Material Request Item', fields = ['distinct parent'],
|
||||||
|
filters = {'production_plan': pln.name}, as_list=1)
|
||||||
|
|
||||||
|
self.assertTrue(len(material_requests), 2)
|
||||||
|
|
||||||
|
pln.make_production_order()
|
||||||
|
production_orders = frappe.get_all('Production Order', fields = ['name'],
|
||||||
|
filters = {'production_plan': pln.name}, as_list=1)
|
||||||
|
|
||||||
|
self.assertTrue(len(production_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])
|
||||||
|
|
||||||
|
pln = frappe.get_doc('Production Plan', pln.name)
|
||||||
|
pln.cancel()
|
||||||
|
|
||||||
|
def test_production_plan_for_existing_ordered_qty(self):
|
||||||
|
sr1 = create_stock_reconciliation(item_code="Raw Material Item 1",
|
||||||
|
target="_Test Warehouse - _TC", qty=1, rate=100)
|
||||||
|
sr2 = create_stock_reconciliation(item_code="Raw Material Item 2",
|
||||||
|
target="_Test Warehouse - _TC", qty=1, rate=100)
|
||||||
|
|
||||||
|
pln = create_production_plan(item_code='Test Production Item 1', ignore_existing_ordered_qty=0)
|
||||||
|
self.assertTrue(len(pln.mr_items), 1)
|
||||||
|
self.assertTrue(flt(pln.mr_items[0].quantity), 1.0)
|
||||||
|
|
||||||
|
sr1.cancel()
|
||||||
|
sr2.cancel()
|
||||||
|
pln.cancel()
|
||||||
|
|
||||||
|
def test_production_plan_with_non_stock_item(self):
|
||||||
|
pln = create_production_plan(item_code='Test Production Item 1', include_non_stock_items=0)
|
||||||
|
self.assertTrue(len(pln.mr_items), 3)
|
||||||
|
pln.cancel()
|
||||||
|
|
||||||
|
def test_production_plan_without_multi_level(self):
|
||||||
|
pln = create_production_plan(item_code='Test Production Item 1', use_multi_level_bom=0)
|
||||||
|
self.assertTrue(len(pln.mr_items), 2)
|
||||||
|
pln.cancel()
|
||||||
|
|
||||||
|
def test_production_plan_without_multi_level_for_existing_ordered_qty(self):
|
||||||
|
sr1 = create_stock_reconciliation(item_code="Raw Material Item 1",
|
||||||
|
target="_Test Warehouse - _TC", qty=1, rate=100)
|
||||||
|
sr2 = create_stock_reconciliation(item_code="Subassembly Item 1",
|
||||||
|
target="_Test Warehouse - _TC", qty=1, rate=100)
|
||||||
|
|
||||||
|
pln = create_production_plan(item_code='Test Production Item 1',
|
||||||
|
use_multi_level_bom=0, ignore_existing_ordered_qty=0)
|
||||||
|
self.assertTrue(len(pln.mr_items), 0)
|
||||||
|
|
||||||
|
sr1.cancel()
|
||||||
|
sr2.cancel()
|
||||||
|
pln.cancel()
|
||||||
|
|
||||||
|
def create_production_plan(**args):
|
||||||
|
args = frappe._dict(args)
|
||||||
|
|
||||||
|
pln = frappe.get_doc({
|
||||||
|
'doctype': 'Production Plan',
|
||||||
|
'company': args.company or '_Test Company',
|
||||||
|
'posting_date': nowdate(),
|
||||||
|
'include_non_stock_items': args.include_non_stock_items or 1,
|
||||||
|
'include_subcontracted_items': args.include_subcontracted_items or 1,
|
||||||
|
'ignore_existing_ordered_qty': args.ignore_existing_ordered_qty or 1,
|
||||||
|
'po_items': [{
|
||||||
|
'use_multi_level_bom': args.use_multi_level_bom or 1,
|
||||||
|
'item_code': args.item_code,
|
||||||
|
'bom_no': frappe.db.get_value('Item', args.item_code, 'default_bom'),
|
||||||
|
'planned_qty': args.planned_qty or 1,
|
||||||
|
'planned_start_date': args.planned_start_date or now_datetime()
|
||||||
|
}]
|
||||||
|
})
|
||||||
|
pln.get_items_for_material_requests()
|
||||||
|
|
||||||
|
if not args.do_not_save:
|
||||||
|
pln.insert()
|
||||||
|
if not args.do_not_submit:
|
||||||
|
pln.submit()
|
||||||
|
|
||||||
|
return pln
|
||||||
|
|
||||||
|
def make_bom(**args):
|
||||||
|
args = frappe._dict(args)
|
||||||
|
|
||||||
|
bom = frappe.get_doc({
|
||||||
|
'doctype': "BOM",
|
||||||
|
'is_default': 1,
|
||||||
|
'item': args.item,
|
||||||
|
'quantity': args.quantity or 1,
|
||||||
|
'company': args.company or '_Test Company'
|
||||||
|
})
|
||||||
|
|
||||||
|
for item in args.raw_materials:
|
||||||
|
item_doc = frappe.get_doc('Item', item)
|
||||||
|
|
||||||
|
bom.append('items', {
|
||||||
|
'item_code': item,
|
||||||
|
'qty': 1,
|
||||||
|
'uom': item_doc.stock_uom,
|
||||||
|
'stock_uom': item_doc.stock_uom,
|
||||||
|
'rate': item_doc.valuation_rate
|
||||||
|
})
|
||||||
|
|
||||||
|
bom.insert(ignore_permissions=True)
|
||||||
|
bom.submit()
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 0,
|
"allow_copy": 0,
|
||||||
|
"allow_guest_to_view": 0,
|
||||||
"allow_import": 0,
|
"allow_import": 0,
|
||||||
"allow_rename": 0,
|
"allow_rename": 0,
|
||||||
"autoname": "hash",
|
"autoname": "hash",
|
||||||
@ -11,16 +12,50 @@
|
|||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
|
"columns": 2,
|
||||||
|
"fieldname": "include_exploded_items",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Include Exploded Items",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 2,
|
||||||
"fieldname": "item_code",
|
"fieldname": "item_code",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "Item Code",
|
"label": "Item Code",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@ -32,6 +67,7 @@
|
|||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"print_width": "150px",
|
"print_width": "150px",
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@ -40,16 +76,20 @@
|
|||||||
"width": "150px"
|
"width": "150px"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
|
"columns": 2,
|
||||||
"fieldname": "bom_no",
|
"fieldname": "bom_no",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "BOM No",
|
"label": "BOM No",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@ -61,6 +101,7 @@
|
|||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"print_width": "100px",
|
"print_width": "100px",
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@ -69,16 +110,20 @@
|
|||||||
"width": "100px"
|
"width": "100px"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
"fieldname": "planned_qty",
|
"fieldname": "planned_qty",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "Planned Qty",
|
"label": "Planned Qty",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@ -89,6 +134,7 @@
|
|||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"print_width": "100px",
|
"print_width": "100px",
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@ -97,17 +143,21 @@
|
|||||||
"width": "100px"
|
"width": "100px"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"default": "",
|
"columns": 0,
|
||||||
|
"default": "Today",
|
||||||
"fieldname": "planned_start_date",
|
"fieldname": "planned_start_date",
|
||||||
"fieldtype": "Datetime",
|
"fieldtype": "Datetime",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "Planned Start Date",
|
"label": "Planned Start Date",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@ -116,6 +166,7 @@
|
|||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@ -123,16 +174,20 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
"fieldname": "column_break_6",
|
"fieldname": "column_break_6",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
@ -140,6 +195,7 @@
|
|||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@ -147,9 +203,11 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
"description": "Reserved Warehouse in Sales Order / Finished Goods Warehouse",
|
"description": "Reserved Warehouse in Sales Order / Finished Goods Warehouse",
|
||||||
"fieldname": "warehouse",
|
"fieldname": "warehouse",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
@ -157,7 +215,9 @@
|
|||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "Warehouse",
|
"label": "Warehouse",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@ -166,6 +226,7 @@
|
|||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@ -173,16 +234,50 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "produced_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": "Produced Qty",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 1,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
"fieldname": "sales_order",
|
"fieldname": "sales_order",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "Sales Order",
|
"label": "Sales Order",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@ -193,6 +288,7 @@
|
|||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@ -200,16 +296,50 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "sales_order_item",
|
||||||
|
"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": "Sales Order Item",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 1,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 1,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
"fieldname": "material_request",
|
"fieldname": "material_request",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "Material Request",
|
"label": "Material Request",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@ -219,6 +349,7 @@
|
|||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@ -226,16 +357,20 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
"fieldname": "pending_qty",
|
"fieldname": "pending_qty",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 1,
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "Pending Qty",
|
"label": "Pending Qty",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@ -246,6 +381,7 @@
|
|||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"print_width": "100px",
|
"print_width": "100px",
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@ -254,16 +390,20 @@
|
|||||||
"width": "100px"
|
"width": "100px"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
"fieldname": "stock_uom",
|
"fieldname": "stock_uom",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "UOM",
|
"label": "UOM",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@ -275,6 +415,7 @@
|
|||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"print_width": "80px",
|
"print_width": "80px",
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@ -283,16 +424,20 @@
|
|||||||
"width": "80px"
|
"width": "80px"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
"fieldname": "description",
|
"fieldname": "description",
|
||||||
"fieldtype": "Text Editor",
|
"fieldtype": "Text Editor",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 1,
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "Description",
|
"label": "Description",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@ -303,6 +448,7 @@
|
|||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"print_width": "200px",
|
"print_width": "200px",
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@ -311,16 +457,20 @@
|
|||||||
"width": "200px"
|
"width": "200px"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
"fieldname": "material_request_item",
|
"fieldname": "material_request_item",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"hidden": 1,
|
"hidden": 1,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "material_request_item",
|
"label": "material_request_item",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@ -329,6 +479,37 @@
|
|||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "ordered_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": "Ordered Qty",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 1,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@ -336,17 +517,17 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"has_web_view": 0,
|
||||||
"hide_heading": 0,
|
"hide_heading": 0,
|
||||||
"hide_toolbar": 0,
|
"hide_toolbar": 0,
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"image_view": 0,
|
"image_view": 0,
|
||||||
"in_create": 0,
|
"in_create": 0,
|
||||||
"in_dialog": 0,
|
|
||||||
"is_submittable": 0,
|
"is_submittable": 0,
|
||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2016-07-11 03:28:04.410743",
|
"modified": "2018-02-16 12:13:41.513586",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "Production Plan Item",
|
"name": "Production Plan Item",
|
||||||
@ -355,6 +536,8 @@
|
|||||||
"quick_entry": 0,
|
"quick_entry": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"read_only_onload": 0,
|
"read_only_onload": 0,
|
||||||
|
"show_name_in_global_search": 0,
|
||||||
"sort_order": "ASC",
|
"sort_order": "ASC",
|
||||||
|
"track_changes": 0,
|
||||||
"track_seen": 0
|
"track_seen": 0
|
||||||
}
|
}
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 0,
|
"allow_copy": 0,
|
||||||
|
"allow_guest_to_view": 0,
|
||||||
"allow_import": 0,
|
"allow_import": 0,
|
||||||
"allow_rename": 0,
|
"allow_rename": 0,
|
||||||
"autoname": "hash",
|
"autoname": "hash",
|
||||||
@ -12,16 +13,20 @@
|
|||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
"fieldname": "material_request",
|
"fieldname": "material_request",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "Material Request",
|
"label": "Material Request",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@ -34,24 +39,29 @@
|
|||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"print_width": "150px",
|
"print_width": "150px",
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0,
|
"unique": 0,
|
||||||
"width": "150px"
|
"width": "150px"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
"fieldname": "col_break1",
|
"fieldname": "col_break1",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
@ -59,6 +69,7 @@
|
|||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@ -66,16 +77,20 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
"fieldname": "material_request_date",
|
"fieldname": "material_request_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "Material Request Date",
|
"label": "Material Request Date",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@ -88,6 +103,7 @@
|
|||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"print_width": "120px",
|
"print_width": "120px",
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@ -96,17 +112,17 @@
|
|||||||
"width": "120px"
|
"width": "120px"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"has_web_view": 0,
|
||||||
"hide_heading": 0,
|
"hide_heading": 0,
|
||||||
"hide_toolbar": 0,
|
"hide_toolbar": 0,
|
||||||
"idx": 0,
|
"idx": 0,
|
||||||
"image_view": 0,
|
"image_view": 0,
|
||||||
"in_create": 0,
|
"in_create": 0,
|
||||||
"in_dialog": 0,
|
|
||||||
"is_submittable": 0,
|
"is_submittable": 0,
|
||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2016-07-11 03:28:04.519523",
|
"modified": "2017-10-29 12:31:57.986869",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "Production Plan Material Request",
|
"name": "Production Plan Material Request",
|
||||||
@ -116,7 +132,9 @@
|
|||||||
"quick_entry": 0,
|
"quick_entry": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"read_only_onload": 0,
|
"read_only_onload": 0,
|
||||||
|
"show_name_in_global_search": 0,
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "ASC",
|
"sort_order": "ASC",
|
||||||
|
"track_changes": 0,
|
||||||
"track_seen": 0
|
"track_seen": 0
|
||||||
}
|
}
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 0,
|
"allow_copy": 0,
|
||||||
|
"allow_guest_to_view": 0,
|
||||||
"allow_import": 0,
|
"allow_import": 0,
|
||||||
"allow_rename": 0,
|
"allow_rename": 0,
|
||||||
"autoname": "hash",
|
"autoname": "hash",
|
||||||
@ -11,16 +12,20 @@
|
|||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
"fieldname": "sales_order",
|
"fieldname": "sales_order",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "Sales Order",
|
"label": "Sales Order",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@ -32,24 +37,29 @@
|
|||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"print_width": "150px",
|
"print_width": "150px",
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0,
|
"unique": 0,
|
||||||
"width": "150px"
|
"width": "150px"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
"fieldname": "sales_order_date",
|
"fieldname": "sales_order_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "Sales Order Date",
|
"label": "Sales Order Date",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@ -61,6 +71,7 @@
|
|||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"print_width": "120px",
|
"print_width": "120px",
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@ -69,16 +80,20 @@
|
|||||||
"width": "120px"
|
"width": "120px"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
"fieldname": "col_break1",
|
"fieldname": "col_break1",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
@ -86,6 +101,7 @@
|
|||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@ -93,16 +109,20 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
"fieldname": "customer",
|
"fieldname": "customer",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "Customer",
|
"label": "Customer",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@ -112,6 +132,7 @@
|
|||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"print_width": "150px",
|
"print_width": "150px",
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@ -120,9 +141,11 @@
|
|||||||
"width": "150px"
|
"width": "150px"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
"default": "",
|
"default": "",
|
||||||
"fieldname": "grand_total",
|
"fieldname": "grand_total",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
@ -130,7 +153,9 @@
|
|||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "Grand Total",
|
"label": "Grand Total",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@ -140,6 +165,7 @@
|
|||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"print_width": "120px",
|
"print_width": "120px",
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@ -148,17 +174,17 @@
|
|||||||
"width": "120px"
|
"width": "120px"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"has_web_view": 0,
|
||||||
"hide_heading": 0,
|
"hide_heading": 0,
|
||||||
"hide_toolbar": 0,
|
"hide_toolbar": 0,
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"image_view": 0,
|
"image_view": 0,
|
||||||
"in_create": 0,
|
"in_create": 0,
|
||||||
"in_dialog": 0,
|
|
||||||
"is_submittable": 0,
|
"is_submittable": 0,
|
||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2016-07-11 03:28:04.587544",
|
"modified": "2017-10-29 12:29:36.726079",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "Production Plan Sales Order",
|
"name": "Production Plan Sales Order",
|
||||||
@ -167,6 +193,8 @@
|
|||||||
"quick_entry": 0,
|
"quick_entry": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"read_only_onload": 0,
|
"read_only_onload": 0,
|
||||||
|
"show_name_in_global_search": 0,
|
||||||
"sort_order": "ASC",
|
"sort_order": "ASC",
|
||||||
|
"track_changes": 0,
|
||||||
"track_seen": 0
|
"track_seen": 0
|
||||||
}
|
}
|
@ -1 +0,0 @@
|
|||||||
Tool to create Production Orders from a bunch of Sales Orders and generate Material Requests (MRP) as required.
|
|
@ -1 +0,0 @@
|
|||||||
from __future__ import unicode_literals
|
|
@ -1,128 +0,0 @@
|
|||||||
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
|
||||||
// License: GNU General Public License v3. See license.txt
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
cur_frm.cscript.onload = function(doc) {
|
|
||||||
cur_frm.set_value("company", frappe.defaults.get_user_default("Company"))
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_frm.cscript.refresh = function(doc) {
|
|
||||||
cur_frm.disable_save();
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_frm.add_fetch("material_request", "transaction_date", "material_request_date");
|
|
||||||
|
|
||||||
cur_frm.add_fetch("sales_order", "transaction_date", "sales_order_date");
|
|
||||||
cur_frm.add_fetch("sales_order", "customer", "customer");
|
|
||||||
cur_frm.add_fetch("sales_order", "base_grand_total", "grand_total");
|
|
||||||
|
|
||||||
frappe.ui.form.on("Production Planning Tool", {
|
|
||||||
onload_post_render: function(frm) {
|
|
||||||
frm.get_field("items").grid.set_multiple_add("item_code", "planned_qty");
|
|
||||||
},
|
|
||||||
get_sales_orders: function(frm) {
|
|
||||||
frappe.call({
|
|
||||||
doc: frm.doc,
|
|
||||||
method: "get_open_sales_orders",
|
|
||||||
callback: function(r) {
|
|
||||||
refresh_field("sales_orders");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
get_material_request: function(frm) {
|
|
||||||
frappe.call({
|
|
||||||
doc: frm.doc,
|
|
||||||
method: "get_pending_material_requests",
|
|
||||||
callback: function(r) {
|
|
||||||
refresh_field("material_requests");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
get_items: function(frm) {
|
|
||||||
frappe.call({
|
|
||||||
doc: frm.doc,
|
|
||||||
method: "get_items",
|
|
||||||
callback: function(r) {
|
|
||||||
refresh_field("items");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
create_production_order: function(frm) {
|
|
||||||
frappe.call({
|
|
||||||
doc: frm.doc,
|
|
||||||
method: "raise_production_orders"
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
create_material_requests: function(frm) {
|
|
||||||
frappe.call({
|
|
||||||
doc: frm.doc,
|
|
||||||
method: "raise_material_requests"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
cur_frm.cscript.item_code = function(doc,cdt,cdn) {
|
|
||||||
var d = locals[cdt][cdn];
|
|
||||||
if (d.item_code) {
|
|
||||||
frappe.call({
|
|
||||||
method: "erpnext.manufacturing.doctype.production_order.production_order.get_item_details",
|
|
||||||
args: {
|
|
||||||
"item" : d.item_code
|
|
||||||
},
|
|
||||||
callback: function(r) {
|
|
||||||
$.extend(d, r.message);
|
|
||||||
refresh_field("items");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_frm.cscript.download_materials_required = function(doc, cdt, cdn) {
|
|
||||||
return $c_obj(doc, 'validate_data', '', function(r, rt) {
|
|
||||||
if (!r['exc'])
|
|
||||||
$c_obj_csv(doc, 'download_raw_materials', '', '');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_frm.fields_dict['sales_orders'].grid.get_field('sales_order').get_query = function(doc) {
|
|
||||||
var args = { "docstatus": 1 };
|
|
||||||
if(doc.customer) {
|
|
||||||
args["customer"] = doc.customer;
|
|
||||||
}
|
|
||||||
|
|
||||||
return { filters: args }
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_frm.fields_dict['items'].grid.get_field('item_code').get_query = function(doc) {
|
|
||||||
return erpnext.queries.item({
|
|
||||||
'is_stock_item': 1
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_frm.fields_dict['items'].grid.get_field('bom_no').get_query = function(doc, cdt, cdn) {
|
|
||||||
var d = locals[cdt][cdn];
|
|
||||||
if (d.item_code) {
|
|
||||||
return {
|
|
||||||
query: "erpnext.controllers.queries.bom",
|
|
||||||
filters:{'item': cstr(d.item_code)}
|
|
||||||
}
|
|
||||||
} else frappe.msgprint(__("Please enter Item first"));
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_frm.fields_dict.customer.get_query = function(doc,cdt,cdn) {
|
|
||||||
return{
|
|
||||||
query: "erpnext.controllers.queries.customer_query"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_frm.fields_dict.sales_orders.grid.get_field("customer").get_query =
|
|
||||||
cur_frm.fields_dict.customer.get_query;
|
|
||||||
|
|
||||||
cur_frm.cscript.planned_start_date = function(doc, cdt, cdn) {
|
|
||||||
erpnext.utils.copy_value_in_all_row(doc, cdt, cdn, "items", "planned_start_date");
|
|
||||||
}
|
|
@ -1,388 +0,0 @@
|
|||||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
|
||||||
# MIT License. See license.txt
|
|
||||||
|
|
||||||
import frappe
|
|
||||||
import frappe.defaults
|
|
||||||
import unittest
|
|
||||||
from frappe.test_runner import make_test_records
|
|
||||||
|
|
||||||
from erpnext.manufacturing.doctype.production_planning_tool.production_planning_tool import ProductionPlanningTool
|
|
||||||
|
|
||||||
# load test records and dependencies
|
|
||||||
|
|
||||||
test_records = frappe.get_test_records('Production Planning Tool')
|
|
||||||
|
|
||||||
test_dependencies = ["Item","BOM"]
|
|
||||||
|
|
||||||
class TestEvent(unittest.TestCase):
|
|
||||||
|
|
||||||
def test_materials_requests_all_raw_multi_level(self):
|
|
||||||
items = ["_Test PPT Item Raw A","_Test PPT Item Raw B","_Test PPT Item Raw C","_Test PPT Item Raw D",
|
|
||||||
"_Test PPT Item Sub A","_Test PPT Item Sub B","_Test PPT Item Sub C","_Test PPT Item SC A",
|
|
||||||
"_Test PPT Item SC B","_Test PPT Item Master"]
|
|
||||||
quantities = [14,9,36,1,0,0,0,0,0,0]
|
|
||||||
types = ["Purchase","Purchase","Purchase","Purchase","Manufacture","Manufacture","Manufacture","Purchase",
|
|
||||||
"Purchase","Manufacture"]
|
|
||||||
|
|
||||||
self.runtest_materials_requests(items, quantities, types, use_multi_level_bom=1, only_raw_materials=1, \
|
|
||||||
include_subcontracted=1)
|
|
||||||
|
|
||||||
def test_materials_requests_multi_no_subcontracted(self):
|
|
||||||
items = ["_Test PPT Item Raw A","_Test PPT Item Raw B","_Test PPT Item Raw C","_Test PPT Item Raw D",
|
|
||||||
"_Test PPT Item Sub A","_Test PPT Item Sub B","_Test PPT Item Sub C","_Test PPT Item SC A",
|
|
||||||
"_Test PPT Item SC B","_Test PPT Item Master"]
|
|
||||||
quantities = [14,5,20,0,0,0,0,0,0,0]
|
|
||||||
types = ["Purchase","Purchase","Purchase","Purchase","Manufacture","Manufacture","Manufacture","Purchase",
|
|
||||||
"Purchase","Manufacture"]
|
|
||||||
|
|
||||||
# This one should fail for now
|
|
||||||
self.runtest_materials_requests(items, quantities, types, use_multi_level_bom=1, only_raw_materials=1, \
|
|
||||||
include_subcontracted=0)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def test_materials_requests_manufacture_and_sub_multi_level(self):
|
|
||||||
items = ["_Test PPT Item Raw A","_Test PPT Item Raw B","_Test PPT Item Raw C","_Test PPT Item Raw D",
|
|
||||||
"_Test PPT Item Sub A","_Test PPT Item Sub B","_Test PPT Item Sub C","_Test PPT Item SC A",
|
|
||||||
"_Test PPT Item SC B","_Test PPT Item Master"]
|
|
||||||
quantities = [14,9,36,1,2,5,2,1,4,0]
|
|
||||||
types = ["Purchase","Purchase","Purchase","Purchase","Manufacture","Manufacture","Manufacture","Purchase",
|
|
||||||
"Purchase","Manufacture"]
|
|
||||||
|
|
||||||
self.runtest_materials_requests(items, quantities, types, use_multi_level_bom=1, only_raw_materials=0, \
|
|
||||||
include_subcontracted=1)
|
|
||||||
|
|
||||||
def test_materials_requests_manufacture_multi_level(self):
|
|
||||||
items = ["_Test PPT Item Raw A","_Test PPT Item Raw B","_Test PPT Item Raw C","_Test PPT Item Raw D",
|
|
||||||
"_Test PPT Item Sub A","_Test PPT Item Sub B","_Test PPT Item Sub C","_Test PPT Item SC A",
|
|
||||||
"_Test PPT Item SC B","_Test PPT Item Master"]
|
|
||||||
quantities = [14,5,20,0,2,5,2,1,4,0]
|
|
||||||
types = ["Purchase","Purchase","Purchase","Purchase","Manufacture","Manufacture","Manufacture","Purchase",
|
|
||||||
"Purchase","Manufacture"]
|
|
||||||
|
|
||||||
self.runtest_materials_requests(items, quantities, types, use_multi_level_bom=1, only_raw_materials=0, \
|
|
||||||
include_subcontracted=0)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def test_materials_requests_single_level_purch_only(self):
|
|
||||||
items = ["_Test PPT Item Raw A","_Test PPT Item Raw B","_Test PPT Item Raw C","_Test PPT Item Raw D",
|
|
||||||
"_Test PPT Item Sub A","_Test PPT Item Sub B","_Test PPT Item Sub C","_Test PPT Item SC A",
|
|
||||||
"_Test PPT Item SC B","_Test PPT Item Master"]
|
|
||||||
quantities = [2,0,0,0,0,0,0,1,0,0]
|
|
||||||
types = ["Purchase","Purchase","Purchase","Purchase","Manufacture","Manufacture","Manufacture","Purchase",
|
|
||||||
"Purchase","Manufacture"]
|
|
||||||
|
|
||||||
self.runtest_materials_requests(items, quantities, types, use_multi_level_bom=0, only_raw_materials=1, \
|
|
||||||
include_subcontracted=0)
|
|
||||||
|
|
||||||
def test_materials_requests_single_level(self):
|
|
||||||
items = ["_Test PPT Item Raw A","_Test PPT Item Raw B","_Test PPT Item Raw C","_Test PPT Item Raw D",
|
|
||||||
"_Test PPT Item Sub A","_Test PPT Item Sub B","_Test PPT Item Sub C","_Test PPT Item SC A",
|
|
||||||
"_Test PPT Item SC B","_Test PPT Item Master"]
|
|
||||||
quantities = [2,0,0,0,2,1,0,1,0,0]
|
|
||||||
types = ["Purchase","Purchase","Purchase","Purchase","Manufacture","Manufacture","Manufacture","Purchase",
|
|
||||||
"Purchase","Manufacture"]
|
|
||||||
|
|
||||||
self.runtest_materials_requests(items, quantities, types, use_multi_level_bom=0, only_raw_materials=0, \
|
|
||||||
include_subcontracted=0)
|
|
||||||
|
|
||||||
def runtest_materials_requests(self, items, quantities, types,use_multi_level_bom, only_raw_materials, \
|
|
||||||
include_subcontracted):
|
|
||||||
|
|
||||||
clear_material_requests()
|
|
||||||
create_test_records()
|
|
||||||
|
|
||||||
ppt = run_production_planning_tool(use_multi_level_bom=use_multi_level_bom,
|
|
||||||
only_raw_materials=only_raw_materials, include_subcontracted=include_subcontracted,
|
|
||||||
item_code = "_Test PPT Item Master", bom_no = "BOM-_Test PPT Item Master-001",
|
|
||||||
planned_qty = 1, planned_start_date = "5/5/2029",
|
|
||||||
warehouse = "_Test Warehouse - _TC", company = "_Test Company")
|
|
||||||
|
|
||||||
create_material_requests(ppt)
|
|
||||||
|
|
||||||
for item, qty, type in zip(items, quantities, types):
|
|
||||||
self.assertEqual(qty, get_requested_qty(item))
|
|
||||||
for mat_req_type in get_requested_types(item):
|
|
||||||
self.assertEqual(type, mat_req_type)
|
|
||||||
|
|
||||||
def create_test_records():
|
|
||||||
from erpnext.stock.doctype.item.test_item import make_item
|
|
||||||
|
|
||||||
subA = make_item("_Test PPT Item Sub A",{
|
|
||||||
"item_code": "_Test PPT Item Sub A",
|
|
||||||
"item_name": "_Test PPT Item Sub A",
|
|
||||||
"description": "A manufactured _Test PPT Item Sub Assembly",
|
|
||||||
"default_material_request_type": "Manufacture",
|
|
||||||
"is_sub_contracted_item": 0,
|
|
||||||
"is_stock_item": 1,
|
|
||||||
"stock_uom": "_Test UOM",
|
|
||||||
"item_group": "_Test Item Group",
|
|
||||||
"default_warehouse": "_Test Warehouse - _TC"})
|
|
||||||
|
|
||||||
subB = make_item("_Test PPT Item Sub B",{
|
|
||||||
"item_code": "_Test PPT Item Sub B",
|
|
||||||
"item_name": "_Test PPT Item Sub B",
|
|
||||||
"description": "A manufactured _Test PPT Item Sub Assembly",
|
|
||||||
"default_material_request_type": "Manufacture",
|
|
||||||
"is_sub_contracted_item": 0,
|
|
||||||
"is_stock_item": 1,
|
|
||||||
"stock_uom": "_Test UOM",
|
|
||||||
"item_group": "_Test Item Group",
|
|
||||||
"default_warehouse": "_Test Warehouse - _TC"})
|
|
||||||
|
|
||||||
subC = make_item("_Test PPT Item Sub C",{
|
|
||||||
"item_code": "_Test PPT Item Sub C",
|
|
||||||
"item_name": "_Test PPT Item Sub C",
|
|
||||||
"description": "A manufactured _Test PPT Item Sub Assembly",
|
|
||||||
"default_material_request_type": "Manufacture",
|
|
||||||
"is_sub_contracted_item": 0,
|
|
||||||
"is_stock_item": 1,
|
|
||||||
"stock_uom": "_Test UOM",
|
|
||||||
"item_group": "_Test Item Group",
|
|
||||||
"default_warehouse": "_Test Warehouse - _TC"})
|
|
||||||
|
|
||||||
sCA = make_item("_Test PPT Item SC A",{
|
|
||||||
"item_code": "_Test PPT Item SC A",
|
|
||||||
"item_name": "_Test PPT Item SC A",
|
|
||||||
"description": "A subcontracted part with raw materials",
|
|
||||||
"default_material_request_type": "Purchase",
|
|
||||||
"is_sub_contracted_item": 1,
|
|
||||||
"is_stock_item": 1,
|
|
||||||
"stock_uom": "_Test UOM",
|
|
||||||
"item_group": "_Test Item Group",
|
|
||||||
"default_warehouse": "_Test Warehouse - _TC"})
|
|
||||||
subA = make_item("_Test PPT Item Sub A",{
|
|
||||||
"item_code": "_Test PPT Item Sub A",
|
|
||||||
"item_name": "_Test PPT Item Sub A",
|
|
||||||
"description": "A manufactured _Test PPT Item Sub Assembly",
|
|
||||||
"default_material_request_type": "Manufacture",
|
|
||||||
"is_sub_contracted_item": 0,
|
|
||||||
"is_stock_item": 1,
|
|
||||||
"stock_uom": "_Test UOM",
|
|
||||||
"item_group": "_Test Item Group",
|
|
||||||
"default_warehouse": "_Test Warehouse - _TC"})
|
|
||||||
sCB = make_item("_Test PPT Item SC B",{
|
|
||||||
"item_code": "_Test PPT Item SC B",
|
|
||||||
"item_name": "_Test PPT Item SC B",
|
|
||||||
"description": "A subcontracted part with raw materials",
|
|
||||||
"default_material_request_type": "Purchase",
|
|
||||||
"is_sub_contracted_item": 1,
|
|
||||||
"is_stock_item": 1,
|
|
||||||
"stock_uom": "_Test UOM",
|
|
||||||
"item_group": "_Test Item Group",
|
|
||||||
"default_warehouse": "_Test Warehouse - _TC"})
|
|
||||||
|
|
||||||
rawA = make_item("_Test PPT Item Raw A",{
|
|
||||||
"item_code": "_Test PPT Item Raw A",
|
|
||||||
"item_name": "_Test PPT Item Raw A",
|
|
||||||
"description": "A raw material",
|
|
||||||
"default_material_request_type": "Purchase",
|
|
||||||
"is_sub_contracted_item": 0,
|
|
||||||
"is_stock_item": 1,
|
|
||||||
"stock_uom": "_Test UOM",
|
|
||||||
"item_group": "_Test Item Group",
|
|
||||||
"default_warehouse": "_Test Warehouse - _TC"})
|
|
||||||
|
|
||||||
rawB = make_item("_Test PPT Item Raw B",{
|
|
||||||
"item_code": "_Test PPT Item Raw B",
|
|
||||||
"item_name": "_Test PPT Item Raw B",
|
|
||||||
"description": "A raw material",
|
|
||||||
"default_material_request_type": "Purchase",
|
|
||||||
"is_sub_contracted_item": 0,
|
|
||||||
"is_stock_item": 1,
|
|
||||||
"stock_uom": "_Test UOM",
|
|
||||||
"item_group": "_Test Item Group",
|
|
||||||
"default_warehouse": "_Test Warehouse - _TC"})
|
|
||||||
|
|
||||||
rawC = make_item("_Test PPT Item Raw C",{
|
|
||||||
"item_code": "_Test PPT Item Raw C",
|
|
||||||
"item_name": "_Test PPT Item Raw C",
|
|
||||||
"description": "A raw material",
|
|
||||||
"default_material_request_type": "Purchase",
|
|
||||||
"is_sub_contracted_item": 0,
|
|
||||||
"is_stock_item": 1,
|
|
||||||
"stock_uom": "_Test UOM",
|
|
||||||
"item_group": "_Test Item Group",
|
|
||||||
"default_warehouse": "_Test Warehouse - _TC"})
|
|
||||||
|
|
||||||
rawD = make_item("_Test PPT Item Raw D",{
|
|
||||||
"item_code": "_Test PPT Item Raw D",
|
|
||||||
"item_name": "_Test PPT Item Raw D",
|
|
||||||
"description": "A raw material",
|
|
||||||
"default_material_request_type": "Purchase",
|
|
||||||
"is_sub_contracted_item": 0,
|
|
||||||
"is_stock_item": 1,
|
|
||||||
"stock_uom": "_Test UOM",
|
|
||||||
"item_group": "_Test Item Group",
|
|
||||||
"default_warehouse": "_Test Warehouse - _TC"})
|
|
||||||
|
|
||||||
master = make_item("_Test PPT Item Master",{
|
|
||||||
"item_code": "_Test PPT Item Master",
|
|
||||||
"item_name": "_Test PPT Item Master",
|
|
||||||
"description": "The final assembly",
|
|
||||||
"default_material_request_type": "Manufacture",
|
|
||||||
"is_sub_contracted_item": 0,
|
|
||||||
"is_stock_item": 1,
|
|
||||||
"stock_uom": "_Test UOM",
|
|
||||||
"item_group": "_Test Item Group",
|
|
||||||
"default_warehouse": "_Test Warehouse - _TC"})
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bom_subB = make_bom("BOM-_Test PPT Item Sub B-001",{"quantity":1.0,
|
|
||||||
"item": "_Test PPT Item Sub B",
|
|
||||||
"is_active": 1,
|
|
||||||
"is_default": 1,
|
|
||||||
"docstatus": 1,
|
|
||||||
"with_operations": 0}, [{"item_code": "_Test PPT Item Raw B", "doctype":"BOM Item", "stock_qty":1,
|
|
||||||
"rate":100, "amount": 100, "stock_uom": "_Test UOM"},
|
|
||||||
{"item_code": "_Test PPT Item Raw C", "doctype":"BOM Item", "stock_qty":4, "rate":100,
|
|
||||||
"amount": 400,"stock_uom": "_Test UOM"}])
|
|
||||||
|
|
||||||
bom_subC = make_bom("BOM-_Test PPT Item Sub C-001",{"quantity":1,
|
|
||||||
"item": "_Test PPT Item Sub C",
|
|
||||||
"is_active": 1,
|
|
||||||
"is_default": 1,
|
|
||||||
"docstatus": 1,
|
|
||||||
"with_operations": 0}, [
|
|
||||||
{"item_code": "_Test PPT Item Raw A","item_name": "_Test PPT Item Raw A",
|
|
||||||
"doctype":"BOM Item", "stock_qty":6, "rate":100, "amount": 600},
|
|
||||||
{"item_code": "_Test PPT Item Sub B","item_name": "_Test PPT Item Sub B",
|
|
||||||
"bom_no":"BOM-_Test PPT Item Sub B-001", "doctype":"BOM Item", "stock_qty":2,
|
|
||||||
"rate":100, "amount": 200}])
|
|
||||||
|
|
||||||
bom_sCA = make_bom("BOM-_Test PPT Item SC A-001",{"quantity":1,
|
|
||||||
"item": "_Test PPT Item SC A",
|
|
||||||
"is_active": 1,
|
|
||||||
"is_default": 1,
|
|
||||||
"docstatus": 1,
|
|
||||||
"with_operations": 0}, [
|
|
||||||
{"item_code": "_Test PPT Item Raw D","item_name": "_Test PPT Item Raw D",
|
|
||||||
"doctype":"BOM Item", "stock_qty":1, "rate":100, "amount": 100}])
|
|
||||||
|
|
||||||
bom_sCB = make_bom("BOM-_Test PPT Item SC B-001",{"quantity":1,
|
|
||||||
"item": "_Test PPT Item SC B",
|
|
||||||
"is_active": 1,
|
|
||||||
"is_default": 1,
|
|
||||||
"docstatus": 1,
|
|
||||||
"with_operations": 0}, [
|
|
||||||
{"item_code": "_Test PPT Item Raw B","item_name": "_Test PPT Item Raw B",
|
|
||||||
"doctype":"BOM Item", "stock_qty":1, "rate":100, "amount": 100},
|
|
||||||
{"item_code": "_Test PPT Item Raw C","item_name": "_Test PPT Item Raw C",
|
|
||||||
"doctype":"BOM Item", "stock_qty":4, "rate":100, "amount": 400}])
|
|
||||||
|
|
||||||
bom_subA = make_bom("BOM-_Test PPT Item Sub A-001",{"quantity":1,
|
|
||||||
"item": "_Test PPT Item Sub A",
|
|
||||||
"is_active": 1,
|
|
||||||
"is_default": 1,
|
|
||||||
"docstatus": 1,
|
|
||||||
"with_operations": 0}, [
|
|
||||||
{"item_code": "_Test PPT Item Sub C","item_name": "_Test PPT Item Sub C",
|
|
||||||
"bom_no":"BOM-_Test PPT Item Sub C-001", "doctype":"BOM Item",
|
|
||||||
"stock_qty":1, "rate":100, "amount": 100},
|
|
||||||
{"item_code": "_Test PPT Item SC B","item_name": "_Test PPT Item SC B",
|
|
||||||
"bom_no":"BOM-_Test PPT Item SC B-001", "doctype":"BOM Item", "stock_qty":2,
|
|
||||||
"rate":100, "amount": 200}])
|
|
||||||
|
|
||||||
bom_master = make_bom("BOM-_Test PPT Item Master-001",{"quantity":1,
|
|
||||||
"item": "_Test PPT Item Master",
|
|
||||||
"is_active": 1,
|
|
||||||
"is_default": 1,
|
|
||||||
"docstatus": 1,
|
|
||||||
"with_operations": 0}, [
|
|
||||||
{"item_code": "_Test PPT Item Sub A","item_name": "_Test PPT Item Sub A",
|
|
||||||
"bom_no":"BOM-_Test PPT Item Sub A-001",
|
|
||||||
"doctype":"BOM Item", "stock_qty":2, "rate":100, "amount": 200},
|
|
||||||
{"item_code": "_Test PPT Item Sub B","item_name": "_Test PPT Item Sub B",
|
|
||||||
"bom_no":"BOM-_Test PPT Item Sub B-001",
|
|
||||||
"doctype":"BOM Item", "stock_qty":1, "rate":100, "amount": 100},
|
|
||||||
{"item_code": "_Test PPT Item Raw A","item_name": "_Test PPT Item Raw A",
|
|
||||||
"doctype":"BOM Item", "stock_qty":2, "rate":100,
|
|
||||||
"amount": 200},
|
|
||||||
{"item_code": "_Test PPT Item SC A","item_name": "_Test PPT Item SC A",
|
|
||||||
"bom_no":"BOM-_Test PPT Item SC A-001",
|
|
||||||
"doctype":"BOM Item", "stock_qty":1, "rate":100, "amount": 100}
|
|
||||||
])
|
|
||||||
|
|
||||||
|
|
||||||
def make_bom(name, properties=None, items=None):
|
|
||||||
if frappe.db.exists("BOM", name):
|
|
||||||
return frappe.get_doc("BOM", name)
|
|
||||||
|
|
||||||
bom = frappe.new_doc("BOM")
|
|
||||||
item = frappe.get_doc({
|
|
||||||
"doctype": "BOM",
|
|
||||||
"name": name,
|
|
||||||
"quantity": "1",
|
|
||||||
"with_operations": 0
|
|
||||||
})
|
|
||||||
|
|
||||||
if properties:
|
|
||||||
bom.update(properties)
|
|
||||||
|
|
||||||
if items:
|
|
||||||
for item in items:
|
|
||||||
bom.append("items", item)
|
|
||||||
|
|
||||||
|
|
||||||
bom.insert()
|
|
||||||
bom.submit()
|
|
||||||
|
|
||||||
return bom
|
|
||||||
|
|
||||||
def clear_material_requests():
|
|
||||||
frappe.db.sql("delete from `tabMaterial Request Item`")
|
|
||||||
frappe.db.sql("delete from `tabMaterial Request`")
|
|
||||||
|
|
||||||
|
|
||||||
def run_production_planning_tool(**args):
|
|
||||||
ppt = frappe.new_doc("Production Planning Tool")
|
|
||||||
args = frappe._dict(args)
|
|
||||||
|
|
||||||
if args.use_multi_level_bom:
|
|
||||||
ppt.use_multi_level_bom = args.use_multi_level_bom
|
|
||||||
else:
|
|
||||||
ppt.use_multi_level_bom = 0
|
|
||||||
|
|
||||||
if args.only_raw_materials:
|
|
||||||
ppt.only_raw_materials = args.only_raw_materials
|
|
||||||
else:
|
|
||||||
ppt.only_raw_materials = 0
|
|
||||||
|
|
||||||
if args.include_subcontracted:
|
|
||||||
ppt.include_subcontracted = args.include_subcontracted
|
|
||||||
else:
|
|
||||||
ppt.include_subcontracted = 0
|
|
||||||
|
|
||||||
if args.warehouse:
|
|
||||||
ppt.purchase_request_for_warehouse = args.warehouse
|
|
||||||
|
|
||||||
if args.company:
|
|
||||||
ppt.company = args.company
|
|
||||||
ppt.create_material_requests_for_all_required_qty = 1
|
|
||||||
|
|
||||||
ppt.append("items",{"item_code": args.item_code, "bom_no": args.bom_no, "planned_qty": args.planned_qty,
|
|
||||||
"planned_start_date": args.planned_start_date, "warehouse": args.warehouse})
|
|
||||||
|
|
||||||
return ppt
|
|
||||||
|
|
||||||
def create_material_requests(ppt):
|
|
||||||
ppt.raise_material_requests()
|
|
||||||
|
|
||||||
def get_requested_qty(item_code):
|
|
||||||
total_qty = 0
|
|
||||||
for d in frappe.db.sql("""select item.qty as qty
|
|
||||||
from `tabMaterial Request` mat_req, `tabMaterial Request Item` item
|
|
||||||
where item.item_code = %(item_code)s and item.parent = mat_req.name""", {"item_code":item_code}, as_dict=1):
|
|
||||||
total_qty += d.qty
|
|
||||||
return total_qty
|
|
||||||
|
|
||||||
def get_requested_types(item_code):
|
|
||||||
types = []
|
|
||||||
for d in frappe.db.sql("""select mat_req.material_request_type as type
|
|
||||||
from `tabMaterial Request` mat_req, `tabMaterial Request Item` item
|
|
||||||
where item.item_code = %(item_code)s and item.parent = mat_req.name""", {"item_code":item_code}, as_dict=1):
|
|
||||||
types.append(d.type)
|
|
||||||
return types
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
|||||||
[
|
|
||||||
|
|
||||||
]
|
|
@ -500,3 +500,4 @@ erpnext.patches.v10_0.workflow_expense_claim
|
|||||||
erpnext.patches.v10_0.set_b2c_limit
|
erpnext.patches.v10_0.set_b2c_limit
|
||||||
erpnext.patches.v10_0.update_translatable_fields
|
erpnext.patches.v10_0.update_translatable_fields
|
||||||
erpnext.patches.v10_0.rename_offer_letter_to_job_offer
|
erpnext.patches.v10_0.rename_offer_letter_to_job_offer
|
||||||
|
execute:frappe.delete_doc('DocType', 'Production Planning Tool', ignore_missing=True)
|
||||||
|
@ -234,10 +234,6 @@ class Company(Document):
|
|||||||
frappe.db.set(self, "round_off_cost_center", _("Main") + " - " + self.abbr)
|
frappe.db.set(self, "round_off_cost_center", _("Main") + " - " + self.abbr)
|
||||||
frappe.db.set(self, "depreciation_cost_center", _("Main") + " - " + self.abbr)
|
frappe.db.set(self, "depreciation_cost_center", _("Main") + " - " + self.abbr)
|
||||||
|
|
||||||
def before_rename(self, olddn, newdn, merge=False):
|
|
||||||
if merge:
|
|
||||||
frappe.throw(_("Sorry, companies cannot be merged"))
|
|
||||||
|
|
||||||
def after_rename(self, olddn, newdn, merge=False):
|
def after_rename(self, olddn, newdn, merge=False):
|
||||||
frappe.db.set(self, "company_name", newdn)
|
frappe.db.set(self, "company_name", newdn)
|
||||||
|
|
||||||
|
@ -296,7 +296,7 @@ def make_item_variant():
|
|||||||
|
|
||||||
test_records = frappe.get_test_records('Item')
|
test_records = frappe.get_test_records('Item')
|
||||||
|
|
||||||
def create_item(item_code, is_stock_item=None):
|
def create_item(item_code, is_stock_item=None, valuation_rate=0, warehouse=None):
|
||||||
if not frappe.db.exists("Item", item_code):
|
if not frappe.db.exists("Item", item_code):
|
||||||
item = frappe.new_doc("Item")
|
item = frappe.new_doc("Item")
|
||||||
item.item_code = item_code
|
item.item_code = item_code
|
||||||
@ -304,4 +304,6 @@ def create_item(item_code, is_stock_item=None):
|
|||||||
item.description = item_code
|
item.description = item_code
|
||||||
item.item_group = "All Item Groups"
|
item.item_group = "All Item Groups"
|
||||||
item.is_stock_item = is_stock_item or 1
|
item.is_stock_item = is_stock_item or 1
|
||||||
|
item.valuation_rate = valuation_rate or 0.0
|
||||||
|
item.default_warehouse = warehouse or '_Test Warehouse - _TC'
|
||||||
item.save()
|
item.save()
|
||||||
|
@ -702,6 +702,36 @@
|
|||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 1,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "reference",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"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": "Reference",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"has_web_view": 0,
|
"has_web_view": 0,
|
||||||
@ -716,7 +746,7 @@
|
|||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"menu_index": 0,
|
"menu_index": 0,
|
||||||
"modified": "2017-10-05 18:24:17.148782",
|
"modified": "2017-12-03 18:45:10.293916",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Material Request",
|
"name": "Material Request",
|
||||||
|
@ -92,6 +92,7 @@ class MaterialRequest(BuyingController):
|
|||||||
def on_submit(self):
|
def on_submit(self):
|
||||||
# frappe.db.set(self, 'status', 'Submitted')
|
# frappe.db.set(self, 'status', 'Submitted')
|
||||||
self.update_requested_qty()
|
self.update_requested_qty()
|
||||||
|
self.update_requested_qty_in_production_plan()
|
||||||
|
|
||||||
def before_save(self):
|
def before_save(self):
|
||||||
self.set_status(update=True)
|
self.set_status(update=True)
|
||||||
@ -144,6 +145,7 @@ class MaterialRequest(BuyingController):
|
|||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
self.update_requested_qty()
|
self.update_requested_qty()
|
||||||
|
self.update_requested_qty_in_production_plan()
|
||||||
|
|
||||||
def update_completed_qty(self, mr_items=None, update_modified=True):
|
def update_completed_qty(self, mr_items=None, update_modified=True):
|
||||||
if self.material_request_type == "Purchase":
|
if self.material_request_type == "Purchase":
|
||||||
@ -195,6 +197,22 @@ class MaterialRequest(BuyingController):
|
|||||||
"indented_qty": get_indented_qty(item_code, warehouse)
|
"indented_qty": get_indented_qty(item_code, warehouse)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
def update_requested_qty_in_production_plan(self):
|
||||||
|
production_plans = []
|
||||||
|
for d in self.get('items'):
|
||||||
|
if d.production_plan and d.material_request_plan_item:
|
||||||
|
qty = d.qty if self.docstatus == 1 else 0
|
||||||
|
frappe.db.set_value('Material Request Plan Item',
|
||||||
|
d.material_request_plan_item, 'requested_qty', qty)
|
||||||
|
|
||||||
|
if d.production_plan not in production_plans:
|
||||||
|
production_plans.append(d.production_plan)
|
||||||
|
|
||||||
|
for production_plan in production_plans:
|
||||||
|
doc = frappe.get_doc('Production Plan', production_plan)
|
||||||
|
doc.set_status()
|
||||||
|
doc.db_set('status', doc.status)
|
||||||
|
|
||||||
def update_completed_and_requested_qty(stock_entry, method):
|
def update_completed_and_requested_qty(stock_entry, method):
|
||||||
if stock_entry.doctype == "Stock Entry":
|
if stock_entry.doctype == "Stock Entry":
|
||||||
material_request_map = {}
|
material_request_map = {}
|
||||||
|
@ -701,6 +701,67 @@
|
|||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "production_plan",
|
||||||
|
"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": "Production Plan",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 1,
|
||||||
|
"options": "Production Plan",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 1,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "material_request_plan_item",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"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": "Material Request Plan Item",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 1,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 1,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@ -898,7 +959,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2017-12-15 16:29:18.902085",
|
"modified": "2017-12-20 16:29:18.902085",
|
||||||
"modified_by": "nabinhait@gmail.com",
|
"modified_by": "nabinhait@gmail.com",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Material Request Item",
|
"name": "Material Request Item",
|
||||||
|