mirror of
https://github.com/frappe/erpnext.git
synced 2026-06-05 21:29:11 +00:00
replaced status with completed checkbox
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
frappe.ui.form.on("Timesheet", {
|
frappe.ui.form.on("Timesheet", {
|
||||||
setup: function(frm) {
|
setup: function(frm) {
|
||||||
|
frappe.require("/assets/erpnext/js/projects/timer.js");
|
||||||
frm.add_fetch('employee', 'employee_name', 'employee_name');
|
frm.add_fetch('employee', 'employee_name', 'employee_name');
|
||||||
frm.fields_dict.employee.get_query = function() {
|
frm.fields_dict.employee.get_query = function() {
|
||||||
return {
|
return {
|
||||||
@@ -50,57 +51,42 @@ frappe.ui.form.on("Timesheet", {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$.each(frm.doc.time_logs || [], function(i, row) {
|
if (frm.doc.docstatus < 1) {
|
||||||
if(row.from_time && row.status != 'Completed') {
|
|
||||||
if (frappe.datetime.now_datetime < row.from_time) {
|
$.each(frm.doc.time_logs || [], function(i, row) {
|
||||||
row.status = 'Not Started';
|
if(row.from_time && !row.completed) {
|
||||||
|
if (row.to_time && frappe.datetime.now_datetime() > row.to_time) {
|
||||||
|
frappe.utils.play_sound("alert");
|
||||||
|
frappe.msgprint(__(`Timer exceeded the expected hours for activity ${row.activity_type} in row ${row.idx}.`));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (row.to_time && frappe.datetime.now_datetime > row.to_time) {
|
frm.refresh_fields();
|
||||||
row.status = 'Overdue';
|
});
|
||||||
frappe.utils.play_sound("alert");
|
|
||||||
frappe.msgprint(__(`Timer exceeded the given hours for activity ${row.activity_type} in row ${row.idx}.`));
|
let button;
|
||||||
|
$.each(frm.doc.time_logs || [], function(i, row) {
|
||||||
|
if (row.from_time <= frappe.datetime.now_datetime() && row.completed == 0) {
|
||||||
|
button = 'Resume Timer';
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
row.status = 'Pending';
|
button = 'Start Timer';
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
frm.refresh_fields();
|
frm.add_custom_button(__(button), function() {
|
||||||
});
|
|
||||||
|
|
||||||
if (frm.doc.docstatus < 2) {
|
|
||||||
|
|
||||||
frm.add_custom_button(__('Start Timer'), function() {
|
|
||||||
var flag = true;
|
var flag = true;
|
||||||
var disabled = 1;
|
var disabled = 1;
|
||||||
// Fetch the row for timer where status = Pending i.e in progress
|
// Fetch the row for timer where activity is not completed and from_time is not <= now_time
|
||||||
$.each(frm.doc.time_logs || [], function(i, row) {
|
$.each(frm.doc.time_logs || [], function(i, row) {
|
||||||
if(flag && (row.status == 'Pending' || row.status == 'Overdue')) {
|
if (flag && row.from_time <= frappe.datetime.now_datetime() && row.completed == 0) {
|
||||||
if (row.timer_timestamp) {
|
let timestamp = moment(frappe.datetime.now_datetime()).diff(moment(row.from_time),"seconds");
|
||||||
let timestamp = moment(frappe.datetime.now_datetime()).diff(moment(row.timer_timestamp),"seconds");
|
erpnext.timesheet.timer(frm, disabled, row, timestamp);
|
||||||
timer(frm, disabled, row, timestamp);
|
|
||||||
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
row.timer_timestamp = frappe.datetime.now_datetime();
|
|
||||||
timer(frm, disabled, row);
|
|
||||||
}
|
|
||||||
flag = false;
|
flag = false;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// Fetch the row for timer where status = Not Started
|
// If no activities found to start a timer, create new
|
||||||
if (flag) {
|
|
||||||
$.each(frm.doc.time_logs || [], function(i, row) {
|
|
||||||
if(row.status == 'Not Started') {
|
|
||||||
row.timer_timestamp = frappe.datetime.now_datetime();
|
|
||||||
timer(frm, disabled, row, timestamp);
|
|
||||||
flag = false;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// If no activities found to start a timer
|
|
||||||
if (flag) {
|
if (flag) {
|
||||||
disabled = 0;
|
disabled = 0;
|
||||||
timer(frm,disabled);
|
erpnext.timesheet.timer(frm, disabled);
|
||||||
}
|
}
|
||||||
}).addClass("btn-primary");
|
}).addClass("btn-primary");
|
||||||
}
|
}
|
||||||
@@ -219,158 +205,6 @@ frappe.ui.form.on("Timesheet Detail", {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Spawn dialog for timer when clicked on 'Start RTimer' button
|
|
||||||
var timer = function(frm, disabled, row, timestamp=0) {
|
|
||||||
let dialog = new frappe.ui.Dialog({
|
|
||||||
title: __("Timer"),
|
|
||||||
fields:
|
|
||||||
[
|
|
||||||
{"fieldtype": "Link", "label": __("Activity Type"), "fieldname": "activity_type",
|
|
||||||
"reqd": 1, "options": "Activity Type", "read_only": disabled},
|
|
||||||
{"fieldtype": "Float", "label": __("Hrs"), "fieldname": "hours", "read_only": disabled},
|
|
||||||
{"fieldtype": "Link", "label": __("Project"), "fieldname": "project", "read_only": disabled,
|
|
||||||
"options": "Project"}
|
|
||||||
]
|
|
||||||
|
|
||||||
});
|
|
||||||
if (row) {
|
|
||||||
dialog.set_values({
|
|
||||||
'activity_type': row.activity_type,
|
|
||||||
'project': row.project,
|
|
||||||
'hours': row.hours
|
|
||||||
});
|
|
||||||
}
|
|
||||||
dialog.wrapper.append(frappe.render_template("timesheet"));
|
|
||||||
control_timer(frm, dialog, row, timestamp);
|
|
||||||
dialog.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
var control_timer = function(frm, dialog, row, timestamp=0) {
|
|
||||||
var interval = null;
|
|
||||||
var currentIncrement = timestamp
|
|
||||||
var isPaused = false;
|
|
||||||
var initialised = row ? true : false;
|
|
||||||
var clicked = false;
|
|
||||||
var paused_time = 0;
|
|
||||||
// If row with status = Pending/ Not Completed found, initialize timer on click of 'Start Timer'
|
|
||||||
if (row) {
|
|
||||||
initialised = true;
|
|
||||||
$(".playpause span").removeClass();
|
|
||||||
$(".playpause span").addClass("pause");
|
|
||||||
initialiseTimer();
|
|
||||||
}
|
|
||||||
|
|
||||||
$(".playpause").click(function(e) {
|
|
||||||
if (!initialised) {
|
|
||||||
var args = dialog.get_values();
|
|
||||||
if(!args) return;
|
|
||||||
if (!frm.doc.time_logs[0].activity_type) {
|
|
||||||
frm.doc.time_logs = [];
|
|
||||||
}
|
|
||||||
row = frappe.model.add_child(frm.doc, "Timesheet Detail", "time_logs");
|
|
||||||
row.activity_type = args.activity_type;
|
|
||||||
row.from_time = frappe.datetime.get_datetime_as_string();
|
|
||||||
row.hours = args.hours;
|
|
||||||
row.project = args.project;
|
|
||||||
row.timer_timestamp = frappe.datetime.now_datetime();
|
|
||||||
let d = moment(row.from_time)
|
|
||||||
if(row.hours) {
|
|
||||||
d.add(row.hours, "hours");
|
|
||||||
row.to_time = d.format(moment.defaultDatetimeFormat);
|
|
||||||
}
|
|
||||||
row.status = 'Pending';
|
|
||||||
frm.refresh_field("time_logs");
|
|
||||||
}
|
|
||||||
if (clicked) {
|
|
||||||
e.preventDefault();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!initialised) {
|
|
||||||
initialised = true;
|
|
||||||
isPaused = false;
|
|
||||||
$(".playpause span").removeClass();
|
|
||||||
$(".playpause span").addClass("pause");
|
|
||||||
initialiseTimer();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$(".playpause span").removeClass();
|
|
||||||
if (isPaused) {
|
|
||||||
isPaused = false;
|
|
||||||
$(".playpause span").addClass("pause");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
isPaused = true;
|
|
||||||
$(".playpause span").addClass("play");
|
|
||||||
paused_time = currentIncrement;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// $(".stop").click(function() {
|
|
||||||
// reset();
|
|
||||||
// });
|
|
||||||
|
|
||||||
// Stop the timer and save the time logged by the timer on click of 'Complete' button
|
|
||||||
dialog.set_primary_action(__("Complete"), function() {
|
|
||||||
var grid_row = cur_frm.fields_dict['time_logs'].grid.grid_rows_by_docname[row.name];
|
|
||||||
grid_row.doc.status = "Completed";
|
|
||||||
grid_row.doc.actual_end_time = frappe.datetime.now_datetime();
|
|
||||||
grid_row.refresh();
|
|
||||||
// Save the form
|
|
||||||
frm.save();
|
|
||||||
// frm.set_value(row.timer_timestamp, currentIncrement);
|
|
||||||
reset();
|
|
||||||
dialog.hide();
|
|
||||||
})
|
|
||||||
function initialiseTimer() {
|
|
||||||
interval = setInterval(function() {
|
|
||||||
if (isPaused) return;
|
|
||||||
var current = setCurrentIncrement();
|
|
||||||
updateStopwatch(current);
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateStopwatch(increment) {
|
|
||||||
var hours = Math.floor(increment / 3600);
|
|
||||||
var minutes = Math.floor((increment - (hours * 3600)) / 60);
|
|
||||||
var seconds = increment - (hours * 3600) - (minutes * 60);
|
|
||||||
|
|
||||||
// If modal is closed by clicking outside anywhere the modal, reset the timer
|
|
||||||
if (!$('.modal-dialog').is(':visible')) {
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
if(hours > 99)
|
|
||||||
reset();
|
|
||||||
if(cur_dialog && cur_dialog.get_value('hours') == hours) {
|
|
||||||
isPaused = true;
|
|
||||||
initialised = false;
|
|
||||||
frappe.utils.play_sound("alert");
|
|
||||||
frappe.msgprint(__("Timer exceeded the given hours"));
|
|
||||||
}
|
|
||||||
$(".hours").text(hours < 10 ? ("0" + hours.toString()) : hours.toString());
|
|
||||||
$(".minutes").text(minutes < 10 ? ("0" + minutes.toString()) : minutes.toString());
|
|
||||||
$(".seconds").text(seconds < 10 ? ("0" + seconds.toString()) : seconds.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
function setCurrentIncrement() {
|
|
||||||
currentIncrement += 1;
|
|
||||||
return currentIncrement;
|
|
||||||
}
|
|
||||||
|
|
||||||
function reset() {
|
|
||||||
currentIncrement = 0;
|
|
||||||
isPaused = true;
|
|
||||||
initialised = false;
|
|
||||||
clearInterval(interval);
|
|
||||||
$(".hours").text("00");
|
|
||||||
$(".minutes").text("00");
|
|
||||||
$(".seconds").text("00");
|
|
||||||
$(".playpause span").removeClass();
|
|
||||||
$(".playpause span").addClass("play");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var calculate_end_time = function(frm, cdt, cdn) {
|
var calculate_end_time = function(frm, cdt, cdn) {
|
||||||
let child = locals[cdt][cdn];
|
let child = locals[cdt][cdn];
|
||||||
|
|
||||||
|
|||||||
@@ -103,6 +103,37 @@
|
|||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "expected_hours",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Expected Hrs",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@@ -170,8 +201,9 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"fieldname": "status",
|
"default": "0",
|
||||||
"fieldtype": "Select",
|
"fieldname": "completed",
|
||||||
|
"fieldtype": "Check",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
@@ -179,10 +211,10 @@
|
|||||||
"in_global_search": 0,
|
"in_global_search": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"in_standard_filter": 0,
|
"in_standard_filter": 0,
|
||||||
"label": "Status",
|
"label": "Completed",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"options": "Not Started\nPending\nCompleted\nOverdue",
|
"options": "",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
"precision": "",
|
||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
@@ -386,99 +418,6 @@
|
|||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "timer_details",
|
|
||||||
"fieldtype": "Section Break",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Timer Details",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "timer_timestamp",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Timer Timestamp",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "actual_end_time",
|
|
||||||
"fieldtype": "Datetime",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Actual End Time",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@@ -993,7 +932,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2018-03-21 02:09:24.262360",
|
"modified": "2018-03-21 17:13:32.561550",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Projects",
|
"module": "Projects",
|
||||||
"name": "Timesheet Detail",
|
"name": "Timesheet Detail",
|
||||||
|
|||||||
Reference in New Issue
Block a user