Production Order Enhancements (#9432)
* Production Order Enhancements - Show required items child table - Source warehouse for each raw materials, in Pro Order Item and BOM Item table - Group warehouse allowed for source and wip warehouse - Patch to populate required items, to fix status and reserved qty for stopped pro order - Cleaned up existing codes - Test cases * Set available qty in source and wip warehouse * minor fix in bom query naming * Minor Fixes * Reload BOM doctypes in patch
This commit is contained in:
parent
852cb64e4f
commit
949a920022
@ -5,12 +5,24 @@ frappe.provide("erpnext.bom");
|
|||||||
|
|
||||||
frappe.ui.form.on("BOM", {
|
frappe.ui.form.on("BOM", {
|
||||||
setup: function(frm) {
|
setup: function(frm) {
|
||||||
frm.add_fetch('buying_price_list', 'currency', 'currency');
|
frm.add_fetch('buying_price_list', 'currency', 'currency')
|
||||||
frm.fields_dict["items"].grid.get_field("bom_no").get_query = function(doc, cdt, cdn){
|
|
||||||
|
frm.set_query("bom_no", "items", function() {
|
||||||
return {
|
return {
|
||||||
filters: {'currency': frm.doc.currency}
|
filters: {
|
||||||
|
'currency': frm.doc.currency,
|
||||||
|
'company': frm.doc.company
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
frm.set_query("source_warehouse", "items", function() {
|
||||||
|
return {
|
||||||
|
filters: {
|
||||||
|
'company': frm.doc.company,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
onload_post_render: function(frm) {
|
onload_post_render: function(frm) {
|
||||||
|
@ -408,6 +408,7 @@ class BOM(WebsiteGenerator):
|
|||||||
self.add_to_cur_exploded_items(frappe._dict({
|
self.add_to_cur_exploded_items(frappe._dict({
|
||||||
'item_code' : d.item_code,
|
'item_code' : d.item_code,
|
||||||
'item_name' : d.item_name,
|
'item_name' : d.item_name,
|
||||||
|
'source_warehouse': d.source_warehouse,
|
||||||
'description' : d.description,
|
'description' : d.description,
|
||||||
'image' : d.image,
|
'image' : d.image,
|
||||||
'stock_uom' : d.stock_uom,
|
'stock_uom' : d.stock_uom,
|
||||||
@ -427,7 +428,8 @@ class BOM(WebsiteGenerator):
|
|||||||
def get_child_exploded_items(self, bom_no, stock_qty):
|
def get_child_exploded_items(self, bom_no, stock_qty):
|
||||||
""" Add all items from Flat BOM of child BOM"""
|
""" Add all items from Flat BOM of child BOM"""
|
||||||
# Did not use qty_consumed_per_unit in the query, as it leads to rounding loss
|
# Did not use qty_consumed_per_unit in the query, as it leads to rounding loss
|
||||||
child_fb_items = frappe.db.sql("""select bom_item.item_code, bom_item.item_name, bom_item.description,
|
child_fb_items = frappe.db.sql("""select bom_item.item_code, bom_item.item_name,
|
||||||
|
bom_item.description, bom_item.source_warehouse,
|
||||||
bom_item.stock_uom, bom_item.stock_qty, bom_item.rate,
|
bom_item.stock_uom, bom_item.stock_qty, bom_item.rate,
|
||||||
bom_item.stock_qty / ifnull(bom.quantity, 1) as qty_consumed_per_unit
|
bom_item.stock_qty / ifnull(bom.quantity, 1) as qty_consumed_per_unit
|
||||||
from `tabBOM Explosion Item` bom_item, tabBOM bom
|
from `tabBOM Explosion Item` bom_item, tabBOM bom
|
||||||
@ -437,9 +439,10 @@ class BOM(WebsiteGenerator):
|
|||||||
self.add_to_cur_exploded_items(frappe._dict({
|
self.add_to_cur_exploded_items(frappe._dict({
|
||||||
'item_code' : d['item_code'],
|
'item_code' : d['item_code'],
|
||||||
'item_name' : d['item_name'],
|
'item_name' : d['item_name'],
|
||||||
|
'source_warehouse' : d['source_warehouse'],
|
||||||
'description' : d['description'],
|
'description' : d['description'],
|
||||||
'stock_uom' : d['stock_uom'],
|
'stock_uom' : d['stock_uom'],
|
||||||
'stock_qty' : d['qty_consumed_per_unit']*stock_qty,
|
'stock_qty' : d['qty_consumed_per_unit'] * stock_qty,
|
||||||
'rate' : flt(d['rate']),
|
'rate' : flt(d['rate']),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
@ -493,6 +496,7 @@ def get_bom_items_as_dict(bom, company, qty=1, fetch_exploded=1, fetch_scrap_ite
|
|||||||
item.default_warehouse,
|
item.default_warehouse,
|
||||||
item.expense_account as expense_account,
|
item.expense_account as expense_account,
|
||||||
item.buying_cost_center as cost_center
|
item.buying_cost_center as cost_center
|
||||||
|
{select_columns}
|
||||||
from
|
from
|
||||||
`tab{table}` bom_item, `tabBOM` bom, `tabItem` item
|
`tab{table}` bom_item, `tabBOM` bom, `tabItem` item
|
||||||
where
|
where
|
||||||
@ -501,18 +505,20 @@ def get_bom_items_as_dict(bom, company, qty=1, fetch_exploded=1, fetch_scrap_ite
|
|||||||
and bom_item.parent = bom.name
|
and bom_item.parent = bom.name
|
||||||
and item.name = bom_item.item_code
|
and item.name = bom_item.item_code
|
||||||
and is_stock_item = 1
|
and is_stock_item = 1
|
||||||
{conditions}
|
{where_conditions}
|
||||||
group by item_code, stock_uom"""
|
group by item_code, stock_uom"""
|
||||||
|
|
||||||
if fetch_exploded:
|
if fetch_exploded:
|
||||||
query = query.format(table="BOM Explosion Item",
|
query = query.format(table="BOM Explosion Item",
|
||||||
conditions="""and item.is_sub_contracted_item = 0""")
|
where_conditions="""and item.is_sub_contracted_item = 0""",
|
||||||
|
select_columns = ", bom_item.source_warehouse")
|
||||||
items = frappe.db.sql(query, { "qty": qty, "bom": bom }, as_dict=True)
|
items = frappe.db.sql(query, { "qty": qty, "bom": bom }, as_dict=True)
|
||||||
elif fetch_scrap_items:
|
elif fetch_scrap_items:
|
||||||
query = query.format(table="BOM Scrap Item", conditions="")
|
query = query.format(table="BOM Scrap Item", where_conditions="", select_columns="")
|
||||||
items = frappe.db.sql(query, { "qty": qty, "bom": bom }, as_dict=True)
|
items = frappe.db.sql(query, { "qty": qty, "bom": bom }, as_dict=True)
|
||||||
else:
|
else:
|
||||||
query = query.format(table="BOM Item", conditions="")
|
query = query.format(table="BOM Item", where_conditions="",
|
||||||
|
select_columns = ", bom_item.source_warehouse")
|
||||||
items = frappe.db.sql(query, { "qty": qty, "bom": bom }, as_dict=True)
|
items = frappe.db.sql(query, { "qty": qty, "bom": bom }, as_dict=True)
|
||||||
|
|
||||||
for item in items:
|
for item in items:
|
||||||
|
@ -8,7 +8,8 @@
|
|||||||
"parentfield": "items",
|
"parentfield": "items",
|
||||||
"stock_qty": 1.0,
|
"stock_qty": 1.0,
|
||||||
"rate": 5000.0,
|
"rate": 5000.0,
|
||||||
"stock_uom": "_Test UOM"
|
"stock_uom": "_Test UOM",
|
||||||
|
"source_warehouse": "_Test Warehouse - _TC"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"amount": 2000.0,
|
"amount": 2000.0,
|
||||||
@ -17,7 +18,8 @@
|
|||||||
"parentfield": "items",
|
"parentfield": "items",
|
||||||
"stock_qty": 2.0,
|
"stock_qty": 2.0,
|
||||||
"rate": 1000.0,
|
"rate": 1000.0,
|
||||||
"stock_uom": "_Test UOM"
|
"stock_uom": "_Test UOM",
|
||||||
|
"source_warehouse": "_Test Warehouse - _TC"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"docstatus": 1,
|
"docstatus": 1,
|
||||||
@ -48,7 +50,8 @@
|
|||||||
"parentfield": "items",
|
"parentfield": "items",
|
||||||
"stock_qty": 1.0,
|
"stock_qty": 1.0,
|
||||||
"rate": 5000.0,
|
"rate": 5000.0,
|
||||||
"stock_uom": "_Test UOM"
|
"stock_uom": "_Test UOM",
|
||||||
|
"source_warehouse": "_Test Warehouse - _TC"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"amount": 2000.0,
|
"amount": 2000.0,
|
||||||
@ -57,7 +60,8 @@
|
|||||||
"parentfield": "items",
|
"parentfield": "items",
|
||||||
"stock_qty": 2.0,
|
"stock_qty": 2.0,
|
||||||
"rate": 1000.0,
|
"rate": 1000.0,
|
||||||
"stock_uom": "_Test UOM"
|
"stock_uom": "_Test UOM",
|
||||||
|
"source_warehouse": "_Test Warehouse - _TC"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"docstatus": 1,
|
"docstatus": 1,
|
||||||
@ -86,7 +90,8 @@
|
|||||||
"parentfield": "items",
|
"parentfield": "items",
|
||||||
"stock_qty": 1.0,
|
"stock_qty": 1.0,
|
||||||
"rate": 5000.0,
|
"rate": 5000.0,
|
||||||
"stock_uom": "_Test UOM"
|
"stock_uom": "_Test UOM",
|
||||||
|
"source_warehouse": "_Test Warehouse - _TC"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"amount": 2000.0,
|
"amount": 2000.0,
|
||||||
@ -96,7 +101,8 @@
|
|||||||
"parentfield": "items",
|
"parentfield": "items",
|
||||||
"stock_qty": 3.0,
|
"stock_qty": 3.0,
|
||||||
"rate": 1000.0,
|
"rate": 1000.0,
|
||||||
"stock_uom": "_Test UOM"
|
"stock_uom": "_Test UOM",
|
||||||
|
"source_warehouse": "_Test Warehouse - _TC"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"docstatus": 1,
|
"docstatus": 1,
|
||||||
@ -126,7 +132,8 @@
|
|||||||
"parentfield": "items",
|
"parentfield": "items",
|
||||||
"stock_qty": 2.0,
|
"stock_qty": 2.0,
|
||||||
"rate": 3000.0,
|
"rate": 3000.0,
|
||||||
"stock_uom": "_Test UOM"
|
"stock_uom": "_Test UOM",
|
||||||
|
"source_warehouse": "_Test Warehouse - _TC"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"docstatus": 1,
|
"docstatus": 1,
|
||||||
|
@ -7,9 +7,9 @@
|
|||||||
"beta": 0,
|
"beta": 0,
|
||||||
"creation": "2013-03-07 11:42:57",
|
"creation": "2013-03-07 11:42:57",
|
||||||
"custom": 0,
|
"custom": 0,
|
||||||
"default_print_format": "Standard",
|
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
|
"document_type": "Setup",
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
"fields": [
|
"fields": [
|
||||||
@ -104,6 +104,37 @@
|
|||||||
"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": "source_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": "Source Warehouse",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "Warehouse",
|
||||||
|
"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_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@ -481,7 +512,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2017-06-02 19:29:34.498719",
|
"modified": "2017-05-29 17:51:18.151002",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "BOM Explosion Item",
|
"name": "BOM Explosion Item",
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
"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": 1,
|
||||||
"in_global_search": 0,
|
"in_global_search": 0,
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
"in_standard_filter": 0,
|
||||||
@ -113,7 +113,7 @@
|
|||||||
"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": 1,
|
||||||
"in_global_search": 0,
|
"in_global_search": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"in_standard_filter": 0,
|
"in_standard_filter": 0,
|
||||||
@ -136,6 +136,37 @@
|
|||||||
"unique": 0,
|
"unique": 0,
|
||||||
"width": "150px"
|
"width": "150px"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "source_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": "Source 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,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@ -729,7 +760,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2017-05-23 15:59:37.946963",
|
"modified": "2017-05-29 17:42:37.216408",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "BOM Item",
|
"name": "BOM Item",
|
||||||
|
@ -7,7 +7,63 @@ frappe.ui.form.on("Production Order", {
|
|||||||
'Timesheet': 'Make Timesheet',
|
'Timesheet': 'Make Timesheet',
|
||||||
'Stock Entry': 'Make Stock Entry',
|
'Stock Entry': 'Make Stock Entry',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set query for warehouses
|
||||||
|
frm.set_query("wip_warehouse", function(doc) {
|
||||||
|
return {
|
||||||
|
filters: {
|
||||||
|
'company': frm.doc.company,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
frm.set_query("source_warehouse", "required_items", function() {
|
||||||
|
return {
|
||||||
|
filters: {
|
||||||
|
'company': frm.doc.company,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
frm.set_query("fg_warehouse", function() {
|
||||||
|
return {
|
||||||
|
filters: {
|
||||||
|
'company': frm.doc.company,
|
||||||
|
'is_group': 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set query for BOM
|
||||||
|
frm.set_query("bom_no", function() {
|
||||||
|
if (frm.doc.production_item) {
|
||||||
|
return{
|
||||||
|
query: "erpnext.controllers.queries.bom",
|
||||||
|
filters: {item: cstr(frm.doc.production_item)}
|
||||||
|
}
|
||||||
|
} else msgprint(__("Please enter Production Item first"));
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set query for FG Item
|
||||||
|
frm.set_query("production_item", function() {
|
||||||
|
return {
|
||||||
|
query: "erpnext.controllers.queries.item_query",
|
||||||
|
filters:{
|
||||||
|
'is_stock_item': 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set query for FG Item
|
||||||
|
frm.set_query("project", function() {
|
||||||
|
return{
|
||||||
|
filters:[
|
||||||
|
['Project', 'status', 'not in', 'Completed, Cancelled']
|
||||||
|
]
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
onload: function(frm) {
|
onload: function(frm) {
|
||||||
if (!frm.doc.status)
|
if (!frm.doc.status)
|
||||||
frm.doc.status = 'Draft';
|
frm.doc.status = 'Draft';
|
||||||
@ -28,9 +84,8 @@ frappe.ui.form.on("Production Order", {
|
|||||||
function(doc) { return (frm.doc.qty==doc.completed_qty) ? "green" : "orange" })
|
function(doc) { return (frm.doc.qty==doc.completed_qty) ? "green" : "orange" })
|
||||||
|
|
||||||
erpnext.production_order.set_custom_buttons(frm);
|
erpnext.production_order.set_custom_buttons(frm);
|
||||||
erpnext.production_order.setup_company_filter(frm);
|
|
||||||
erpnext.production_order.setup_bom_filter(frm);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
refresh: function(frm) {
|
refresh: function(frm) {
|
||||||
erpnext.toggle_naming_series();
|
erpnext.toggle_naming_series();
|
||||||
erpnext.production_order.set_custom_buttons(frm);
|
erpnext.production_order.set_custom_buttons(frm);
|
||||||
@ -53,6 +108,7 @@ frappe.ui.form.on("Production Order", {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
show_progress: function(frm) {
|
show_progress: function(frm) {
|
||||||
var bars = [];
|
var bars = [];
|
||||||
var message = '';
|
var message = '';
|
||||||
@ -85,10 +141,83 @@ frappe.ui.form.on("Production Order", {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
frm.dashboard.add_progress(__('Status'), bars, message);
|
frm.dashboard.add_progress(__('Status'), bars, message);
|
||||||
|
},
|
||||||
|
|
||||||
|
production_item: function(frm) {
|
||||||
|
frappe.call({
|
||||||
|
method: "erpnext.manufacturing.doctype.production_order.production_order.get_item_details",
|
||||||
|
args: {
|
||||||
|
item: frm.doc.production_item,
|
||||||
|
project: frm.doc.project
|
||||||
|
},
|
||||||
|
callback: function(r) {
|
||||||
|
if(r.message) {
|
||||||
|
erpnext.in_production_item_onchange = true;
|
||||||
|
$.each(["description", "stock_uom", "project", "bom_no"], function(i, field) {
|
||||||
|
frm.set_value(field, r.message[field]);
|
||||||
|
});
|
||||||
|
|
||||||
|
if(r.message["set_scrap_wh_mandatory"]){
|
||||||
|
frm.toggle_reqd("scrap_warehouse", true);
|
||||||
|
}
|
||||||
|
erpnext.in_production_item_onchange = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
project: function(frm) {
|
||||||
|
if(!erpnext.in_production_item_onchange) {
|
||||||
|
frm.trigger("production_item");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
bom_no: function(frm) {
|
||||||
|
return frm.call({
|
||||||
|
doc: frm.doc,
|
||||||
|
method: "get_items_and_operations_from_bom",
|
||||||
|
callback: function(r) {
|
||||||
|
if(r.message["set_scrap_wh_mandatory"]){
|
||||||
|
frm.toggle_reqd("scrap_warehouse", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
use_multi_level_bom: function(frm) {
|
||||||
|
if(frm.doc.bom_no) {
|
||||||
|
frm.trigger("bom_no");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
qty: function(frm) {
|
||||||
|
frm.trigger('bom_no');
|
||||||
|
},
|
||||||
|
|
||||||
|
before_submit: function(frm) {
|
||||||
|
frm.toggle_reqd(["fg_warehouse", "wip_warehouse"], true);
|
||||||
|
frm.fields_dict.required_items.grid.toggle_reqd("source_warehouse", true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
frappe.ui.form.on("Production Order Item", {
|
||||||
|
source_warehouse: function(frm, cdt, cdn) {
|
||||||
|
var row = locals[cdt][cdn];
|
||||||
|
if(row.source_warehouse) {
|
||||||
|
frappe.call({
|
||||||
|
"method": "erpnext.stock.utils.get_latest_stock_qty",
|
||||||
|
args: {
|
||||||
|
item_code: row.item_code,
|
||||||
|
warehouse: row.source_warehouse
|
||||||
|
},
|
||||||
|
callback: function (r) {
|
||||||
|
frappe.model.set_value(row.doctype, row.name,
|
||||||
|
"available_qty_at_source_warehouse", r.message);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
frappe.ui.form.on("Production Order Operation", {
|
frappe.ui.form.on("Production Order Operation", {
|
||||||
workstation: function(frm, cdt, cdn) {
|
workstation: function(frm, cdt, cdn) {
|
||||||
@ -119,38 +248,45 @@ erpnext.production_order = {
|
|||||||
var doc = frm.doc;
|
var doc = frm.doc;
|
||||||
if (doc.docstatus === 1) {
|
if (doc.docstatus === 1) {
|
||||||
if (doc.status != 'Stopped' && doc.status != 'Completed') {
|
if (doc.status != 'Stopped' && doc.status != 'Completed') {
|
||||||
frm.add_custom_button(__('Stop'), cur_frm.cscript['Stop Production Order'], __("Status"));
|
frm.add_custom_button(__('Stop'), function() {
|
||||||
|
erpnext.production_order.stop_production_order(frm, "Stopped");
|
||||||
|
}, __("Status"));
|
||||||
} else if (doc.status == 'Stopped') {
|
} else if (doc.status == 'Stopped') {
|
||||||
frm.add_custom_button(__('Re-open'), cur_frm.cscript['Unstop Production Order'], __("Status"));
|
frm.add_custom_button(__('Re-open'), function() {
|
||||||
|
erpnext.production_order.stop_production_order(frm, "Resumed");
|
||||||
|
}, __("Status"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!frm.doc.skip_transfer){
|
if(!frm.doc.skip_transfer){
|
||||||
if ((flt(doc.material_transferred_for_manufacturing) < flt(doc.qty)) && frm.doc.status != 'Stopped') {
|
if ((flt(doc.material_transferred_for_manufacturing) < flt(doc.qty))
|
||||||
|
&& frm.doc.status != 'Stopped') {
|
||||||
frm.has_start_btn = true;
|
frm.has_start_btn = true;
|
||||||
var btn = frm.add_custom_button(__('Start'),
|
var start_btn = frm.add_custom_button(__('Start'), function() {
|
||||||
cur_frm.cscript['Transfer Raw Materials']);
|
erpnext.production_order.make_se(frm, 'Material Transfer for Manufacture');
|
||||||
btn.addClass('btn-primary');
|
});
|
||||||
|
start_btn.addClass('btn-primary');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!frm.doc.skip_transfer){
|
if(!frm.doc.skip_transfer){
|
||||||
if ((flt(doc.produced_qty) < flt(doc.material_transferred_for_manufacturing)) && frm.doc.status != 'Stopped') {
|
if ((flt(doc.produced_qty) < flt(doc.material_transferred_for_manufacturing))
|
||||||
|
&& frm.doc.status != 'Stopped') {
|
||||||
frm.has_finish_btn = true;
|
frm.has_finish_btn = true;
|
||||||
var btn = frm.add_custom_button(__('Finish'),
|
var finish_btn = frm.add_custom_button(__('Finish'), function() {
|
||||||
cur_frm.cscript['Update Finished Goods']);
|
erpnext.production_order.make_se(frm, 'Manufacture');
|
||||||
|
});
|
||||||
|
|
||||||
if(doc.material_transferred_for_manufacturing==doc.qty) {
|
if(doc.material_transferred_for_manufacturing==doc.qty) {
|
||||||
// all materials transferred for manufacturing,
|
// all materials transferred for manufacturing, make this primary
|
||||||
// make this primary
|
finish_btn.addClass('btn-primary');
|
||||||
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;
|
frm.has_finish_btn = true;
|
||||||
var btn = frm.add_custom_button(__('Finish'),
|
var finish_btn = frm.add_custom_button(__('Finish'),
|
||||||
cur_frm.cscript['Update Finished Goods']);
|
cur_frm.cscript['Update Finished Goods']);
|
||||||
btn.addClass('btn-primary');
|
finish_btn.addClass('btn-primary');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -162,8 +298,8 @@ erpnext.production_order = {
|
|||||||
doc.planned_operating_cost = 0.0;
|
doc.planned_operating_cost = 0.0;
|
||||||
for(var i=0;i<op.length;i++) {
|
for(var i=0;i<op.length;i++) {
|
||||||
var planned_operating_cost = flt(flt(op[i].hour_rate) * flt(op[i].time_in_mins) / 60, 2);
|
var planned_operating_cost = flt(flt(op[i].hour_rate) * flt(op[i].time_in_mins) / 60, 2);
|
||||||
frappe.model.set_value('Production Order Operation',op[i].name, "planned_operating_cost", planned_operating_cost);
|
frappe.model.set_value('Production Order Operation', op[i].name,
|
||||||
|
"planned_operating_cost", planned_operating_cost);
|
||||||
doc.planned_operating_cost += planned_operating_cost;
|
doc.planned_operating_cost += planned_operating_cost;
|
||||||
}
|
}
|
||||||
refresh_field('planned_operating_cost');
|
refresh_field('planned_operating_cost');
|
||||||
@ -176,37 +312,10 @@ erpnext.production_order = {
|
|||||||
frm.set_value("total_operating_cost", (flt(frm.doc.additional_operating_cost) + variable_cost))
|
frm.set_value("total_operating_cost", (flt(frm.doc.additional_operating_cost) + variable_cost))
|
||||||
},
|
},
|
||||||
|
|
||||||
setup_company_filter: function(frm) {
|
|
||||||
var company_filter = function(doc) {
|
|
||||||
return {
|
|
||||||
filters: {
|
|
||||||
'company': frm.doc.company,
|
|
||||||
'is_group': 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
frm.fields_dict.source_warehouse.get_query = company_filter;
|
|
||||||
frm.fields_dict.fg_warehouse.get_query = company_filter;
|
|
||||||
frm.fields_dict.wip_warehouse.get_query = company_filter;
|
|
||||||
},
|
|
||||||
|
|
||||||
setup_bom_filter: function(frm) {
|
|
||||||
frm.set_query("bom_no", function(doc) {
|
|
||||||
if (doc.production_item) {
|
|
||||||
return{
|
|
||||||
query: "erpnext.controllers.queries.bom",
|
|
||||||
filters: {item: cstr(doc.production_item)}
|
|
||||||
}
|
|
||||||
} else frappe.msgprint(__("Please enter Production Item first"));
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
set_default_warehouse: function(frm) {
|
set_default_warehouse: function(frm) {
|
||||||
if (!(frm.doc.wip_warehouse || frm.doc.fg_warehouse)) {
|
if (!(frm.doc.wip_warehouse || frm.doc.fg_warehouse)) {
|
||||||
frappe.call({
|
frappe.call({
|
||||||
method: "erpnext.manufacturing.doctype.production_order.production_order.get_default_warehouse",
|
method: "erpnext.manufacturing.doctype.production_order.production_order.get_default_warehouse",
|
||||||
|
|
||||||
callback: function(r) {
|
callback: function(r) {
|
||||||
if(!r.exe) {
|
if(!r.exe) {
|
||||||
frm.set_value("wip_warehouse", r.message.wip_warehouse);
|
frm.set_value("wip_warehouse", r.message.wip_warehouse);
|
||||||
@ -215,45 +324,15 @@ erpnext.production_order = {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$.extend(cur_frm.cscript, {
|
|
||||||
before_submit: function() {
|
|
||||||
cur_frm.toggle_reqd(["fg_warehouse", "wip_warehouse"], true);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
production_item: function(doc) {
|
make_se: function(frm, purpose) {
|
||||||
frappe.call({
|
if(!frm.doc.skip_transfer){
|
||||||
method: "erpnext.manufacturing.doctype.production_order.production_order.get_item_details",
|
|
||||||
args: {
|
|
||||||
item: doc.production_item,
|
|
||||||
project: doc.project
|
|
||||||
},
|
|
||||||
callback: function(r) {
|
|
||||||
$.each(["description", "stock_uom", "project", "bom_no"], function(i, field) {
|
|
||||||
cur_frm.set_value(field, r.message[field]);
|
|
||||||
});
|
|
||||||
|
|
||||||
if(r.message["set_scrap_wh_mandatory"]){
|
|
||||||
cur_frm.toggle_reqd("scrap_warehouse", true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
project: function(doc) {
|
|
||||||
cur_frm.cscript.production_item(doc)
|
|
||||||
},
|
|
||||||
|
|
||||||
make_se: function(purpose) {
|
|
||||||
var me = this;
|
|
||||||
if(!this.frm.doc.skip_transfer){
|
|
||||||
var max = (purpose === "Manufacture") ?
|
var max = (purpose === "Manufacture") ?
|
||||||
flt(this.frm.doc.material_transferred_for_manufacturing) - flt(this.frm.doc.produced_qty) :
|
flt(frm.doc.material_transferred_for_manufacturing) - flt(frm.doc.produced_qty) :
|
||||||
flt(this.frm.doc.qty) - flt(this.frm.doc.material_transferred_for_manufacturing);
|
flt(frm.doc.qty) - flt(frm.doc.material_transferred_for_manufacturing);
|
||||||
} else {
|
} else {
|
||||||
var max = flt(this.frm.doc.qty) - flt(this.frm.doc.produced_qty);
|
var max = flt(frm.doc.qty) - flt(frm.doc.produced_qty);
|
||||||
}
|
}
|
||||||
|
|
||||||
frappe.prompt({fieldtype:"Float", label: __("Qty for {0}", [purpose]), fieldname:"qty",
|
frappe.prompt({fieldtype:"Float", label: __("Qty for {0}", [purpose]), fieldname:"qty",
|
||||||
@ -266,7 +345,7 @@ $.extend(cur_frm.cscript, {
|
|||||||
frappe.call({
|
frappe.call({
|
||||||
method:"erpnext.manufacturing.doctype.production_order.production_order.make_stock_entry",
|
method:"erpnext.manufacturing.doctype.production_order.production_order.make_stock_entry",
|
||||||
args: {
|
args: {
|
||||||
"production_order_id": me.frm.doc.name,
|
"production_order_id": frm.doc.name,
|
||||||
"purpose": purpose,
|
"purpose": purpose,
|
||||||
"qty": data.qty
|
"qty": data.qty
|
||||||
},
|
},
|
||||||
@ -278,58 +357,19 @@ $.extend(cur_frm.cscript, {
|
|||||||
}, __("Select Quantity"), __("Make"));
|
}, __("Select Quantity"), __("Make"));
|
||||||
},
|
},
|
||||||
|
|
||||||
bom_no: function() {
|
stop_production_order: function(frm, status) {
|
||||||
return this.frm.call({
|
frappe.call({
|
||||||
doc: this.frm.doc,
|
method: "erpnext.manufacturing.doctype.production_order.production_order.stop_unstop",
|
||||||
method: "set_production_order_operations",
|
args: {
|
||||||
|
production_order: frm.doc.name,
|
||||||
|
status: status
|
||||||
|
},
|
||||||
callback: function(r) {
|
callback: function(r) {
|
||||||
if(r.message["set_scrap_wh_mandatory"]){
|
if(r.message) {
|
||||||
cur_frm.toggle_reqd("scrap_warehouse", true);
|
frm.set_value("status", r.message);
|
||||||
|
frm.reload_doc();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
},
|
|
||||||
|
|
||||||
use_multi_level_bom: function() {
|
|
||||||
if(this.frm.doc.bom_no) {
|
|
||||||
this.frm.trigger("bom_no");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
qty: function() {
|
|
||||||
frappe.ui.form.trigger("Production Order", 'bom_no')
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
cur_frm.cscript['Stop Production Order'] = function() {
|
|
||||||
$c_obj(cur_frm.doc, 'stop_unstop', 'Stopped', function(r, rt) {cur_frm.refresh();});
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_frm.cscript['Unstop Production Order'] = function() {
|
|
||||||
$c_obj(cur_frm.doc, 'stop_unstop', 'Unstopped', function(r, rt) {cur_frm.refresh();});
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_frm.cscript['Transfer Raw Materials'] = function() {
|
|
||||||
cur_frm.cscript.make_se('Material Transfer for Manufacture');
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_frm.cscript['Update Finished Goods'] = function() {
|
|
||||||
cur_frm.cscript.make_se('Manufacture');
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_frm.fields_dict['production_item'].get_query = function(doc) {
|
|
||||||
return {
|
|
||||||
query: "erpnext.controllers.queries.item_query",
|
|
||||||
filters:{
|
|
||||||
'is_stock_item': 1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_frm.fields_dict['project'].get_query = function(doc, dt, dn) {
|
|
||||||
return{
|
|
||||||
filters:[
|
|
||||||
['Project', 'status', 'not in', 'Completed, Cancelled']
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -95,7 +95,7 @@
|
|||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"oldfieldname": "status",
|
"oldfieldname": "status",
|
||||||
"oldfieldtype": "Select",
|
"oldfieldtype": "Select",
|
||||||
"options": "\nDraft\nSubmitted\nNot Started\nStopped\nUnstopped\nIn Process\nCompleted\nCancelled",
|
"options": "\nDraft\nSubmitted\nNot Started\nIn Process\nCompleted\nStopped\nCancelled",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
@ -139,38 +139,6 @@
|
|||||||
"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": "project",
|
|
||||||
"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": "Project",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"oldfieldname": "project",
|
|
||||||
"oldfieldtype": "Link",
|
|
||||||
"options": "Project",
|
|
||||||
"permlevel": 0,
|
|
||||||
"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_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@ -266,37 +234,6 @@
|
|||||||
"unique": 0,
|
"unique": 0,
|
||||||
"width": "50%"
|
"width": "50%"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"description": "",
|
|
||||||
"fieldname": "sales_order",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 1,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Sales Order",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Sales Order",
|
|
||||||
"permlevel": 0,
|
|
||||||
"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_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@ -329,37 +266,6 @@
|
|||||||
"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,
|
|
||||||
"description": "Check if material transfer entry is not required",
|
|
||||||
"fieldname": "skip_transfer",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"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": "Skip Material Transfer",
|
|
||||||
"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_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@ -427,6 +333,100 @@
|
|||||||
"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,
|
||||||
|
"description": "",
|
||||||
|
"fieldname": "sales_order",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 1,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Sales Order",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "Sales Order",
|
||||||
|
"permlevel": 0,
|
||||||
|
"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": "project",
|
||||||
|
"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": "Project",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"oldfieldname": "project",
|
||||||
|
"oldfieldtype": "Link",
|
||||||
|
"options": "Project",
|
||||||
|
"permlevel": 0,
|
||||||
|
"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,
|
||||||
|
"description": "Check if material transfer entry is not required",
|
||||||
|
"fieldname": "skip_transfer",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"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": "Skip Material Transfer",
|
||||||
|
"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_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@ -457,38 +457,6 @@
|
|||||||
"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,
|
|
||||||
"description": "",
|
|
||||||
"fieldname": "source_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": "Source Warehouse (for reserving Items)",
|
|
||||||
"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,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@ -519,34 +487,6 @@
|
|||||||
"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": "column_break_12",
|
|
||||||
"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,
|
|
||||||
"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_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@ -579,6 +519,34 @@
|
|||||||
"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": "column_break_12",
|
||||||
|
"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,
|
||||||
|
"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_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@ -616,7 +584,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"fieldname": "time",
|
"fieldname": "required_items_section",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
@ -625,10 +593,9 @@
|
|||||||
"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",
|
"label": "Required Items",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"options": "fa fa-time",
|
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
"precision": "",
|
||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
@ -647,9 +614,8 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"depends_on": "",
|
"fieldname": "required_items",
|
||||||
"fieldname": "expected_delivery_date",
|
"fieldtype": "Table",
|
||||||
"fieldtype": "Date",
|
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
@ -657,10 +623,43 @@
|
|||||||
"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": "Expected Delivery Date",
|
"label": "Required Items",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 1,
|
||||||
|
"options": "Production Order Item",
|
||||||
|
"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": "time",
|
||||||
|
"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": "Time",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
|
"options": "fa fa-time",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
|
"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,
|
||||||
@ -708,7 +707,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"fieldname": "planned_end_date",
|
"fieldname": "actual_start_date",
|
||||||
"fieldtype": "Datetime",
|
"fieldtype": "Datetime",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
@ -717,9 +716,9 @@
|
|||||||
"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": "Planned End Date",
|
"label": "Actual Start Date",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 1,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
"precision": "",
|
||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
@ -767,7 +766,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"fieldname": "actual_start_date",
|
"fieldname": "planned_end_date",
|
||||||
"fieldtype": "Datetime",
|
"fieldtype": "Datetime",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
@ -776,9 +775,9 @@
|
|||||||
"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": "Actual Start Date",
|
"label": "Planned End Date",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 1,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
"precision": "",
|
||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
@ -821,6 +820,36 @@
|
|||||||
"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,
|
||||||
|
"depends_on": "",
|
||||||
|
"fieldname": "expected_delivery_date",
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"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": "Expected Delivery Date",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"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_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@ -1070,67 +1099,6 @@
|
|||||||
"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": "required_items_section",
|
|
||||||
"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": "Required 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": 0,
|
|
||||||
"fieldname": "required_items",
|
|
||||||
"fieldtype": "Table",
|
|
||||||
"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": "Required Items",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 1,
|
|
||||||
"options": "Production Order Item",
|
|
||||||
"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,
|
||||||
|
@ -3,24 +3,21 @@
|
|||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
|
|
||||||
import json
|
import json
|
||||||
from frappe.utils import flt, get_datetime, getdate, date_diff, cint, nowdate
|
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.utils import time_diff_in_seconds
|
from frappe.utils import flt, get_datetime, getdate, date_diff, cint, nowdate
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
from frappe.model.mapper import get_mapped_doc
|
from erpnext.manufacturing.doctype.bom.bom import validate_bom_no, get_bom_items_as_dict
|
||||||
from erpnext.manufacturing.doctype.bom.bom import validate_bom_no
|
|
||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
from erpnext.stock.doctype.item.item import validate_end_of_life
|
from erpnext.stock.doctype.item.item import validate_end_of_life
|
||||||
from erpnext.manufacturing.doctype.workstation.workstation import WorkstationHolidayError, NotInWorkingHoursError
|
from erpnext.manufacturing.doctype.workstation.workstation import WorkstationHolidayError
|
||||||
from erpnext.projects.doctype.timesheet.timesheet import OverlapError
|
from erpnext.projects.doctype.timesheet.timesheet import OverlapError
|
||||||
from erpnext.stock.doctype.stock_entry.stock_entry import get_additional_costs
|
from erpnext.stock.doctype.stock_entry.stock_entry import get_additional_costs
|
||||||
from erpnext.manufacturing.doctype.manufacturing_settings.manufacturing_settings import get_mins_between_operations
|
from erpnext.manufacturing.doctype.manufacturing_settings.manufacturing_settings import get_mins_between_operations
|
||||||
from erpnext.stock.stock_balance import get_planned_qty, update_bin_qty
|
from erpnext.stock.stock_balance import get_planned_qty, update_bin_qty
|
||||||
from erpnext.manufacturing.doctype.bom.bom import get_bom_items_as_dict
|
|
||||||
from erpnext.stock.utils import get_bin
|
|
||||||
from frappe.utils.csvutils import getlink
|
from frappe.utils.csvutils import getlink
|
||||||
|
from erpnext.stock.utils import get_bin, validate_warehouse_company, get_latest_stock_qty
|
||||||
|
from erpnext.utilities.transaction_base import validate_uom_is_integer
|
||||||
|
|
||||||
class OverProductionError(frappe.ValidationError): pass
|
class OverProductionError(frappe.ValidationError): pass
|
||||||
class StockOverProductionError(frappe.ValidationError): pass
|
class StockOverProductionError(frappe.ValidationError): pass
|
||||||
@ -38,15 +35,19 @@ class ProductionOrder(Document):
|
|||||||
validate_bom_no(self.production_item, self.bom_no)
|
validate_bom_no(self.production_item, self.bom_no)
|
||||||
|
|
||||||
self.validate_sales_order()
|
self.validate_sales_order()
|
||||||
self.validate_warehouse()
|
self.validate_warehouse_belongs_to_company()
|
||||||
self.calculate_operating_cost()
|
self.calculate_operating_cost()
|
||||||
self.validate_qty()
|
self.validate_qty()
|
||||||
self.validate_operation_time()
|
self.validate_operation_time()
|
||||||
self.status = self.get_status()
|
self.status = self.get_status()
|
||||||
|
|
||||||
from erpnext.utilities.transaction_base import validate_uom_is_integer
|
|
||||||
validate_uom_is_integer(self, "stock_uom", ["qty", "produced_qty"])
|
validate_uom_is_integer(self, "stock_uom", ["qty", "produced_qty"])
|
||||||
|
|
||||||
|
if not self.get("required_items"):
|
||||||
|
self.set_required_items()
|
||||||
|
else:
|
||||||
|
self.set_available_qty()
|
||||||
|
|
||||||
def validate_sales_order(self):
|
def validate_sales_order(self):
|
||||||
if self.sales_order:
|
if self.sales_order:
|
||||||
so = frappe.db.sql("""select name, delivery_date, project from `tabSales Order`
|
so = frappe.db.sql("""select name, delivery_date, project from `tabSales Order`
|
||||||
@ -64,11 +65,14 @@ class ProductionOrder(Document):
|
|||||||
else:
|
else:
|
||||||
frappe.throw(_("Sales Order {0} is not valid").format(self.sales_order))
|
frappe.throw(_("Sales Order {0} is not valid").format(self.sales_order))
|
||||||
|
|
||||||
def validate_warehouse(self):
|
def validate_warehouse_belongs_to_company(self):
|
||||||
from erpnext.stock.utils import validate_warehouse_company
|
warehouses = [self.fg_warehouse, self.wip_warehouse]
|
||||||
|
for d in self.get("required_items"):
|
||||||
|
if d.source_warehouse not in warehouses:
|
||||||
|
warehouses.append(d.source_warehouse)
|
||||||
|
|
||||||
for w in [self.source_warehouse, self.fg_warehouse, self.wip_warehouse]:
|
for wh in warehouses:
|
||||||
validate_warehouse_company(w, self.company)
|
validate_warehouse_company(wh, self.company)
|
||||||
|
|
||||||
def calculate_operating_cost(self):
|
def calculate_operating_cost(self):
|
||||||
self.planned_operating_cost, self.actual_operating_cost = 0.0, 0.0
|
self.planned_operating_cost, self.actual_operating_cost = 0.0, 0.0
|
||||||
@ -79,7 +83,8 @@ class ProductionOrder(Document):
|
|||||||
self.planned_operating_cost += flt(d.planned_operating_cost)
|
self.planned_operating_cost += flt(d.planned_operating_cost)
|
||||||
self.actual_operating_cost += flt(d.actual_operating_cost)
|
self.actual_operating_cost += flt(d.actual_operating_cost)
|
||||||
|
|
||||||
variable_cost = self.actual_operating_cost if self.actual_operating_cost else self.planned_operating_cost
|
variable_cost = self.actual_operating_cost if self.actual_operating_cost \
|
||||||
|
else self.planned_operating_cost
|
||||||
self.total_operating_cost = flt(self.additional_operating_cost) + flt(variable_cost)
|
self.total_operating_cost = flt(self.additional_operating_cost) + flt(variable_cost)
|
||||||
|
|
||||||
def validate_production_order_against_so(self):
|
def validate_production_order_against_so(self):
|
||||||
@ -101,22 +106,16 @@ class ProductionOrder(Document):
|
|||||||
# total qty in SO
|
# total qty in SO
|
||||||
so_qty = flt(so_item_qty) + flt(dnpi_qty)
|
so_qty = flt(so_item_qty) + flt(dnpi_qty)
|
||||||
|
|
||||||
allowance_percentage = flt(frappe.db.get_single_value("Manufacturing Settings", "over_production_allowance_percentage"))
|
allowance_percentage = flt(frappe.db.get_single_value("Manufacturing Settings",
|
||||||
|
"over_production_allowance_percentage"))
|
||||||
|
|
||||||
if total_qty > so_qty + (allowance_percentage/100 * so_qty):
|
if total_qty > so_qty + (allowance_percentage/100 * so_qty):
|
||||||
frappe.throw(_("Cannot produce more Item {0} than Sales Order quantity {1}").format(self.production_item,
|
frappe.throw(_("Cannot produce more Item {0} than Sales Order quantity {1}")
|
||||||
so_qty), OverProductionError)
|
.format(self.production_item, so_qty), OverProductionError)
|
||||||
|
|
||||||
def stop_unstop(self, status):
|
|
||||||
""" Called from client side on Stop/Unstop event"""
|
|
||||||
status = self.update_status(status)
|
|
||||||
self.update_planned_qty()
|
|
||||||
frappe.msgprint(_("Production Order status is {0}").format(status))
|
|
||||||
self.notify_update()
|
|
||||||
|
|
||||||
|
|
||||||
def update_status(self, status=None):
|
def update_status(self, status=None):
|
||||||
'''Update status of production order if unknown'''
|
'''Update status of production order if unknown'''
|
||||||
if not status:
|
if status != "Stopped":
|
||||||
status = self.get_status(status)
|
status = self.get_status(status)
|
||||||
|
|
||||||
if status != self.status:
|
if status != self.status:
|
||||||
@ -167,7 +166,6 @@ class ProductionOrder(Document):
|
|||||||
self.db_set(fieldname, qty)
|
self.db_set(fieldname, qty)
|
||||||
|
|
||||||
def before_submit(self):
|
def before_submit(self):
|
||||||
self.set_required_items()
|
|
||||||
self.make_time_logs()
|
self.make_time_logs()
|
||||||
|
|
||||||
def on_submit(self):
|
def on_submit(self):
|
||||||
@ -184,10 +182,10 @@ class ProductionOrder(Document):
|
|||||||
self.validate_cancel()
|
self.validate_cancel()
|
||||||
|
|
||||||
frappe.db.set(self,'status', 'Cancelled')
|
frappe.db.set(self,'status', 'Cancelled')
|
||||||
self.clear_required_items()
|
|
||||||
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_reserved_qty_for_production()
|
||||||
|
|
||||||
def validate_cancel(self):
|
def validate_cancel(self):
|
||||||
if self.status == "Stopped":
|
if self.status == "Stopped":
|
||||||
@ -214,13 +212,12 @@ class ProductionOrder(Document):
|
|||||||
|
|
||||||
def set_production_order_operations(self):
|
def set_production_order_operations(self):
|
||||||
"""Fetch operations from BOM and set in 'Production Order'"""
|
"""Fetch operations from BOM and set in 'Production Order'"""
|
||||||
|
self.set('operations', [])
|
||||||
|
|
||||||
if not self.bom_no \
|
if not self.bom_no \
|
||||||
or cint(frappe.db.get_single_value("Manufacturing Settings", "disable_capacity_planning")):
|
or cint(frappe.db.get_single_value("Manufacturing Settings", "disable_capacity_planning")):
|
||||||
return
|
return
|
||||||
|
|
||||||
self.set('operations', [])
|
|
||||||
|
|
||||||
if self.use_multi_level_bom:
|
if self.use_multi_level_bom:
|
||||||
bom_list = frappe.get_doc("BOM", self.bom_no).traverse_tree()
|
bom_list = frappe.get_doc("BOM", self.bom_no).traverse_tree()
|
||||||
else:
|
else:
|
||||||
@ -240,8 +237,6 @@ class ProductionOrder(Document):
|
|||||||
self.set('operations', operations)
|
self.set('operations', operations)
|
||||||
self.calculate_time()
|
self.calculate_time()
|
||||||
|
|
||||||
return check_if_scrap_warehouse_mandatory(self.bom_no)
|
|
||||||
|
|
||||||
def calculate_time(self):
|
def calculate_time(self):
|
||||||
bom_qty = frappe.db.get_value("BOM", self.bom_no, "quantity")
|
bom_qty = frappe.db.get_value("BOM", self.bom_no, "quantity")
|
||||||
|
|
||||||
@ -403,62 +398,60 @@ class ProductionOrder(Document):
|
|||||||
update bin reserved_qty_for_production
|
update bin reserved_qty_for_production
|
||||||
called from Stock Entry for production, after submit, cancel
|
called from Stock Entry for production, after submit, cancel
|
||||||
'''
|
'''
|
||||||
if self.docstatus==1 and self.source_warehouse:
|
if self.docstatus==1:
|
||||||
if self.material_transferred_for_manufacturing == self.produced_qty:
|
# calculate transferred qty based on submitted stock entries
|
||||||
# clear required items table and save document
|
|
||||||
self.clear_required_items()
|
|
||||||
else:
|
|
||||||
# calculate transferred qty based on submitted
|
|
||||||
# stock entries
|
|
||||||
self.update_transaferred_qty_for_required_items()
|
self.update_transaferred_qty_for_required_items()
|
||||||
|
|
||||||
# update in bin
|
# update in bin
|
||||||
self.update_reserved_qty_for_production()
|
self.update_reserved_qty_for_production()
|
||||||
|
|
||||||
def clear_required_items(self):
|
|
||||||
'''Remove the required_items table and update the bins'''
|
|
||||||
items = [d.item_code for d in self.required_items]
|
|
||||||
self.required_items = []
|
|
||||||
|
|
||||||
self.update_child_table('required_items')
|
|
||||||
|
|
||||||
# completed, update reserved qty in bin
|
|
||||||
self.update_reserved_qty_for_production(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'''
|
||||||
if not self.source_warehouse:
|
for d in self.required_items:
|
||||||
return
|
if d.source_warehouse:
|
||||||
|
stock_bin = get_bin(d.item_code, d.source_warehouse)
|
||||||
if not items:
|
|
||||||
items = [d.item_code for d in self.required_items]
|
|
||||||
|
|
||||||
for item in items:
|
|
||||||
stock_bin = get_bin(item, self.source_warehouse)
|
|
||||||
stock_bin.update_reserved_qty_for_production()
|
stock_bin.update_reserved_qty_for_production()
|
||||||
|
|
||||||
|
def get_items_and_operations_from_bom(self):
|
||||||
|
self.set_required_items()
|
||||||
|
self.set_production_order_operations()
|
||||||
|
|
||||||
|
return check_if_scrap_warehouse_mandatory(self.bom_no)
|
||||||
|
|
||||||
|
def set_available_qty(self):
|
||||||
|
for d in self.get("required_items"):
|
||||||
|
if d.source_warehouse:
|
||||||
|
d.available_qty_at_source_warehouse = get_latest_stock_qty(d.item_code, d.source_warehouse)
|
||||||
|
|
||||||
|
if self.wip_warehouse:
|
||||||
|
d.available_qty_at_wip_warehouse = get_latest_stock_qty(d.item_code, self.wip_warehouse)
|
||||||
|
|
||||||
def set_required_items(self):
|
def set_required_items(self):
|
||||||
'''set required_items for production to keep track of reserved qty'''
|
'''set required_items for production to keep track of reserved qty'''
|
||||||
if self.source_warehouse:
|
self.required_items = []
|
||||||
|
if self.bom_no and self.qty:
|
||||||
item_dict = get_bom_items_as_dict(self.bom_no, self.company, qty=self.qty,
|
item_dict = get_bom_items_as_dict(self.bom_no, self.company, qty=self.qty,
|
||||||
fetch_exploded = self.use_multi_level_bom)
|
fetch_exploded = self.use_multi_level_bom)
|
||||||
|
|
||||||
for item in item_dict.values():
|
for item in item_dict.values():
|
||||||
self.append('required_items', {'item_code': item.item_code,
|
self.append('required_items', {
|
||||||
'required_qty': item.qty})
|
'item_code': item.item_code,
|
||||||
|
'required_qty': item.qty,
|
||||||
|
'source_warehouse': item.source_warehouse or item.default_warehouse
|
||||||
|
})
|
||||||
|
|
||||||
#print frappe.as_json(self.required_items)
|
self.set_available_qty()
|
||||||
|
|
||||||
def update_transaferred_qty_for_required_items(self):
|
def update_transaferred_qty_for_required_items(self):
|
||||||
'''update transferred qty from submitted stock entries for that item against
|
'''update transferred qty from submitted stock entries for that item against
|
||||||
the production order'''
|
the production order'''
|
||||||
|
|
||||||
for d in self.required_items:
|
for d in self.required_items:
|
||||||
transferred_qty = frappe.db.sql('''select count(qty)
|
transferred_qty = frappe.db.sql('''select sum(qty)
|
||||||
from `tabStock Entry` entry, `tabStock Entry Detail` detail
|
from `tabStock Entry` entry, `tabStock Entry Detail` detail
|
||||||
where
|
where
|
||||||
entry.production_order = %s
|
entry.production_order = %s
|
||||||
entry.purpose = "Material Transfer for Manufacture"
|
and entry.purpose = "Material Transfer for Manufacture"
|
||||||
and entry.docstatus = 1
|
and entry.docstatus = 1
|
||||||
and detail.parent = entry.name
|
and detail.parent = entry.name
|
||||||
and detail.item_code = %s''', (self.name, d.item_code))[0][0]
|
and detail.item_code = %s''', (self.name, d.item_code))[0][0]
|
||||||
@ -496,10 +489,12 @@ def get_item_details(item, project = None):
|
|||||||
|
|
||||||
if not res["bom_no"]:
|
if not res["bom_no"]:
|
||||||
if project:
|
if project:
|
||||||
frappe.throw(_("Default BOM for {0} not found for Project {1}").format(item, project))
|
res = get_item_details(item)
|
||||||
|
frappe.msgprint(_("Default BOM not found for Item {0} and Project {1}").format(item, project))
|
||||||
|
else:
|
||||||
frappe.throw(_("Default BOM for {0} not found").format(item))
|
frappe.throw(_("Default BOM for {0} not found").format(item))
|
||||||
|
|
||||||
res['project'] = frappe.db.get_value('BOM', res['bom_no'], 'project')
|
res['project'] = project or frappe.db.get_value('BOM', res['bom_no'], 'project')
|
||||||
res.update(check_if_scrap_warehouse_mandatory(res["bom_no"]))
|
res.update(check_if_scrap_warehouse_mandatory(res["bom_no"]))
|
||||||
|
|
||||||
return res
|
return res
|
||||||
@ -507,6 +502,7 @@ def get_item_details(item, project = None):
|
|||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def check_if_scrap_warehouse_mandatory(bom_no):
|
def check_if_scrap_warehouse_mandatory(bom_no):
|
||||||
res = {"set_scrap_wh_mandatory": False }
|
res = {"set_scrap_wh_mandatory": False }
|
||||||
|
if bom_no:
|
||||||
bom = frappe.get_doc("BOM", bom_no)
|
bom = frappe.get_doc("BOM", bom_no)
|
||||||
|
|
||||||
if len(bom.scrap_items) > 0:
|
if len(bom.scrap_items) > 0:
|
||||||
@ -517,6 +513,10 @@ def check_if_scrap_warehouse_mandatory(bom_no):
|
|||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def make_stock_entry(production_order_id, purpose, qty=None):
|
def make_stock_entry(production_order_id, purpose, qty=None):
|
||||||
production_order = frappe.get_doc("Production Order", production_order_id)
|
production_order = frappe.get_doc("Production Order", production_order_id)
|
||||||
|
if not frappe.db.get_value("Warehouse", production_order.wip_warehouse, "is_group"):
|
||||||
|
wip_warehouse = production_order.wip_warehouse
|
||||||
|
else:
|
||||||
|
wip_warehouse = None
|
||||||
|
|
||||||
stock_entry = frappe.new_doc("Stock Entry")
|
stock_entry = frappe.new_doc("Stock Entry")
|
||||||
stock_entry.purpose = purpose
|
stock_entry.purpose = purpose
|
||||||
@ -528,12 +528,10 @@ def make_stock_entry(production_order_id, purpose, qty=None):
|
|||||||
stock_entry.fg_completed_qty = qty or (flt(production_order.qty) - flt(production_order.produced_qty))
|
stock_entry.fg_completed_qty = qty or (flt(production_order.qty) - flt(production_order.produced_qty))
|
||||||
|
|
||||||
if purpose=="Material Transfer for Manufacture":
|
if purpose=="Material Transfer for Manufacture":
|
||||||
if production_order.source_warehouse:
|
stock_entry.to_warehouse = wip_warehouse
|
||||||
stock_entry.from_warehouse = production_order.source_warehouse
|
|
||||||
stock_entry.to_warehouse = production_order.wip_warehouse
|
|
||||||
stock_entry.project = production_order.project
|
stock_entry.project = production_order.project
|
||||||
else:
|
else:
|
||||||
stock_entry.from_warehouse = production_order.wip_warehouse
|
stock_entry.from_warehouse = wip_warehouse
|
||||||
stock_entry.to_warehouse = production_order.fg_warehouse
|
stock_entry.to_warehouse = production_order.fg_warehouse
|
||||||
additional_costs = get_additional_costs(production_order, fg_qty=stock_entry.fg_completed_qty)
|
additional_costs = get_additional_costs(production_order, fg_qty=stock_entry.fg_completed_qty)
|
||||||
stock_entry.project = production_order.project
|
stock_entry.project = production_order.project
|
||||||
@ -601,3 +599,18 @@ def make_new_timesheet(source_name, target_doc=None):
|
|||||||
frappe.throw(_("Already completed"))
|
frappe.throw(_("Already completed"))
|
||||||
|
|
||||||
return ts
|
return ts
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def stop_unstop(production_order, status):
|
||||||
|
""" Called from client side on Stop/Unstop event"""
|
||||||
|
|
||||||
|
if not frappe.has_permission("Production Order", "write"):
|
||||||
|
frappe.throw(_("Not permitted"), frappe.PermissionError)
|
||||||
|
|
||||||
|
pro_order = frappe.get_doc("Production Order", production_order)
|
||||||
|
pro_order.update_status(status)
|
||||||
|
pro_order.update_planned_qty()
|
||||||
|
frappe.msgprint(_("Production Order has been {0}").format(status))
|
||||||
|
pro_order.notify_update()
|
||||||
|
|
||||||
|
return pro_order.status
|
@ -8,7 +8,7 @@ import frappe
|
|||||||
from frappe.utils import flt, time_diff_in_hours, now, add_days, cint
|
from frappe.utils import flt, time_diff_in_hours, now, add_days, cint
|
||||||
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
|
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
|
||||||
from erpnext.manufacturing.doctype.production_order.production_order \
|
from erpnext.manufacturing.doctype.production_order.production_order \
|
||||||
import make_stock_entry, ItemHasVariantError
|
import make_stock_entry, ItemHasVariantError, stop_unstop
|
||||||
from erpnext.stock.doctype.stock_entry import test_stock_entry
|
from erpnext.stock.doctype.stock_entry import test_stock_entry
|
||||||
from erpnext.stock.doctype.item.test_item import get_total_projected_qty
|
from erpnext.stock.doctype.item.test_item import get_total_projected_qty
|
||||||
from erpnext.stock.utils import get_bin
|
from erpnext.stock.utils import get_bin
|
||||||
@ -229,9 +229,45 @@ class TestProductionOrder(unittest.TestCase):
|
|||||||
self.assertEqual(cint(bin1_on_end_production.projected_qty),
|
self.assertEqual(cint(bin1_on_end_production.projected_qty),
|
||||||
cint(bin1_on_end_production.projected_qty))
|
cint(bin1_on_end_production.projected_qty))
|
||||||
|
|
||||||
# required_items removed
|
def test_reserved_qty_for_stopped_production(self):
|
||||||
self.pro_order.reload()
|
test_stock_entry.make_stock_entry(item_code="_Test Item",
|
||||||
self.assertEqual(len(self.pro_order.required_items), 0)
|
target= self.warehouse, qty=100, basic_rate=100)
|
||||||
|
test_stock_entry.make_stock_entry(item_code="_Test Item Home Desktop 100",
|
||||||
|
target= self.warehouse, qty=100, basic_rate=100)
|
||||||
|
|
||||||
|
# 0 0 0
|
||||||
|
|
||||||
|
self.test_reserved_qty_for_production_submit()
|
||||||
|
|
||||||
|
#2 0 -2
|
||||||
|
|
||||||
|
s = frappe.get_doc(make_stock_entry(self.pro_order.name,
|
||||||
|
"Material Transfer for Manufacture", 1))
|
||||||
|
|
||||||
|
s.submit()
|
||||||
|
|
||||||
|
#1 -1 0
|
||||||
|
|
||||||
|
bin1_on_start_production = get_bin(self.item, self.warehouse)
|
||||||
|
|
||||||
|
# reserved_qty_for_producion updated
|
||||||
|
self.assertEqual(cint(self.bin1_at_start.reserved_qty_for_production) + 1,
|
||||||
|
cint(bin1_on_start_production.reserved_qty_for_production))
|
||||||
|
|
||||||
|
# projected qty will now be 2 less (becuase of item movement)
|
||||||
|
self.assertEqual(cint(self.bin1_at_start.projected_qty),
|
||||||
|
cint(bin1_on_start_production.projected_qty) + 2)
|
||||||
|
|
||||||
|
# STOP
|
||||||
|
stop_unstop(self.pro_order.name, "Stopped")
|
||||||
|
|
||||||
|
bin1_on_stop_production = get_bin(self.item, self.warehouse)
|
||||||
|
|
||||||
|
# no change in reserved / projected
|
||||||
|
self.assertEqual(cint(bin1_on_stop_production.reserved_qty_for_production),
|
||||||
|
cint(self.bin1_at_start.reserved_qty_for_production))
|
||||||
|
self.assertEqual(cint(bin1_on_stop_production.projected_qty) + 1,
|
||||||
|
cint(self.bin1_at_start.projected_qty))
|
||||||
|
|
||||||
def test_scrap_material_qty(self):
|
def test_scrap_material_qty(self):
|
||||||
prod_order = make_prod_order_test_record(planned_start_date=now(), qty=2)
|
prod_order = make_prod_order_test_record(planned_start_date=now(), qty=2)
|
||||||
@ -286,10 +322,11 @@ def make_prod_order_test_record(**args):
|
|||||||
pro_order.company = args.company or "_Test Company"
|
pro_order.company = args.company or "_Test Company"
|
||||||
pro_order.stock_uom = args.stock_uom or "_Test UOM"
|
pro_order.stock_uom = args.stock_uom or "_Test UOM"
|
||||||
pro_order.use_multi_level_bom=0
|
pro_order.use_multi_level_bom=0
|
||||||
pro_order.set_production_order_operations()
|
pro_order.get_items_and_operations_from_bom()
|
||||||
|
|
||||||
if args.source_warehouse:
|
if args.source_warehouse:
|
||||||
pro_order.source_warehouse = args.source_warehouse
|
for item in pro_order.get("required_items"):
|
||||||
|
item.source_warehouse = args.source_warehouse
|
||||||
|
|
||||||
if args.planned_start_date:
|
if args.planned_start_date:
|
||||||
pro_order.planned_start_date = args.planned_start_date
|
pro_order.planned_start_date = args.planned_start_date
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@ -43,6 +44,157 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "source_warehouse",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 1,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Source 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,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "column_break_3",
|
||||||
|
"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": "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,
|
||||||
|
"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": "description",
|
||||||
|
"fieldtype": "Text",
|
||||||
|
"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": "Description",
|
||||||
|
"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": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "qty_section",
|
||||||
|
"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": "Qty",
|
||||||
|
"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,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@ -72,6 +224,7 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@ -99,6 +252,95 @@
|
|||||||
"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": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "column_break_9",
|
||||||
|
"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": "available_qty_at_source_warehouse",
|
||||||
|
"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": "Available Qty at Source Warehouse",
|
||||||
|
"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": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "available_qty_at_wip_warehouse",
|
||||||
|
"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": "Available Qty at WIP Warehouse",
|
||||||
|
"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,
|
"has_web_view": 0,
|
||||||
@ -111,7 +353,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2017-03-28 14:18:36.342161",
|
"modified": "2017-05-15 17:37:20.212361",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "Production Order Item",
|
"name": "Production Order Item",
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@ -42,6 +43,7 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@ -74,6 +76,7 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@ -85,7 +88,7 @@
|
|||||||
"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": 0,
|
||||||
"in_standard_filter": 0,
|
"in_standard_filter": 0,
|
||||||
"label": "BOM",
|
"label": "BOM",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
@ -104,6 +107,7 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@ -135,6 +139,7 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@ -163,6 +168,7 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@ -193,6 +199,7 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@ -224,6 +231,7 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@ -256,6 +264,7 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@ -285,6 +294,7 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@ -314,6 +324,7 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@ -343,6 +354,7 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@ -371,6 +383,7 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@ -403,6 +416,7 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@ -434,6 +448,7 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@ -464,6 +479,7 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@ -493,6 +509,7 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@ -522,6 +539,7 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@ -552,6 +570,7 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@ -580,6 +599,7 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@ -610,6 +630,7 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@ -651,7 +672,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2017-03-27 15:56:29.010336",
|
"modified": "2017-05-29 18:02:04.252419",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "Production Order Operation",
|
"name": "Production Order Operation",
|
||||||
|
@ -412,3 +412,4 @@ erpnext.patches.v8_1.setup_gst_india #2017-06-27
|
|||||||
execute:frappe.reload_doc('regional', 'doctype', 'gst_hsn_code')
|
execute:frappe.reload_doc('regional', 'doctype', 'gst_hsn_code')
|
||||||
erpnext.patches.v8_1.removed_roles_from_gst_report_non_indian_account
|
erpnext.patches.v8_1.removed_roles_from_gst_report_non_indian_account
|
||||||
erpnext.patches.v8_1.gst_fixes
|
erpnext.patches.v8_1.gst_fixes
|
||||||
|
erpnext.patches.v8_0.update_production_orders
|
||||||
|
44
erpnext/patches/v8_0/update_production_orders.py
Normal file
44
erpnext/patches/v8_0/update_production_orders.py
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||||
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
# reload schema
|
||||||
|
for doctype in ("Production Order", "Production Order Item", "Production Order Operation",
|
||||||
|
"BOM Item", "BOM Explosion Item", "BOM"):
|
||||||
|
frappe.reload_doctype(doctype)
|
||||||
|
|
||||||
|
# fetch all draft and submitted production orders
|
||||||
|
fields = ["name"]
|
||||||
|
if "source_warehouse" in frappe.db.get_table_columns("Production Order"):
|
||||||
|
fields.append("source_warehouse")
|
||||||
|
|
||||||
|
pro_orders = frappe.get_all("Production Order", filters={"docstatus": ["!=", 2]}, fields=fields)
|
||||||
|
|
||||||
|
for p in pro_orders:
|
||||||
|
pro_order = frappe.get_doc("Production Order", p.name)
|
||||||
|
|
||||||
|
# set required items table
|
||||||
|
pro_order.set_required_items()
|
||||||
|
|
||||||
|
for item in pro_order.get("required_items"):
|
||||||
|
# set source warehouse based on parent
|
||||||
|
if not item.source_warehouse and "source_warehouse" in fields:
|
||||||
|
item.source_warehouse = pro_order.get("source_warehouse")
|
||||||
|
item.db_update()
|
||||||
|
|
||||||
|
if pro_order.docstatus == 1:
|
||||||
|
# update transferred qty based on Stock Entry, it also updates db
|
||||||
|
pro_order.update_transaferred_qty_for_required_items()
|
||||||
|
|
||||||
|
# Set status where it was 'Unstopped', as it is deprecated
|
||||||
|
if pro_order.status == "Unstopped":
|
||||||
|
status = pro_order.get_status()
|
||||||
|
pro_order.db_set("status", status)
|
||||||
|
elif pro_order.status == "Stopped":
|
||||||
|
pro_order.update_reserved_qty_for_production()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
from frappe import _
|
|
||||||
from frappe.utils import flt, nowdate
|
from frappe.utils import flt, nowdate
|
||||||
import frappe.defaults
|
import frappe.defaults
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
@ -15,7 +14,6 @@ class Bin(Document):
|
|||||||
|
|
||||||
self.validate_mandatory()
|
self.validate_mandatory()
|
||||||
self.set_projected_qty()
|
self.set_projected_qty()
|
||||||
self.block_transactions_against_group_warehouse()
|
|
||||||
|
|
||||||
def on_update(self):
|
def on_update(self):
|
||||||
update_item_projected_qty(self.item_code)
|
update_item_projected_qty(self.item_code)
|
||||||
@ -26,10 +24,6 @@ class Bin(Document):
|
|||||||
if (not getattr(self, f, None)) or (not self.get(f)):
|
if (not getattr(self, f, None)) or (not self.get(f)):
|
||||||
self.set(f, 0.0)
|
self.set(f, 0.0)
|
||||||
|
|
||||||
def block_transactions_against_group_warehouse(self):
|
|
||||||
from erpnext.stock.utils import is_group_warehouse
|
|
||||||
is_group_warehouse(self.warehouse)
|
|
||||||
|
|
||||||
def update_stock(self, args, allow_negative_stock=False, via_landed_cost_voucher=False):
|
def update_stock(self, args, allow_negative_stock=False, via_landed_cost_voucher=False):
|
||||||
'''Called from erpnext.stock.utils.update_bin'''
|
'''Called from erpnext.stock.utils.update_bin'''
|
||||||
self.update_qty(args)
|
self.update_qty(args)
|
||||||
@ -91,7 +85,8 @@ class Bin(Document):
|
|||||||
item.item_code = %s
|
item.item_code = %s
|
||||||
and item.parent = pro.name
|
and item.parent = pro.name
|
||||||
and pro.docstatus = 1
|
and pro.docstatus = 1
|
||||||
and pro.source_warehouse = %s''', (self.item_code, self.warehouse))[0][0]
|
and item.source_warehouse = %s
|
||||||
|
and pro.status not in ("Stopped", "Completed")''', (self.item_code, self.warehouse))[0][0]
|
||||||
|
|
||||||
self.set_projected_qty()
|
self.set_projected_qty()
|
||||||
|
|
||||||
|
@ -708,13 +708,11 @@ class StockEntry(StockController):
|
|||||||
issue (item quantity) that is pending to issue or desire to transfer,
|
issue (item quantity) that is pending to issue or desire to transfer,
|
||||||
whichever is less
|
whichever is less
|
||||||
"""
|
"""
|
||||||
item_dict = self.get_bom_raw_materials(1)
|
item_dict = self.get_pro_order_required_items()
|
||||||
issued_item_qty = self.get_issued_qty()
|
|
||||||
|
|
||||||
max_qty = flt(self.pro_doc.qty)
|
max_qty = flt(self.pro_doc.qty)
|
||||||
for item in item_dict:
|
for item, item_details in item_dict.items():
|
||||||
pending_to_issue = (max_qty * item_dict[item]["qty"]) - issued_item_qty.get(item, 0)
|
pending_to_issue = flt(item_details.required_qty) - flt(item_details.transferred_qty)
|
||||||
desire_to_transfer = flt(self.fg_completed_qty) * item_dict[item]["qty"]
|
desire_to_transfer = flt(self.fg_completed_qty) * flt(item_details.required_qty) / max_qty
|
||||||
|
|
||||||
if desire_to_transfer <= pending_to_issue:
|
if desire_to_transfer <= pending_to_issue:
|
||||||
item_dict[item]["qty"] = desire_to_transfer
|
item_dict[item]["qty"] = desire_to_transfer
|
||||||
@ -734,34 +732,43 @@ class StockEntry(StockController):
|
|||||||
|
|
||||||
return item_dict
|
return item_dict
|
||||||
|
|
||||||
def get_issued_qty(self):
|
def get_pro_order_required_items(self):
|
||||||
issued_item_qty = {}
|
item_dict = frappe._dict()
|
||||||
result = frappe.db.sql("""select t1.item_code, sum(t1.qty)
|
pro_order = frappe.get_doc("Production Order", self.production_order)
|
||||||
from `tabStock Entry Detail` t1, `tabStock Entry` t2
|
if not frappe.db.get_value("Warehouse", pro_order.wip_warehouse, "is_group"):
|
||||||
where t1.parent = t2.name and t2.production_order = %s and t2.docstatus = 1
|
wip_warehouse = pro_order.wip_warehouse
|
||||||
and t2.purpose = 'Material Transfer for Manufacture'
|
else:
|
||||||
group by t1.item_code""", self.production_order)
|
wip_warehouse = None
|
||||||
for t in result:
|
|
||||||
issued_item_qty[t[0]] = flt(t[1])
|
|
||||||
|
|
||||||
return issued_item_qty
|
for d in pro_order.get("required_items"):
|
||||||
|
if flt(d.required_qty) > flt(d.transferred_qty):
|
||||||
|
item_row = d.as_dict()
|
||||||
|
if d.source_warehouse and not frappe.db.get_value("Warehouse", d.source_warehouse, "is_group"):
|
||||||
|
item_row["from_warehouse"] = d.source_warehouse
|
||||||
|
|
||||||
|
item_row["to_warehouse"] = wip_warehouse
|
||||||
|
item_dict.setdefault(d.item_code, item_row)
|
||||||
|
|
||||||
|
return item_dict
|
||||||
|
|
||||||
def add_to_stock_entry_detail(self, item_dict, bom_no=None):
|
def add_to_stock_entry_detail(self, item_dict, bom_no=None):
|
||||||
expense_account, cost_center = frappe.db.get_values("Company", self.company, \
|
expense_account, cost_center = frappe.db.get_values("Company", self.company, \
|
||||||
["default_expense_account", "cost_center"])[0]
|
["default_expense_account", "cost_center"])[0]
|
||||||
|
|
||||||
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")
|
||||||
|
|
||||||
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")
|
||||||
se_child.item_code = cstr(d)
|
se_child.item_code = cstr(d)
|
||||||
se_child.item_name = item_dict[d]["item_name"]
|
se_child.item_name = item_dict[d]["item_name"]
|
||||||
se_child.description = item_dict[d]["description"]
|
se_child.description = item_dict[d]["description"]
|
||||||
se_child.uom = item_dict[d]["stock_uom"]
|
se_child.uom = stock_uom
|
||||||
se_child.stock_uom = item_dict[d]["stock_uom"]
|
se_child.stock_uom = stock_uom
|
||||||
se_child.qty = flt(item_dict[d]["qty"])
|
se_child.qty = flt(item_dict[d]["qty"])
|
||||||
se_child.expense_account = item_dict[d]["expense_account"] or expense_account
|
se_child.expense_account = item_dict[d].get("expense_account") or expense_account
|
||||||
se_child.cost_center = item_dict[d]["cost_center"] or cost_center
|
se_child.cost_center = item_dict[d].get("cost_center") or cost_center
|
||||||
|
|
||||||
if se_child.s_warehouse==None:
|
if se_child.s_warehouse==None:
|
||||||
se_child.s_warehouse = self.from_warehouse
|
se_child.s_warehouse = self.from_warehouse
|
||||||
|
@ -132,7 +132,7 @@ def get_ordered_qty(item_code, warehouse):
|
|||||||
def get_planned_qty(item_code, warehouse):
|
def get_planned_qty(item_code, warehouse):
|
||||||
planned_qty = frappe.db.sql("""
|
planned_qty = frappe.db.sql("""
|
||||||
select sum(qty - produced_qty) from `tabProduction Order`
|
select sum(qty - produced_qty) from `tabProduction Order`
|
||||||
where production_item = %s and fg_warehouse = %s and status != "Stopped"
|
where production_item = %s and fg_warehouse = %s and status not in ("Stopped", "Completed")
|
||||||
and docstatus=1 and qty > produced_qty""", (item_code, warehouse))
|
and docstatus=1 and qty > produced_qty""", (item_code, warehouse))
|
||||||
|
|
||||||
return flt(planned_qty[0][0]) if planned_qty else 0
|
return flt(planned_qty[0][0]) if planned_qty else 0
|
||||||
|
@ -41,7 +41,8 @@ def get_stock_value_on(warehouse=None, posting_date=None, item_code=None):
|
|||||||
|
|
||||||
sle_map = {}
|
sle_map = {}
|
||||||
for sle in stock_ledger_entries:
|
for sle in stock_ledger_entries:
|
||||||
sle_map[sle.item_code] = sle_map.get(sle.item_code, 0.0) + flt(sle.stock_value)
|
if not sle_map.has_key((sle.item_code, sle.warehouse)):
|
||||||
|
sle_map[(sle.item_code, sle.warehouse)] = flt(sle.stock_value)
|
||||||
|
|
||||||
return sum(sle_map.values())
|
return sum(sle_map.values())
|
||||||
|
|
||||||
@ -67,6 +68,28 @@ def get_stock_balance(item_code, warehouse, posting_date=None, posting_time=None
|
|||||||
else:
|
else:
|
||||||
return last_entry.qty_after_transaction if last_entry else 0.0
|
return last_entry.qty_after_transaction if last_entry else 0.0
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def get_latest_stock_qty(item_code, warehouse=None):
|
||||||
|
values, condition = [item_code], ""
|
||||||
|
if warehouse:
|
||||||
|
lft, rgt, is_group = frappe.db.get_value("Warehouse", warehouse, ["lft", "rgt", "is_group"])
|
||||||
|
|
||||||
|
if is_group:
|
||||||
|
values.extend([lft, rgt])
|
||||||
|
condition += "and exists (\
|
||||||
|
select name from `tabWarehouse` wh where wh.name = tabBin.warehouse\
|
||||||
|
and wh.lft >= %s and wh.rgt <= %s)"
|
||||||
|
|
||||||
|
else:
|
||||||
|
values.append(warehouse)
|
||||||
|
condition += " AND warehouse = %s"
|
||||||
|
|
||||||
|
actual_qty = frappe.db.sql("""select sum(actual_qty) from tabBin
|
||||||
|
where item_code=%s {0}""".format(condition), values)[0][0]
|
||||||
|
|
||||||
|
return actual_qty
|
||||||
|
|
||||||
|
|
||||||
def get_latest_stock_balance():
|
def get_latest_stock_balance():
|
||||||
bin_map = {}
|
bin_map = {}
|
||||||
for d in frappe.db.sql("""SELECT item_code, warehouse, stock_value as stock_value
|
for d in frappe.db.sql("""SELECT item_code, warehouse, stock_value as stock_value
|
||||||
|
Loading…
x
Reference in New Issue
Block a user