Clock in Clock out in HR Module

Is there a way, under attendance, clock in and clock out time can be added? Also can attendance be restructured in a way that employees just log into the system then under attendance they find only 2 buttons:

  1. Clock In
  2. Clock Out

This will save the exact time and date a user clocks in and out of the system.

Did this got implemented?

You can use the Checkin option for the same:

Reference:

https://docs.erpnext.com/docs/v13/user/manual/en/human-resources/employee_checkin

I’ve added a webform that does the trick. warning: it could be improved.


This goes in the Client Script section:

function get_formatted_date(){
    var now = new Date();
    let Year =  now.getFullYear();
    let month= now.getMonth()+1;
    let day= now.getDate();
    let Hours= now.getHours();
    let Minutes= now.getMinutes();
    let Seconds= now.getSeconds();
    var txtdate =  Year +'-';
    
    if (month < 10) { txtdate +=  '0';}
    txtdate += month +'-';
    if (day < 10) { txtdate +=  '0';}
    txtdate += day+' ';
    if (Hours < 10) { txtdate +=  '0';}
    txtdate +=Hours+ ":"  ;
    if (Minutes < 10) { txtdate +=  '0';}
    txtdate += Minutes + ":" ;
    if (Seconds < 10) { txtdate +=  '0';}
    txtdate += Seconds;
    
    return  txtdate;
}

function min_passed(date){
    const c_full_data = date.split(" ");
    const c_date = c_full_data[0].split("-");
    const c_time = c_full_data[1].split(":");
    
    var now = new Date();
    let Year =  now.getFullYear();
    let month= now.getMonth()+1;
    let day= now.getDate();
    let Hours= now.getHours();
    let Minutes= now.getMinutes();
    let Seconds= now.getSeconds();
    var min_passed=0;
    min_passed += (Year - c_date[0]) *1440*30*12;
    min_passed += (month - c_date[1]) *1440*30;
    min_passed += (day - c_date[2])  * 1440;
    min_passed += (Hours - c_time[0])  *60;
    min_passed += (Minutes - c_time[1])    ;
    return  min_passed;
}

frappe.call({
        method: 'frappe.client.get_value',
        args: {
            'doctype': 'Employee',
            'filters': {'prefered_email': frappe.session.user},
            'fieldname': [
                'name',
                'first_name',
                'last_name',
                'prefered_email',
                'employee_number'
            ]
        },
        callback(r) {
                    frappe.call({
                    method: 'frappe.client.get_list',
                    args: {
                        'doctype': 'Employee Checkin',
                        'pluck':'name',
                        'fields' : ['name','time','log_type'],
                        'filters': {'employee': (r.message).name},
                        'order_by':'time desc',
                        'as_list':'True'
                    },
                    callback(r1) {
                        var c_Action='OUT';
                        var c_Color = '#b10000';
                        console.log(r1.message.length);
                        if (r1.message.length != 0){
                            c_Action=r1.message[0].log_type;
                            var c_Header = document.getElementsByClassName('page-header');
                            let node = document.createTextNode("Clocked "+c_Action+" since "+r1.message[0].time);
                            c_Header[0].appendChild(node);
                           
                        }
                        if(c_Action == 'IN'){
                            c_Action =  "OUT";
                            c_Color = '#b10000';
                        }
                        else{
                            c_Action = "IN";
                            c_Color = '#00b159';
                        }
                        frappe.web_form.set_value('log_type', c_Action);
                        var htmlElements = document.getElementsByClassName('btn btn-primary btn-sm ml-2');
                        for (let i = 0; i < htmlElements.length; i++) {
                            htmlElements[i].innerHTML="CLOCK "+c_Action;
                            htmlElements[i].style.background = c_Color;
                            }
                        }
                     });
            
            $.getJSON("https://ipinfo.io/", function (data) {
                frappe.web_form.set_value('device_id', data.city + " | " + data.region + " | " + data.country + " | " + data.postal + " | " + data.loc + " | " + data.timezone + " | " + data.ip  + " | " + data.hostname);
            })
            frappe.web_form.set_value('employee', (r.message).name );
            frappe.web_form.set_df_property("log_type","read_only",1)
            frappe.web_form.set_df_property("employee","read_only",1)
            frappe.web_form.set_df_property("device_id","read_only",1)
            frappe.web_form.set_value('time',get_formatted_date());
            frappe.web_form.set_df_property("time","read_only",1)
          }
         });
         
frappe.web_form.validate = () => {
    let data = frappe.web_form.get_values();
   if (min_passed(data.time) > 1) {
        frappe.msgprint("It's been a long time try to refresh your page.");
        return false;
    }
    else{
        return true;
    }
}

frappe.web_form.after_save = () => {
    window.location.href = "/app/";
    };