[Enhance] Provision to set overproduction percentage for work order (#14248)
This commit is contained in:
parent
09e46a4e5f
commit
05152dad0b
File diff suppressed because it is too large
Load Diff
@ -158,15 +158,15 @@ frappe.ui.form.on("Work Order", {
|
||||
added_min = 0.5;
|
||||
}
|
||||
message = title;
|
||||
|
||||
// pending qty
|
||||
if(!frm.doc.skip_transfer){
|
||||
var pending_complete = frm.doc.material_transferred_for_manufacturing - frm.doc.produced_qty;
|
||||
if(pending_complete) {
|
||||
var title = __('{0} items in progress', [pending_complete]);
|
||||
var width = ((pending_complete / frm.doc.qty * 100) - added_min);
|
||||
bars.push({
|
||||
'title': title,
|
||||
'width': ((pending_complete / frm.doc.qty * 100) - added_min) + '%',
|
||||
'width': (width > 100 ? "99.5" : width) + '%',
|
||||
'progress_class': 'progress-bar-warning'
|
||||
})
|
||||
message = message + '. ' + title;
|
||||
@ -356,7 +356,7 @@ erpnext.work_order = {
|
||||
erpnext.work_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, make this primary
|
||||
finish_btn.addClass('btn-primary');
|
||||
}
|
||||
|
@ -133,7 +133,7 @@ class WorkOrder(Document):
|
||||
so_qty = flt(so_item_qty) + flt(dnpi_qty)
|
||||
|
||||
allowance_percentage = flt(frappe.db.get_single_value("Manufacturing Settings",
|
||||
"over_production_allowance_percentage"))
|
||||
"overproduction_percentage_for_sales_order"))
|
||||
|
||||
if total_qty > so_qty + (allowance_percentage/100 * so_qty):
|
||||
frappe.throw(_("Cannot produce more Item {0} than Sales Order quantity {1}")
|
||||
@ -168,7 +168,7 @@ class WorkOrder(Document):
|
||||
if stock_entries:
|
||||
status = "In Process"
|
||||
produced_qty = stock_entries.get("Manufacture")
|
||||
if flt(produced_qty) == flt(self.qty):
|
||||
if flt(produced_qty) >= flt(self.qty):
|
||||
status = "Completed"
|
||||
else:
|
||||
status = 'Cancelled'
|
||||
@ -179,15 +179,20 @@ class WorkOrder(Document):
|
||||
"""Update **Manufactured Qty** and **Material Transferred for Qty** in Work Order
|
||||
based on Stock Entry"""
|
||||
|
||||
allowance_percentage = flt(frappe.db.get_single_value("Manufacturing Settings",
|
||||
"overproduction_percentage_for_work_order"))
|
||||
|
||||
for purpose, fieldname in (("Manufacture", "produced_qty"),
|
||||
("Material Transfer for Manufacture", "material_transferred_for_manufacturing")):
|
||||
|
||||
qty = flt(frappe.db.sql("""select sum(fg_completed_qty)
|
||||
from `tabStock Entry` where work_order=%s and docstatus=1
|
||||
and purpose=%s""", (self.name, purpose))[0][0])
|
||||
|
||||
if qty > self.qty:
|
||||
completed_qty = self.qty + (allowance_percentage/100 * self.qty)
|
||||
if qty > completed_qty:
|
||||
frappe.throw(_("{0} ({1}) cannot be greater than planned quantity ({2}) in Work Order {3}").format(\
|
||||
self.meta.get_label(fieldname), qty, self.qty, self.name), StockOverProductionError)
|
||||
self.meta.get_label(fieldname), qty, completed_qty, self.name), StockOverProductionError)
|
||||
|
||||
self.db_set(fieldname, qty)
|
||||
|
||||
|
@ -0,0 +1,29 @@
|
||||
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
/* eslint-disable */
|
||||
|
||||
frappe.query_reports["BOM Variance Report"] = {
|
||||
"filters": [
|
||||
{
|
||||
"fieldname":"bom_no",
|
||||
"label": __("BOM No"),
|
||||
"fieldtype": "Link",
|
||||
"options": "BOM"
|
||||
},
|
||||
{
|
||||
"fieldname":"work_order",
|
||||
"label": __("Work Order"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Work Order",
|
||||
"get_query": function() {
|
||||
var bom_no = frappe.query_report_filters_by_name.bom_no.get_value();
|
||||
return{
|
||||
query: "erpnext.manufacturing.report.bom_variance_report.bom_variance_report.get_work_orders",
|
||||
filters: {
|
||||
'bom_no': bom_no
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
{
|
||||
"add_total_row": 0,
|
||||
"creation": "2018-05-28 16:22:24.040106",
|
||||
"disabled": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "Report",
|
||||
"idx": 0,
|
||||
"is_standard": "Yes",
|
||||
"letter_head": "Gadgets International",
|
||||
"modified": "2018-05-28 16:22:24.040106",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "BOM Variance Report",
|
||||
"owner": "Administrator",
|
||||
"ref_doctype": "Stock Entry",
|
||||
"report_name": "BOM Variance Report",
|
||||
"report_type": "Script Report",
|
||||
"roles": [
|
||||
{
|
||||
"role": "Manufacturing Manager"
|
||||
},
|
||||
{
|
||||
"role": "Stock Manager"
|
||||
},
|
||||
{
|
||||
"role": "Stock User"
|
||||
},
|
||||
{
|
||||
"role": "Manufacturing User"
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,107 @@
|
||||
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
|
||||
def execute(filters=None):
|
||||
columns, data = [], []
|
||||
columns = get_columns(filters)
|
||||
data = get_data(filters)
|
||||
return columns, data
|
||||
|
||||
def get_columns(filters):
|
||||
columns = [{
|
||||
"label": _("Work Order"),
|
||||
"fieldname": "work_order",
|
||||
"fieldtype": "Link",
|
||||
"options": "Work Order",
|
||||
"width": 120
|
||||
}]
|
||||
|
||||
if not filters.get('bom_no'):
|
||||
columns.extend([
|
||||
{
|
||||
"label": _("BOM No"),
|
||||
"fieldname": "bom_no",
|
||||
"fieldtype": "Link",
|
||||
"options": "BOM",
|
||||
"width": 180
|
||||
}
|
||||
])
|
||||
|
||||
columns.extend([
|
||||
{
|
||||
"label": _("Finished Good"),
|
||||
"fieldname": "production_item",
|
||||
"fieldtype": "Link",
|
||||
"options": "Item",
|
||||
"width": 120
|
||||
},
|
||||
{
|
||||
"label": _("Ordered Qty"),
|
||||
"fieldname": "qty",
|
||||
"fieldtype": "Float",
|
||||
"width": 120
|
||||
},
|
||||
{
|
||||
"label": _("Produced Qty"),
|
||||
"fieldname": "produced_qty",
|
||||
"fieldtype": "Float",
|
||||
"width": 120
|
||||
},
|
||||
{
|
||||
"label": _("Raw Material"),
|
||||
"fieldname": "raw_material_code",
|
||||
"fieldtype": "Link",
|
||||
"options": "Item",
|
||||
"width": 120
|
||||
},
|
||||
{
|
||||
"label": _("Required Qty"),
|
||||
"fieldname": "required_qty",
|
||||
"fieldtype": "Float",
|
||||
"width": 120
|
||||
},
|
||||
{
|
||||
"label": _("Consumed Qty"),
|
||||
"fieldname": "consumed_qty",
|
||||
"fieldtype": "Float",
|
||||
"width": 120
|
||||
}
|
||||
])
|
||||
|
||||
return columns
|
||||
|
||||
def get_data(filters):
|
||||
cond = "1=1"
|
||||
|
||||
if filters.get('bom_no') and not filters.get('work_order'):
|
||||
cond += " and bom_no = '%s'" % filters.get('bom_no')
|
||||
|
||||
if filters.get('work_order'):
|
||||
cond += " and name = '%s'" % filters.get('work_order')
|
||||
|
||||
results = []
|
||||
for d in frappe.db.sql(""" select name as work_order, qty, produced_qty, production_item, bom_no
|
||||
from `tabWork Order` where produced_qty > qty and docstatus = 1 and {0}""".format(cond), as_dict=1):
|
||||
results.append(d)
|
||||
|
||||
for data in frappe.get_all('Work Order Item', fields=["item_code as raw_material_code",
|
||||
"required_qty", "consumed_qty"], filters={'parent': d.work_order, 'parenttype': 'Work Order'}):
|
||||
results.append(data)
|
||||
|
||||
return results
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_work_orders(doctype, txt, searchfield, start, page_len, filters):
|
||||
cond = "1=1"
|
||||
if filters.get('bom_no'):
|
||||
cond += " and bom_no = '%s'" % filters.get('bom_no')
|
||||
|
||||
return frappe.db.sql("""select name from `tabWork Order`
|
||||
where name like %(name)s and {0} and produced_qty > qty and docstatus = 1
|
||||
order by name limit {1}, {2}""".format(cond, start, page_len),{
|
||||
'name': "%%%s%%" % txt
|
||||
}, as_list=1)
|
@ -542,3 +542,4 @@ erpnext.patches.v11_0.make_asset_finance_book_against_old_entries
|
||||
erpnext.patches.v11_0.check_buying_selling_in_currency_exchange
|
||||
erpnext.patches.v11_0.refactor_erpnext_shopify
|
||||
erpnext.patches.v11_0.move_item_defaults_to_child_table_for_multicompany
|
||||
erpnext.patches.v11_0.rename_overproduction_percent_field
|
||||
|
10
erpnext/patches/v11_0/rename_overproduction_percent_field.py
Normal file
10
erpnext/patches/v11_0/rename_overproduction_percent_field.py
Normal file
@ -0,0 +1,10 @@
|
||||
# Copyright (c) 2018, Frappe and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
from frappe.model.utils.rename_field import rename_field
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
frappe.reload_doc('manufacturing', 'doctype', 'manufacturing_settings')
|
||||
rename_field('Manufacturing Settings', 'over_production_allowance_percentage', 'overproduction_percentage_for_sales_order')
|
@ -350,7 +350,7 @@ frappe.ui.form.on('Stock Entry', {
|
||||
|
||||
target_warehouse_address: function(frm) {
|
||||
erpnext.utils.get_address_display(frm, 'target_warehouse_address', 'target_address_display', false);
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
frappe.ui.form.on('Stock Entry Detail', {
|
||||
|
@ -252,10 +252,13 @@ class StockEntry(StockController):
|
||||
def check_if_operations_completed(self):
|
||||
"""Check if Time Sheets are completed against before manufacturing to capture operating costs."""
|
||||
prod_order = frappe.get_doc("Work Order", self.work_order)
|
||||
allowance_percentage = flt(frappe.db.get_single_value("Manufacturing Settings",
|
||||
"overproduction_percentage_for_work_order"))
|
||||
|
||||
for d in prod_order.get("operations"):
|
||||
total_completed_qty = flt(self.fg_completed_qty) + flt(prod_order.produced_qty)
|
||||
if total_completed_qty > flt(d.completed_qty):
|
||||
completed_qty = d.completed_qty + (allowance_percentage/100 * d.completed_qty)
|
||||
if total_completed_qty > flt(completed_qty):
|
||||
frappe.throw(_("Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order # {3}. Please update operation status via Time Logs")
|
||||
.format(d.idx, d.operation, total_completed_qty, self.work_order), OperationsNotCompleteError)
|
||||
|
||||
@ -469,8 +472,11 @@ class StockEntry(StockController):
|
||||
def validate_finished_goods(self):
|
||||
"""validation: finished good quantity should be same as manufacturing quantity"""
|
||||
items_with_target_warehouse = []
|
||||
allowance_percentage = flt(frappe.db.get_single_value("Manufacturing Settings",
|
||||
"overproduction_percentage_for_work_order"))
|
||||
|
||||
for d in self.get('items'):
|
||||
if self.purpose != "Subcontract" and d.bom_no and flt(d.transfer_qty) != flt(self.fg_completed_qty) and (d.t_warehouse != getattr(self, "pro_doc", frappe._dict()).scrap_warehouse):
|
||||
if self.purpose != "Subcontract" and d.bom_no and flt(d.transfer_qty) > flt(self.fg_completed_qty) and (d.t_warehouse != getattr(self, "pro_doc", frappe._dict()).scrap_warehouse):
|
||||
frappe.throw(_("Quantity in row {0} ({1}) must be same as manufactured quantity {2}"). \
|
||||
format(d.idx, d.transfer_qty, self.fg_completed_qty))
|
||||
|
||||
@ -478,8 +484,14 @@ class StockEntry(StockController):
|
||||
items_with_target_warehouse.append(d.item_code)
|
||||
|
||||
if self.work_order and self.purpose == "Manufacture":
|
||||
production_item = frappe.db.get_value("Work Order",
|
||||
self.work_order, "production_item")
|
||||
production_item, wo_qty = frappe.db.get_value("Work Order",
|
||||
self.work_order, ["production_item", "qty"])
|
||||
|
||||
allowed_qty = wo_qty + (allowance_percentage/100 * wo_qty)
|
||||
if self.fg_completed_qty > allowed_qty:
|
||||
frappe.throw(_("For quantity {0} should not be grater than work order quantity {1}")
|
||||
.format(flt(self.fg_completed_qty), wo_qty))
|
||||
|
||||
if production_item not in items_with_target_warehouse:
|
||||
frappe.throw(_("Finished Item {0} must be entered for Manufacture type entry")
|
||||
.format(production_item))
|
||||
|
Loading…
x
Reference in New Issue
Block a user