[Fixes] Time sheet fixes and changed timesheets to time_logs

This commit is contained in:
Rohit Waghchaure 2016-06-29 17:57:39 +05:30
parent e6920f6a58
commit 3fa0b51e5e
13 changed files with 100 additions and 116 deletions

View File

@ -237,7 +237,7 @@ class SalesInvoice(SellingController):
return {"print_format": pos.get("print_format") } return {"print_format": pos.get("print_format") }
def update_time_sheet(self, sales_invoice): def update_time_sheet(self, sales_invoice):
for d in self.get("timesheets"): for d in self.timesheets:
if d.time_sheet: if d.time_sheet:
timesheet = frappe.get_doc("Time Sheet", d.time_sheet) timesheet = frappe.get_doc("Time Sheet", d.time_sheet)
timesheet.sales_invoice = sales_invoice timesheet.sales_invoice = sales_invoice
@ -246,7 +246,7 @@ class SalesInvoice(SellingController):
timesheet.save() timesheet.save()
def validate_time_sheets_are_submitted(self): def validate_time_sheets_are_submitted(self):
for data in self.get("timesheets"): for data in self.timesheets:
if data.time_sheet: if data.time_sheet:
status = frappe.db.get_value("Time Sheet", data.time_sheet, "status") status = frappe.db.get_value("Time Sheet", data.time_sheet, "status")
if status not in ['Submitted', 'Payslip']: if status not in ['Submitted', 'Payslip']:

View File

@ -31,13 +31,10 @@ frappe.ui.form.on("Salary Slip", {
}, },
toggle_fields: function(frm) { toggle_fields: function(frm) {
if(frm.doc.salary_slip_based_on_timesheet) { frm.toggle_display(['start_date', 'end_date', 'hourly_wages', 'timesheets'],
hide_field(['fiscal_year', 'month', 'total_days_in_month', 'leave_without_pay', 'payment_days']) cint(frm.doc.salary_slip_based_on_timesheet)==1);
unhide_field(['start_date', 'end_date', 'hourly_wages', 'timesheets']) frm.toggle_display(['fiscal_year', 'month', 'total_days_in_month', 'leave_without_pay', 'payment_days'],
}else { cint(frm.doc.salary_slip_based_on_timesheet)==0);
unhide_field(['fiscal_year', 'month', 'total_days_in_month', 'leave_without_pay', 'payment_days'])
hide_field(['start_date', 'end_date', 'hourly_wages', 'timesheets'])
}
} }
}) })

View File

@ -83,7 +83,7 @@ class SalarySlip(TransactionBase):
struct = frappe.db.sql("""select name from `tabSalary Structure` struct = frappe.db.sql("""select name from `tabSalary Structure`
where employee=%s and is_active = 'Yes' where employee=%s and is_active = 'Yes'
and (from_date <= %s or from_date <= %s) and (from_date <= %s or from_date <= %s)
and (to_date is null or to_date >= %s or to_date >= %s)""", and (to_date is null or to_date >= %s or to_date >= %s) order by from_date desc limit 1""",
(self.employee, self.start_date, joining_date, self.end_date, relieving_date)) (self.employee, self.start_date, joining_date, self.end_date, relieving_date))
if not struct: if not struct:

View File

