[Enhancement] Work Order Material Consumption (#13384)
* Work Order Material Consumption * Test cases and other minor fixes * Test cases fixes * Travis Fixes * Work Order Material Consumption Request Changes * Update work_order.js
This commit is contained in:
parent
e9638be032
commit
ad76f9ad70
Binary file not shown.
|
After Width: | Height: | Size: 112 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 296 KiB |
BIN
erpnext/docs/assets/img/manufacturing/consumed-qty.png
Normal file
BIN
erpnext/docs/assets/img/manufacturing/consumed-qty.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 145 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 127 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 209 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 134 KiB |
@ -0,0 +1,34 @@
|
|||||||
|
#Material consumption
|
||||||
|
|
||||||
|
Material Consumption functionality allows you to have multiple consumption `Stock Entry` against a Work Order. To enable this, go to Manufacturing > Manufacturing Settings.
|
||||||
|
|
||||||
|
<img class="screenshot" alt="Item Alternative" src="{{docs_base_url}}/assets/img/manufacturing/allow-material-consumption.png">
|
||||||
|
|
||||||
|
Once enabled, a `Material Consumption` button will be available in Work Order once started.
|
||||||
|
|
||||||
|
<img class="screenshot" alt="Item Alternative" src="{{docs_base_url}}/assets/img/manufacturing/material-consumption-button.png">
|
||||||
|
|
||||||
|
When button is clicked, it will do the following:
|
||||||
|
|
||||||
|
1. It will create Stock Entry with purpose `Material Consumption for Manufacture`.
|
||||||
|
|
||||||
|
<img class="screenshot" alt="Item Alternative" src="{{docs_base_url}}/assets/img/manufacturing/material-consumption-for-manufacture.png">
|
||||||
|
|
||||||
|
2. If the "Backflush Raw Materials Based On" in the Manufacturing Settings is set to `BOM`, if will propose to consume all required qty for manufacture.
|
||||||
|
3. If the "Backflush Raw Materials Based On" in the Manufacturing Settings is set to `Material Transferred for Manufacture`, if will propose to consume all transferred qty for manufacture.
|
||||||
|
4. Once submitted, it will update `Consumed Qty` column in the Work Order.
|
||||||
|
|
||||||
|
<img class="screenshot" alt="Item Alternative" src="{{docs_base_url}}/assets/img/manufacturing/consumed-qty.png">
|
||||||
|
|
||||||
|
5. In succeeding Material Consumption, it will suggest unconsumed qty.
|
||||||
|
6. Once "Finish" button is clicked in Work Order, it will take into account consumed qty.
|
||||||
|
|
||||||
|
### Validations
|
||||||
|
|
||||||
|
* If "Allow Multiple Material Consumption" is not set in Manufacturing Settings but "Material Consumption for Manufacture" is use in Stock Entry.
|
||||||
|
|
||||||
|
<img class="screenshot" alt="Item Alternative" src="{{docs_base_url}}/assets/img/manufacturing/material-consumption-stock-entry.gif">
|
||||||
|
|
||||||
|
* Cannot cancel "Material Consumption for Manufacture" for completed Work Order.
|
||||||
|
|
||||||
|
<img class="screenshot" alt="Item Alternative" src="{{docs_base_url}}/assets/img/manufacturing/cancel-material-consumption-stock-entry.gif">
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
// For license information, please see license.txt
|
||||||
|
|
||||||
|
frappe.ui.form.on('Manufacturing Settings', {
|
||||||
|
});
|
||||||
@ -1,493 +1,539 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 0,
|
"allow_copy": 0,
|
||||||
"allow_guest_to_view": 0,
|
"allow_guest_to_view": 0,
|
||||||
"allow_import": 0,
|
"allow_import": 0,
|
||||||
"allow_rename": 0,
|
"allow_rename": 0,
|
||||||
"beta": 0,
|
"beta": 0,
|
||||||
"creation": "2014-11-27 14:12:07.542534",
|
"creation": "2014-11-27 14:12:07.542534",
|
||||||
"custom": 0,
|
"custom": 0,
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"document_type": "Document",
|
"document_type": "Document",
|
||||||
"editable_grid": 0,
|
"editable_grid": 0,
|
||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"fieldname": "capacity_planning",
|
"fieldname": "capacity_planning",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section 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_global_search": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"in_standard_filter": 0,
|
"in_standard_filter": 0,
|
||||||
"label": "Capacity Planning",
|
"label": "Capacity Planning",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
"precision": "",
|
||||||
"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,
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"description": "Disables creation of time logs against Work Orders. Operations shall not be tracked against Work Order",
|
"description": "Disables creation of time logs against Work Orders. Operations shall not be tracked against Work Order",
|
||||||
"fieldname": "disable_capacity_planning",
|
"fieldname": "disable_capacity_planning",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"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_global_search": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"in_standard_filter": 0,
|
"in_standard_filter": 0,
|
||||||
"label": "Disable Capacity Planning and Time Tracking",
|
"label": "Disable Capacity Planning and Time Tracking",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
"precision": "",
|
||||||
"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,
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"description": "Plan time logs outside Workstation Working Hours.",
|
"description": "Plan time logs outside Workstation Working Hours.",
|
||||||
"fieldname": "allow_overtime",
|
"fieldname": "allow_overtime",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"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_global_search": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"in_standard_filter": 0,
|
"in_standard_filter": 0,
|
||||||
"label": "Allow Overtime",
|
"label": "Allow Overtime",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
"precision": "",
|
||||||
"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,
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"default": "",
|
"default": "",
|
||||||
"fieldname": "allow_production_on_holidays",
|
"fieldname": "allow_production_on_holidays",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"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_global_search": 0,
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
"in_standard_filter": 0,
|
||||||
"label": "Allow Production on Holidays",
|
"label": "Allow Production on Holidays",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"options": "",
|
"options": "",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
"precision": "",
|
||||||
"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,
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"fieldname": "column_break_3",
|
"fieldname": "column_break_3",
|
||||||
"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_global_search": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"in_standard_filter": 0,
|
"in_standard_filter": 0,
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
"precision": "",
|
||||||
"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,
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"default": "30",
|
"default": "30",
|
||||||
"description": "Try planning operations for X days in advance.",
|
"description": "Try planning operations for X days in advance.",
|
||||||
"fieldname": "capacity_planning_for_days",
|
"fieldname": "capacity_planning_for_days",
|
||||||
"fieldtype": "Int",
|
"fieldtype": "Int",
|
||||||
"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_global_search": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"in_standard_filter": 0,
|
"in_standard_filter": 0,
|
||||||
"label": "Capacity Planning For (Days)",
|
"label": "Capacity Planning For (Days)",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
"precision": "",
|
||||||
"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,
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"description": "Default 10 mins",
|
"description": "Default 10 mins",
|
||||||
"fieldname": "mins_between_operations",
|
"fieldname": "mins_between_operations",
|
||||||
"fieldtype": "Int",
|
"fieldtype": "Int",
|
||||||
"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_global_search": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"in_standard_filter": 0,
|
"in_standard_filter": 0,
|
||||||
"label": "Time Between Operations (in mins)",
|
"label": "Time Between Operations (in mins)",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
"precision": "",
|
||||||
"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,
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"fieldname": "section_break_6",
|
"fieldname": "section_break_6",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section 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_global_search": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"in_standard_filter": 0,
|
"in_standard_filter": 0,
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
"precision": "",
|
||||||
"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,
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"fieldname": "over_production_allowance_percentage",
|
"fieldname": "over_production_allowance_percentage",
|
||||||
"fieldtype": "Percent",
|
"fieldtype": "Percent",
|
||||||
"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_global_search": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"in_standard_filter": 0,
|
"in_standard_filter": 0,
|
||||||
"label": "Over Production Allowance Percentage",
|
"label": "Over Production Allowance Percentage",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
"precision": "",
|
||||||
"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,
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"default": "BOM",
|
"default": "BOM",
|
||||||
"fieldname": "backflush_raw_materials_based_on",
|
"fieldname": "backflush_raw_materials_based_on",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"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_global_search": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"in_standard_filter": 0,
|
"in_standard_filter": 0,
|
||||||
"label": "Backflush Raw Materials Based On",
|
"label": "Backflush Raw Materials Based On",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"options": "BOM\nMaterial Transferred for Manufacture",
|
"options": "BOM\nMaterial Transferred for Manufacture",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
"precision": "",
|
||||||
"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,
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"description": "Update BOM cost automatically via Scheduler, based on latest valuation rate / price list rate / last purchase rate of raw materials.",
|
"description": "Allow multiple Material Consumption against a Work Order",
|
||||||
"fieldname": "update_bom_costs_automatically",
|
"fieldname": "material_consumption",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"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_global_search": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"in_standard_filter": 0,
|
"in_standard_filter": 0,
|
||||||
"label": "Update BOM Cost Automatically",
|
"label": "Allow Multiple Material Consumption",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
"precision": "",
|
||||||
"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,
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"fieldname": "column_break_11",
|
"description": "Update BOM cost automatically via Scheduler, based on latest valuation rate / price list rate / last purchase rate of raw materials.",
|
||||||
"fieldtype": "Column Break",
|
"fieldname": "update_bom_costs_automatically",
|
||||||
"hidden": 0,
|
"fieldtype": "Check",
|
||||||
"ignore_user_permissions": 0,
|
"hidden": 0,
|
||||||
"ignore_xss_filter": 0,
|
"ignore_user_permissions": 0,
|
||||||
"in_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_global_search": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_global_search": 0,
|
||||||
"in_standard_filter": 0,
|
"in_list_view": 0,
|
||||||
"length": 0,
|
"in_standard_filter": 0,
|
||||||
"no_copy": 0,
|
"label": "Update BOM Cost Automatically",
|
||||||
"permlevel": 0,
|
"length": 0,
|
||||||
"precision": "",
|
"no_copy": 0,
|
||||||
"print_hide": 0,
|
"permlevel": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"precision": "",
|
||||||
"read_only": 0,
|
"print_hide": 0,
|
||||||
"remember_last_selected_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"report_hide": 0,
|
"read_only": 0,
|
||||||
"reqd": 0,
|
"remember_last_selected_value": 0,
|
||||||
"search_index": 0,
|
"report_hide": 0,
|
||||||
"set_only_once": 0,
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"fieldname": "default_wip_warehouse",
|
"fieldname": "column_break_11",
|
||||||
"fieldtype": "Link",
|
"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_global_search": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"in_standard_filter": 0,
|
"in_standard_filter": 0,
|
||||||
"label": "Default Work In Progress Warehouse",
|
"length": 0,
|
||||||
"length": 0,
|
"no_copy": 0,
|
||||||
"no_copy": 0,
|
"permlevel": 0,
|
||||||
"options": "Warehouse",
|
"precision": "",
|
||||||
"permlevel": 0,
|
"print_hide": 0,
|
||||||
"precision": "",
|
"print_hide_if_no_value": 0,
|
||||||
"print_hide": 0,
|
"read_only": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"remember_last_selected_value": 0,
|
||||||
"read_only": 0,
|
"report_hide": 0,
|
||||||
"remember_last_selected_value": 0,
|
"reqd": 0,
|
||||||
"report_hide": 0,
|
"search_index": 0,
|
||||||
"reqd": 0,
|
"set_only_once": 0,
|
||||||
"search_index": 0,
|
"translatable": 0,
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"fieldname": "default_fg_warehouse",
|
"fieldname": "default_wip_warehouse",
|
||||||
"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_global_search": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"in_standard_filter": 0,
|
"in_standard_filter": 0,
|
||||||
"label": "Default Finished Goods Warehouse",
|
"label": "Default Work In Progress Warehouse",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"options": "Warehouse",
|
"options": "Warehouse",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
"precision": "",
|
||||||
"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,
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "default_fg_warehouse",
|
||||||
|
"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": "Default Finished Goods 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": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"has_web_view": 0,
|
"has_web_view": 0,
|
||||||
"hide_heading": 0,
|
"hide_heading": 0,
|
||||||
"hide_toolbar": 0,
|
"hide_toolbar": 0,
|
||||||
"icon": "icon-wrench",
|
"icon": "icon-wrench",
|
||||||
"idx": 0,
|
"idx": 0,
|
||||||
"image_view": 0,
|
"image_view": 0,
|
||||||
"in_create": 0,
|
"in_create": 0,
|
||||||
"is_submittable": 0,
|
"is_submittable": 0,
|
||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"menu_index": 0,
|
"menu_index": 0,
|
||||||
"modified": "2018-02-16 13:18:17.964103",
|
"modified": "2018-03-28 13:56:31.187520",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "Manufacturing Settings",
|
"name": "Manufacturing Settings",
|
||||||
"name_case": "",
|
"name_case": "",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
"amend": 0,
|
"amend": 0,
|
||||||
"apply_user_permissions": 0,
|
"apply_user_permissions": 0,
|
||||||
"cancel": 0,
|
"cancel": 0,
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 0,
|
"delete": 0,
|
||||||
"email": 0,
|
"email": 0,
|
||||||
"export": 0,
|
"export": 0,
|
||||||
"if_owner": 0,
|
"if_owner": 0,
|
||||||
"import": 0,
|
"import": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print": 0,
|
"print": 0,
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"report": 0,
|
"report": 0,
|
||||||
"role": "Manufacturing Manager",
|
"role": "Manufacturing Manager",
|
||||||
"set_user_permissions": 0,
|
"set_user_permissions": 0,
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"submit": 0,
|
"submit": 0,
|
||||||
"write": 1
|
"write": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"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,
|
"show_name_in_global_search": 0,
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"track_changes": 1,
|
"track_changes": 1,
|
||||||
"track_seen": 0
|
"track_seen": 0
|
||||||
}
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
|
# See license.txt
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
class TestManufacturingSettings(unittest.TestCase):
|
||||||
|
pass
|
||||||
@ -60,6 +60,7 @@ class TestWorkOrder(unittest.TestCase):
|
|||||||
|
|
||||||
def test_over_production(self):
|
def test_over_production(self):
|
||||||
from erpnext.manufacturing.doctype.work_order.work_order import StockOverProductionError
|
from erpnext.manufacturing.doctype.work_order.work_order import StockOverProductionError
|
||||||
|
|
||||||
wo_doc = self.check_planned_qty()
|
wo_doc = self.check_planned_qty()
|
||||||
|
|
||||||
test_stock_entry.make_stock_entry(item_code="_Test Item",
|
test_stock_entry.make_stock_entry(item_code="_Test Item",
|
||||||
@ -300,6 +301,7 @@ def make_wo_order_test_record(**args):
|
|||||||
wo_order.company = args.company or "_Test Company"
|
wo_order.company = args.company or "_Test Company"
|
||||||
wo_order.stock_uom = args.stock_uom or "_Test UOM"
|
wo_order.stock_uom = args.stock_uom or "_Test UOM"
|
||||||
wo_order.use_multi_level_bom=0
|
wo_order.use_multi_level_bom=0
|
||||||
|
wo_order.skip_transfer=1
|
||||||
wo_order.get_items_and_operations_from_bom()
|
wo_order.get_items_and_operations_from_bom()
|
||||||
|
|
||||||
if args.source_warehouse:
|
if args.source_warehouse:
|
||||||
|
|||||||
@ -7,7 +7,7 @@ frappe.ui.form.on("Work Order", {
|
|||||||
'Timesheet': 'Make Timesheet',
|
'Timesheet': 'Make Timesheet',
|
||||||
'Stock Entry': 'Make Stock Entry',
|
'Stock Entry': 'Make Stock Entry',
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set query for warehouses
|
// Set query for warehouses
|
||||||
frm.set_query("wip_warehouse", function(doc) {
|
frm.set_query("wip_warehouse", function(doc) {
|
||||||
return {
|
return {
|
||||||
@ -16,7 +16,7 @@ frappe.ui.form.on("Work Order", {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
frm.set_query("source_warehouse", function() {
|
frm.set_query("source_warehouse", function() {
|
||||||
return {
|
return {
|
||||||
filters: {
|
filters: {
|
||||||
@ -24,7 +24,7 @@ frappe.ui.form.on("Work Order", {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
frm.set_query("source_warehouse", "required_items", function() {
|
frm.set_query("source_warehouse", "required_items", function() {
|
||||||
return {
|
return {
|
||||||
filters: {
|
filters: {
|
||||||
@ -32,7 +32,7 @@ frappe.ui.form.on("Work Order", {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
frm.set_query("fg_warehouse", function() {
|
frm.set_query("fg_warehouse", function() {
|
||||||
return {
|
return {
|
||||||
filters: {
|
filters: {
|
||||||
@ -41,7 +41,7 @@ frappe.ui.form.on("Work Order", {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
frm.set_query("scrap_warehouse", function() {
|
frm.set_query("scrap_warehouse", function() {
|
||||||
return {
|
return {
|
||||||
filters: {
|
filters: {
|
||||||
@ -50,7 +50,7 @@ frappe.ui.form.on("Work Order", {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Set query for BOM
|
// Set query for BOM
|
||||||
frm.set_query("bom_no", function() {
|
frm.set_query("bom_no", function() {
|
||||||
if (frm.doc.production_item) {
|
if (frm.doc.production_item) {
|
||||||
@ -60,7 +60,7 @@ frappe.ui.form.on("Work Order", {
|
|||||||
}
|
}
|
||||||
} else msgprint(__("Please enter Production Item first"));
|
} else msgprint(__("Please enter Production Item first"));
|
||||||
});
|
});
|
||||||
|
|
||||||
// Set query for FG Item
|
// Set query for FG Item
|
||||||
frm.set_query("production_item", function() {
|
frm.set_query("production_item", function() {
|
||||||
return {
|
return {
|
||||||
@ -84,7 +84,7 @@ frappe.ui.form.on("Work Order", {
|
|||||||
frm.set_indicator_formatter('operation',
|
frm.set_indicator_formatter('operation',
|
||||||
function(doc) { return (frm.doc.qty==doc.completed_qty) ? "green" : "orange" });
|
function(doc) { return (frm.doc.qty==doc.completed_qty) ? "green" : "orange" });
|
||||||
},
|
},
|
||||||
|
|
||||||
onload: function(frm) {
|
onload: function(frm) {
|
||||||
if (!frm.doc.status)
|
if (!frm.doc.status)
|
||||||
frm.doc.status = 'Draft';
|
frm.doc.status = 'Draft';
|
||||||
@ -122,7 +122,7 @@ frappe.ui.form.on("Work Order", {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
show_progress: function(frm) {
|
show_progress: function(frm) {
|
||||||
var bars = [];
|
var bars = [];
|
||||||
var message = '';
|
var message = '';
|
||||||
@ -156,7 +156,7 @@ frappe.ui.form.on("Work Order", {
|
|||||||
}
|
}
|
||||||
frm.dashboard.add_progress(__('Status'), bars, message);
|
frm.dashboard.add_progress(__('Status'), bars, message);
|
||||||
},
|
},
|
||||||
|
|
||||||
production_item: function(frm) {
|
production_item: function(frm) {
|
||||||
if (frm.doc.production_item) {
|
if (frm.doc.production_item) {
|
||||||
frappe.call({
|
frappe.call({
|
||||||
@ -184,13 +184,13 @@ frappe.ui.form.on("Work Order", {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
project: function(frm) {
|
project: function(frm) {
|
||||||
if(!erpnext.in_production_item_onchange) {
|
if(!erpnext.in_production_item_onchange) {
|
||||||
frm.trigger("production_item");
|
frm.trigger("production_item");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
bom_no: function(frm) {
|
bom_no: function(frm) {
|
||||||
return frm.call({
|
return frm.call({
|
||||||
doc: frm.doc,
|
doc: frm.doc,
|
||||||
@ -203,7 +203,7 @@ frappe.ui.form.on("Work Order", {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
use_multi_level_bom: function(frm) {
|
use_multi_level_bom: function(frm) {
|
||||||
if(frm.doc.bom_no) {
|
if(frm.doc.bom_no) {
|
||||||
frm.trigger("bom_no");
|
frm.trigger("bom_no");
|
||||||
@ -213,7 +213,7 @@ frappe.ui.form.on("Work Order", {
|
|||||||
qty: function(frm) {
|
qty: function(frm) {
|
||||||
frm.trigger('bom_no');
|
frm.trigger('bom_no');
|
||||||
},
|
},
|
||||||
|
|
||||||
before_submit: function(frm) {
|
before_submit: function(frm) {
|
||||||
frm.toggle_reqd(["fg_warehouse", "wip_warehouse"], true);
|
frm.toggle_reqd(["fg_warehouse", "wip_warehouse"], true);
|
||||||
frm.fields_dict.required_items.grid.toggle_reqd("source_warehouse", true);
|
frm.fields_dict.required_items.grid.toggle_reqd("source_warehouse", true);
|
||||||
@ -251,7 +251,7 @@ frappe.ui.form.on("Work Order Item", {
|
|||||||
item_code: row.item_code,
|
item_code: row.item_code,
|
||||||
warehouse: row.source_warehouse
|
warehouse: row.source_warehouse
|
||||||
},
|
},
|
||||||
callback: function (r) {
|
callback: function (r) {
|
||||||
frappe.model.set_value(row.doctype, row.name,
|
frappe.model.set_value(row.doctype, row.name,
|
||||||
"available_qty_at_source_warehouse", r.message);
|
"available_qty_at_source_warehouse", r.message);
|
||||||
}
|
}
|
||||||
@ -310,21 +310,42 @@ erpnext.work_order = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(!frm.doc.skip_transfer){
|
if(!frm.doc.skip_transfer){
|
||||||
if ((flt(doc.produced_qty) < flt(doc.material_transferred_for_manufacturing))
|
// If "Material Consumption is check in Manufacturing Settings, allow Material Consumption
|
||||||
&& frm.doc.status != 'Stopped') {
|
frappe.model.get_value('Manufacturing Settings', {'name': 'Manufacturing Settings'}, 'material_consumption', function(d) {
|
||||||
frm.has_finish_btn = true;
|
if ((flt(doc.produced_qty) < flt(doc.material_transferred_for_manufacturing))
|
||||||
var finish_btn = frm.add_custom_button(__('Finish'), function() {
|
&& frm.doc.status != 'Stopped') {
|
||||||
erpnext.work_order.make_se(frm, 'Manufacture');
|
frm.has_finish_btn = true;
|
||||||
});
|
|
||||||
|
|
||||||
if(doc.material_transferred_for_manufacturing==doc.qty) {
|
if (d.material_consumption == 1) {
|
||||||
// all materials transferred for manufacturing, make this primary
|
// Only show "Material Consumption" when required_qty > consumed_qty
|
||||||
finish_btn.addClass('btn-primary');
|
var counter = 0;
|
||||||
|
var tbl = frm.doc.required_items || [];
|
||||||
|
var tbl_lenght = tbl.length;
|
||||||
|
for (var i = 0, len = tbl_lenght; i < len; i++) {
|
||||||
|
if (flt(frm.doc.required_items[i].required_qty) > flt(frm.doc.required_items[i].consumed_qty)) {
|
||||||
|
counter += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (counter > 0) {
|
||||||
|
var consumption_btn = frm.add_custom_button(__('Material Consumption'), function() {
|
||||||
|
erpnext.work_order.make_consumption_se(frm, d.backflush_raw_materials_based_on);
|
||||||
|
});
|
||||||
|
consumption_btn.addClass('btn-primary');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var finish_btn = frm.add_custom_button(__('Finish'), function() {
|
||||||
|
erpnext.work_order.make_se(frm, 'Manufacture');
|
||||||
|
});
|
||||||
|
|
||||||
|
if(doc.material_transferred_for_manufacturing==doc.qty) {
|
||||||
|
// all materials transferred for manufacturing, make this primary
|
||||||
|
finish_btn.addClass('btn-primary');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
} else {
|
} else {
|
||||||
if ((flt(doc.produced_qty) < flt(doc.qty)) && frm.doc.status != 'Stopped') {
|
if ((flt(doc.produced_qty) < flt(doc.qty)) && frm.doc.status != 'Stopped') {
|
||||||
frm.has_finish_btn = true;
|
|
||||||
var finish_btn = frm.add_custom_button(__('Finish'), function() {
|
var finish_btn = frm.add_custom_button(__('Finish'), function() {
|
||||||
erpnext.work_order.make_se(frm, 'Manufacture');
|
erpnext.work_order.make_se(frm, 'Manufacture');
|
||||||
});
|
});
|
||||||
@ -367,7 +388,7 @@ erpnext.work_order = {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
make_se: function(frm, purpose) {
|
make_se: function(frm, purpose) {
|
||||||
if(!frm.doc.skip_transfer){
|
if(!frm.doc.skip_transfer){
|
||||||
var max = (purpose === "Manufacture") ?
|
var max = (purpose === "Manufacture") ?
|
||||||
@ -399,7 +420,31 @@ erpnext.work_order = {
|
|||||||
});
|
});
|
||||||
}, __("Select Quantity"), __("Make"));
|
}, __("Select Quantity"), __("Make"));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
make_consumption_se: function(frm, backflush_raw_materials_based_on) {
|
||||||
|
if(!frm.doc.skip_transfer){
|
||||||
|
var max = (backflush_raw_materials_based_on === "Material Transferred for Manufacture") ?
|
||||||
|
flt(frm.doc.material_transferred_for_manufacturing) - flt(frm.doc.produced_qty) :
|
||||||
|
flt(frm.doc.qty) - flt(frm.doc.produced_qty);
|
||||||
|
// flt(frm.doc.qty) - flt(frm.doc.material_transferred_for_manufacturing);
|
||||||
|
} else {
|
||||||
|
var max = flt(frm.doc.qty) - flt(frm.doc.produced_qty);
|
||||||
|
}
|
||||||
|
|
||||||
|
frappe.call({
|
||||||
|
method:"erpnext.manufacturing.doctype.work_order.work_order.make_stock_entry",
|
||||||
|
args: {
|
||||||
|
"work_order_id": frm.doc.name,
|
||||||
|
"purpose": "Material Consumption for Manufacture",
|
||||||
|
"qty": max
|
||||||
|
},
|
||||||
|
callback: function(r) {
|
||||||
|
var doclist = frappe.model.sync(r.message);
|
||||||
|
frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
stop_work_order: function(frm, status) {
|
stop_work_order: function(frm, status) {
|
||||||
frappe.call({
|
frappe.call({
|
||||||
method: "erpnext.manufacturing.doctype.work_order.work_order.stop_unstop",
|
method: "erpnext.manufacturing.doctype.work_order.work_order.stop_unstop",
|
||||||
|
|||||||
@ -64,7 +64,7 @@ class WorkOrder(Document):
|
|||||||
so.name, so_item.delivery_date, so.project
|
so.name, so_item.delivery_date, so.project
|
||||||
from
|
from
|
||||||
`tabSales Order` so, `tabSales Order Item` so_item, `tabPacked Item` packed_item
|
`tabSales Order` so, `tabSales Order Item` so_item, `tabPacked Item` packed_item
|
||||||
where so.name=%s
|
where so.name=%s
|
||||||
and so.name=so_item.parent
|
and so.name=so_item.parent
|
||||||
and so.name=packed_item.parent
|
and so.name=packed_item.parent
|
||||||
and so_item.item_code = packed_item.parent_item
|
and so_item.item_code = packed_item.parent_item
|
||||||
@ -88,7 +88,7 @@ class WorkOrder(Document):
|
|||||||
self.wip_warehouse = frappe.db.get_single_value("Manufacturing Settings", "default_wip_warehouse")
|
self.wip_warehouse = frappe.db.get_single_value("Manufacturing Settings", "default_wip_warehouse")
|
||||||
if not self.fg_warehouse:
|
if not self.fg_warehouse:
|
||||||
self.fg_warehouse = frappe.db.get_single_value("Manufacturing Settings", "default_fg_warehouse")
|
self.fg_warehouse = frappe.db.get_single_value("Manufacturing Settings", "default_fg_warehouse")
|
||||||
|
|
||||||
def validate_warehouse_belongs_to_company(self):
|
def validate_warehouse_belongs_to_company(self):
|
||||||
warehouses = [self.fg_warehouse, self.wip_warehouse]
|
warehouses = [self.fg_warehouse, self.wip_warehouse]
|
||||||
for d in self.get("required_items"):
|
for d in self.get("required_items"):
|
||||||
@ -184,7 +184,7 @@ class WorkOrder(Document):
|
|||||||
and purpose=%s""", (self.name, purpose))[0][0])
|
and purpose=%s""", (self.name, purpose))[0][0])
|
||||||
|
|
||||||
if qty > self.qty:
|
if qty > self.qty:
|
||||||
frappe.throw(_("{0} ({1}) cannot be greater than planned quanitity ({2}) in Work Order {3}").format(\
|
frappe.throw(_("{0} ({1}) cannot be greater than planned quantity ({2}) in Work Order {3}").format(\
|
||||||
self.meta.get_label(fieldname), qty, self.qty, self.name), StockOverProductionError)
|
self.meta.get_label(fieldname), qty, self.qty, self.name), StockOverProductionError)
|
||||||
|
|
||||||
self.db_set(fieldname, qty)
|
self.db_set(fieldname, qty)
|
||||||
@ -449,6 +449,9 @@ class WorkOrder(Document):
|
|||||||
# update in bin
|
# update in bin
|
||||||
self.update_reserved_qty_for_production()
|
self.update_reserved_qty_for_production()
|
||||||
|
|
||||||
|
# calculate consumed qty based on submitted stock entries
|
||||||
|
self.update_consumed_qty_for_required_items()
|
||||||
|
|
||||||
def update_reserved_qty_for_production(self, items=None):
|
def update_reserved_qty_for_production(self, items=None):
|
||||||
'''update reserved_qty_for_production in bins'''
|
'''update reserved_qty_for_production in bins'''
|
||||||
for d in self.required_items:
|
for d in self.required_items:
|
||||||
@ -515,6 +518,24 @@ class WorkOrder(Document):
|
|||||||
|
|
||||||
d.db_set('transferred_qty', flt(transferred_qty), update_modified = False)
|
d.db_set('transferred_qty', flt(transferred_qty), update_modified = False)
|
||||||
|
|
||||||
|
def update_consumed_qty_for_required_items(self):
|
||||||
|
'''update consumed qty from submitted stock entries for that item against
|
||||||
|
the work order'''
|
||||||
|
|
||||||
|
for d in self.required_items:
|
||||||
|
consumed_qty = frappe.db.sql('''select sum(qty)
|
||||||
|
from `tabStock Entry` entry, `tabStock Entry Detail` detail
|
||||||
|
where
|
||||||
|
entry.work_order = %s
|
||||||
|
and (entry.purpose = "Material Consumption for Manufacture"
|
||||||
|
or entry.purpose = "Manufacture")
|
||||||
|
and entry.docstatus = 1
|
||||||
|
and detail.parent = entry.name
|
||||||
|
and detail.item_code = %s''', (self.name, d.item_code))[0][0]
|
||||||
|
|
||||||
|
d.db_set('consumed_qty', flt(consumed_qty), update_modified = False)
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_item_details(item, project = None):
|
def get_item_details(item, project = None):
|
||||||
res = frappe.db.sql("""
|
res = frappe.db.sql("""
|
||||||
@ -600,9 +621,10 @@ def make_stock_entry(work_order_id, purpose, qty=None):
|
|||||||
else:
|
else:
|
||||||
stock_entry.from_warehouse = wip_warehouse
|
stock_entry.from_warehouse = wip_warehouse
|
||||||
stock_entry.to_warehouse = work_order.fg_warehouse
|
stock_entry.to_warehouse = work_order.fg_warehouse
|
||||||
additional_costs = get_additional_costs(work_order, fg_qty=stock_entry.fg_completed_qty)
|
|
||||||
stock_entry.project = work_order.project
|
stock_entry.project = work_order.project
|
||||||
stock_entry.set("additional_costs", additional_costs)
|
if purpose=="Manufacture":
|
||||||
|
additional_costs = get_additional_costs(work_order, fg_qty=stock_entry.fg_completed_qty)
|
||||||
|
stock_entry.set("additional_costs", additional_costs)
|
||||||
|
|
||||||
stock_entry.get_items()
|
stock_entry.get_items()
|
||||||
return stock_entry.as_dict()
|
return stock_entry.as_dict()
|
||||||
@ -668,5 +690,5 @@ def query_sales_order(production_item):
|
|||||||
select distinct so.name from `tabSales Order` so, `tabPacked Item` pi_item
|
select distinct so.name from `tabSales Order` so, `tabPacked Item` pi_item
|
||||||
where pi_item.parent=so.name and pi_item.item_code=%s and so.docstatus=1
|
where pi_item.parent=so.name and pi_item.item_code=%s and so.docstatus=1
|
||||||
""", (production_item, production_item))
|
""", (production_item, production_item))
|
||||||
|
|
||||||
return out
|
return out
|
||||||
|
|||||||
@ -1,16 +1,16 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 0,
|
"allow_copy": 0,
|
||||||
"allow_guest_to_view": 0,
|
"allow_guest_to_view": 0,
|
||||||
"allow_import": 0,
|
"allow_import": 0,
|
||||||
"allow_rename": 0,
|
"allow_rename": 0,
|
||||||
"beta": 0,
|
"beta": 0,
|
||||||
"creation": "2016-04-18 07:38:26.314642",
|
"creation": "2016-04-18 07:38:26.314642",
|
||||||
"custom": 0,
|
"custom": 0,
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"document_type": "",
|
"document_type": "",
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
@ -41,9 +41,9 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@ -73,9 +73,9 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@ -103,9 +103,9 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@ -134,9 +134,9 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@ -165,9 +165,9 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@ -196,9 +196,9 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@ -227,9 +227,9 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@ -290,39 +290,41 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"fieldname": "column_break_9",
|
"depends_on": "eval:!parent.skip_transfer",
|
||||||
"fieldtype": "Column Break",
|
"fieldname": "consumed_qty",
|
||||||
"hidden": 0,
|
"fieldtype": "Float",
|
||||||
"ignore_user_permissions": 0,
|
"hidden": 0,
|
||||||
"ignore_xss_filter": 0,
|
"ignore_user_permissions": 0,
|
||||||
"in_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_global_search": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_global_search": 0,
|
||||||
"in_standard_filter": 0,
|
"in_list_view": 1,
|
||||||
"length": 0,
|
"in_standard_filter": 0,
|
||||||
"no_copy": 0,
|
"label": "Consumed Qty",
|
||||||
"permlevel": 0,
|
"length": 0,
|
||||||
"precision": "",
|
"no_copy": 0,
|
||||||
"print_hide": 0,
|
"permlevel": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"precision": "",
|
||||||
"read_only": 0,
|
"print_hide": 0,
|
||||||
"remember_last_selected_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"report_hide": 0,
|
"read_only": 1,
|
||||||
"reqd": 0,
|
"remember_last_selected_value": 0,
|
||||||
"search_index": 0,
|
"report_hide": 0,
|
||||||
"set_only_once": 0,
|
"reqd": 0,
|
||||||
"translatable": 0,
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@ -351,14 +353,14 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"fieldname": "available_qty_at_wip_warehouse",
|
"fieldname": "available_qty_at_wip_warehouse",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
@ -398,17 +400,17 @@
|
|||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2018-03-05 13:07:07.530725",
|
"modified": "2018-03-05 13:07:07.530725",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "Work Order Item",
|
"name": "Work Order Item",
|
||||||
"name_case": "",
|
"name_case": "",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [],
|
"permissions": [],
|
||||||
"quick_entry": 1,
|
"quick_entry": 1,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"read_only_onload": 0,
|
"read_only_onload": 0,
|
||||||
"show_name_in_global_search": 0,
|
"show_name_in_global_search": 0,
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"track_changes": 1,
|
"track_changes": 1,
|
||||||
"track_seen": 0
|
"track_seen": 0
|
||||||
}
|
}
|
||||||
@ -95,6 +95,7 @@ frappe.ui.form.on('Stock Entry', {
|
|||||||
|
|
||||||
refresh: function(frm) {
|
refresh: function(frm) {
|
||||||
if(!frm.doc.docstatus) {
|
if(!frm.doc.docstatus) {
|
||||||
|
frm.trigger('validate_purpose_consumption');
|
||||||
frm.add_custom_button(__('Make Material Request'), function() {
|
frm.add_custom_button(__('Make Material Request'), function() {
|
||||||
frappe.model.with_doctype('Material Request', function() {
|
frappe.model.with_doctype('Material Request', function() {
|
||||||
var mr = frappe.model.get_new_doc('Material Request');
|
var mr = frappe.model.get_new_doc('Material Request');
|
||||||
@ -168,10 +169,20 @@ frappe.ui.form.on('Stock Entry', {
|
|||||||
},
|
},
|
||||||
|
|
||||||
purpose: function(frm) {
|
purpose: function(frm) {
|
||||||
|
frm.trigger('validate_purpose_consumption');
|
||||||
frm.fields_dict.items.grid.refresh();
|
frm.fields_dict.items.grid.refresh();
|
||||||
frm.cscript.toggle_related_fields(frm.doc);
|
frm.cscript.toggle_related_fields(frm.doc);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
validate_purpose_consumption: function(frm) {
|
||||||
|
frappe.model.get_value('Manufacturing Settings', {'name': 'Manufacturing Settings'}, 'material_consumption', function(d) {
|
||||||
|
if (d.material_consumption==0 && frm.doc.purpose=="Material Consumption for Manufacture") {
|
||||||
|
frm.set_value("purpose", 'Manufacture');
|
||||||
|
frappe.throw(__('Material Consumption is not set in Manufacturing Settings.'));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
company: function(frm) {
|
company: function(frm) {
|
||||||
if(frm.doc.company) {
|
if(frm.doc.company) {
|
||||||
var company_doc = frappe.get_doc(":Company", frm.doc.company);
|
var company_doc = frappe.get_doc(":Company", frm.doc.company);
|
||||||
@ -519,11 +530,11 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.frm.set_indicator_formatter('item_code',
|
this.frm.set_indicator_formatter('item_code',
|
||||||
function(doc) {
|
function(doc) {
|
||||||
if (!doc.s_warehouse) {
|
if (!doc.s_warehouse) {
|
||||||
return 'blue';
|
return 'blue';
|
||||||
} else {
|
} else {
|
||||||
return (doc.qty<=doc.actual_qty) ? "green" : "orange"
|
return (doc.qty<=doc.actual_qty) ? "green" : "orange"
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -592,7 +603,8 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
|
|||||||
clean_up: function() {
|
clean_up: function() {
|
||||||
// Clear Work Order record from locals, because it is updated via Stock Entry
|
// Clear Work Order record from locals, because it is updated via Stock Entry
|
||||||
if(this.frm.doc.work_order &&
|
if(this.frm.doc.work_order &&
|
||||||
in_list(["Manufacture", "Material Transfer for Manufacture"], this.frm.doc.purpose)) {
|
in_list(["Manufacture", "Material Transfer for Manufacture", "Material Consumption for Manufacture"],
|
||||||
|
this.frm.doc.purpose)) {
|
||||||
frappe.model.remove_from_locals("Work Order",
|
frappe.model.remove_from_locals("Work Order",
|
||||||
this.frm.doc.work_order);
|
this.frm.doc.work_order);
|
||||||
}
|
}
|
||||||
@ -637,16 +649,17 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
|
|||||||
me.frm.set_value("to_warehouse", r.message["wip_warehouse"]);
|
me.frm.set_value("to_warehouse", r.message["wip_warehouse"]);
|
||||||
|
|
||||||
|
|
||||||
if (me.frm.doc.purpose == "Manufacture") {
|
if (me.frm.doc.purpose == "Manufacture" || me.frm.doc.purpose == "Material Consumption for Manufacture" ) {
|
||||||
if(r.message["additional_costs"].length) {
|
if (me.frm.doc.purpose == "Manufacture") {
|
||||||
$.each(r.message["additional_costs"], function(i, row) {
|
if (!me.frm.doc.to_warehouse) me.frm.set_value("to_warehouse", r.message["fg_warehouse"]);
|
||||||
me.frm.add_child("additional_costs", row);
|
if (r.message["additional_costs"].length) {
|
||||||
})
|
$.each(r.message["additional_costs"], function(i, row) {
|
||||||
refresh_field("additional_costs");
|
me.frm.add_child("additional_costs", row);
|
||||||
|
})
|
||||||
|
refresh_field("additional_costs");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!me.frm.doc.from_warehouse) me.frm.set_value("from_warehouse", r.message["wip_warehouse"]);
|
if (!me.frm.doc.from_warehouse) me.frm.set_value("from_warehouse", r.message["wip_warehouse"]);
|
||||||
if (!me.frm.doc.to_warehouse) me.frm.set_value("to_warehouse", r.message["fg_warehouse"]);
|
|
||||||
}
|
}
|
||||||
me.get_items()
|
me.get_items()
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -43,6 +43,7 @@ class StockEntry(StockController):
|
|||||||
self.validate_posting_time()
|
self.validate_posting_time()
|
||||||
self.validate_purpose()
|
self.validate_purpose()
|
||||||
self.validate_item()
|
self.validate_item()
|
||||||
|
self.validate_qty()
|
||||||
self.set_transfer_qty()
|
self.set_transfer_qty()
|
||||||
self.validate_uom_is_integer("uom", "qty")
|
self.validate_uom_is_integer("uom", "qty")
|
||||||
self.validate_uom_is_integer("stock_uom", "transfer_qty")
|
self.validate_uom_is_integer("stock_uom", "transfer_qty")
|
||||||
@ -80,15 +81,26 @@ class StockEntry(StockController):
|
|||||||
self.update_cost_in_project()
|
self.update_cost_in_project()
|
||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
self.update_stock_ledger()
|
|
||||||
self.update_work_order()
|
|
||||||
if self.purchase_order and self.purpose == "Subcontract":
|
if self.purchase_order and self.purpose == "Subcontract":
|
||||||
self.update_purchase_order_supplied_items()
|
self.update_purchase_order_supplied_items()
|
||||||
|
|
||||||
|
if self.work_order and self.purpose == "Material Consumption for Manufacture":
|
||||||
|
self.validate_work_order_status()
|
||||||
|
else:
|
||||||
|
self.update_work_order()
|
||||||
|
|
||||||
|
self.update_stock_ledger()
|
||||||
self.make_gl_entries_on_cancel()
|
self.make_gl_entries_on_cancel()
|
||||||
|
|
||||||
|
def validate_work_order_status(self):
|
||||||
|
pro_doc = frappe.get_doc("Work Order", self.work_order)
|
||||||
|
if pro_doc.status == 'Completed':
|
||||||
|
frappe.throw(_("Cannot cancel transaction for Completed Work Order."))
|
||||||
|
|
||||||
def validate_purpose(self):
|
def validate_purpose(self):
|
||||||
valid_purposes = ["Material Issue", "Material Receipt", "Material Transfer", "Material Transfer for Manufacture",
|
valid_purposes = ["Material Issue", "Material Receipt", "Material Transfer", "Material Transfer for Manufacture",
|
||||||
"Manufacture", "Repack", "Subcontract"]
|
"Manufacture", "Repack", "Subcontract", "Material Consumption for Manufacture"]
|
||||||
if self.purpose not in valid_purposes:
|
if self.purpose not in valid_purposes:
|
||||||
frappe.throw(_("Purpose must be one of {0}").format(comma_or(valid_purposes)))
|
frappe.throw(_("Purpose must be one of {0}").format(comma_or(valid_purposes)))
|
||||||
|
|
||||||
@ -139,11 +151,39 @@ class StockEntry(StockController):
|
|||||||
frappe.throw(_("Row #{0}: Please specify Serial No for Item {1}").format(item.idx, item.item_code),
|
frappe.throw(_("Row #{0}: Please specify Serial No for Item {1}").format(item.idx, item.item_code),
|
||||||
frappe.MandatoryError)
|
frappe.MandatoryError)
|
||||||
|
|
||||||
|
def validate_qty(self):
|
||||||
|
manufacture_purpose = ["Manufacture", "Material Consumption for Manufacture"]
|
||||||
|
|
||||||
|
if self.purpose in manufacture_purpose and self.work_order:
|
||||||
|
if not frappe.get_value('Work Order', self.work_order, 'skip_transfer'):
|
||||||
|
item_code = []
|
||||||
|
for item in self.items:
|
||||||
|
if cstr(item.t_warehouse) == '':
|
||||||
|
req_items = frappe.get_all('Work Order Item',
|
||||||
|
filters={'parent': self.work_order, 'item_code': item.item_code}, fields=["item_code"])
|
||||||
|
|
||||||
|
transferred_materials = frappe.db.sql("""
|
||||||
|
select
|
||||||
|
sum(qty) as qty
|
||||||
|
from `tabStock Entry` se,`tabStock Entry Detail` sed
|
||||||
|
where
|
||||||
|
se.name = sed.parent and se.docstatus=1 and
|
||||||
|
(se.purpose='Material Transfer for Manufacture' or se.purpose='Manufacture')
|
||||||
|
and sed.item_code=%s and se.work_order= %s and ifnull(sed.t_warehouse, '') != ''
|
||||||
|
""", (item.item_code, self.work_order), as_dict=1)
|
||||||
|
|
||||||
|
stock_qty = flt(item.qty)
|
||||||
|
trans_qty = flt(transferred_materials[0].qty)
|
||||||
|
if req_items:
|
||||||
|
if stock_qty > trans_qty:
|
||||||
|
item_code.append(item.item_code)
|
||||||
|
|
||||||
def validate_warehouse(self):
|
def validate_warehouse(self):
|
||||||
"""perform various (sometimes conditional) validations on warehouse"""
|
"""perform various (sometimes conditional) validations on warehouse"""
|
||||||
|
|
||||||
source_mandatory = ["Material Issue", "Material Transfer", "Subcontract", "Material Transfer for Manufacture"]
|
source_mandatory = ["Material Issue", "Material Transfer", "Subcontract", "Material Transfer for Manufacture",
|
||||||
target_mandatory = ["Material Receipt", "Material Transfer", "Subcontract", "Material Transfer for Manufacture"]
|
"Material Consumption for Manufacture"]
|
||||||
|
target_mandatory = ["Material Receipt", "Material Transfer", "Subcontract", "Material Transfer for Manufacture",]
|
||||||
|
|
||||||
validate_for_manufacture_repack = any([d.bom_no for d in self.get("items")])
|
validate_for_manufacture_repack = any([d.bom_no for d in self.get("items")])
|
||||||
|
|
||||||
@ -196,10 +236,11 @@ class StockEntry(StockController):
|
|||||||
frappe.throw(_("Source and target warehouse cannot be same for row {0}").format(d.idx))
|
frappe.throw(_("Source and target warehouse cannot be same for row {0}").format(d.idx))
|
||||||
|
|
||||||
def validate_work_order(self):
|
def validate_work_order(self):
|
||||||
if self.purpose in ("Manufacture", "Material Transfer for Manufacture"):
|
if self.purpose in ("Manufacture", "Material Transfer for Manufacture", "Material Consumption for Manufacture"):
|
||||||
# check if work order is entered
|
# check if work order is entered
|
||||||
|
|
||||||
if self.purpose=="Manufacture" and self.work_order:
|
if (self.purpose=="Manufacture" or self.purpose=="Material Consumption for Manufacture") \
|
||||||
|
and self.work_order:
|
||||||
if not self.fg_completed_qty:
|
if not self.fg_completed_qty:
|
||||||
frappe.throw(_("For Quantity (Manufactured Qty) is mandatory"))
|
frappe.throw(_("For Quantity (Manufactured Qty) is mandatory"))
|
||||||
self.check_if_operations_completed()
|
self.check_if_operations_completed()
|
||||||
@ -234,8 +275,7 @@ class StockEntry(StockController):
|
|||||||
where parent in (%s)
|
where parent in (%s)
|
||||||
and item_code = %s
|
and item_code = %s
|
||||||
and ifnull(s_warehouse,'')='' """ % (", ".join(["%s" * len(other_ste)]), "%s"), args)[0][0]
|
and ifnull(s_warehouse,'')='' """ % (", ".join(["%s" * len(other_ste)]), "%s"), args)[0][0]
|
||||||
|
if fg_qty_already_entered and fg_qty_already_entered >= qty:
|
||||||
if fg_qty_already_entered >= qty:
|
|
||||||
frappe.throw(_("Stock Entries already created for Work Order ")
|
frappe.throw(_("Stock Entries already created for Work Order ")
|
||||||
+ self.work_order + ":" + ", ".join(other_ste), DuplicateEntryForWorkOrderError)
|
+ self.work_order + ":" + ", ".join(other_ste), DuplicateEntryForWorkOrderError)
|
||||||
|
|
||||||
@ -590,8 +630,10 @@ class StockEntry(StockController):
|
|||||||
self.set_work_order_details()
|
self.set_work_order_details()
|
||||||
|
|
||||||
if self.bom_no:
|
if self.bom_no:
|
||||||
|
|
||||||
if self.purpose in ["Material Issue", "Material Transfer", "Manufacture", "Repack",
|
if self.purpose in ["Material Issue", "Material Transfer", "Manufacture", "Repack",
|
||||||
"Subcontract", "Material Transfer for Manufacture"]:
|
"Subcontract", "Material Transfer for Manufacture", "Material Consumption for Manufacture"]:
|
||||||
|
|
||||||
if self.work_order and self.purpose == "Material Transfer for Manufacture":
|
if self.work_order and self.purpose == "Material Transfer for Manufacture":
|
||||||
item_dict = self.get_pending_raw_materials()
|
item_dict = self.get_pending_raw_materials()
|
||||||
if self.to_warehouse and self.pro_doc:
|
if self.to_warehouse and self.pro_doc:
|
||||||
@ -599,10 +641,15 @@ class StockEntry(StockController):
|
|||||||
item["to_warehouse"] = self.pro_doc.wip_warehouse
|
item["to_warehouse"] = self.pro_doc.wip_warehouse
|
||||||
self.add_to_stock_entry_detail(item_dict)
|
self.add_to_stock_entry_detail(item_dict)
|
||||||
|
|
||||||
elif self.work_order and self.purpose == "Manufacture" and \
|
elif self.work_order and (self.purpose == "Manufacture" or self.purpose == "Material Consumption for Manufacture") and \
|
||||||
frappe.db.get_single_value("Manufacturing Settings", "backflush_raw_materials_based_on")== "Material Transferred for Manufacture":
|
frappe.db.get_single_value("Manufacturing Settings", "backflush_raw_materials_based_on")== "Material Transferred for Manufacture":
|
||||||
self.get_transfered_raw_materials()
|
self.get_transfered_raw_materials()
|
||||||
|
|
||||||
|
elif self.work_order and (self.purpose == "Manufacture" or self.purpose == "Material Consumption for Manufacture") and \
|
||||||
|
frappe.db.get_single_value("Manufacturing Settings", "backflush_raw_materials_based_on")== "BOM" and \
|
||||||
|
frappe.db.get_single_value("Manufacturing Settings", "material_consumption")== 1:
|
||||||
|
self.get_unconsumed_raw_materials()
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if not self.fg_completed_qty:
|
if not self.fg_completed_qty:
|
||||||
frappe.throw(_("Manufacturing Quantity is mandatory"))
|
frappe.throw(_("Manufacturing Quantity is mandatory"))
|
||||||
@ -613,7 +660,7 @@ class StockEntry(StockController):
|
|||||||
if self.purchase_order and self.purpose == "Subcontract":
|
if self.purchase_order and self.purpose == "Subcontract":
|
||||||
#Get PO Supplied Items Details
|
#Get PO Supplied Items Details
|
||||||
item_wh = frappe._dict(frappe.db.sql("""
|
item_wh = frappe._dict(frappe.db.sql("""
|
||||||
select rm_item_code, reserve_warehouse
|
select rm_item_code, reserve_warehouse
|
||||||
from `tabPurchase Order` po, `tabPurchase Order Item Supplied` poitemsup
|
from `tabPurchase Order` po, `tabPurchase Order Item Supplied` poitemsup
|
||||||
where po.name = poitemsup.parent
|
where po.name = poitemsup.parent
|
||||||
and po.name = %s""",self.purchase_order))
|
and po.name = %s""",self.purchase_order))
|
||||||
@ -726,6 +773,45 @@ class StockEntry(StockController):
|
|||||||
item.from_warehouse = ""
|
item.from_warehouse = ""
|
||||||
return item_dict
|
return item_dict
|
||||||
|
|
||||||
|
def get_unconsumed_raw_materials(self):
|
||||||
|
wo = frappe.get_doc("Work Order", self.work_order)
|
||||||
|
wo_items = frappe.get_all('Work Order Item',
|
||||||
|
filters={'parent': self.work_order},
|
||||||
|
fields=["item_code", "required_qty", "consumed_qty"]
|
||||||
|
)
|
||||||
|
|
||||||
|
for item in wo_items:
|
||||||
|
qty = item.required_qty
|
||||||
|
item_account_details = frappe.db.get_value("Item", item.item_code, ["item_name",
|
||||||
|
"description", "stock_uom", "expense_account", "buying_cost_center", "name", "default_warehouse"], as_dict=1)
|
||||||
|
# Take into account consumption if there are any.
|
||||||
|
if self.purpose == 'Manufacture':
|
||||||
|
req_qty_each = flt(item.required_qty / wo.qty)
|
||||||
|
if (flt(item.consumed_qty) != 0):
|
||||||
|
remaining_qty = flt(item.consumed_qty) - (flt(wo.produced_qty) * req_qty_each)
|
||||||
|
exhaust_qty = req_qty_each * wo.produced_qty
|
||||||
|
if remaining_qty > exhaust_qty :
|
||||||
|
if (remaining_qty/(req_qty_each * flt(self.fg_completed_qty))) >= 1:
|
||||||
|
qty =0
|
||||||
|
else:
|
||||||
|
qty = (req_qty_each * flt(self.fg_completed_qty)) - remaining_qty
|
||||||
|
else:
|
||||||
|
qty = req_qty_each * flt(self.fg_completed_qty)
|
||||||
|
|
||||||
|
if qty > 0:
|
||||||
|
self.add_to_stock_entry_detail({
|
||||||
|
item.item_code: {
|
||||||
|
"from_warehouse": wo.wip_warehouse,
|
||||||
|
"to_warehouse": "",
|
||||||
|
"qty": qty,
|
||||||
|
"item_name": item.item_name,
|
||||||
|
"description": item.description,
|
||||||
|
"stock_uom": item_account_details.stock_uom,
|
||||||
|
"expense_account": item_account_details.expense_account,
|
||||||
|
"cost_center": item_account_details.buying_cost_center,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
def get_transfered_raw_materials(self):
|
def get_transfered_raw_materials(self):
|
||||||
transferred_materials = frappe.db.sql("""
|
transferred_materials = frappe.db.sql("""
|
||||||
select
|
select
|
||||||
@ -744,7 +830,8 @@ class StockEntry(StockController):
|
|||||||
from
|
from
|
||||||
`tabStock Entry` se, `tabStock Entry Detail` sed
|
`tabStock Entry` se, `tabStock Entry Detail` sed
|
||||||
where
|
where
|
||||||
se.name = sed.parent and se.docstatus=1 and se.purpose='Manufacture'
|
se.name = sed.parent and se.docstatus=1
|
||||||
|
and (se.purpose='Manufacture' or se.purpose='Material Consumption for Manufacture')
|
||||||
and se.work_order= %s and ifnull(sed.s_warehouse, '') != ''
|
and se.work_order= %s and ifnull(sed.s_warehouse, '') != ''
|
||||||
group by sed.item_code, sed.s_warehouse
|
group by sed.item_code, sed.s_warehouse
|
||||||
""", self.work_order, as_dict=1)
|
""", self.work_order, as_dict=1)
|
||||||
@ -755,20 +842,47 @@ class StockEntry(StockController):
|
|||||||
|
|
||||||
po_qty = frappe.db.sql("""select qty, produced_qty, material_transferred_for_manufacturing from
|
po_qty = frappe.db.sql("""select qty, produced_qty, material_transferred_for_manufacturing from
|
||||||
`tabWork Order` where name=%s""", self.work_order, as_dict=1)[0]
|
`tabWork Order` where name=%s""", self.work_order, as_dict=1)[0]
|
||||||
|
|
||||||
manufacturing_qty = flt(po_qty.qty)
|
manufacturing_qty = flt(po_qty.qty)
|
||||||
produced_qty = flt(po_qty.produced_qty)
|
produced_qty = flt(po_qty.produced_qty)
|
||||||
trans_qty = flt(po_qty.material_transferred_for_manufacturing)
|
trans_qty = flt(po_qty.material_transferred_for_manufacturing)
|
||||||
|
|
||||||
for item in transferred_materials:
|
for item in transferred_materials:
|
||||||
qty= item.qty
|
qty= item.qty
|
||||||
|
req_items = frappe.get_all('Work Order Item',
|
||||||
|
filters={'parent': self.work_order, 'item_code': item.item_code},
|
||||||
|
fields=["required_qty", "consumed_qty"]
|
||||||
|
)
|
||||||
|
req_qty = flt(req_items[0].required_qty)
|
||||||
|
req_qty_each = flt(req_qty / manufacturing_qty)
|
||||||
|
consumed_qty = flt(req_items[0].consumed_qty)
|
||||||
|
|
||||||
|
if trans_qty and manufacturing_qty >= (produced_qty + flt(self.fg_completed_qty)):
|
||||||
|
if qty >= req_qty:
|
||||||
|
qty = (req_qty/trans_qty) * flt(self.fg_completed_qty)
|
||||||
|
else:
|
||||||
|
qty = qty - consumed_qty
|
||||||
|
|
||||||
|
if self.purpose == 'Manufacture':
|
||||||
|
# If Material Consumption is booked, must pull only remaining components to finish product
|
||||||
|
if consumed_qty != 0:
|
||||||
|
remaining_qty = consumed_qty - (produced_qty * req_qty_each)
|
||||||
|
exhaust_qty = req_qty_each * produced_qty
|
||||||
|
if remaining_qty > exhaust_qty :
|
||||||
|
if (remaining_qty/(req_qty_each * flt(self.fg_completed_qty))) >= 1:
|
||||||
|
qty =0
|
||||||
|
else:
|
||||||
|
qty = (req_qty_each * flt(self.fg_completed_qty)) - remaining_qty
|
||||||
|
else:
|
||||||
|
qty = req_qty_each * flt(self.fg_completed_qty)
|
||||||
|
|
||||||
if trans_qty and manufacturing_qty > (produced_qty + flt(self.fg_completed_qty)):
|
|
||||||
qty = (qty/trans_qty) * flt(self.fg_completed_qty)
|
|
||||||
|
|
||||||
elif backflushed_materials.get(item.item_code):
|
elif backflushed_materials.get(item.item_code):
|
||||||
for d in backflushed_materials.get(item.item_code):
|
for d in backflushed_materials.get(item.item_code):
|
||||||
if d.get(item.warehouse):
|
if d.get(item.warehouse):
|
||||||
qty-= d.get(item.warehouse)
|
if (qty > req_qty):
|
||||||
|
qty = req_qty
|
||||||
|
qty-= d.get(item.warehouse)
|
||||||
|
|
||||||
if qty > 0:
|
if qty > 0:
|
||||||
self.add_to_stock_entry_detail({
|
self.add_to_stock_entry_detail({
|
||||||
@ -841,7 +955,7 @@ class StockEntry(StockController):
|
|||||||
|
|
||||||
for d in item_dict:
|
for d in item_dict:
|
||||||
stock_uom = item_dict[d].get("stock_uom") or frappe.db.get_value("Item", d, "stock_uom")
|
stock_uom = item_dict[d].get("stock_uom") or frappe.db.get_value("Item", d, "stock_uom")
|
||||||
|
|
||||||
se_child = self.append('items')
|
se_child = self.append('items')
|
||||||
se_child.s_warehouse = item_dict[d].get("from_warehouse")
|
se_child.s_warehouse = item_dict[d].get("from_warehouse")
|
||||||
se_child.t_warehouse = item_dict[d].get("to_warehouse")
|
se_child.t_warehouse = item_dict[d].get("to_warehouse")
|
||||||
@ -894,7 +1008,7 @@ class StockEntry(StockController):
|
|||||||
def update_purchase_order_supplied_items(self):
|
def update_purchase_order_supplied_items(self):
|
||||||
#Get PO Supplied Items Details
|
#Get PO Supplied Items Details
|
||||||
item_wh = frappe._dict(frappe.db.sql("""
|
item_wh = frappe._dict(frappe.db.sql("""
|
||||||
select rm_item_code, reserve_warehouse
|
select rm_item_code, reserve_warehouse
|
||||||
from `tabPurchase Order` po, `tabPurchase Order Item Supplied` poitemsup
|
from `tabPurchase Order` po, `tabPurchase Order Item Supplied` poitemsup
|
||||||
where po.name = poitemsup.parent
|
where po.name = poitemsup.parent
|
||||||
and po.name = %s""", self.purchase_order))
|
and po.name = %s""", self.purchase_order))
|
||||||
@ -905,7 +1019,7 @@ class StockEntry(StockController):
|
|||||||
reserve_warehouse = item_wh.get(item_code)
|
reserve_warehouse = item_wh.get(item_code)
|
||||||
stock_bin = get_bin(item_code, reserve_warehouse)
|
stock_bin = get_bin(item_code, reserve_warehouse)
|
||||||
stock_bin.update_reserved_qty_for_sub_contracting()
|
stock_bin.update_reserved_qty_for_sub_contracting()
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def move_sample_to_retention_warehouse(company, items):
|
def move_sample_to_retention_warehouse(company, items):
|
||||||
if isinstance(items, string_types):
|
if isinstance(items, string_types):
|
||||||
@ -1075,4 +1189,4 @@ def validate_sample_quantity(item_code, sample_quantity, qty, batch_no = None):
|
|||||||
frappe.msgprint(_("Maximum Samples - {0} can be retained for Batch {1} and Item {2}.").
|
frappe.msgprint(_("Maximum Samples - {0} can be retained for Batch {1} and Item {2}.").
|
||||||
format(max_retain_qty, batch_no, item_code), alert=True)
|
format(max_retain_qty, batch_no, item_code), alert=True)
|
||||||
sample_quantity = qty_diff
|
sample_quantity = qty_diff
|
||||||
return sample_quantity
|
return sample_quantity
|
||||||
|
|||||||
@ -575,7 +575,8 @@ class TestStockEntry(unittest.TestCase):
|
|||||||
"bom_no": bom_no,
|
"bom_no": bom_no,
|
||||||
"qty": 1.0,
|
"qty": 1.0,
|
||||||
"stock_uom": "_Test UOM",
|
"stock_uom": "_Test UOM",
|
||||||
"wip_warehouse": "_Test Warehouse - _TC"
|
"wip_warehouse": "_Test Warehouse - _TC",
|
||||||
|
"skip_transfer": 1
|
||||||
})
|
})
|
||||||
work_order.insert()
|
work_order.insert()
|
||||||
work_order.submit()
|
work_order.submit()
|
||||||
@ -680,6 +681,34 @@ class TestStockEntry(unittest.TestCase):
|
|||||||
repack.insert()
|
repack.insert()
|
||||||
self.assertRaises(frappe.ValidationError, repack.submit)
|
self.assertRaises(frappe.ValidationError, repack.submit)
|
||||||
|
|
||||||
|
def test_material_consumption(self):
|
||||||
|
from erpnext.manufacturing.doctype.work_order.work_order \
|
||||||
|
import make_stock_entry as _make_stock_entry
|
||||||
|
bom_no = frappe.db.get_value("BOM", {"item": "_Test FG Item 2",
|
||||||
|
"is_default": 1, "docstatus": 1}, ["name", "operating_cost"])
|
||||||
|
|
||||||
|
work_order = frappe.new_doc("Work Order")
|
||||||
|
work_order.update({
|
||||||
|
"company": "_Test Company",
|
||||||
|
"fg_warehouse": "_Test Warehouse 1 - _TC",
|
||||||
|
"production_item": "_Test FG Item 2",
|
||||||
|
"bom_no": bom_no,
|
||||||
|
"qty": 4.0,
|
||||||
|
"stock_uom": "_Test UOM",
|
||||||
|
"wip_warehouse": "_Test Warehouse - _TC",
|
||||||
|
"additional_operating_cost": 1000
|
||||||
|
})
|
||||||
|
work_order.insert()
|
||||||
|
work_order.submit()
|
||||||
|
|
||||||
|
make_stock_entry(item_code="_Test Serialized Item With Series", target="_Test Warehouse - _TC", qty=50, basic_rate=100)
|
||||||
|
make_stock_entry(item_code="_Test Item 2", target="_Test Warehouse - _TC", qty=50, basic_rate=20)
|
||||||
|
|
||||||
|
stock_entry = frappe.get_doc(_make_stock_entry(work_order.name, "Material Consumption for Manufacture", 2))
|
||||||
|
self.assertEqual(stock_entry.get("items")[0].qty, 10)
|
||||||
|
self.assertEqual(stock_entry.get("items")[1].qty, 6)
|
||||||
|
|
||||||
|
|
||||||
def make_serialized_item(item_code=None, serial_no=None, target_warehouse=None):
|
def make_serialized_item(item_code=None, serial_no=None, target_warehouse=None):
|
||||||
se = frappe.copy_doc(test_records[0])
|
se = frappe.copy_doc(test_records[0])
|
||||||
se.get("items")[0].item_code = item_code or "_Test Serialized Item With Series"
|
se.get("items")[0].item_code = item_code or "_Test Serialized Item With Series"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user