Actual operation cost in stock entry, fixed cost removed from bom and workstation
This commit is contained in:
parent
0de6256bcc
commit
89c52eacc7
@ -38,8 +38,7 @@ erpnext.bom.set_operation = function(doc) {
|
||||
operations[i] = (i+1);
|
||||
}
|
||||
|
||||
frappe.meta.get_docfield("BOM Item", "operation",
|
||||
cur_frm.docname).options = operations.join("\n");
|
||||
frappe.meta.get_docfield("BOM Item", "operation", cur_frm.docname).options = operations.join("\n");
|
||||
|
||||
refresh_field("bom_materials");
|
||||
}
|
||||
@ -54,7 +53,6 @@ cur_frm.add_fetch("item", "stock_uom", "uom");
|
||||
|
||||
cur_frm.cscript.hour_rate = function(doc, dt, dn) {
|
||||
erpnext.bom.calculate_op_cost(doc);
|
||||
erpnext.bom.calculate_fixed_cost(doc);
|
||||
erpnext.bom.calculate_total(doc);
|
||||
}
|
||||
|
||||
@ -114,16 +112,14 @@ cur_frm.cscript.rate = function(doc, cdt, cdn) {
|
||||
|
||||
erpnext.bom.calculate_op_cost = function(doc) {
|
||||
var op = doc.bom_operations || [];
|
||||
doc.total_variable_cost, doc.total_fixed_cost = 0.0, 0.0;
|
||||
doc.operating_cost = 0.0;
|
||||
for(var i=0;i<op.length;i++) {
|
||||
variable_cost = flt(flt(op[i].hour_rate) * flt(op[i].time_in_mins) / 60, 2);
|
||||
frappe.model.set_value('BOM Operation',op[i].name, "variable_cost", variable_cost);
|
||||
operating_cost = flt(flt(op[i].hour_rate) * flt(op[i].time_in_mins) / 60, 2);
|
||||
frappe.model.set_value('BOM Operation',op[i].name, "operating_cost", operating_cost);
|
||||
|
||||
doc.total_variable_cost += variable_cost;
|
||||
doc.total_fixed_cost += flt(op[i].fixed_cost);
|
||||
doc.operating_cost += operating_cost;
|
||||
}
|
||||
refresh_field(['total_fixed_cost', 'total_variable_cost']);
|
||||
frappe.model.set_value("total_operating_cost", (doc.total_variable_cost + doc.total_fixed_cost))
|
||||
refresh_field('operating_cost');
|
||||
}
|
||||
|
||||
erpnext.bom.calculate_rm_cost = function(doc) {
|
||||
@ -142,8 +138,8 @@ erpnext.bom.calculate_rm_cost = function(doc) {
|
||||
|
||||
// Calculate Total Cost
|
||||
erpnext.bom.calculate_total = function(doc) {
|
||||
total_cost = flt(doc.total_operating_cost) + flt(doc.raw_material_cost);
|
||||
frappe.model.set_value("total_cost", total_cost);
|
||||
total_cost = flt(doc.operating_cost) + flt(doc.raw_material_cost);
|
||||
frappe.model.set_value(doc.doctype, doc.name, "total_cost", total_cost);
|
||||
}
|
||||
|
||||
|
||||
@ -184,7 +180,6 @@ cur_frm.fields_dict['bom_materials'].grid.get_field('bom_no').get_query = functi
|
||||
cur_frm.cscript.validate = function(doc, dt, dn) {
|
||||
erpnext.bom.calculate_op_cost(doc);
|
||||
erpnext.bom.calculate_rm_cost(doc);
|
||||
erpnext.bom.calculate_fixed_cost(doc);
|
||||
erpnext.bom.calculate_total(doc);
|
||||
}
|
||||
|
||||
@ -216,9 +211,7 @@ frappe.ui.form.on("BOM Operation", "workstation", function(frm, cdt, cdn) {
|
||||
},
|
||||
callback: function (data) {
|
||||
frappe.model.set_value(d.doctype, d.name, "hour_rate", data.message.hour_rate);
|
||||
frappe.model.set_value(d.doctype, d.name, "fixed_cost", data.message.fixed_cost);
|
||||
erpnext.bom.calculate_op_cost(frm.doc);
|
||||
erpnext.bom.calculate_fixed_cost(frm.doc);
|
||||
erpnext.bom.calculate_total(frm.doc);
|
||||
}
|
||||
})
|
||||
|
@ -93,34 +93,6 @@
|
||||
"options": "BOM Operation",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_10",
|
||||
"fieldtype": "Section Break",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"fieldname": "total_fixed_cost",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Total Fixed Cost",
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_12",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"fieldname": "total_variable_cost",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Total Variable Cost",
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "materials",
|
||||
"fieldtype": "Section Break",
|
||||
@ -156,10 +128,10 @@
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "total_operating_cost",
|
||||
"fieldname": "operating_cost",
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 1,
|
||||
"label": "Total Operating Cost",
|
||||
"label": "Operating Cost",
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
@ -167,7 +139,7 @@
|
||||
{
|
||||
"fieldname": "raw_material_cost",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Total Raw Material Cost",
|
||||
"label": "Raw Material Cost",
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
@ -272,7 +244,7 @@
|
||||
"is_submittable": 1,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"modified": "2014-12-17 17:05:21.347760",
|
||||
"modified": "2014-12-23 16:39:14.197038",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "BOM",
|
||||
|
@ -118,11 +118,10 @@ class BOM(Document):
|
||||
return
|
||||
|
||||
for d in self.get("bom_materials"):
|
||||
d.rate = self.get_bom_material_detail({
|
||||
'item_code': d.item_code,
|
||||
'bom_no': d.bom_no,
|
||||
'qty': d.qty
|
||||
})["rate"]
|
||||
rate = self.get_bom_material_detail({'item_code': d.item_code, 'bom_no': d.bom_no,
|
||||
'qty': d.qty})["rate"]
|
||||
if rate:
|
||||
d.rate = rate
|
||||
|
||||
if self.docstatus == 1:
|
||||
self.ignore_validate_update_after_submit = True
|
||||
@ -130,20 +129,31 @@ class BOM(Document):
|
||||
self.save()
|
||||
|
||||
def get_bom_unitcost(self, bom_no):
|
||||
bom = frappe.db.sql("""select name, total_variable_cost/quantity as unit_cost from `tabBOM`
|
||||
bom = frappe.db.sql("""select name, total_cost/quantity as unit_cost from `tabBOM`
|
||||
where is_active = 1 and name = %s""", bom_no, as_dict=1)
|
||||
return bom and bom[0]['unit_cost'] or 0
|
||||
|
||||
def get_valuation_rate(self, args):
|
||||
""" Get weighted average of valuation rate from all warehouses """
|
||||
|
||||
total_qty, total_value = 0.0, 0.0
|
||||
total_qty, total_value, valuation_rate = 0.0, 0.0, 0.0
|
||||
for d in frappe.db.sql("""select actual_qty, stock_value from `tabBin`
|
||||
where item_code=%s and actual_qty > 0""", args['item_code'], as_dict=1):
|
||||
where item_code=%s""", args['item_code'], as_dict=1):
|
||||
total_qty += flt(d.actual_qty)
|
||||
total_value += flt(d.stock_value)
|
||||
|
||||
return total_value / total_qty if total_qty else 0.0
|
||||
if total_qty:
|
||||
valuation_rate = total_value / total_qty
|
||||
|
||||
if valuation_rate <= 0:
|
||||
last_valuation_rate = frappe.db.sql("""select valuation_rate
|
||||
from `tabStock Ledger Entry`
|
||||
where item_code = %s and ifnull(valuation_rate, 0) > 0
|
||||
order by posting_date desc, posting_time desc, name desc limit 1""", args['item_code'])
|
||||
|
||||
valuation_rate = flt(last_valuation_rate[0][0]) if last_valuation_rate else 0
|
||||
|
||||
return valuation_rate
|
||||
|
||||
def manage_default_bom(self):
|
||||
""" Uncheck others if current one is selected as default,
|
||||
@ -247,28 +257,20 @@ class BOM(Document):
|
||||
"""Calculate bom totals"""
|
||||
self.calculate_op_cost()
|
||||
self.calculate_rm_cost()
|
||||
self.total_cost = self.total_operating_cost + self.raw_material_cost
|
||||
self.total_cost = self.operating_cost + self.raw_material_cost
|
||||
|
||||
def calculate_op_cost(self):
|
||||
"""Update workstation rate and calculates totals"""
|
||||
total_variable_cost, total_fixed_cost = 0, 0
|
||||
self.operating_cost = 0
|
||||
for d in self.get('bom_operations'):
|
||||
if d.workstation:
|
||||
w = frappe.db.get_value("Workstation", d.workstation, ["hour_rate", "fixed_cost"])
|
||||
if not d.hour_rate:
|
||||
d.hour_rate = flt(w[0])
|
||||
|
||||
total_fixed_cost += flt(w[1])
|
||||
d.hour_rate = flt(frappe.db.get_value("Workstation", d.workstation, "hour_rate"))
|
||||
|
||||
if d.hour_rate and d.time_in_mins:
|
||||
d.variable_cost = flt(d.hour_rate) * flt(d.time_in_mins) / 60.0
|
||||
d.operating_cost = flt(d.hour_rate) * flt(d.time_in_mins) / 60.0
|
||||
|
||||
d.operating_cost = flt(d.fixed_cost) + flt(d.variable_cost)
|
||||
total_variable_cost += flt(d.variable_cost)
|
||||
|
||||
self.total_variable_cost = total_variable_cost
|
||||
self.total_fixed_cost = total_fixed_cost
|
||||
self.total_operating_cost = self.total_variable_cost + self.total_fixed_cost
|
||||
self.operating_cost += flt(d.operating_cost)
|
||||
|
||||
def calculate_rm_cost(self):
|
||||
"""Fetch RM rate as per today's valuation rate and calculate totals"""
|
||||
|
@ -15,6 +15,6 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-2 text-right">
|
||||
{%= doc.get_formatted("total_variable_cost") %}
|
||||
{%= doc.get_formatted("total_cost") %}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,3 +1,3 @@
|
||||
frappe.listview_settings['BOM'] = {
|
||||
add_fields: ["is_active", "is_default", "total_variable_cost"]
|
||||
add_fields: ["is_active", "is_default", "total_cost"]
|
||||
};
|
||||
|
@ -40,13 +40,6 @@
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "fixed_cost",
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 0,
|
||||
"label": "Fixed Cost",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "hour_rate",
|
||||
"fieldtype": "Float",
|
||||
@ -69,14 +62,6 @@
|
||||
"permlevel": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "variable_cost",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Variable Cost",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"fieldname": "operating_cost",
|
||||
@ -92,7 +77,7 @@
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"modified": "2014-12-17 17:54:34.313130",
|
||||
"modified": "2014-12-23 15:01:54.340605",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "BOM Operation",
|
||||
|
@ -25,7 +25,7 @@ class BOMReplaceTool(Document):
|
||||
frappe.throw(_("Current BOM and New BOM can not be same"))
|
||||
|
||||
def update_new_bom(self):
|
||||
current_bom_unitcost = frappe.db.sql("""select total_variable_cost/quantity
|
||||
current_bom_unitcost = frappe.db.sql("""select total_cost/quantity
|
||||
from `tabBOM` where name = %s""", self.current_bom)
|
||||
current_bom_unitcost = current_bom_unitcost and flt(current_bom_unitcost[0][0]) or 0
|
||||
frappe.db.sql("""update `tabBOM Item` set bom_no=%s,
|
||||
|
@ -1,14 +0,0 @@
|
||||
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
frappe.provide("erpnext.operation");
|
||||
|
||||
$.extend(cur_frm.cscript, {
|
||||
time_in_min: function(doc) {
|
||||
doc.operating_cost = flt(doc.hour_rate) * flt(doc.time_in_min) / 60.0;
|
||||
refresh_field('operating_cost');
|
||||
}
|
||||
});
|
||||
|
||||
cur_frm.add_fetch('workstation', 'hour_rate', 'hour_rate');
|
||||
cur_frm.add_fetch('workstation', 'fixed_cycle_cost', 'fixed_cycle_cost');
|
@ -77,7 +77,8 @@ $.extend(cur_frm.cscript, {
|
||||
"from_time": child.planned_start_time,
|
||||
"to_time": child.planned_end_time,
|
||||
"project": doc.project,
|
||||
"workstation": child.workstation
|
||||
"workstation": child.workstation,
|
||||
"qty": flt(doc.qty) - flt(child.completed_qty)
|
||||
},
|
||||
callback: function(r) {
|
||||
var doclist = frappe.model.sync(r.message);
|
||||
@ -164,11 +165,7 @@ cur_frm.set_query("bom_no", function(doc) {
|
||||
} else msgprint(__("Please enter Production Item first"));
|
||||
});
|
||||
|
||||
cur_frm.add_fetch('bom_no', 'total_fixed_cost', 'total_fixed_cost');
|
||||
cur_frm.add_fetch('bom_no', 'total_variable_cost', 'planned_variable_cost');
|
||||
cur_frm.add_fetch('bom_no', 'total_operating_cost', 'total_operating_cost');
|
||||
|
||||
frappe.ui.form.on("Production Order", "total_fixed_cost", function(frm) {
|
||||
var variable_cost = frm.doc.actual_variable_cost ? flt(frm.doc.actual_variable_cost) : flt(frm.doc.planned_variable_cost)
|
||||
frm.set_value("total_operating_cost", (flt(frm.doc.total_fixed_cost) + variable_cost))
|
||||
frappe.ui.form.on("Production Order", "additional_operating_cost", function(frm) {
|
||||
var variable_cost = frm.doc.actual_operating_cost ? flt(frm.doc.actual_operating_cost) : flt(frm.doc.planned_operating_cost)
|
||||
frm.set_value("total_operating_cost", (flt(frm.doc.additional_operating_cost) + variable_cost))
|
||||
})
|
||||
|
@ -217,31 +217,34 @@
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"depends_on": "",
|
||||
"fieldname": "total_fixed_cost",
|
||||
"fieldname": "planned_operating_cost",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Total Fixed Cost",
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "planned_variable_cost",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Planned Variable Cost",
|
||||
"label": "Planned Operating Cost",
|
||||
"no_copy": 0,
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "actual_variable_cost",
|
||||
"fieldname": "actual_operating_cost",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Actual Variable Cost",
|
||||
"label": "Actual Operating Cost",
|
||||
"no_copy": 1,
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "additional_operating_cost",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Additional Operating Cost",
|
||||
"no_copy": 1,
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_24",
|
||||
"fieldtype": "Column Break",
|
||||
@ -252,6 +255,7 @@
|
||||
"fieldname": "total_operating_cost",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Total Operating Cost",
|
||||
"no_copy": 1,
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
@ -347,7 +351,7 @@
|
||||
"idx": 1,
|
||||
"in_create": 0,
|
||||
"is_submittable": 1,
|
||||
"modified": "2014-12-19 14:23:50.701164",
|
||||
"modified": "2014-12-23 15:07:26.516227",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "Production Order",
|
||||
|
@ -59,20 +59,15 @@ class ProductionOrder(Document):
|
||||
validate_warehouse_company(w, self.company)
|
||||
|
||||
def calculate_operating_cost(self):
|
||||
if self.total_fixed_cost==None:
|
||||
self.total_fixed_cost = frappe.db.get_value("BOM", self.bom_no, "total_fixed_cost")
|
||||
|
||||
self.planned_variable_cost, self.actual_variable_cost = 0.0, 0.0
|
||||
self.planned_operating_cost, self.actual_operating_cost = 0.0, 0.0
|
||||
for d in self.get("production_order_operations"):
|
||||
d.actual_operating_cost = flt(d.hour_rate) * flt(d.actual_operation_time) / 60
|
||||
|
||||
d.actual_variable_cost = flt(d.hour_rate) * flt(d.actual_operation_time) / 60
|
||||
|
||||
self.planned_variable_cost += flt(d.variable_cost)
|
||||
self.actual_variable_cost += flt(d.actual_variable_cost)
|
||||
|
||||
variable_cost = self.actual_variable_cost if self.actual_variable_cost else self.planned_variable_cost
|
||||
self.total_operating_cost = flt(self.total_fixed_cost) + flt(variable_cost)
|
||||
self.planned_operating_cost += flt(d.planned_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
|
||||
self.total_operating_cost = flt(self.additional_operating_cost) + flt(variable_cost)
|
||||
|
||||
def validate_production_order_against_so(self):
|
||||
# already ordered qty
|
||||
@ -171,15 +166,16 @@ class ProductionOrder(Document):
|
||||
self.set('production_order_operations', [])
|
||||
|
||||
operations = frappe.db.sql("""select operation, opn_description, workstation,
|
||||
hour_rate, time_in_mins, fixed_cost, variable_cost, "Pending" as status
|
||||
hour_rate, time_in_mins, operating_cost as "planned_operating_cost", "Pending" as status
|
||||
from `tabBOM Operation` where parent = %s""", self.bom_no, as_dict=1)
|
||||
|
||||
self.set('production_order_operations', operations)
|
||||
|
||||
self.plan_operations()
|
||||
self.calculate_operating_cost()
|
||||
|
||||
def plan_operations(self):
|
||||
scheduled_datetime = self.production_start_date
|
||||
scheduled_datetime = self.planned_start_date
|
||||
for d in self.get('production_order_operations'):
|
||||
while getdate(scheduled_datetime) in self.get_holidays(d.workstation):
|
||||
scheduled_datetime = get_datetime(scheduled_datetime) + relativedelta(days=1)
|
||||
@ -188,7 +184,7 @@ class ProductionOrder(Document):
|
||||
scheduled_datetime = get_datetime(scheduled_datetime) + relativedelta(minutes=d.time_in_mins)
|
||||
d.planned_end_time = scheduled_datetime
|
||||
|
||||
self.production_end_date = scheduled_datetime
|
||||
self.planned_end_date = scheduled_datetime
|
||||
|
||||
|
||||
def get_holidays(self, workstation):
|
||||
@ -202,6 +198,17 @@ class ProductionOrder(Document):
|
||||
|
||||
return self.holidays[holiday_list]
|
||||
|
||||
def update_operation_status(self):
|
||||
for d in self.get("production_order_operations"):
|
||||
if not d.completed_qty:
|
||||
d.status = "Pending"
|
||||
elif flt(d.completed_qty) < flt(self.qty):
|
||||
d.status = "Work in Progress"
|
||||
elif flt(d.completed_qty) == flt(self.qty):
|
||||
d.status = "Completed"
|
||||
else:
|
||||
frappe.throw(_("Completed Qty can not be greater than 'Qty to Manufacture'"))
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_item_details(item):
|
||||
@ -213,10 +220,7 @@ def get_item_details(item):
|
||||
return {}
|
||||
|
||||
res = res[0]
|
||||
bom = frappe.db.sql("""select name as bom_no,total_fixed_cost from `tabBOM` where item=%s
|
||||
and ifnull(is_default, 0)=1""", item, as_dict=1)
|
||||
if bom:
|
||||
res.update(bom[0])
|
||||
res["bom_no"] = frappe.db.get_value("BOM", filters={"item": item, "is_default": 1})
|
||||
return res
|
||||
|
||||
@frappe.whitelist()
|
||||
@ -228,6 +232,7 @@ def make_stock_entry(production_order_id, purpose, qty=None):
|
||||
stock_entry.production_order = production_order_id
|
||||
stock_entry.company = production_order.company
|
||||
stock_entry.bom_no = production_order.bom_no
|
||||
stock_entry.additional_operating_cost = production_order.additional_operating_cost
|
||||
stock_entry.use_multi_level_bom = production_order.use_multi_level_bom
|
||||
stock_entry.fg_completed_qty = qty or (flt(production_order.qty) - flt(production_order.produced_qty))
|
||||
|
||||
@ -267,7 +272,7 @@ def get_events(start, end, filters=None):
|
||||
return data
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_time_log(name, operation, from_time, to_time, qty=None, project=None, workstation=None):
|
||||
def make_time_log(name, operation, from_time, to_time, qty=None, project=None, workstation=None):
|
||||
time_log = frappe.new_doc("Time Log")
|
||||
time_log.time_log_for = 'Manufacturing'
|
||||
time_log.from_time = from_time
|
||||
@ -276,16 +281,24 @@ def make_time_log(name, operation, from_time, to_time, qty=None, project=None, w
|
||||
time_log.project = project
|
||||
time_log.operation= operation
|
||||
time_log.workstation= workstation
|
||||
time_log.completed_qty = flt(qty)
|
||||
if from_time and to_time :
|
||||
time_log.calculate_total_hours()
|
||||
return time_log
|
||||
|
||||
@frappe.whitelist()
|
||||
def auto_make_time_log(production_order_id):
|
||||
if frappe.db.get_value("Time Log", filters={"production_order": production_order_id}):
|
||||
frappe.throw(_("Time logs already exists against this Production Order"))
|
||||
|
||||
time_logs = []
|
||||
prod_order = frappe.get_doc("Production Order", production_order_id)
|
||||
|
||||
for d in prod_order.production_order_operations:
|
||||
operation = cstr(d.idx) + ". " + d.operation
|
||||
time_log = make_time_log(prod_order.name, operation, d.planned_start_time, d.planned_end_time,
|
||||
prod_order.qty, prod_order.project_name, d.workstation)
|
||||
flt(prod_order.qty) - flt(d.completed_qty), prod_order.project_name, d.workstation)
|
||||
time_log.save()
|
||||
frappe.msgprint(_("Time Logs created."))
|
||||
time_logs.append(time_log.name)
|
||||
if time_logs:
|
||||
frappe.msgprint(_("Time Logs created:") + "\n" + "\n".join(time_logs))
|
||||
|
@ -79,12 +79,23 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"description": "Operation completed for how many finished goods?",
|
||||
"fieldname": "completed_qty",
|
||||
"fieldtype": "Float",
|
||||
"label": "Completed Qty",
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"default": "Pending",
|
||||
"fieldname": "status",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "Status",
|
||||
"no_copy": 1,
|
||||
"options": "Pending\nWork in Progress\nCompleted",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
@ -121,57 +132,24 @@
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"fieldname": "hour_rate",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"fieldname": "planned_start_time",
|
||||
"fieldtype": "Datetime",
|
||||
"in_list_view": 0,
|
||||
"label": "Hour Rate",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "hour_rate",
|
||||
"oldfieldtype": "Currency",
|
||||
"label": "Planned Start Time",
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"fieldname": "fixed_cost",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"fieldname": "planned_end_time",
|
||||
"fieldtype": "Datetime",
|
||||
"in_list_view": 0,
|
||||
"label": "Fixed Cost",
|
||||
"no_copy": 0,
|
||||
"options": "Company:company:default_currency",
|
||||
"label": "Planned End Time",
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "variable_cost",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Variable Cost",
|
||||
"no_copy": 0,
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"read_only": 1
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_10",
|
||||
@ -203,56 +181,41 @@
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "planned_start_time",
|
||||
"fieldtype": "Datetime",
|
||||
"in_list_view": 0,
|
||||
"label": "Planned Start Time",
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "planned_end_time",
|
||||
"fieldtype": "Datetime",
|
||||
"in_list_view": 0,
|
||||
"label": "Planned End Time",
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_9",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Actual Time and Cost",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"description": "in Minutes\nUpdated via 'Time Log'",
|
||||
"fieldname": "actual_operation_time",
|
||||
"allow_on_submit": 0,
|
||||
"fieldname": "hour_rate",
|
||||
"fieldtype": "Float",
|
||||
"label": "Actual Operation Time",
|
||||
"no_copy": 1,
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Hour Rate",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "hour_rate",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"read_only": 1
|
||||
"print_hide": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"description": "Hour Rate * Actual Operating Cost",
|
||||
"fieldname": "actual_variable_cost",
|
||||
"fieldname": "planned_operating_cost",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Actual Variable Cost",
|
||||
"no_copy": 1,
|
||||
"label": "Planned Operating Cost",
|
||||
"no_copy": 0,
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_11",
|
||||
"fieldtype": "Column Break",
|
||||
"fieldname": "section_break_9",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Actual Time and Cost",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
@ -275,6 +238,33 @@
|
||||
"precision": "",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_11",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"description": "in Minutes\nUpdated via 'Time Log'",
|
||||
"fieldname": "actual_operation_time",
|
||||
"fieldtype": "Float",
|
||||
"label": "Actual Operation Time",
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"description": "Hour Rate * Actual Operating Cost",
|
||||
"fieldname": "actual_operating_cost",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Actual Operating Cost",
|
||||
"no_copy": 1,
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"depends_on": "eval:(doc.docstatus==1 && doc.status!=\"Completed\")",
|
||||
@ -292,7 +282,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2014-12-19 12:49:49.918120",
|
||||
"modified": "2014-12-23 15:42:34.892964",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "Production Order Operation",
|
||||
|
@ -4,7 +4,6 @@
|
||||
"name": "_Test Workstation 1",
|
||||
"workstation_name": "_Test Workstation 1",
|
||||
"warehouse": "_Test warehouse - _TC",
|
||||
"fixed_cycle_cost": 1000,
|
||||
"hour_rate":100,
|
||||
"holiday_list": "_Test Holiday List",
|
||||
"workstation_operation_hours": [
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
|
||||
|
||||
|
||||
//--------- ONLOAD -------------
|
||||
cur_frm.cscript.onload = function(doc, cdt, cdn) {
|
||||
@ -15,7 +15,3 @@ cur_frm.cscript.onload = function(doc, cdt, cdn) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
cur_frm.cscript.refresh = function(doc, cdt, cdn) {
|
||||
|
||||
}
|
@ -60,19 +60,6 @@
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"fieldname": "fixed_costs",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Fixed Costs",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"fieldname": "fixed_cost",
|
||||
"fieldtype": "Float",
|
||||
"label": "Fixed Cost",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "over_heads",
|
||||
"fieldtype": "Section Break",
|
||||
@ -98,15 +85,6 @@
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"description": "per hour",
|
||||
"fieldname": "hour_rate_rent",
|
||||
"fieldtype": "Float",
|
||||
"label": "Rent Cost",
|
||||
"oldfieldname": "hour_rate_rent",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_11",
|
||||
"fieldtype": "Column Break",
|
||||
@ -115,13 +93,12 @@
|
||||
},
|
||||
{
|
||||
"description": "per hour",
|
||||
"fieldname": "total_variable_cost",
|
||||
"fieldname": "hour_rate_rent",
|
||||
"fieldtype": "Float",
|
||||
"label": "Total Variable Cost",
|
||||
"oldfieldname": "overhead",
|
||||
"label": "Rent Cost",
|
||||
"oldfieldname": "hour_rate_rent",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"description": "Wages per hour",
|
||||
@ -161,7 +138,7 @@
|
||||
],
|
||||
"icon": "icon-wrench",
|
||||
"idx": 1,
|
||||
"modified": "2014-12-22 14:18:40.253034",
|
||||
"modified": "2014-12-23 15:27:58.477925",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "Workstation",
|
||||
|
@ -25,9 +25,8 @@ class Workstation(Document):
|
||||
def on_update(self):
|
||||
self.validate_overlap_for_operation_timings()
|
||||
|
||||
frappe.db.set(self, 'total_variable_cost', flt(self.hour_rate_electricity) +
|
||||
frappe.db.set(self, 'hour_rate', flt(self.hour_rate_labour) + flt(self.hour_rate_electricity) +
|
||||
flt(self.hour_rate_consumable) + flt(self.hour_rate_rent))
|
||||
frappe.db.set(self, 'hour_rate', flt(self.hour_rate_labour) + flt(self.total_variable_cost))
|
||||
|
||||
self.update_bom_operation()
|
||||
|
||||
@ -41,8 +40,8 @@ class Workstation(Document):
|
||||
(%s between start_time and end_time))
|
||||
""", (self.name, d.name, d.start_time, d.end_time, d.start_time, d.end_time, d.start_time))
|
||||
|
||||
if existing:
|
||||
frappe.throw(_("Row #{0}: Timings conflicts with row {1}").format(d.idx, comma_and(existing)), OverlapError)
|
||||
if existing:
|
||||
frappe.throw(_("Row #{0}: Timings conflicts with row {1}").format(d.idx, comma_and(existing)), OverlapError)
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_default_holiday_list():
|
||||
|
@ -80,7 +80,6 @@ execute:frappe.delete_doc("DocType", "Landed Cost Wizard")
|
||||
erpnext.patches.v4_2.default_website_style
|
||||
erpnext.patches.v4_2.set_company_country
|
||||
erpnext.patches.v4_2.update_sales_order_invoice_field_name
|
||||
erpnext.patches.v4_2.cost_of_production_cycle
|
||||
erpnext.patches.v4_2.seprate_manufacture_and_repack
|
||||
execute:frappe.delete_doc("Report", "Warehouse-Wise Stock Balance")
|
||||
execute:frappe.delete_doc("DocType", "Purchase Request")
|
||||
|
@ -1,9 +0,0 @@
|
||||
# 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():
|
||||
frappe.reload_doc("manufacturing", "doctype", "bom")
|
||||
frappe.db.sql("""update tabBOM set total_variable_cost = total_cost""")
|
@ -4,20 +4,5 @@
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
for dt in ["workstation", "bom", "bom_operation"]:
|
||||
frappe.reload_doc("manufacturing", "doctype", dt)
|
||||
|
||||
frappe.db.sql("update `tabWorkstation` set fixed_cost = fixed_cycle_cost, total_variable_cost = overhead")
|
||||
|
||||
frappe.db.sql("update `tabBOM Operation` set fixed_cost = fixed_cycle_cost")
|
||||
|
||||
for d in frappe.db.sql("select name from `tabBOM` where docstatus < 2"):
|
||||
try:
|
||||
bom = frappe.get_doc('BOM', d[0])
|
||||
if bom.docstatus == 1:
|
||||
bom.ignore_validate_update_after_submit = True
|
||||
bom.calculate_cost()
|
||||
bom.save()
|
||||
except:
|
||||
print "error", frappe.get_traceback()
|
||||
pass
|
||||
frappe.reload_doc("stock", "doctype", "stock_entry")
|
||||
frappe.db.sql("update tabBOM set additional_operating_cost = total_fixed_cost")
|
||||
|
@ -14,7 +14,7 @@ frappe.ui.form.on("Time Log", "refresh", function(frm) {
|
||||
var is_manufacturing = frm.doc.time_log_for=="Manufacturing" ? true : false;
|
||||
frm.toggle_reqd("production_order", is_manufacturing);
|
||||
frm.toggle_reqd("operation", is_manufacturing);
|
||||
frm.toggle_reqd("operation_status", is_manufacturing);
|
||||
frm.toggle_reqd("completed_qty", is_manufacturing);
|
||||
});
|
||||
|
||||
// set to time if hours is updated
|
||||
|
@ -116,11 +116,10 @@
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"default": "Work in Progress",
|
||||
"fieldname": "operation_status",
|
||||
"fieldtype": "Select",
|
||||
"label": "Operation Status",
|
||||
"options": "\nWork in Progress\nCompleted",
|
||||
"description": "Operation completed for how many finished goods?",
|
||||
"fieldname": "completed_qty",
|
||||
"fieldtype": "Float",
|
||||
"label": "Completed Qty",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
@ -200,7 +199,7 @@
|
||||
"icon": "icon-time",
|
||||
"idx": 1,
|
||||
"is_submittable": 1,
|
||||
"modified": "2014-12-19 14:20:41.381152",
|
||||
"modified": "2014-12-22 15:22:00.664972",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Projects",
|
||||
"name": "Time Log",
|
||||
|
@ -23,7 +23,6 @@ class TimeLog(Document):
|
||||
self.validate_time_log_for()
|
||||
self.check_workstation_timings()
|
||||
self.validate_production_order()
|
||||
self.validate_operation_status()
|
||||
|
||||
def on_submit(self):
|
||||
self.update_production_order()
|
||||
@ -77,7 +76,7 @@ class TimeLog(Document):
|
||||
|
||||
def validate_time_log_for(self):
|
||||
if self.time_log_for == "Project":
|
||||
for fld in ["production_order", "operation", "workstation", "operation_status"]:
|
||||
for fld in ["production_order", "operation", "workstation", "completed_qty"]:
|
||||
self.set(fld, None)
|
||||
|
||||
def check_workstation_timings(self):
|
||||
@ -92,33 +91,25 @@ class TimeLog(Document):
|
||||
if frappe.db.get_value("Production Order", self.production_order, "docstatus") != 1 :
|
||||
frappe.throw(_("You can make a time log only against a submitted production order"), NotSubmittedError)
|
||||
|
||||
def validate_operation_status(self):
|
||||
if self.time_log_for=="Manufacturing" and self.production_order and self.operation:
|
||||
if self.operation_status == "Work in Progress":
|
||||
latest_time_log = self.get_latest_time_log()
|
||||
if latest_time_log and latest_time_log[0].operation_status == "Completed":
|
||||
frappe.throw("Operation is already completed via Time Log {}".format(latest_time_log[0].name))
|
||||
|
||||
def update_production_order(self):
|
||||
"""Updates `start_date`, `end_date`, `status` for operation in Production Order."""
|
||||
|
||||
if self.time_log_for=="Manufacturing" and self.operation:
|
||||
operation = self.operation.split('. ',1)
|
||||
|
||||
dates = self.get_operation_start_end_time()
|
||||
tl = self.get_all_time_logs()
|
||||
|
||||
latest_time_log = self.get_latest_time_log()
|
||||
op_status = latest_time_log[0].operation_status if latest_time_log else "Pending"
|
||||
|
||||
actual_op_time = self.get_actual_op_time()
|
||||
d = self.operation.split('. ',1)
|
||||
|
||||
frappe.db.sql("""update `tabProduction Order Operation`
|
||||
set actual_start_time = %s, actual_end_time = %s, status = %s, actual_operation_time = %s
|
||||
set actual_start_time = %s, actual_end_time = %s, completed_qty = %s, actual_operation_time = %s
|
||||
where parent=%s and idx=%s and operation = %s""",
|
||||
(dates.start_date, dates.end_date, op_status,
|
||||
actual_op_time, self.production_order, d[0], d[1]))
|
||||
(dates.start_date, dates.end_date, tl.completed_qty,
|
||||
tl.hours, self.production_order, operation[0], operation[1]))
|
||||
|
||||
pro_order = frappe.get_doc("Production Order", self.production_order)
|
||||
pro_order.ignore_validate_update_after_submit = True
|
||||
pro_order.update_operation_status()
|
||||
pro_order.calculate_operating_cost()
|
||||
pro_order.save()
|
||||
|
||||
@ -128,17 +119,13 @@ class TimeLog(Document):
|
||||
where production_order = %s and operation = %s and docstatus=1""",
|
||||
(self.production_order, self.operation), as_dict=1)[0]
|
||||
|
||||
def get_actual_op_time(self):
|
||||
def get_all_time_logs(self):
|
||||
"""Returns 'Actual Operating Time'. """
|
||||
actual_time = frappe.db.sql("""select sum(hours*60) as time_diff from
|
||||
`tabTime Log` where production_order = %s and operation = %s and docstatus=1""",
|
||||
(self.production_order, self.operation))
|
||||
return actual_time[0][0] if actual_time else 0
|
||||
|
||||
def get_latest_time_log(self):
|
||||
return frappe.db.sql("""select name, operation_status from `tabTime Log`
|
||||
where production_order=%s and operation=%s and docstatus=1
|
||||
order by to_time desc limit 1""", (self.production_order, self.operation), as_dict=1)
|
||||
return frappe.db.sql("""select
|
||||
sum(hours*60) as hours, sum(ifnull(completed_qty, 0)) as completed_qty
|
||||
from `tabTime Log`
|
||||
where production_order = %s and operation = %s and docstatus=1""",
|
||||
(self.production_order, self.operation), as_dict=1)[0]
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_workstation(production_order, operation):
|
||||
|
@ -461,8 +461,6 @@ cur_frm.fields_dict.customer.get_query = function(doc, cdt, cdn) {
|
||||
cur_frm.fields_dict.supplier.get_query = function(doc, cdt, cdn) {
|
||||
return { query: "erpnext.controllers.queries.supplier_query" }
|
||||
}
|
||||
cur_frm.add_fetch('production_order', 'total_fixed_cost', 'total_fixed_cost');
|
||||
cur_frm.add_fetch('bom_no', 'total_fixed_cost', 'total_fixed_cost');
|
||||
|
||||
cur_frm.cscript.company = function(doc, cdt, cdn) {
|
||||
erpnext.get_fiscal_year(doc.company, doc.posting_date);
|
||||
|
@ -299,9 +299,11 @@
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:inList([\"Manufacture\", \"Repack\"], doc.purpose)",
|
||||
"fieldname": "total_fixed_cost",
|
||||
"fieldtype": "Float",
|
||||
"label": "Total Fixed Cost",
|
||||
"fieldname": "additional_operating_cost",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Additional Operating Cost",
|
||||
"no_copy": 1,
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"read_only": 0
|
||||
},
|
||||
@ -585,7 +587,7 @@
|
||||
"is_submittable": 1,
|
||||
"issingle": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2014-10-03 14:55:44.916658",
|
||||
"modified": "2014-12-23 15:03:42.963697",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Stock Entry",
|
||||
|
@ -171,10 +171,20 @@ class StockEntry(StockController):
|
||||
if not self.production_order:
|
||||
frappe.throw(_("Production order number is mandatory for stock entry purpose manufacture"))
|
||||
# check for double entry
|
||||
self.check_if_operations_completed()
|
||||
self.check_duplicate_entry_for_production_order()
|
||||
elif self.purpose != "Material Transfer":
|
||||
self.production_order = None
|
||||
|
||||
def check_if_operations_completed(self):
|
||||
prod_order = frappe.get_doc("Production Order", self.production_order)
|
||||
if prod_order.actual_operating_cost:
|
||||
for d in prod_order.get("production_order_operations"):
|
||||
total_completed_qty = flt(self.fg_completed_qty) + flt(prod_order.produced_qty)
|
||||
if total_completed_qty > flt(d.completed_qty):
|
||||
frappe.throw(_("Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Production Order # {3}. Please update operation status via Time Logs")
|
||||
.format(d.idx, d.operation, total_completed_qty, self.production_order))
|
||||
|
||||
def check_duplicate_entry_for_production_order(self):
|
||||
other_ste = [t[0] for t in frappe.db.get_values("Stock Entry", {
|
||||
"production_order": self.production_order,
|
||||
@ -258,14 +268,28 @@ class StockEntry(StockController):
|
||||
for d in self.get("mtn_details"):
|
||||
if d.bom_no or (d.t_warehouse and number_of_fg_items == 1):
|
||||
if not flt(d.incoming_rate) or force:
|
||||
operation_cost_per_unit = 0
|
||||
if d.bom_no:
|
||||
bom = frappe.db.get_value("BOM", d.bom_no, ["operating_cost", "quantity"], as_dict=1)
|
||||
operation_cost_per_unit = flt(bom.operating_cost) / flt(bom.quantity)
|
||||
d.incoming_rate = operation_cost_per_unit + (raw_material_cost + flt(self.total_fixed_cost)) / flt(d.transfer_qty)
|
||||
operation_cost_per_unit = self.get_operation_cost_per_unit(d.bom_no, d.qty)
|
||||
d.incoming_rate = operation_cost_per_unit + (raw_material_cost / flt(d.transfer_qty))
|
||||
d.amount = flt(d.transfer_qty) * flt(d.incoming_rate)
|
||||
break
|
||||
|
||||
def get_operation_cost_per_unit(self, bom_no, qty):
|
||||
operation_cost_per_unit = 0
|
||||
|
||||
if self.production_order:
|
||||
pro_order = frappe.get_doc("Production Order", self.production_order)
|
||||
for d in pro_order.get("production_order_operations"):
|
||||
if flt(d.completed_qty):
|
||||
operation_cost_per_unit += flt(d.actual_operating_cost) / flt(d.completed_qty)
|
||||
else:
|
||||
operation_cost_per_unit += flt(d.planned_operating_cost) / flt(self.qty)
|
||||
|
||||
if not operation_cost_per_unit and bom_no:
|
||||
bom = frappe.db.get_value("BOM", bom_no, ["operating_cost", "quantity"], as_dict=1)
|
||||
operation_cost_per_unit = flt(bom.operating_cost) / flt(bom.quantity)
|
||||
|
||||
return operation_cost_per_unit + flt(self.additional_operating_cost) / flt(qty)
|
||||
|
||||
def get_incoming_rate(self, args):
|
||||
incoming_rate = 0
|
||||
if self.purpose == "Sales Return":
|
||||
@ -643,10 +667,12 @@ def get_party_details(ref_dt, ref_dn):
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_production_order_details(production_order):
|
||||
result = frappe.db.sql("""select bom_no,
|
||||
ifnull(qty, 0) - ifnull(produced_qty, 0) as fg_completed_qty, use_multi_level_bom,
|
||||
wip_warehouse from `tabProduction Order` where name = %s""", production_order, as_dict=1)
|
||||
return result and result[0] or {}
|
||||
res = frappe.db.sql("""select bom_no, use_multi_level_bom, wip_warehouse,
|
||||
ifnull(qty, 0) - ifnull(produced_qty, 0) as fg_completed_qty,
|
||||
(infull(additional_operating_cost, 0) / qty)*(ifnull(qty, 0) - ifnull(produced_qty, 0)) as additional_operating_cost
|
||||
from `tabProduction Order` where name = %s""", production_order, as_dict=1)
|
||||
|
||||
return res and res[0] or {}
|
||||
|
||||
def query_sales_return_doc(doctype, txt, searchfield, start, page_len, filters):
|
||||
conditions = ""
|
||||
|
@ -918,7 +918,7 @@ class TestStockEntry(unittest.TestCase):
|
||||
"production_order": production_order.name,
|
||||
"bom_no": bom_no,
|
||||
"fg_completed_qty": "1",
|
||||
"total_fixed_cost": 1000
|
||||
"additional_operating_cost": 1000
|
||||
})
|
||||
stock_entry.get_items()
|
||||
|
||||
|
@ -115,7 +115,7 @@ def get_item_bom_rate():
|
||||
|
||||
item_bom_map = {}
|
||||
|
||||
for b in frappe.db.sql("""select item, (total_variable_cost/quantity) as bom_rate
|
||||
for b in frappe.db.sql("""select item, (total_cost/quantity) as bom_rate
|
||||
from `tabBOM` where is_active=1 and is_default=1""", as_dict=1):
|
||||
item_bom_map.setdefault(b.item, flt(b.bom_rate))
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user