@ -12,13 +12,27 @@ cur_frm.cscript.onload = function(doc, dt, dn){
} }
cur_frm.cscript.refresh = function(doc, dt, dn){ cur_frm.cscript.refresh = function(doc, dt, dn){
if((!doc.__islocal) && (doc.is_active == 'Yes') && (doc.salary_slip_based_on_timesheet == 0)){ if((!doc.__islocal) && (doc.is_active == 'Yes') && cint(doc.salary_slip_based_on_timesheet == 0)){
cur_frm.add_custom_button(__('Salary Slip'), cur_frm.add_custom_button(__('Salary Slip'),
cur_frm.cscript['Make Salary Slip'], __("Make")); cur_frm.cscript['Make Salary Slip'], __("Make"));
cur_frm.page.set_inner_btn_group_as_primary(__("Make")); cur_frm.page.set_inner_btn_group_as_primary(__("Make"));
} }
} }
frappe.ui.form.on('Salary Structure', {
refresh: function(frm) {
frm.trigger("toggle_fields")
},
salary_slip_based_on_timesheet: function(frm) {
frm.trigger("toggle_fields")
},
toggle_fields: function(frm) {
frm.toggle_display('time_sheet_earning_detail', cint(frm.doc.salary_slip_based_on_timesheet)==1);
}
})
cur_frm.cscript['Make Salary Slip'] = function() { cur_frm.cscript['Make Salary Slip'] = function() {
frappe.model.open_mapped_doc({ frappe.model.open_mapped_doc({
method: "erpnext.hr.doctype.salary_structure.salary_structure.make_salary_slip", method: "erpnext.hr.doctype.salary_structure.salary_structure.make_salary_slip",

View File

@ -353,7 +353,7 @@
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"depends_on": "eval:!doc.__islocal", "depends_on": "",
"fieldname": "salary_slip_based_on_timesheet", "fieldname": "salary_slip_based_on_timesheet",
"fieldtype": "Check", "fieldtype": "Check",
"hidden": 0, "hidden": 0,
@ -379,14 +379,14 @@
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"depends_on": "eval:doc.salary_slip_based_on_timesheet", "fieldname": "time_sheet_earning_detail",
"fieldname": "section_break_15",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
"ignore_user_permissions": 0, "ignore_user_permissions": 0,
"ignore_xss_filter": 0, "ignore_xss_filter": 0,
"in_filter": 0, "in_filter": 0,
"in_list_view": 0, "in_list_view": 0,
"label": "",
"length": 0, "length": 0,
"no_copy": 0, "no_copy": 0,
"permlevel": 0, "permlevel": 0,
@ -779,7 +779,7 @@
"issingle": 0, "issingle": 0,
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"modified": "2016-06-27 16:23:16.856237", "modified": "2016-06-29 15:41:48.243771",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "HR", "module": "HR",
"name": "Salary Structure", "name": "Salary Structure",

View File

@ -160,7 +160,7 @@ class ProductionOrder(Document):
def before_submit(self): def before_submit(self):
self.set_required_items() self.set_required_items()
self.make_timesheets() self.make_time_logs()
def before_cancel(self): def before_cancel(self):
for data in self.operations: for data in self.operations:
@ -240,7 +240,7 @@ class ProductionOrder(Document):
return holidays[holiday_list] return holidays[holiday_list]
def make_timesheets(self): def make_time_logs(self):
"""Capacity Planning. Plan time logs based on earliest availablity of workstation after """Capacity Planning. Plan time logs based on earliest availablity of workstation after
Planned Start Date. Time logs will be created and remain in Draft mode and must be submitted Planned Start Date. Time logs will be created and remain in Draft mode and must be submitted
before manufacturing entry can be made.""" before manufacturing entry can be made."""
@ -267,7 +267,7 @@ class ProductionOrder(Document):
# validate operating hours if workstation [not mandatory] is specified # validate operating hours if workstation [not mandatory] is specified
self.check_operation_fits_in_working_hours(d) self.check_operation_fits_in_working_hours(d)
try: try:
time_sheet.validate_timesheets() time_sheet.validate_time_logs()
except OverlapError: except OverlapError:
time_sheet.move_to_next_non_overlapping_slot(d.idx) time_sheet.move_to_next_non_overlapping_slot(d.idx)
@ -319,7 +319,7 @@ class ProductionOrder(Document):
frappe.throw(_("Capacity Planning Error")) frappe.throw(_("Capacity Planning Error"))
def get_start_end_time(self, time_sheet, operation_id): def get_start_end_time(self, time_sheet, operation_id):
for data in time_sheet.timesheets: for data in time_sheet.time_logs:
if data.operation_id == operation_id: if data.operation_id == operation_id:
return data.from_time, data.to_time return data.from_time, data.to_time
@ -518,7 +518,7 @@ def add_timesheet_detail(time_sheet, args):
if isinstance(args, unicode): if isinstance(args, unicode):
args = json.loads(args) args = json.loads(args)
time_sheet.append('timesheets', args) time_sheet.append('time_logs', args)
return time_sheet return time_sheet
@frappe.whitelist() @frappe.whitelist()

View File

@ -89,7 +89,7 @@ class TestProductionOrder(unittest.TestCase):
self.assertEqual(prod_order.name, time_sheet_doc.production_order) self.assertEqual(prod_order.name, time_sheet_doc.production_order)
self.assertEqual((prod_order.qty - d.completed_qty), sum([d.completed_qty for d in time_sheet_doc.timesheets])) self.assertEqual((prod_order.qty - d.completed_qty), sum([d.completed_qty for d in time_sheet_doc.time_logs]))
manufacturing_settings = frappe.get_doc({ manufacturing_settings = frappe.get_doc({
"doctype": "Manufacturing Settings", "doctype": "Manufacturing Settings",
@ -106,7 +106,7 @@ class TestProductionOrder(unittest.TestCase):
self.assertEqual(prod_order.operations[0].actual_operating_cost, 100) self.assertEqual(prod_order.operations[0].actual_operating_cost, 100)
time_sheet_doc1 = make_timesheet(prod_order.name) time_sheet_doc1 = make_timesheet(prod_order.name)
self.assertEqual(len(time_sheet_doc1.get('timesheets')), 0) self.assertEqual(len(time_sheet_doc1.get('time_logs')), 0)
time_sheet_doc.cancel() time_sheet_doc.cancel()

View File

@ -9,12 +9,13 @@ def execute():
time_sheet.employee= "" time_sheet.employee= ""
time_sheet.company = frappe.db.get_single_value('Global Defaults', 'default_company') time_sheet.company = frappe.db.get_single_value('Global Defaults', 'default_company')
time_sheet.sales_invoice = tlb.sales_invoice time_sheet.sales_invoice = tlb.sales_invoice
for data in tlb.time_logs: if tlb.get('time_logs'):
args = get_timesheet_data(data) for data in tlb.time_logs:
add_timesheet_detail(time_sheet, args) args = get_timesheet_data(data)
add_timesheet_detail(time_sheet, args)
time_sheet.docstatus = tlb.docstatus time_sheet.docstatus = tlb.docstatus
time_sheet.save(ignore_permissions=True) time_sheet.save(ignore_permissions=True)
def get_timesheet_data(data): def get_timesheet_data(data):
time_log = frappe.get_doc('Time Log', data.time_log) time_log = frappe.get_doc('Time Log', data.time_log)

View File

@ -16,8 +16,8 @@ class TestTimeSheet(unittest.TestCase):
time_sheet = make_time_sheet("_T-Employee-0001", True) time_sheet = make_time_sheet("_T-Employee-0001", True)
self.assertEquals(time_sheet.total_hours, 2) self.assertEquals(time_sheet.total_hours, 2)
self.assertEquals(time_sheet.timesheets[0].billing_rate, 50) self.assertEquals(time_sheet.time_logs[0].billing_rate, 50)
self.assertEquals(time_sheet.timesheets[0].billing_amount, 100) self.assertEquals(time_sheet.time_logs[0].billing_amount, 100)
def test_salary_slip_from_timesheet(self): def test_salary_slip_from_timesheet(self):
salary_structure = make_salary_structure("_T-Employee-0001") salary_structure = make_salary_structure("_T-Employee-0001")
@ -58,9 +58,10 @@ class TestTimeSheet(unittest.TestCase):
def make_salary_structure(employee): def make_salary_structure(employee):
name = frappe.db.get_value('Salary Structure', {'employee': employee, 'salary_slip_based_on_timesheet': 1}, 'name') name = frappe.db.get_value('Salary Structure', {'employee': employee, 'salary_slip_based_on_timesheet': 1}, 'name')
if name: if name:
frappe.delete_doc('Salary Structure', name) salary_structure = frappe.get_doc('Salary Structure', name)
else:
salary_structure = frappe.new_doc("Salary Structure")
salary_structure = frappe.new_doc("Salary Structure")
salary_structure.salary_slip_based_on_timesheet = 1 salary_structure.salary_slip_based_on_timesheet = 1
salary_structure.employee = employee salary_structure.employee = employee
salary_structure.from_date = nowdate() salary_structure.from_date = nowdate()
@ -89,14 +90,14 @@ def make_time_sheet(employee, simulate=False, billable = 0):
update_activity_type("_Test Activity Type") update_activity_type("_Test Activity Type")
time_sheet = frappe.new_doc("Time Sheet") time_sheet = frappe.new_doc("Time Sheet")
time_sheet.employee = employee time_sheet.employee = employee
time_sheet_detail = time_sheet.append('timesheets', {}) time_sheet_detail = time_sheet.append('time_logs', {})
time_sheet_detail.billable = billable time_sheet_detail.billable = billable
time_sheet_detail.activity_type = "_Test Activity Type" time_sheet_detail.activity_type = "_Test Activity Type"
time_sheet_detail.from_time = now_datetime() time_sheet_detail.from_time = now_datetime()
time_sheet_detail.hours = 2 time_sheet_detail.hours = 2
time_sheet_detail.to_time = time_sheet_detail.from_time + datetime.timedelta(hours= time_sheet_detail.hours) time_sheet_detail.to_time = time_sheet_detail.from_time + datetime.timedelta(hours= time_sheet_detail.hours)
for data in time_sheet.get('timesheets'): for data in time_sheet.get('time_logs'):
if simulate: if simulate:
while True: while True:
try: try:

View File

@ -1,11 +1,9 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors // Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt // License: GNU General Public License v3. See license.txt
cur_frm.add_fetch("activity_type", "billing_rate", "billing_rate");
frappe.ui.form.on("Time Sheet", { frappe.ui.form.on("Time Sheet", {
setup: function(frm) { setup: function(frm) {
frm.get_field('timesheets').grid.editable_fields = [ frm.get_field('time_logs').grid.editable_fields = [
{fieldname: 'activity_type', columns: 2}, {fieldname: 'activity_type', columns: 2},
{fieldname: 'from_time', columns: 2}, {fieldname: 'from_time', columns: 2},
{fieldname: 'hours', columns: 2}, {fieldname: 'hours', columns: 2},
@ -18,7 +16,7 @@ frappe.ui.form.on("Time Sheet", {
} }
} }
frm.fields_dict['timesheets'].grid.get_field('task').get_query = function(frm, cdt, cdn) { frm.fields_dict['time_logs'].grid.get_field('task').get_query = function(frm, cdt, cdn) {
child = locals[cdt][cdn]; child = locals[cdt][cdn];
return{ return{
filters: { filters: {
@ -29,7 +27,7 @@ frappe.ui.form.on("Time Sheet", {
}, },
onload: function(frm){ onload: function(frm){
if (frm.doc.__islocal && frm.doc.timesheets) { if (frm.doc.__islocal && frm.doc.time_logs) {
frm.set_value("employee", "") frm.set_value("employee", "")
calculate_time_and_amount(frm); calculate_time_and_amount(frm);
} }
@ -66,7 +64,7 @@ frappe.ui.form.on("Time Sheet", {
}) })
frappe.ui.form.on("Time Sheet Detail", { frappe.ui.form.on("Time Sheet Detail", {
timesheets_remove: function(frm) { time_logs_remove: function(frm) {
calculate_time_and_amount(frm); calculate_time_and_amount(frm);
}, },
@ -94,54 +92,64 @@ frappe.ui.form.on("Time Sheet Detail", {
}, },
billing_rate: function(frm, cdt, cdn) { billing_rate: function(frm, cdt, cdn) {
var child = locals[cdt][cdn] calculate_billing_costing_amount(frm, cdt, cdn)
if(child.hours && child.billing_rate){
frappe.mode.set_value(cdt, cdn, 'total_billing_amount', flt(child.billing_rate * child.hours))
}
calculate_billing_amount(frm, cdt, cdn)
}, },
costing_rate: function(frm, cdt, cdn) { costing_rate: function(frm, cdt, cdn) {
var child = locals[cdt][cdn] calculate_billing_costing_amount(frm, cdt, cdn)
frappe.mode.set_value(cdt, cdn, 'total_costing_amount', flt(child.costing_rate * child.hours))
calculate_billing_amount(frm, cdt, cdn)
}, },
billable: function(frm, cdt, cdn) { billable: function(frm, cdt, cdn) {
calculate_billing_amount(frm, cdt, cdn) calculate_billing_costing_amount(frm, cdt, cdn)
},
activity_type: function(frm, cdt, cdn) {
child = locals[cdt][cdn];
frappe.call({
method: "erpnext.projects.doctype.time_sheet.time_sheet.get_activity_cost",
args: {
employee: frm.doc.employee,
activity_type: child.activity_type
},
callback: function(r){
if(r.message){
frappe.model.set_value(cdt, cdn, 'billing_rate', r.message['billing_rate']);
frappe.model.set_value(cdt, cdn, 'costing_rate', r.message['costing_rate']);
calculate_billing_costing_amount(frm, cdt, cdn)
}
}
})
} }
}); });
calculate_end_time = function(frm, cdt, cdn){ calculate_end_time = function(frm, cdt, cdn){
var child = locals[cdt][cdn]; var child = locals[cdt][cdn];
if(!child.from_time) {
frappe.model.set_value(cdt, cdn, "from_time", frappe.datetime.now_datetime());
}
var d = moment(child.from_time); var d = moment(child.from_time);
d.add(child.hours, "hours"); d.add(child.hours, "hours");
frm._setting_hours = true; frm._setting_hours = true;
frappe.model.set_value(cdt, cdn, "to_time", d.format(moment.defaultDatetimeFormat)); frappe.model.set_value(cdt, cdn, "to_time", d.format(moment.defaultDatetimeFormat));
frm._setting_hours = false; frm._setting_hours = false;
calculate_billing_amount(frm, cdt, cdn) calculate_billing_costing_amount(frm, cdt, cdn)
} }
var calculate_billing_amount = function(frm, cdt, cdn){ var calculate_billing_costing_amount = function(frm, cdt, cdn){
child = locals[cdt][cdn] child = locals[cdt][cdn]
billing_amount = 0.0 billing_amount = costing_amount = 0.0;
if(child.hours && child.billable){ if(child.hours && child.billable){
billing_amount = (child.hours * child.billing_rate) billing_amount = (child.hours * child.billing_rate);
costing_amount = flt(child.costing_rate * child.hours);
} }
frappe.model.set_value(cdt, cdn, 'billing_amount', billing_amount) frappe.model.set_value(cdt, cdn, 'billing_amount', billing_amount);
frappe.model.set_value(cdt, cdn, 'costing_amount', costing_amount);
calculate_time_and_amount(frm) calculate_time_and_amount(frm)
} }
var calculate_time_and_amount = function(frm) { var calculate_time_and_amount = function(frm) {
var tl = frm.doc.timesheets || []; var tl = frm.doc.time_logs || [];
total_hr = 0; total_hr = 0;
total_billing_amount = 0; total_billing_amount = 0;
for(var i=0; i<tl.length; i++) { for(var i=0; i<tl.length; i++) {

View File

@ -426,7 +426,7 @@
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"fieldname": "timesheets", "fieldname": "time_logs",
"fieldtype": "Table", "fieldtype": "Table",
"hidden": 0, "hidden": 0,
"ignore_user_permissions": 0, "ignore_user_permissions": 0,
@ -586,7 +586,7 @@
"issingle": 0, "issingle": 0,
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"modified": "2016-06-27 01:45:26.226915", "modified": "2016-06-29 15:16:31.668367",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Projects", "module": "Projects",
"name": "Time Sheet", "name": "Time Sheet",
@ -611,46 +611,6 @@
"share": 1, "share": 1,
"submit": 1, "submit": 1,
"write": 1 "write": 1
},
{
"amend": 1,
"apply_user_permissions": 0,
"cancel": 1,
"create": 0,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Projects Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 1,
"write": 1
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 0,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Manufacturing User",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 0
} }
], ],
"quick_entry": 0, "quick_entry": 0,

View File

@ -22,9 +22,9 @@ class TimeSheet(Document):
self.total_hours = 0.0 self.total_hours = 0.0
self.total_billing_amount = 0.0 self.total_billing_amount = 0.0
self.validate_dates() self.validate_dates()
self.validate_timesheets() self.validate_time_logs()
self.update_cost() self.update_cost()
for d in self.get("timesheets"): for d in self.get("time_logs"):
self.total_hours += flt(d.hours) self.total_hours += flt(d.hours)
if d.billable: self.total_billing_amount += flt(d.billing_amount) if d.billable: self.total_billing_amount += flt(d.billing_amount)
@ -46,8 +46,8 @@ class TimeSheet(Document):
def set_dates(self): def set_dates(self):
if self.docstatus < 2: if self.docstatus < 2:
start_date = min([d.from_time for d in self.timesheets]) start_date = min([d.from_time for d in self.time_logs])
end_date = max([d.to_time for d in self.timesheets]) end_date = max([d.to_time for d in self.time_logs])
if start_date and end_date: if start_date and end_date:
self.start_date = getdate(start_date) self.start_date = getdate(start_date)
@ -73,7 +73,7 @@ class TimeSheet(Document):
production_order = frappe.get_doc("Production Order", self.production_order) production_order = frappe.get_doc("Production Order", self.production_order)
pending_qty = flt(production_order.qty) - flt(production_order.produced_qty) pending_qty = flt(production_order.qty) - flt(production_order.produced_qty)
for data in self.timesheets: for data in self.time_logs:
if not data.from_time and not data.to_time: if not data.from_time and not data.to_time:
frappe.throw(_("Row {0}: From Time and To Time is mandatory.").format(data.idx)) frappe.throw(_("Row {0}: From Time and To Time is mandatory.").format(data.idx))
@ -94,7 +94,7 @@ class TimeSheet(Document):
if self.production_order: if self.production_order:
pro = frappe.get_doc('Production Order', self.production_order) pro = frappe.get_doc('Production Order', self.production_order)
for timesheet in self.timesheets: for timesheet in self.time_logs:
for data in pro.operations: for data in pro.operations:
if data.name == timesheet.operation_id: if data.name == timesheet.operation_id:
summary = self.get_actual_timesheet_summary(timesheet.operation_id) summary = self.get_actual_timesheet_summary(timesheet.operation_id)
@ -119,7 +119,7 @@ class TimeSheet(Document):
(self.production_order, operation_id), as_dict=1)[0] (self.production_order, operation_id), as_dict=1)[0]
def update_task_and_project(self): def update_task_and_project(self):
for data in self.timesheets: for data in self.time_logs:
if data.task: if data.task:
task = frappe.get_doc("Task", data.task) task = frappe.get_doc("Task", data.task)
task.update_time_and_costing() task.update_time_and_costing()
@ -129,12 +129,12 @@ class TimeSheet(Document):
frappe.get_doc("Project", data.project).update_project() frappe.get_doc("Project", data.project).update_project()
def validate_dates(self): def validate_dates(self):
for data in self.timesheets: for data in self.time_logs:
if time_diff_in_hours(data.to_time, data.from_time) < 0: if time_diff_in_hours(data.to_time, data.from_time) < 0:
frappe.throw(_("To date cannot be before from date")) frappe.throw(_("To date cannot be before from date"))
def validate_timesheets(self): def validate_time_logs(self):
for data in self.get('timesheets'): for data in self.get('time_logs'):
self.validate_overlap(data) self.validate_overlap(data)
self.check_workstation_timings(data) self.check_workstation_timings(data)
@ -180,8 +180,8 @@ class TimeSheet(Document):
def move_to_next_non_overlapping_slot(self, index): def move_to_next_non_overlapping_slot(self, index):
from datetime import timedelta from datetime import timedelta
if self.timesheets: if self.time_logs:
for data in self.timesheets: for data in self.time_logs:
if data.idx == index: if data.idx == index:
overlapping = self.get_overlap_for("workstation", data) overlapping = self.get_overlap_for("workstation", data)
if not overlapping: if not overlapping:
@ -199,7 +199,7 @@ class TimeSheet(Document):
{'workstation': workstation}, as_dict=True)[0] {'workstation': workstation}, as_dict=True)[0]
def update_cost(self): def update_cost(self):
for data in self.timesheets: for data in self.time_logs:
if data.activity_type and not data.billing_amount: if data.activity_type and not data.billing_amount:
rate = get_activity_cost(self.employee, data.activity_type) rate = get_activity_cost(self.employee, data.activity_type)
hours = data.hours or 0 hours = data.hours or 0
@ -253,7 +253,7 @@ def set_missing_values(time_sheet, target):
target.salary_slip_based_on_timesheet = 1 target.salary_slip_based_on_timesheet = 1
target.start_date = doc.start_date target.start_date = doc.start_date
target.end_date = doc.end_date target.end_date = doc.end_date
@frappe.whitelist() @frappe.whitelist()
def get_activity_cost(employee=None, activity_type=None): def get_activity_cost(employee=None, activity_type=None):
rate = frappe.db.get_values("Activity Cost", {"employee": employee, rate = frappe.db.get_values("Activity Cost", {"employee": employee,
@ -263,7 +263,7 @@ def get_activity_cost(employee=None, activity_type=None):
["costing_rate", "billing_rate"], as_dict=True) ["costing_rate", "billing_rate"], as_dict=True)
return rate[0] if rate else {} return rate[0] if rate else {}
@frappe.whitelist() @frappe.whitelist()
def get_employee_list(doctype, txt, searchfield, start, page_len, filters): def get_employee_list(doctype, txt, searchfield, start, page_len, filters):
return frappe.db.sql("""select distinct(employee) as employee return frappe.db.sql("""select distinct(employee) as employee

View File

@ -295,6 +295,7 @@
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"depends_on": "eval:parent.production_order",
"fieldname": "completed_qty", "fieldname": "completed_qty",
"fieldtype": "Float", "fieldtype": "Float",
"hidden": 0, "hidden": 0,
@ -421,6 +422,7 @@
"collapsible": 0, "collapsible": 0,
"default": "0", "default": "0",
"depends_on": "", "depends_on": "",
"description": "To display value check Billable",
"fieldname": "billing_amount", "fieldname": "billing_amount",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@ -447,6 +449,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"default": "0", "default": "0",
"description": "To display value check Billable",
"fieldname": "costing_amount", "fieldname": "costing_amount",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@ -479,7 +482,7 @@
"issingle": 0, "issingle": 0,
"istable": 1, "istable": 1,
"max_attachments": 0, "max_attachments": 0,
"modified": "2016-06-24 15:55:30.746870", "modified": "2016-06-29 17:18:37.442965",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Projects", "module": "Projects",
"name": "Time Sheet Detail", "name": "Time Sheet Detail",