replaced status with completed checkbox
diff --git a/erpnext/projects/doctype/timesheet/timesheet.js b/erpnext/projects/doctype/timesheet/timesheet.js
index a176112..94dd35d 100644
--- a/erpnext/projects/doctype/timesheet/timesheet.js
+++ b/erpnext/projects/doctype/timesheet/timesheet.js
@@ -3,6 +3,7 @@
frappe.ui.form.on("Timesheet", {
setup: function(frm) {
+ frappe.require("/assets/erpnext/js/projects/timer.js");
frm.add_fetch('employee', 'employee_name', 'employee_name');
frm.fields_dict.employee.get_query = function() {
return {
@@ -50,57 +51,42 @@
}
}
- $.each(frm.doc.time_logs || [], function(i, row) {
- if(row.from_time && row.status != 'Completed') {
- if (frappe.datetime.now_datetime < row.from_time) {
- row.status = 'Not Started';
+ if (frm.doc.docstatus < 1) {
+
+ $.each(frm.doc.time_logs || [], function(i, row) {
+ 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) {
- row.status = 'Overdue';
- frappe.utils.play_sound("alert");
- frappe.msgprint(__(`Timer exceeded the given hours for activity ${row.activity_type} in row ${row.idx}.`));
+ frm.refresh_fields();
+ });
+
+ 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 {
- row.status = 'Pending';
+ button = 'Start Timer';
}
- }
- frm.refresh_fields();
- });
-
- if (frm.doc.docstatus < 2) {
-
- frm.add_custom_button(__('Start Timer'), function() {
+ })
+ frm.add_custom_button(__(button), function() {
var flag = true;
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) {
- if(flag && (row.status == 'Pending' || row.status == 'Overdue')) {
- if (row.timer_timestamp) {
- let timestamp = moment(frappe.datetime.now_datetime()).diff(moment(row.timer_timestamp),"seconds");
- timer(frm, disabled, row, timestamp);
-
- }
- else {
- row.timer_timestamp = frappe.datetime.now_datetime();
- timer(frm, disabled, row);
- }
+ if (flag && row.from_time <= frappe.datetime.now_datetime() && row.completed == 0) {
+ let timestamp = moment(frappe.datetime.now_datetime()).diff(moment(row.from_time),"seconds");
+ erpnext.timesheet.timer(frm, disabled, row, timestamp);
flag = false;
}
})
- // Fetch the row for timer where status = Not Started
- 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 no activities found to start a timer, create new
if (flag) {
disabled = 0;
- timer(frm,disabled);
+ erpnext.timesheet.timer(frm, disabled);
}
}).addClass("btn-primary");
}
@@ -219,158 +205,6 @@
}
});
-// 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) {
let child = locals[cdt][cdn];
diff --git a/erpnext/projects/doctype/timesheet_detail/timesheet_detail.json b/erpnext/projects/doctype/timesheet_detail/timesheet_detail.json
index b731dcf..b948238 100644
--- a/erpnext/projects/doctype/timesheet_detail/timesheet_detail.json
+++ b/erpnext/projects/doctype/timesheet_detail/timesheet_detail.json
@@ -108,6 +108,37 @@
"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_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
"columns": 1,
"fieldname": "hours",
"fieldtype": "Float",
@@ -170,8 +201,9 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "status",
- "fieldtype": "Select",
+ "default": "0",
+ "fieldname": "completed",
+ "fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -179,10 +211,10 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "Status",
+ "label": "Completed",
"length": 0,
"no_copy": 0,
- "options": "Not Started\nPending\nCompleted\nOverdue",
+ "options": "",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -392,99 +424,6 @@
"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_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "project_details",
"fieldtype": "Section Break",
"hidden": 0,
@@ -993,7 +932,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
- "modified": "2018-03-21 02:09:24.262360",
+ "modified": "2018-03-21 17:13:32.561550",
"modified_by": "Administrator",
"module": "Projects",
"name": "Timesheet Detail",