Operations added in Production Order DocType Auto-Fetch added to operations in Production Order DocType made operations in production order read-only capacity & duration of cycle added to workstation workstation operation timings added operation master added, Time log added Time Log Fixed Test Records added to Production Order Test Recorde for over Production Time Log added Validation added to check if time log timings are within working hours of the workstation. Validation added to check if workstation is closed on time log dates. Test Case added for Time Log
This commit is contained in:
parent
0a726e2335
commit
637d804abd
@ -27,6 +27,11 @@ def get_data():
|
||||
"name": "Workstation",
|
||||
"description": _("Where manufacturing operations are carried out."),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Operation",
|
||||
"description": _("Details of the operations carried out."),
|
||||
},
|
||||
|
||||
]
|
||||
},
|
||||
|
@ -5,11 +5,11 @@
|
||||
"holiday_list_details": [
|
||||
{
|
||||
"description": "New Year",
|
||||
"doctype": "Holiday",
|
||||
"holiday_date": "2013-01-01",
|
||||
"parent": "_Test Holiday List",
|
||||
"parentfield": "holiday_list_details",
|
||||
"parenttype": "Holiday List"
|
||||
"holiday_date": "2013-01-01"
|
||||
},
|
||||
{
|
||||
"description": "Test Holiday",
|
||||
"holiday_date": "2013-02-01"
|
||||
}
|
||||
],
|
||||
"holiday_list_name": "_Test Holiday List",
|
||||
|
@ -12,7 +12,7 @@ cur_frm.cscript.refresh = function(doc,dt,dn){
|
||||
}
|
||||
|
||||
cur_frm.cscript.with_operations(doc);
|
||||
erpnext.bom.set_operation_no(doc);
|
||||
erpnext.bom.set_operation(doc);
|
||||
}
|
||||
|
||||
cur_frm.cscript.update_cost = function() {
|
||||
@ -26,62 +26,41 @@ cur_frm.cscript.update_cost = function() {
|
||||
}
|
||||
|
||||
cur_frm.cscript.with_operations = function(doc) {
|
||||
cur_frm.fields_dict["bom_materials"].grid.set_column_disp("operation_no", doc.with_operations);
|
||||
cur_frm.fields_dict["bom_materials"].grid.toggle_reqd("operation_no", doc.with_operations);
|
||||
cur_frm.fields_dict["bom_materials"].grid.set_column_disp("operation", doc.with_operations);
|
||||
cur_frm.fields_dict["bom_materials"].grid.toggle_reqd("operation", doc.with_operations);
|
||||
}
|
||||
|
||||
cur_frm.cscript.operation_no = function(doc, cdt, cdn) {
|
||||
var child = locals[cdt][cdn];
|
||||
if(child.parentfield=="bom_operations") erpnext.bom.set_operation_no(doc);
|
||||
}
|
||||
|
||||
erpnext.bom.set_operation_no = function(doc) {
|
||||
erpnext.bom.set_operation = function(doc) {
|
||||
var op_table = doc.bom_operations || [];
|
||||
var operations = [];
|
||||
|
||||
for (var i=0, j=op_table.length; i<j; i++) {
|
||||
var op = op_table[i].operation_no;
|
||||
if (op && !inList(operations, op)) operations.push(op);
|
||||
operations[i] = (i+1);
|
||||
}
|
||||
|
||||
frappe.meta.get_docfield("BOM Item", "operation_no",
|
||||
frappe.meta.get_docfield("BOM Item", "operation",
|
||||
cur_frm.docname).options = operations.join("\n");
|
||||
|
||||
$.each(doc.bom_materials || [], function(i, v) {
|
||||
if(!inList(operations, cstr(v.operation_no))) v.operation_no = null;
|
||||
});
|
||||
|
||||
refresh_field("bom_materials");
|
||||
}
|
||||
|
||||
cur_frm.cscript.bom_operations_remove = function(){
|
||||
erpnext.bom.set_operation_no(doc);
|
||||
erpnext.bom.set_operation(doc);
|
||||
}
|
||||
|
||||
cur_frm.add_fetch("item", "description", "description");
|
||||
cur_frm.add_fetch("item", "stock_uom", "uom");
|
||||
|
||||
cur_frm.cscript.workstation = function(doc,dt,dn) {
|
||||
var d = locals[dt][dn];
|
||||
frappe.model.with_doc("Workstation", d.workstation, function(name, r) {
|
||||
d.hour_rate = r.docs[0].hour_rate;
|
||||
refresh_field("hour_rate", dn, "bom_operations");
|
||||
d.fixed_cycle_cost = r.docs[0].fixed_cycle_cost;
|
||||
refresh_field("fixed_cycle_cost", dn, "bom_operations");
|
||||
erpnext.bom.calculate_op_cost(doc);
|
||||
erpnext.bom.calculate_fixed_cost(doc);
|
||||
erpnext.bom.calculate_total(doc);
|
||||
});
|
||||
get_workstation_detail(doc,dt,dn);
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
cur_frm.cscript.time_in_mins = cur_frm.cscript.hour_rate;
|
||||
|
||||
cur_frm.cscript.item_code = function(doc, cdt, cdn) {
|
||||
@ -218,3 +197,29 @@ cur_frm.cscript.validate = function(doc, dt, dn) {
|
||||
erpnext.bom.calculate_total(doc);
|
||||
}
|
||||
|
||||
cur_frm.cscript.operation = function(doc,dt,dn) {
|
||||
var d = locals[dt][dn];
|
||||
|
||||
if(d.parentfield=="bom_operations") {
|
||||
erpnext.bom.set_operation(doc);
|
||||
frappe.model.with_doc("Operation", d.operation, function(name, r) {
|
||||
d.opn_description = r.docs[0].opn_description;
|
||||
d.workstation = r.docs[0].workstation;
|
||||
refresh_field("bom_operations");
|
||||
get_workstation_detail(doc,dt,dn);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var get_workstation_detail = function(doc, dt, dn) {
|
||||
var d = locals[dt][dn];
|
||||
frappe.model.with_doc("Workstation", d.workstation, function(name, r) {
|
||||
d.hour_rate = r.docs[0].hour_rate;
|
||||
refresh_field("hour_rate", dn, "bom_operations");
|
||||
d.fixed_cycle_cost = r.docs[0].fixed_cycle_cost;
|
||||
refresh_field("fixed_cycle_cost", dn, "bom_operations");
|
||||
erpnext.bom.calculate_op_cost(doc);
|
||||
erpnext.bom.calculate_fixed_cost(doc);
|
||||
erpnext.bom.calculate_total(doc);
|
||||
});
|
||||
}
|
||||
|
@ -27,7 +27,6 @@ class BOM(Document):
|
||||
from erpnext.utilities.transaction_base import validate_uom_is_integer
|
||||
validate_uom_is_integer(self, "stock_uom", "qty")
|
||||
|
||||
self.validate_operations()
|
||||
self.validate_materials()
|
||||
self.set_bom_material_details()
|
||||
self.calculate_cost()
|
||||
@ -171,7 +170,7 @@ class BOM(Document):
|
||||
if not self.with_operations:
|
||||
self.set('bom_operations', [])
|
||||
for d in self.get("bom_materials"):
|
||||
d.operation_no = None
|
||||
d.operation = None
|
||||
|
||||
def validate_main_item(self):
|
||||
""" Validate main FG item"""
|
||||
@ -183,23 +182,10 @@ class BOM(Document):
|
||||
self.description = ret[0]
|
||||
self.uom = ret[1]
|
||||
|
||||
def validate_operations(self):
|
||||
""" Check duplicate operation no"""
|
||||
self.op = []
|
||||
for d in self.get('bom_operations'):
|
||||
if cstr(d.operation_no) in self.op:
|
||||
frappe.throw(_("Operation {0} is repeated in Operations Table").format(d.operation_no))
|
||||
else:
|
||||
# add operation in op list
|
||||
self.op.append(cstr(d.operation_no))
|
||||
|
||||
def validate_materials(self):
|
||||
""" Validate raw material entries """
|
||||
check_list = []
|
||||
for m in self.get('bom_materials'):
|
||||
# check if operation no not in op table
|
||||
if self.with_operations and cstr(m.operation_no) not in self.op:
|
||||
frappe.throw(_("Operation {0} not present in Operations Table").format(m.operation_no))
|
||||
|
||||
if m.bom_no:
|
||||
validate_bom_no(m.item_code, m.bom_no)
|
||||
@ -207,7 +193,7 @@ class BOM(Document):
|
||||
if flt(m.qty) <= 0:
|
||||
frappe.throw(_("Quantity required for Item {0} in row {1}").format(m.item_code, m.idx))
|
||||
|
||||
self.check_if_item_repeated(m.item_code, m.operation_no, check_list)
|
||||
self.check_if_item_repeated(m.item_code, m.operation, check_list)
|
||||
|
||||
|
||||
def check_if_item_repeated(self, item, op, check_list):
|
||||
@ -426,4 +412,3 @@ def validate_bom_no(item, bom_no):
|
||||
if item and not (bom.item == item or \
|
||||
bom.item == frappe.db.get_value("Item", item, "variant_of")):
|
||||
frappe.throw(_("BOM {0} does not belong to Item {1}").format(bom_no, item))
|
||||
|
||||
|
@ -58,7 +58,7 @@
|
||||
{
|
||||
"bom_operations": [
|
||||
{
|
||||
"operation_no": "1",
|
||||
"operation": "_Test Operation 1",
|
||||
"opn_description": "_Test",
|
||||
"workstation": "_Test Workstation 1",
|
||||
"time_in_min": 60,
|
||||
@ -67,7 +67,7 @@
|
||||
],
|
||||
"bom_materials": [
|
||||
{
|
||||
"operation_no": 1,
|
||||
"operation": 1,
|
||||
"amount": 5000.0,
|
||||
"doctype": "BOM Item",
|
||||
"item_code": "_Test Item",
|
||||
@ -77,7 +77,7 @@
|
||||
"stock_uom": "_Test UOM"
|
||||
},
|
||||
{
|
||||
"operation_no": 1,
|
||||
"operation": 1,
|
||||
"amount": 2000.0,
|
||||
"bom_no": "BOM/_Test Item Home Desktop Manufactured/001",
|
||||
"doctype": "BOM Item",
|
||||
@ -99,7 +99,7 @@
|
||||
{
|
||||
"bom_operations": [
|
||||
{
|
||||
"operation_no": "1",
|
||||
"operation": "_Test Operation 1",
|
||||
"opn_description": "_Test",
|
||||
"workstation": "_Test Workstation 1",
|
||||
"time_in_min": 60,
|
||||
@ -108,7 +108,7 @@
|
||||
],
|
||||
"bom_materials": [
|
||||
{
|
||||
"operation_no": 1,
|
||||
"operation": 1,
|
||||
"amount": 5000.0,
|
||||
"doctype": "BOM Item",
|
||||
"item_code": "_Test Item",
|
||||
|
@ -1,147 +1,147 @@
|
||||
{
|
||||
"creation": "2013-02-22 01:27:49",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"creation": "2013-02-22 01:27:49",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "operation_no",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "Operation No",
|
||||
"oldfieldname": "operation_no",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0,
|
||||
"fieldname": "operation",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "Operation",
|
||||
"oldfieldname": "operation_no",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "item_code",
|
||||
"fieldtype": "Link",
|
||||
"in_filter": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Item Code",
|
||||
"oldfieldname": "item_code",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Item",
|
||||
"permlevel": 0,
|
||||
"reqd": 1,
|
||||
"fieldname": "item_code",
|
||||
"fieldtype": "Link",
|
||||
"in_filter": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Item Code",
|
||||
"oldfieldname": "item_code",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Item",
|
||||
"permlevel": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "bom_no",
|
||||
"fieldtype": "Link",
|
||||
"in_filter": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "BOM No",
|
||||
"oldfieldname": "bom_no",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "BOM",
|
||||
"permlevel": 0,
|
||||
"print_width": "150px",
|
||||
"reqd": 0,
|
||||
"search_index": 1,
|
||||
"fieldname": "bom_no",
|
||||
"fieldtype": "Link",
|
||||
"in_filter": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "BOM No",
|
||||
"oldfieldname": "bom_no",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "BOM",
|
||||
"permlevel": 0,
|
||||
"print_width": "150px",
|
||||
"reqd": 0,
|
||||
"search_index": 1,
|
||||
"width": "150px"
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "col_break1",
|
||||
"fieldtype": "Column Break",
|
||||
"fieldname": "col_break1",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Text",
|
||||
"label": "Item Description",
|
||||
"oldfieldname": "description",
|
||||
"oldfieldtype": "Text",
|
||||
"permlevel": 0,
|
||||
"print_width": "250px",
|
||||
"reqd": 0,
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Text",
|
||||
"label": "Item Description",
|
||||
"oldfieldname": "description",
|
||||
"oldfieldtype": "Text",
|
||||
"permlevel": 0,
|
||||
"print_width": "250px",
|
||||
"reqd": 0,
|
||||
"width": "250px"
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "quantity_and_rate",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Quantity and Rate",
|
||||
"fieldname": "quantity_and_rate",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Quantity and Rate",
|
||||
"permlevel": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "qty",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 1,
|
||||
"label": "Qty",
|
||||
"oldfieldname": "qty",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0,
|
||||
"fieldname": "qty",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 1,
|
||||
"label": "Qty",
|
||||
"oldfieldname": "qty",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0,
|
||||
"reqd": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"description": "See \"Rate Of Materials Based On\" in Costing Section",
|
||||
"fieldname": "rate",
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 1,
|
||||
"label": "Rate",
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"description": "See \"Rate Of Materials Based On\" in Costing Section",
|
||||
"fieldname": "rate",
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 1,
|
||||
"label": "Rate",
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"reqd": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "col_break2",
|
||||
"fieldtype": "Column Break",
|
||||
"fieldname": "col_break2",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "stock_uom",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 0,
|
||||
"label": "Stock UOM",
|
||||
"oldfieldname": "stock_uom",
|
||||
"oldfieldtype": "Data",
|
||||
"options": "UOM",
|
||||
"permlevel": 0,
|
||||
"read_only": 1,
|
||||
"fieldname": "stock_uom",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 0,
|
||||
"label": "Stock UOM",
|
||||
"oldfieldname": "stock_uom",
|
||||
"oldfieldtype": "Data",
|
||||
"options": "UOM",
|
||||
"permlevel": 0,
|
||||
"read_only": 1,
|
||||
"reqd": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "amount",
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 1,
|
||||
"label": "Amount",
|
||||
"oldfieldname": "amount_as_per_mar",
|
||||
"oldfieldtype": "Currency",
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"print_width": "150px",
|
||||
"read_only": 1,
|
||||
"fieldname": "amount",
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 1,
|
||||
"label": "Amount",
|
||||
"oldfieldname": "amount_as_per_mar",
|
||||
"oldfieldtype": "Currency",
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"print_width": "150px",
|
||||
"read_only": 1,
|
||||
"width": "150px"
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "scrap",
|
||||
"fieldtype": "Float",
|
||||
"label": "Scrap %",
|
||||
"oldfieldname": "scrap",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0,
|
||||
"fieldname": "scrap",
|
||||
"fieldtype": "Float",
|
||||
"label": "Scrap %",
|
||||
"oldfieldname": "scrap",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "qty_consumed_per_unit",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 1,
|
||||
"label": "Qty Consumed Per Unit",
|
||||
"oldfieldname": "qty_consumed_per_unit",
|
||||
"oldfieldtype": "Float",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"fieldname": "qty_consumed_per_unit",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 1,
|
||||
"label": "Qty Consumed Per Unit",
|
||||
"oldfieldname": "qty_consumed_per_unit",
|
||||
"oldfieldtype": "Float",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"modified": "2014-12-12 11:15:43.798755",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "BOM Item",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "modified",
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"modified": "2014-12-12 11:15:43.798755",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "BOM Item",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
}
|
||||
}
|
||||
|
@ -1,92 +1,94 @@
|
||||
{
|
||||
"creation": "2013-02-22 01:27:49",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"creation": "2013-02-22 01:27:49",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "operation_no",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Operation No",
|
||||
"oldfieldname": "operation_no",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0,
|
||||
"fieldname": "operation",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Operation",
|
||||
"oldfieldname": "operation_no",
|
||||
"oldfieldtype": "Data",
|
||||
"options": "Operation",
|
||||
"permlevel": 0,
|
||||
"reqd": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "opn_description",
|
||||
"fieldtype": "Text",
|
||||
"in_list_view": 1,
|
||||
"label": "Operation Description",
|
||||
"oldfieldname": "opn_description",
|
||||
"oldfieldtype": "Text",
|
||||
"permlevel": 0,
|
||||
"fieldname": "opn_description",
|
||||
"fieldtype": "Text",
|
||||
"in_list_view": 1,
|
||||
"label": "Operation Description",
|
||||
"oldfieldname": "opn_description",
|
||||
"oldfieldtype": "Text",
|
||||
"permlevel": 0,
|
||||
"reqd": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "col_break1",
|
||||
"fieldtype": "Column Break",
|
||||
"fieldname": "col_break1",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "workstation",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Workstation",
|
||||
"oldfieldname": "workstation",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Workstation",
|
||||
"permlevel": 0,
|
||||
"fieldname": "workstation",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Workstation",
|
||||
"oldfieldname": "workstation",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Workstation",
|
||||
"permlevel": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "hour_rate",
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 0,
|
||||
"label": "Hour Rate",
|
||||
"oldfieldname": "hour_rate",
|
||||
"oldfieldtype": "Currency",
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"fieldname": "hour_rate",
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 0,
|
||||
"label": "Hour Rate",
|
||||
"oldfieldname": "hour_rate",
|
||||
"oldfieldtype": "Currency",
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "time_in_mins",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 0,
|
||||
"label": "Operation Time (mins)",
|
||||
"oldfieldname": "time_in_mins",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0,
|
||||
"fieldname": "time_in_mins",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 0,
|
||||
"label": "Operation Time ",
|
||||
"oldfieldname": "time_in_mins",
|
||||
"oldfieldtype": "Currency",
|
||||
"options": "in min",
|
||||
"permlevel": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"fieldname": "operating_cost",
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 1,
|
||||
"label": "Operating Cost",
|
||||
"oldfieldname": "operating_cost",
|
||||
"oldfieldtype": "Currency",
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"allow_on_submit": 0,
|
||||
"fieldname": "operating_cost",
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 1,
|
||||
"label": "Operating Cost",
|
||||
"oldfieldname": "operating_cost",
|
||||
"oldfieldtype": "Currency",
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "fixed_cycle_cost",
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 0,
|
||||
"label": "Fixed Cycle Cost",
|
||||
"options": "Company:company:default_currency",
|
||||
"fieldname": "fixed_cycle_cost",
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 0,
|
||||
"label": "Fixed Cycle Cost",
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0
|
||||
}
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"modified": "2014-12-12 11:16:49.031521",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "BOM Operation",
|
||||
"owner": "Administrator",
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"modified": "2014-12-12 11:16:49.031521",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "BOM Operation",
|
||||
"owner": "Administrator",
|
||||
"permissions": []
|
||||
}
|
||||
}
|
||||
|
0
erpnext/manufacturing/doctype/operation/__init__.py
Normal file
0
erpnext/manufacturing/doctype/operation/__init__.py
Normal file
14
erpnext/manufacturing/doctype/operation/operation.js
Normal file
14
erpnext/manufacturing/doctype/operation/operation.js
Normal file
@ -0,0 +1,14 @@
|
||||
// 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');
|
98
erpnext/manufacturing/doctype/operation/operation.json
Normal file
98
erpnext/manufacturing/doctype/operation/operation.json
Normal file
@ -0,0 +1,98 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"autoname": "field:operation",
|
||||
"creation": "2014-11-07 16:20:30.683186",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Master",
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"fieldname": "operation",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Operation",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_2",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"fieldname": "workstation",
|
||||
"fieldtype": "Link",
|
||||
"label": "Default Workstation",
|
||||
"options": "Workstation",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_4",
|
||||
"fieldtype": "Section Break",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"fieldname": "opn_description",
|
||||
"fieldtype": "Text",
|
||||
"label": "Operation Description",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
}
|
||||
],
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"icon": "icon-wrench",
|
||||
"in_create": 0,
|
||||
"in_dialog": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"modified": "2014-11-12 15:29:01.766553",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "Operation",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 0,
|
||||
"export": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 0,
|
||||
"read": 1,
|
||||
"report": 0,
|
||||
"role": "All",
|
||||
"set_user_permissions": 0,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
}
|
14
erpnext/manufacturing/doctype/operation/operation.py
Normal file
14
erpnext/manufacturing/doctype/operation/operation.py
Normal file
@ -0,0 +1,14 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
class Operation(Document):
|
||||
def calculate_op_cost(self):
|
||||
if self.hour_rate and self.time_in_mins:
|
||||
self.operating_cost = flt(self.hour_rate) * flt(self.time_in_mins) / 60.0
|
||||
else :
|
||||
self.operating_cost = 0
|
||||
|
10
erpnext/manufacturing/doctype/operation/test_operation.py
Normal file
10
erpnext/manufacturing/doctype/operation/test_operation.py
Normal file
@ -0,0 +1,10 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors and Contributors
|
||||
# See license.txt
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
|
||||
test_records = frappe.get_test_records('Operation')
|
||||
|
||||
class TestOperation(unittest.TestCase):
|
||||
pass
|
@ -0,0 +1,7 @@
|
||||
[
|
||||
{
|
||||
"doctype": "Operation",
|
||||
"operation": "_Test Operation 1",
|
||||
"workstation": "_Test Workstation 1"
|
||||
}
|
||||
]
|
@ -53,7 +53,37 @@ $.extend(cur_frm.cscript, {
|
||||
frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
bom_no: function() {
|
||||
return this.frm.call({
|
||||
doc: this.frm.doc,
|
||||
method: "get_production_order_operations",
|
||||
callback: function(r) {
|
||||
if(!r.exc) refresh_field("get_production_order_operations");
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
make_time_log: function(doc, cdt, cdn){
|
||||
var child = locals[cdt][cdn]
|
||||
frappe.call({
|
||||
method:"erpnext.manufacturing.doctype.production_order.production_order.make_time_log",
|
||||
args: {
|
||||
"name": doc.name,
|
||||
"operation": child.idx + ". " + child.operation,
|
||||
"from_time": child.planned_start_time,
|
||||
"to_time": child.planned_end_time,
|
||||
"project": doc.project,
|
||||
"qty": doc.qty - child.qty_completed,
|
||||
"workstation": child.workstation
|
||||
},
|
||||
callback: function(r) {
|
||||
var doclist = frappe.model.sync(r.message);
|
||||
frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
var cfn_set_fields = function(doc, dt, dn) {
|
||||
|
@ -102,13 +102,7 @@
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "production_item",
|
||||
"fieldname": "total_fixed_cost",
|
||||
"fieldtype": "Float",
|
||||
"label": "Total Fixed Cost",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "eval:doc.docstatus==1",
|
||||
"description": "Automatically updated via Stock Entry of type Manufacture or Repack",
|
||||
"fieldname": "produced_qty",
|
||||
@ -121,12 +115,26 @@
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "sales_order",
|
||||
"fieldname": "time",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Time",
|
||||
"options": "icon-time",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"depends_on": "",
|
||||
"fieldname": "expected_delivery_date",
|
||||
"fieldtype": "Date",
|
||||
"label": "Expected Delivery Date",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
"read_only": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_13",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"fieldname": "start_date",
|
||||
@ -174,6 +182,31 @@
|
||||
"permlevel": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
{
|
||||
"depends_on": "bom_no",
|
||||
"fieldname": "operations",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Operations",
|
||||
"options": "icon-wrench",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"depends_on": "production_item",
|
||||
"fieldname": "total_fixed_cost",
|
||||
"fieldtype": "Float",
|
||||
"label": "Total Fixed Cost",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "production_order_operations",
|
||||
"fieldtype": "Table",
|
||||
"label": "Production Order Operations",
|
||||
"options": "Production Order Operation",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "more_info",
|
||||
"fieldtype": "Section Break",
|
||||
@ -246,7 +279,7 @@
|
||||
"idx": 1,
|
||||
"in_create": 0,
|
||||
"is_submittable": 1,
|
||||
"modified": "2014-10-27 13:42:31.476892",
|
||||
"modified": "2014-11-07 15:04:01.242315",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "Production Order",
|
||||
|
@ -2,7 +2,7 @@
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe, json
|
||||
import frappe, json, time, datetime
|
||||
|
||||
from frappe.utils import flt, nowdate
|
||||
from frappe import _
|
||||
@ -145,6 +145,19 @@ class ProductionOrder(Document):
|
||||
from erpnext.stock.utils import update_bin
|
||||
update_bin(args)
|
||||
|
||||
def get_production_order_operations(self):
|
||||
self.set('production_order_operations', [])
|
||||
operations = frappe.db.sql("""select operation, opn_description, workstation, hour_rate, time_in_mins,
|
||||
operating_cost, fixed_cycle_cost from `tabBOM Operation` where parent = %s""", self.bom_no, as_dict=1)
|
||||
self.set('production_order_operations', operations)
|
||||
|
||||
for d in self.get('production_order_operations'):
|
||||
d.status = "Pending"
|
||||
d.qty_completed=0
|
||||
|
||||
def auto_caluclate_production_dates(self):
|
||||
pass
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_item_details(item):
|
||||
res = frappe.db.sql("""select stock_uom, description
|
||||
@ -205,3 +218,17 @@ def get_events(start, end, filters=None):
|
||||
"end": end
|
||||
}, as_dict=True, update={"allDay": 0})
|
||||
return data
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_time_log(name, operation, from_time=None, to_time=None, 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
|
||||
time_log.to_time = to_time
|
||||
time_log.production_order = name
|
||||
time_log.project = project
|
||||
time_log.operation= operation
|
||||
time_log.qty= qty
|
||||
time_log.workstation= workstation
|
||||
time_log.calculate_total_hours()
|
||||
return time_log
|
@ -58,4 +58,59 @@ class TestProductionOrder(unittest.TestCase):
|
||||
|
||||
self.assertRaises(StockOverProductionError, s.submit)
|
||||
|
||||
def test_make_time_log(self):
|
||||
prod_order = frappe.get_doc({
|
||||
"doctype":"Production Order",
|
||||
"production_item": "_Test FG Item 2",
|
||||
"bom_no": "BOM/_Test FG Item 2/002",
|
||||
"qty": 1
|
||||
})
|
||||
|
||||
|
||||
prod_order.get_production_order_operations()
|
||||
prod_order.production_order_operations[0].update({
|
||||
"planned_start_time": "2014-11-25 00:00:00",
|
||||
"planned_end_time": "2014-11-25 10:00:00"
|
||||
})
|
||||
|
||||
prod_order.insert()
|
||||
|
||||
d = prod_order.production_order_operations[0]
|
||||
|
||||
from erpnext.manufacturing.doctype.production_order.production_order import make_time_log
|
||||
from frappe.utils import cstr
|
||||
from frappe.utils import time_diff_in_hours
|
||||
|
||||
time_log = make_time_log( prod_order.name, cstr(d.idx) + ". " + d.operation, \
|
||||
d.planned_start_time, d.planned_end_time, prod_order.qty - d.qty_completed)
|
||||
|
||||
self.assertEqual(prod_order.name, time_log.production_order)
|
||||
self.assertEqual((prod_order.qty - d.qty_completed), time_log.qty)
|
||||
self.assertEqual(time_diff_in_hours(d.planned_end_time, d.planned_start_time),time_log.hours)
|
||||
|
||||
time_log.save()
|
||||
time_log.submit()
|
||||
|
||||
prod_order.load_from_db()
|
||||
self.assertEqual(prod_order.production_order_operations[0].status, "Completed")
|
||||
self.assertEqual(prod_order.production_order_operations[0].qty_completed, prod_order.qty)
|
||||
|
||||
self.assertEqual(prod_order.production_order_operations[0].actual_start_time, time_log.from_time)
|
||||
self.assertEqual(prod_order.production_order_operations[0].actual_end_time, time_log.to_time)
|
||||
|
||||
time_log.cancel()
|
||||
|
||||
prod_order.load_from_db()
|
||||
self.assertEqual(prod_order.production_order_operations[0].status,"Pending")
|
||||
self.assertEqual(prod_order.production_order_operations[0].qty_completed,0)
|
||||
|
||||
time_log2 = frappe.copy_doc(time_log)
|
||||
time_log2.update({
|
||||
"qty": 10,
|
||||
"from_time": "2014-11-26 00:00:00",
|
||||
"to_time": "2014-11-26 00:00:00",
|
||||
"docstatus": 0
|
||||
})
|
||||
self.assertRaises(frappe.ValidationError, time_log2.save)
|
||||
|
||||
test_records = frappe.get_test_records('Production Order')
|
||||
|
@ -0,0 +1,290 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"creation": "2014-10-16 14:35:41.950175",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "details",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Details",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"fieldname": "operation",
|
||||
"fieldtype": "Text",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Operation",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "operation_no",
|
||||
"oldfieldtype": "Data",
|
||||
"options": "",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"fieldname": "opn_description",
|
||||
"fieldtype": "Text",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Operation Description",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "opn_description",
|
||||
"oldfieldtype": "Text",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"fieldname": "col_break1",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"default": "Pending",
|
||||
"fieldname": "status",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "Status",
|
||||
"options": "Pending\nWork in Progress\nCompleted",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "qty_completed",
|
||||
"fieldtype": "Float",
|
||||
"label": "Qty Completed",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"fieldname": "workstation",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Workstation",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "workstation",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Workstation",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "cost",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Cost",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"fieldname": "hour_rate",
|
||||
"fieldtype": "Float",
|
||||
"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": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"fieldname": "time_in_mins",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Operation Time (mins)",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "time_in_mins",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_10",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"description": "Hour rate * hours",
|
||||
"fieldname": "operating_cost",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Operating Cost",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "operating_cost",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"fieldname": "fixed_cycle_cost",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Fixed Cycle Cost",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_9",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Time",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"fieldname": "planned_start_time",
|
||||
"fieldtype": "Datetime",
|
||||
"label": "Planned Start Time",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"fieldname": "planned_end_time",
|
||||
"fieldtype": "Datetime",
|
||||
"label": "Planned End Time",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_11",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"fieldname": "actual_start_time",
|
||||
"fieldtype": "Datetime",
|
||||
"label": "Actual Start Time",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"fieldname": "actual_end_time",
|
||||
"fieldtype": "Datetime",
|
||||
"label": "Actual End Time",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"fieldname": "make_time_log",
|
||||
"fieldtype": "Button",
|
||||
"label": "Make Time Log",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
}
|
||||
],
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"in_create": 0,
|
||||
"in_dialog": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2014-11-13 16:47:31.015973",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "Production Order Operation",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
class ProductionOrderOperation(Document):
|
||||
pass
|
@ -5,6 +5,12 @@
|
||||
"workstation_name": "_Test Workstation 1",
|
||||
"warehouse": "_Test warehouse - _TC",
|
||||
"fixed_cycle_cost": 1000,
|
||||
"hour_rate":100
|
||||
"hour_rate":100,
|
||||
"workstation_operation_hours": [
|
||||
{
|
||||
"start_time": "10:00:00",
|
||||
"end_time": "20:00:00"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
@ -9,4 +9,7 @@ test_records = frappe.get_test_records('Workstation')
|
||||
|
||||
|
||||
class TestWorkstation(unittest.TestCase):
|
||||
pass
|
||||
|
||||
def test_validate_timings(self):
|
||||
wks = frappe.get_doc("Workstation", "_Test Workstation 1")
|
||||
self.assertEqual(1,wks.check_workstation_for_operation_time("2013-02-01 05:00:00", "2013-02-02 20:00:00"))
|
||||
|
@ -1,161 +1,183 @@
|
||||
{
|
||||
"allow_import": 1,
|
||||
"allow_rename": 1,
|
||||
"autoname": "field:workstation_name",
|
||||
"creation": "2013-01-10 16:34:17",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Master",
|
||||
"allow_import": 1,
|
||||
"allow_rename": 1,
|
||||
"autoname": "field:workstation_name",
|
||||
"creation": "2013-01-10 16:34:17",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Master",
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "workstation_name",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Workstation Name",
|
||||
"oldfieldname": "workstation_name",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0,
|
||||
"reqd": 1
|
||||
},
|
||||
"fieldname": "description_and_warehouse",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Description and Warehouse",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"fieldname": "warehouse",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Warehouse",
|
||||
"oldfieldname": "warehouse",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Warehouse",
|
||||
"permlevel": 0,
|
||||
"fieldname": "workstation_name",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Workstation Name",
|
||||
"oldfieldname": "workstation_name",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0,
|
||||
"reqd": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Text",
|
||||
"in_list_view": 1,
|
||||
"label": "Description",
|
||||
"oldfieldname": "description",
|
||||
"oldfieldtype": "Text",
|
||||
"permlevel": 0,
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Text",
|
||||
"in_list_view": 1,
|
||||
"label": "Description",
|
||||
"oldfieldname": "description",
|
||||
"oldfieldtype": "Text",
|
||||
"permlevel": 0,
|
||||
"width": "300px"
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "capacity",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Capacity",
|
||||
"oldfieldname": "capacity",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
"fieldname": "column_break_4",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"fieldname": "capacity_units",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Capacity Units",
|
||||
"oldfieldname": "capacity_units",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "\nUnits/Shifts\nUnits/Hour",
|
||||
"permlevel": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
"fieldname": "warehouse",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Warehouse",
|
||||
"oldfieldname": "warehouse",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Warehouse",
|
||||
"permlevel": 0,
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "fixed_cycle_cost",
|
||||
"fieldtype": "Float",
|
||||
"label": "Fixed Cycle Cost",
|
||||
"fieldname": "fixed_costs",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Fixed Costs",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"fieldname": "fixed_cycle_cost",
|
||||
"fieldtype": "Float",
|
||||
"label": "Fixed Cycle Cost",
|
||||
"permlevel": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "hour_rate_labour",
|
||||
"fieldtype": "Float",
|
||||
"label": "Hour Rate Labour",
|
||||
"oldfieldname": "hour_rate_labour",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "over_heads",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Overheads",
|
||||
"oldfieldtype": "Section Break",
|
||||
"fieldname": "over_heads",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Operating Costs",
|
||||
"oldfieldtype": "Section Break",
|
||||
"permlevel": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"description": "Electricity cost per hour",
|
||||
"fieldname": "hour_rate_electricity",
|
||||
"fieldtype": "Float",
|
||||
"label": "Electricity Cost",
|
||||
"oldfieldname": "hour_rate_electricity",
|
||||
"oldfieldtype": "Currency",
|
||||
"description": "per hour",
|
||||
"fieldname": "hour_rate_electricity",
|
||||
"fieldtype": "Float",
|
||||
"label": "Electricity Cost",
|
||||
"oldfieldname": "hour_rate_electricity",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"description": "Consumable cost per hour",
|
||||
"fieldname": "hour_rate_consumable",
|
||||
"fieldtype": "Float",
|
||||
"label": "Consumable Cost",
|
||||
"oldfieldname": "hour_rate_consumable",
|
||||
"oldfieldtype": "Currency",
|
||||
"description": "per hour",
|
||||
"fieldname": "hour_rate_consumable",
|
||||
"fieldtype": "Float",
|
||||
"label": "Consumable Cost",
|
||||
"oldfieldname": "hour_rate_consumable",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"description": "Rent per hour",
|
||||
"fieldname": "hour_rate_rent",
|
||||
"fieldtype": "Float",
|
||||
"label": "Rent Cost",
|
||||
"oldfieldname": "hour_rate_rent",
|
||||
"oldfieldtype": "Currency",
|
||||
"description": "per hour",
|
||||
"fieldname": "hour_rate_rent",
|
||||
"fieldtype": "Float",
|
||||
"label": "Rent Cost",
|
||||
"oldfieldname": "hour_rate_rent",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "overhead",
|
||||
"fieldtype": "Float",
|
||||
"label": "Overhead",
|
||||
"oldfieldname": "overhead",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0,
|
||||
"fieldname": "column_break_11",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"description": "per hour",
|
||||
"fieldname": "overhead",
|
||||
"fieldtype": "Float",
|
||||
"label": "Total Operating Cost",
|
||||
"oldfieldname": "overhead",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "hour_rate_section_break",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Hour Rate",
|
||||
"oldfieldtype": "Section Break",
|
||||
"permlevel": 0
|
||||
},
|
||||
"description": "Wages per hour",
|
||||
"fieldname": "hour_rate_labour",
|
||||
"fieldtype": "Float",
|
||||
"label": "Wages",
|
||||
"oldfieldname": "hour_rate_labour",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "hour_rate",
|
||||
"fieldtype": "Float",
|
||||
"label": "Hour Rate",
|
||||
"oldfieldname": "hour_rate",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0,
|
||||
"description": "per hour",
|
||||
"fieldname": "hour_rate",
|
||||
"fieldtype": "Float",
|
||||
"label": "Net Hour Rate",
|
||||
"oldfieldname": "hour_rate",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "operation_timings",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Operation Timings",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"fieldname": "workstation_operation_hours",
|
||||
"fieldtype": "Table",
|
||||
"label": "Workstation Operation Hours",
|
||||
"options": "Workstation Operation Hours",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"fieldname": "holiday_list",
|
||||
"fieldtype": "Link",
|
||||
"label": "Holiday List",
|
||||
"options": "Holiday List",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
}
|
||||
],
|
||||
"icon": "icon-wrench",
|
||||
"idx": 1,
|
||||
"modified": "2014-09-15 10:59:07.960814",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "Workstation",
|
||||
"owner": "Administrator",
|
||||
],
|
||||
"icon": "icon-wrench",
|
||||
"idx": 1,
|
||||
"modified": "2014-11-07 11:39:37.720913",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "Workstation",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"apply_user_permissions": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Manufacturing User",
|
||||
"submit": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Manufacturing User",
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
@ -3,6 +3,8 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
import datetime
|
||||
from frappe import _
|
||||
from frappe.utils import flt
|
||||
|
||||
from frappe.model.document import Document
|
||||
@ -20,4 +22,36 @@ class Workstation(Document):
|
||||
frappe.db.set(self, 'overhead', 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.overhead))
|
||||
self.update_bom_operation()
|
||||
self.update_bom_operation()
|
||||
|
||||
def check_if_within_operating_hours(self, from_time, to_time):
|
||||
if self.check_workstation_for_operation_time(from_time, to_time):
|
||||
frappe.msgprint(_("Warning: Time Log timings outside workstation Operating Hours !"))
|
||||
|
||||
msg = self.check_workstation_for_holiday(from_time, to_time)
|
||||
if msg != None:
|
||||
frappe.msgprint(msg)
|
||||
|
||||
def check_workstation_for_operation_time(self, from_time, to_time):
|
||||
start_time = datetime.datetime.strptime(from_time,'%Y-%m-%d %H:%M:%S').strftime('%H:%M:%S')
|
||||
end_time = datetime.datetime.strptime(to_time,'%Y-%m-%d %H:%M:%S').strftime('%H:%M:%S')
|
||||
|
||||
if frappe.db.sql("""select start_time, end_time from `tabWorkstation Operation Hours`
|
||||
where parent = %s and (%s <start_time or %s > end_time )""",(self.workstation_name, start_time, end_time), as_dict=1):
|
||||
return 1
|
||||
|
||||
def check_workstation_for_holiday(self, from_time, to_time):
|
||||
holiday_list = frappe.db.get_value("Workstation", self.workstation_name, "holiday_list")
|
||||
start_date = datetime.datetime.strptime(from_time,'%Y-%m-%d %H:%M:%S').strftime('%Y-%m-%d')
|
||||
end_date = datetime.datetime.strptime(to_time,'%Y-%m-%d %H:%M:%S').strftime('%Y-%m-%d')
|
||||
msg = _("Workstation is closed on the following dates as per Holiday List:")
|
||||
flag = 0
|
||||
for d in frappe.db.sql("""select holiday_date from `tabHoliday` where parent = %s and holiday_date between
|
||||
%s and %s """,(holiday_list, start_date, end_date), as_dict=1):
|
||||
flag = 1
|
||||
msg = msg + "\n" + d.holiday_date
|
||||
|
||||
if flag ==1:
|
||||
return msg
|
||||
else:
|
||||
return None
|
@ -0,0 +1,76 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"creation": "2014-10-29 13:00:43.921508",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"fieldname": "start_time",
|
||||
"fieldtype": "Time",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Start Time",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_2",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"fieldname": "end_time",
|
||||
"fieldtype": "Time",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "End Time",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"in_create": 0,
|
||||
"in_dialog": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2014-10-29 13:02:24.631554",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "Workstation Operation Hours",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
class WorkstationOperationHours(Document):
|
||||
pass
|
@ -16,6 +16,6 @@ class TestTimeLog(unittest.TestCase):
|
||||
self.assertRaises(OverlapError, ts.insert)
|
||||
|
||||
frappe.db.sql("delete from `tabTime Log`")
|
||||
|
||||
|
||||
test_records = frappe.get_test_records('Time Log')
|
||||
test_ignore = ["Time Log Batch", "Sales Invoice"]
|
||||
|
@ -27,3 +27,36 @@ frappe.ui.form.on("Time Log", "to_time", function(frm) {
|
||||
});
|
||||
|
||||
cur_frm.add_fetch('task','project','project');
|
||||
|
||||
$.extend(cur_frm.cscript, {
|
||||
production_order: function(doc) {
|
||||
if (doc.production_order){
|
||||
var operations = [];
|
||||
frappe.model.with_doc("Production Order", doc.production_order, function(pro) {
|
||||
doc = frappe.get_doc("Production Order",pro);
|
||||
$.each(doc.production_order_operations , function(i, row){
|
||||
operations[i] = (i+1) +". "+ row.operation;
|
||||
});
|
||||
frappe.meta.get_docfield("Time Log", "operation", me.frm.doc.name).options = operations.join("\n");
|
||||
refresh_field("operation");
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
operation: function(doc) {
|
||||
return cur_frm.call({
|
||||
method: "erpnext.projects.doctype.time_log.time_log.get_workstation",
|
||||
args: {
|
||||
"production_order": doc.production_order,
|
||||
"operation": doc.operation
|
||||
},
|
||||
callback: function(r) {
|
||||
doc.workstation = r.workstation;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if (cur_frm.doc.time_log_for == "Manufacturing") {
|
||||
cur_frm.cscript.onload = cur_frm.cscript.production_order;
|
||||
}
|
@ -16,6 +16,15 @@
|
||||
"read_only": 0,
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "time_log_for",
|
||||
"fieldtype": "Select",
|
||||
"label": "Time Log For",
|
||||
"options": "Project\nManufacturing",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "from_time",
|
||||
"fieldtype": "Datetime",
|
||||
@ -59,6 +68,7 @@
|
||||
"reqd": 0
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.time_log_for == 'Project'",
|
||||
"fieldname": "activity_type",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
@ -66,9 +76,10 @@
|
||||
"options": "Activity Type",
|
||||
"permlevel": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 1
|
||||
"reqd": 0
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.time_log_for == 'Project'",
|
||||
"fieldname": "task",
|
||||
"fieldtype": "Link",
|
||||
"label": "Task",
|
||||
@ -76,6 +87,41 @@
|
||||
"permlevel": 0,
|
||||
"read_only": 0
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.time_log_for == 'Manufacturing'",
|
||||
"fieldname": "production_order",
|
||||
"fieldtype": "Link",
|
||||
"label": "Production Order",
|
||||
"options": "Production Order",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.time_log_for == 'Manufacturing'",
|
||||
"fieldname": "operation",
|
||||
"fieldtype": "Select",
|
||||
"label": "Operation",
|
||||
"options": "",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.time_log_for == 'Manufacturing'",
|
||||
"fieldname": "workstation",
|
||||
"fieldtype": "Link",
|
||||
"label": "Workstation",
|
||||
"options": "Workstation",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.time_log_for == 'Manufacturing'",
|
||||
"fieldname": "qty",
|
||||
"fieldtype": "Float",
|
||||
"label": "Quantity",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"fieldname": "billable",
|
||||
"fieldtype": "Check",
|
||||
@ -151,7 +197,7 @@
|
||||
"icon": "icon-time",
|
||||
"idx": 1,
|
||||
"is_submittable": 1,
|
||||
"modified": "2014-10-22 16:53:26.993828",
|
||||
"modified": "2014-11-19 11:39:02.633802",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Projects",
|
||||
"name": "Time Log",
|
||||
|
@ -6,7 +6,8 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils import cstr, comma_and
|
||||
from frappe.utils import cstr, cint, comma_and
|
||||
|
||||
|
||||
|
||||
class OverlapError(frappe.ValidationError): pass
|
||||
@ -19,6 +20,14 @@ class TimeLog(Document):
|
||||
self.set_status()
|
||||
self.validate_overlap()
|
||||
self.calculate_total_hours()
|
||||
self.check_workstation_timings()
|
||||
self.validate_qty()
|
||||
|
||||
def on_submit(self):
|
||||
self.update_production_order()
|
||||
|
||||
def on_cancel(self):
|
||||
self.update_production_order_on_cancel()
|
||||
|
||||
def calculate_total_hours(self):
|
||||
from frappe.utils import time_diff_in_hours
|
||||
@ -59,6 +68,72 @@ class TimeLog(Document):
|
||||
def before_update_after_submit(self):
|
||||
self.set_status()
|
||||
|
||||
def update_production_order(self):
|
||||
if self.time_log_for=="Manufacturing" and self.operation:
|
||||
d = self.get_qty_and_status()
|
||||
required_qty = cint(frappe.db.get_value("Production Order" , self.production_order, "qty"))
|
||||
if d.get('qty') == required_qty:
|
||||
d['status'] = "Completed"
|
||||
|
||||
dates = self.get_production_dates()
|
||||
if self.from_time < dates.start_date:
|
||||
dates.start_date = self.from_time
|
||||
if self.to_time > dates.end_date:
|
||||
dates.end_date = self.to_time
|
||||
|
||||
self.production_order_update(dates, d.get('qty'), d['status'])
|
||||
|
||||
def update_production_order_on_cancel(self):
|
||||
if self.time_log_for=="Manufacturing" and self.operation:
|
||||
d = frappe._dict()
|
||||
d = self.get_qty_and_status()
|
||||
dates = self.get_production_dates()
|
||||
self.production_order_update(dates, d.get('qty'), d.get('status'))
|
||||
|
||||
def get_qty_and_status(self):
|
||||
status = "Work in Progress"
|
||||
qty = cint(frappe.db.sql("""select sum(qty) as qty from `tabTime Log` where production_order = %s
|
||||
and operation = %s and docstatus=1""", (self.production_order, self.operation),as_dict=1)[0].qty)
|
||||
if qty == 0:
|
||||
status = "Pending"
|
||||
return {
|
||||
"qty": qty,
|
||||
"status": status
|
||||
}
|
||||
|
||||
def get_production_dates(self):
|
||||
return frappe.db.sql("""select min(from_time) as start_date, max(to_time) as end_date from `tabTime Log`
|
||||
where production_order = %s and operation = %s and docstatus=1""",
|
||||
(self.production_order, self.operation), as_dict=1)[0]
|
||||
|
||||
def production_order_update(self, dates, qty, status):
|
||||
d = self.operation.split('. ',1)
|
||||
frappe.db.sql("""update `tabProduction Order Operation` set actual_start_time = %s, actual_end_time = %s,
|
||||
qty_completed = %s, status = %s where idx=%s and parent=%s and operation = %s """,
|
||||
(dates.start_date, dates.end_date, qty, status, d[0], self.production_order, d[1] ))
|
||||
|
||||
def check_workstation_timings(self):
|
||||
if self.workstation:
|
||||
frappe.get_doc("Workstation", self.workstation).check_if_within_operating_hours(self.from_time, self.to_time)
|
||||
|
||||
def validate_qty(self):
|
||||
if self.qty == None:
|
||||
self.qty=0
|
||||
required_qty = cint(frappe.db.get_value("Production Order" , self.production_order, "qty"))
|
||||
completed_qty = self.get_qty_and_status().get('qty')
|
||||
if (completed_qty + cint(self.qty)) > required_qty:
|
||||
frappe.throw(_("Quantity cannot be greater than pending quantity that is {0}").format(required_qty))
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_workstation(production_order, operation):
|
||||
if operation:
|
||||
d = operation.split('. ',1)
|
||||
idx = d[0]
|
||||
operation = d[1]
|
||||
|
||||
return frappe.db.sql("""select workstation from `tabProduction Order Operation` where idx=%s and
|
||||
parent=%s and operation = %s""", (idx, production_order, operation), as_dict=1)[0]
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_events(start, end):
|
||||
from frappe.desk.reportview import build_match_conditions
|
||||
|
@ -82,10 +82,10 @@ class Company(Document):
|
||||
|
||||
def create_default_accounts(self):
|
||||
if not self.chart_of_accounts:
|
||||
frappe.throw(_("Please select Chart of Accounts"))
|
||||
else:
|
||||
from erpnext.accounts.doctype.account.chart_of_accounts.chart_of_accounts import create_charts
|
||||
create_charts(self.chart_of_accounts, self.name)
|
||||
self.chart_of_accounts = "Standard"
|
||||
|
||||
from erpnext.accounts.doctype.account.chart_of_accounts.chart_of_accounts import create_charts
|
||||
create_charts(self.chart_of_accounts, self.name)
|
||||
|
||||
frappe.db.set(self, "default_receivable_account", frappe.db.get_value("Account",
|
||||
{"company": self.name, "account_type": "Receivable"}))
|
||||
|
Loading…
Reference in New Issue
Block a user