time log and workstations
This commit is contained in:
parent
0f4350dd61
commit
0de6256bcc
@ -9,33 +9,26 @@
|
|||||||
"document_type": "Master",
|
"document_type": "Master",
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"allow_on_submit": 0,
|
"description": "Will not allow to make time logs outside \"Workstation operation timings\"",
|
||||||
"default": "30",
|
"fieldname": "dont_allow_overtime",
|
||||||
"description": "Maximum Overtime allowed against an workstation.\n( in mins )",
|
"fieldtype": "Check",
|
||||||
"fieldname": "max_overtime",
|
"label": "Don't allow overtime",
|
||||||
"fieldtype": "Float",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 1,
|
|
||||||
"label": "Maximum Overtime",
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
"precision": ""
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "No",
|
"default": "",
|
||||||
"fieldname": "allow_production_on_holidays",
|
"fieldname": "allow_production_on_holidays",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Check",
|
||||||
|
"in_list_view": 1,
|
||||||
"label": "Allow Production on Holidays",
|
"label": "Allow Production on Holidays",
|
||||||
"options": "Yes\nNo",
|
"options": "",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_3",
|
||||||
|
"fieldtype": "Column Break",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": ""
|
"precision": ""
|
||||||
},
|
},
|
||||||
@ -44,6 +37,7 @@
|
|||||||
"description": "Delay in start time of production order operations if automatically make time logs is used.\n(in mins)",
|
"description": "Delay in start time of production order operations if automatically make time logs is used.\n(in mins)",
|
||||||
"fieldname": "operations_start_delay",
|
"fieldname": "operations_start_delay",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
|
"in_list_view": 1,
|
||||||
"label": "Operations Start Delay",
|
"label": "Operations Start Delay",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": ""
|
"precision": ""
|
||||||
@ -57,7 +51,7 @@
|
|||||||
"is_submittable": 0,
|
"is_submittable": 0,
|
||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"modified": "2014-12-18 16:22:26.052642",
|
"modified": "2014-12-22 12:43:15.261503",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "Manufacturing Settings",
|
"name": "Manufacturing Settings",
|
||||||
|
@ -122,6 +122,20 @@
|
|||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"read_only": 0
|
"read_only": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "planned_start_date",
|
||||||
|
"fieldtype": "Datetime",
|
||||||
|
"label": "Planned Start Date",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "planned_end_date",
|
||||||
|
"fieldtype": "Datetime",
|
||||||
|
"label": "Planned End Date",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": ""
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "column_break_13",
|
"fieldname": "column_break_13",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break",
|
||||||
@ -129,18 +143,20 @@
|
|||||||
"precision": ""
|
"precision": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "production_start_date",
|
"fieldname": "actual_start_date",
|
||||||
"fieldtype": "Datetime",
|
"fieldtype": "Datetime",
|
||||||
"label": "Production Start Date",
|
"label": "Actual Start Date",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": ""
|
"precision": "",
|
||||||
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "production_end_date",
|
"fieldname": "actual_end_date",
|
||||||
"fieldtype": "Datetime",
|
"fieldtype": "Datetime",
|
||||||
"label": "Production End Date",
|
"label": "Actual End Date",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": ""
|
"precision": "",
|
||||||
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "warehouses",
|
"fieldname": "warehouses",
|
||||||
@ -331,7 +347,7 @@
|
|||||||
"idx": 1,
|
"idx": 1,
|
||||||
"in_create": 0,
|
"in_create": 0,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"modified": "2014-12-18 15:06:41.802390",
|
"modified": "2014-12-19 14:23:50.701164",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "Production Order",
|
"name": "Production Order",
|
||||||
|
@ -64,8 +64,8 @@ class ProductionOrder(Document):
|
|||||||
|
|
||||||
self.planned_variable_cost, self.actual_variable_cost = 0.0, 0.0
|
self.planned_variable_cost, self.actual_variable_cost = 0.0, 0.0
|
||||||
for d in self.get("production_order_operations"):
|
for d in self.get("production_order_operations"):
|
||||||
d.actual_variable_cost = flt(d.hour_rate) * flt(d.actual_operation_time) / 60 \
|
|
||||||
if d.actual_operation_time else d.time_in_mins
|
d.actual_variable_cost = flt(d.hour_rate) * flt(d.actual_operation_time) / 60
|
||||||
|
|
||||||
self.planned_variable_cost += flt(d.variable_cost)
|
self.planned_variable_cost += flt(d.variable_cost)
|
||||||
self.actual_variable_cost += flt(d.actual_variable_cost)
|
self.actual_variable_cost += flt(d.actual_variable_cost)
|
||||||
@ -254,11 +254,13 @@ def get_events(start, end, filters=None):
|
|||||||
if filters[key]:
|
if filters[key]:
|
||||||
conditions += " and " + key + ' = "' + filters[key].replace('"', '\"') + '"'
|
conditions += " and " + key + ' = "' + filters[key].replace('"', '\"') + '"'
|
||||||
|
|
||||||
data = frappe.db.sql("""select name,production_item, production_start_date, production_end_date from `tabProduction Order`
|
data = frappe.db.sql("""select name,production_item, production_start_date, production_end_date
|
||||||
|
from `tabProduction Order`
|
||||||
where ((ifnull(production_start_date, '0000-00-00')!= '0000-00-00') \
|
where ((ifnull(production_start_date, '0000-00-00')!= '0000-00-00') \
|
||||||
and (production_start_date between %(start)s and %(end)s) \
|
and (production_start_date between %(start)s and %(end)s) \
|
||||||
or ((ifnull(production_start_date, '0000-00-00')!= '0000-00-00') \
|
or ((ifnull(production_start_date, '0000-00-00')!= '0000-00-00') \
|
||||||
and production_end_date between %(start)s and %(end)s)){conditions}""".format(conditions=conditions), {
|
and production_end_date between %(start)s and %(end)s)) {conditions}
|
||||||
|
""".format(conditions=conditions), {
|
||||||
"start": start,
|
"start": start,
|
||||||
"end": end
|
"end": end
|
||||||
}, as_dict=True, update={"allDay": 0})
|
}, as_dict=True, update={"allDay": 0})
|
||||||
|
@ -100,7 +100,7 @@ class TestProductionOrder(unittest.TestCase):
|
|||||||
manufacturing_settings = frappe.get_doc({
|
manufacturing_settings = frappe.get_doc({
|
||||||
"doctype": "Manufacturing Settings",
|
"doctype": "Manufacturing Settings",
|
||||||
"maximum_overtime": 30,
|
"maximum_overtime": 30,
|
||||||
"allow_production_on_holidays": "No"
|
"allow_production_on_holidays": 0
|
||||||
})
|
})
|
||||||
|
|
||||||
manufacturing_settings.save()
|
manufacturing_settings.save()
|
||||||
|
@ -277,7 +277,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 1,
|
"allow_on_submit": 1,
|
||||||
"depends_on": "eval:doc.docstatus==1",
|
"depends_on": "eval:(doc.docstatus==1 && doc.status!=\"Completed\")",
|
||||||
"fieldname": "make_time_log",
|
"fieldname": "make_time_log",
|
||||||
"fieldtype": "Button",
|
"fieldtype": "Button",
|
||||||
"label": "Make Time Log",
|
"label": "Make Time Log",
|
||||||
@ -292,7 +292,7 @@
|
|||||||
"is_submittable": 0,
|
"is_submittable": 0,
|
||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"modified": "2014-12-18 12:18:51.655535",
|
"modified": "2014-12-19 12:49:49.918120",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "Production Order Operation",
|
"name": "Production Order Operation",
|
||||||
|
@ -154,14 +154,14 @@
|
|||||||
"fieldname": "workstation_operation_hours",
|
"fieldname": "workstation_operation_hours",
|
||||||
"fieldtype": "Table",
|
"fieldtype": "Table",
|
||||||
"label": "Workstation Operation Hours",
|
"label": "Workstation Operation Hours",
|
||||||
"options": "Workstation Operation Hours",
|
"options": "Workstation Operation Hour",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": ""
|
"precision": ""
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "icon-wrench",
|
"icon": "icon-wrench",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"modified": "2014-12-18 13:01:47.143326",
|
"modified": "2014-12-22 14:18:40.253034",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "Workstation",
|
"name": "Workstation",
|
||||||
|
@ -5,12 +5,13 @@ from __future__ import unicode_literals
|
|||||||
import frappe
|
import frappe
|
||||||
import datetime
|
import datetime
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.utils import flt, cint
|
from frappe.utils import flt, cint, getdate, formatdate, comma_and
|
||||||
|
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
|
||||||
class WorkstationHolidayError(frappe.ValidationError): pass
|
class WorkstationHolidayError(frappe.ValidationError): pass
|
||||||
class WorkstationIsClosedError(frappe.ValidationError): pass
|
class WorkstationIsClosedError(frappe.ValidationError): pass
|
||||||
|
class OverlapError(frappe.ValidationError): pass
|
||||||
|
|
||||||
class Workstation(Document):
|
class Workstation(Document):
|
||||||
def update_bom_operation(self):
|
def update_bom_operation(self):
|
||||||
@ -22,51 +23,58 @@ class Workstation(Document):
|
|||||||
(self.hour_rate, bom_no[0], self.name))
|
(self.hour_rate, bom_no[0], self.name))
|
||||||
|
|
||||||
def on_update(self):
|
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, 'total_variable_cost', flt(self.hour_rate_electricity) +
|
||||||
flt(self.hour_rate_consumable) + flt(self.hour_rate_rent))
|
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))
|
frappe.db.set(self, 'hour_rate', flt(self.hour_rate_labour) + flt(self.total_variable_cost))
|
||||||
|
|
||||||
self.update_bom_operation()
|
self.update_bom_operation()
|
||||||
|
|
||||||
|
def validate_overlap_for_operation_timings(self):
|
||||||
|
for d in self.get("workstation_operation_hours"):
|
||||||
|
existing = frappe.db.sql_list("""select idx from `tabWorkstation Operation Hours`
|
||||||
|
where parent = %s and name != %s
|
||||||
|
and (
|
||||||
|
(start_time between %s and %s) or
|
||||||
|
(end_time between %s and %s) or
|
||||||
|
(%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)
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_default_holiday_list():
|
def get_default_holiday_list():
|
||||||
return frappe.db.get_value("Company", frappe.defaults.get_user_default("company"), "default_holiday_list")
|
return frappe.db.get_value("Company", frappe.defaults.get_user_default("company"), "default_holiday_list")
|
||||||
|
|
||||||
def check_if_within_operating_hours(workstation, from_time, to_time):
|
def check_if_within_operating_hours(workstation, from_datetime, to_datetime):
|
||||||
if check_workstation_for_operation_time(workstation, from_time, to_time):
|
if not is_within_operating_hours(workstation, from_datetime, to_datetime):
|
||||||
frappe.throw(_("Time Log timings outside workstation Operating Hours !"), WorkstationIsClosedError)
|
frappe.throw(_("Time Log timings outside workstation operating hours"), WorkstationIsClosedError)
|
||||||
|
|
||||||
if frappe.db.get_value("Manufacturing Settings", "None", "allow_production_on_holidays") == "No":
|
if not cint(frappe.db.get_value("Manufacturing Settings", "None", "allow_production_on_holidays")):
|
||||||
msg = check_workstation_for_holiday(workstation, from_time, to_time)
|
check_workstation_for_holiday(workstation, from_datetime, to_datetime)
|
||||||
if msg != None:
|
|
||||||
frappe.throw(msg, WorkstationHolidayError)
|
|
||||||
|
|
||||||
def check_workstation_for_operation_time(workstation, from_time, to_time):
|
def is_within_operating_hours(workstation, from_datetime, to_datetime):
|
||||||
start_time = datetime.datetime.strptime(from_time,'%Y-%m-%d %H:%M:%S').strftime('%H:%M:%S')
|
if not cint(frappe.db.get_value("Manufacturing Settings", None, "dont_allow_overtime")):
|
||||||
end_time = datetime.datetime.strptime(to_time,'%Y-%m-%d %H:%M:%S').strftime('%H:%M:%S')
|
return True
|
||||||
max_time_diff = frappe.db.get_value("Manufacturing Settings", "None", "max_overtime")
|
|
||||||
|
|
||||||
for d in frappe.db.sql("""select time_to_sec(timediff( start_time, %s))/60 as st_diff ,
|
start_time = datetime.datetime.strptime(from_datetime,'%Y-%m-%d %H:%M:%S').strftime('%H:%M:%S')
|
||||||
time_to_sec(timediff( %s, end_time))/60 as et_diff from `tabWorkstation Operation Hours`
|
end_time = datetime.datetime.strptime(to_datetime,'%Y-%m-%d %H:%M:%S').strftime('%H:%M:%S')
|
||||||
where parent = %s and (%s <start_time or %s > end_time )""",
|
|
||||||
(start_time, end_time, workstation, start_time, end_time), as_dict=1):
|
|
||||||
if cint(d.st_diff) > cint(max_time_diff):
|
|
||||||
return 1
|
|
||||||
if cint(d.et_diff) > cint(max_time_diff):
|
|
||||||
return 1
|
|
||||||
|
|
||||||
def check_workstation_for_holiday(workstation, from_time, to_time):
|
for d in frappe.db.sql("""select start_time, end_time from `tabWorkstation Operation Hours`
|
||||||
|
where parent = %s and ifnull(enabled, 0) = 1""", workstation, as_dict=1):
|
||||||
|
if d.end_time >= start_time >= d.start_time and d.end_time >= end_time >= d.start_time:
|
||||||
|
return True
|
||||||
|
|
||||||
|
def check_workstation_for_holiday(workstation, from_datetime, to_datetime):
|
||||||
holiday_list = frappe.db.get_value("Workstation", workstation, "holiday_list")
|
holiday_list = frappe.db.get_value("Workstation", workstation, "holiday_list")
|
||||||
start_date = datetime.datetime.strptime(from_time,'%Y-%m-%d %H:%M:%S').strftime('%Y-%m-%d')
|
if holiday_list:
|
||||||
end_date = datetime.datetime.strptime(to_time,'%Y-%m-%d %H:%M:%S').strftime('%Y-%m-%d')
|
applicable_holidays = []
|
||||||
msg = _("Workstation is closed on the following dates as per Holiday List:")
|
for d in frappe.db.sql("""select holiday_date from `tabHoliday` where parent = %s
|
||||||
flag = 0
|
and holiday_date between %s and %s """, (holiday_list, getdate(from_datetime), getdate(to_datetime))):
|
||||||
for d in frappe.db.sql("""select holiday_date from `tabHoliday` where parent = %s and holiday_date between
|
applicable_holidays.append(formatdate(d[0]))
|
||||||
%s and %s """,(holiday_list, start_date, end_date), as_dict=1):
|
|
||||||
flag = 1
|
if applicable_holidays:
|
||||||
msg = msg + "\n" + d.holiday_date
|
frappe.throw(_("Workstation is closed on the following dates as per Holiday List: {0}")
|
||||||
if flag ==1:
|
.format(holiday_list) + "\n" + "\n".join(applicable_holidays), WorkstationHolidayError)
|
||||||
return msg
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"allow_copy": 0,
|
"allow_copy": 0,
|
||||||
"allow_import": 0,
|
"allow_import": 0,
|
||||||
"allow_rename": 0,
|
"allow_rename": 0,
|
||||||
"creation": "2014-10-29 13:00:43.921508",
|
"creation": "2014-12-22 14:18:20.786493",
|
||||||
"custom": 0,
|
"custom": 0,
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
@ -29,10 +29,23 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "section_break_2",
|
"allow_on_submit": 0,
|
||||||
|
"fieldname": "column_break_2",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": ""
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@ -53,6 +66,46 @@
|
|||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"fieldname": "section_break_2",
|
||||||
|
"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
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"default": "1",
|
||||||
|
"fieldname": "enabled",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Enabled",
|
||||||
|
"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_heading": 0,
|
||||||
@ -62,10 +115,10 @@
|
|||||||
"is_submittable": 0,
|
"is_submittable": 0,
|
||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"modified": "2014-10-29 13:02:24.631554",
|
"modified": "2014-12-22 14:18:31.091653",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "Workstation Operation Hours",
|
"name": "Workstation Operation Hour",
|
||||||
"name_case": "",
|
"name_case": "",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [],
|
"permissions": [],
|
@ -5,5 +5,5 @@ from __future__ import unicode_literals
|
|||||||
import frappe
|
import frappe
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
|
||||||
class WorkstationOperationHours(Document):
|
class WorkstationOperationHour(Document):
|
||||||
pass
|
pass
|
@ -5,6 +5,16 @@ frappe.provide("erpnext.projects");
|
|||||||
|
|
||||||
frappe.ui.form.on("Time Log", "onload", function(frm) {
|
frappe.ui.form.on("Time Log", "onload", function(frm) {
|
||||||
frm.set_query("task", erpnext.queries.task);
|
frm.set_query("task", erpnext.queries.task);
|
||||||
|
if (frm.doc.time_log_for == "Manufacturing") {
|
||||||
|
frappe.ui.form.trigger("Time Log", "production_order");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
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);
|
||||||
});
|
});
|
||||||
|
|
||||||
// set to time if hours is updated
|
// set to time if hours is updated
|
||||||
@ -45,7 +55,7 @@ $.extend(cur_frm.cscript, {
|
|||||||
$.each(doc.production_order_operations , function(i, row){
|
$.each(doc.production_order_operations , function(i, row){
|
||||||
operations[i] = (i+1) +". "+ row.operation;
|
operations[i] = (i+1) +". "+ row.operation;
|
||||||
});
|
});
|
||||||
frappe.meta.get_docfield("Time Log", "operation", me.frm.doc.name).options = operations.join("\n");
|
frappe.meta.get_docfield("Time Log", "operation", me.frm.doc.name).options = "\n" + operations.join("\n");
|
||||||
refresh_field("operation");
|
refresh_field("operation");
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -60,14 +70,10 @@ $.extend(cur_frm.cscript, {
|
|||||||
},
|
},
|
||||||
callback: function(r) {
|
callback: function(r) {
|
||||||
if(!r.exc) {
|
if(!r.exc) {
|
||||||
|
console.log(r.message)
|
||||||
cur_frm.set_value("workstation", r.message)
|
cur_frm.set_value("workstation", r.message)
|
||||||
}
|
}
|
||||||
doc.workstation = r.workstation;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (cur_frm.doc.time_log_for == "Manufacturing") {
|
|
||||||
cur_frm.cscript.onload = cur_frm.cscript.production_order;
|
|
||||||
}
|
|
||||||
|
@ -152,7 +152,7 @@
|
|||||||
"read_only": 0
|
"read_only": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "eval:doc.time_log_for == 'Project'",
|
"depends_on": "eval:doc.time_log_for",
|
||||||
"fieldname": "project",
|
"fieldname": "project",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
@ -200,7 +200,7 @@
|
|||||||
"icon": "icon-time",
|
"icon": "icon-time",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"modified": "2014-12-18 17:21:01.520646",
|
"modified": "2014-12-19 14:20:41.381152",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Projects",
|
"module": "Projects",
|
||||||
"name": "Time Log",
|
"name": "Time Log",
|
||||||
|
@ -8,7 +8,6 @@ import frappe, json
|
|||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.utils import cstr, comma_and, flt
|
from frappe.utils import cstr, comma_and, flt
|
||||||
|
|
||||||
|
|
||||||
class OverlapError(frappe.ValidationError): pass
|
class OverlapError(frappe.ValidationError): pass
|
||||||
class OverProductionError(frappe.ValidationError): pass
|
class OverProductionError(frappe.ValidationError): pass
|
||||||
class NotSubmittedError(frappe.ValidationError): pass
|
class NotSubmittedError(frappe.ValidationError): pass
|
||||||
@ -21,8 +20,10 @@ class TimeLog(Document):
|
|||||||
self.validate_overlap()
|
self.validate_overlap()
|
||||||
self.validate_timings()
|
self.validate_timings()
|
||||||
self.calculate_total_hours()
|
self.calculate_total_hours()
|
||||||
|
self.validate_time_log_for()
|
||||||
self.check_workstation_timings()
|
self.check_workstation_timings()
|
||||||
self.validate_production_order()
|
self.validate_production_order()
|
||||||
|
self.validate_operation_status()
|
||||||
|
|
||||||
def on_submit(self):
|
def on_submit(self):
|
||||||
self.update_production_order()
|
self.update_production_order()
|
||||||
@ -74,6 +75,11 @@ class TimeLog(Document):
|
|||||||
from frappe.utils import time_diff_in_seconds
|
from frappe.utils import time_diff_in_seconds
|
||||||
self.hours = flt(time_diff_in_seconds(self.to_time, self.from_time)) / 3600
|
self.hours = flt(time_diff_in_seconds(self.to_time, self.from_time)) / 3600
|
||||||
|
|
||||||
|
def validate_time_log_for(self):
|
||||||
|
if self.time_log_for == "Project":
|
||||||
|
for fld in ["production_order", "operation", "workstation", "operation_status"]:
|
||||||
|
self.set(fld, None)
|
||||||
|
|
||||||
def check_workstation_timings(self):
|
def check_workstation_timings(self):
|
||||||
"""Checks if **Time Log** is between operating hours of the **Workstation**."""
|
"""Checks if **Time Log** is between operating hours of the **Workstation**."""
|
||||||
if self.workstation:
|
if self.workstation:
|
||||||
@ -82,28 +88,39 @@ class TimeLog(Document):
|
|||||||
|
|
||||||
def validate_production_order(self):
|
def validate_production_order(self):
|
||||||
"""Throws 'NotSubmittedError' if **production order** is not submitted. """
|
"""Throws 'NotSubmittedError' if **production order** is not submitted. """
|
||||||
|
|
||||||
if self.production_order:
|
if self.production_order:
|
||||||
if frappe.db.get_value("Production Order", self.production_order, "docstatus") != 1 :
|
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)
|
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):
|
def update_production_order(self):
|
||||||
"""Updates `start_date`, `end_date`, `status` for operation in Production Order."""
|
"""Updates `start_date`, `end_date`, `status` for operation in Production Order."""
|
||||||
|
|
||||||
if self.time_log_for=="Manufacturing" and self.operation:
|
if self.time_log_for=="Manufacturing" and self.operation:
|
||||||
dates = self.get_operation_start_end_time()
|
dates = self.get_operation_start_end_time()
|
||||||
op_status = self.get_op_status()
|
|
||||||
actual_op_time = self.get_actual_op_time()
|
|
||||||
|
|
||||||
|
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)
|
d = self.operation.split('. ',1)
|
||||||
|
|
||||||
frappe.db.sql("""update `tabProduction Order Operation`
|
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, status = %s, actual_operation_time = %s
|
||||||
where parent=%s and idx=%s and operation = %s""",
|
where parent=%s and idx=%s and operation = %s""",
|
||||||
(dates.start_date, dates.end_date, op_status, actual_op_time,
|
(dates.start_date, dates.end_date, op_status,
|
||||||
self.production_order, d[0], d[1]))
|
actual_op_time, self.production_order, d[0], d[1]))
|
||||||
|
|
||||||
frappe.get_doc("Production Order", self.production_order).save()
|
pro_order = frappe.get_doc("Production Order", self.production_order)
|
||||||
|
pro_order.ignore_validate_update_after_submit = True
|
||||||
|
pro_order.calculate_operating_cost()
|
||||||
|
pro_order.save()
|
||||||
|
|
||||||
def get_operation_start_end_time(self):
|
def get_operation_start_end_time(self):
|
||||||
"""Returns Min From and Max To Dates of Time Logs against a specific Operation. """
|
"""Returns Min From and Max To Dates of Time Logs against a specific Operation. """
|
||||||
@ -118,12 +135,10 @@ class TimeLog(Document):
|
|||||||
(self.production_order, self.operation))
|
(self.production_order, self.operation))
|
||||||
return actual_time[0][0] if actual_time else 0
|
return actual_time[0][0] if actual_time else 0
|
||||||
|
|
||||||
def get_op_status(self):
|
def get_latest_time_log(self):
|
||||||
status = frappe.db.sql("""select operation_status from `tabTime Log`
|
return frappe.db.sql("""select name, operation_status from `tabTime Log`
|
||||||
where production_order=%s and operation=%s and docstatus=1
|
where production_order=%s and operation=%s and docstatus=1
|
||||||
order by to_time desc limit 1""", (self.production_order, self.operation))
|
order by to_time desc limit 1""", (self.production_order, self.operation), as_dict=1)
|
||||||
|
|
||||||
return status if status else self.status
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_workstation(production_order, operation):
|
def get_workstation(production_order, operation):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user