Skip to content

Commit

Permalink
⬆️1️⃣1️⃣ base_attendance (#651)
Browse files Browse the repository at this point in the history
  • Loading branch information
KolushovAlexandr authored and Ivan Yelizariev committed Sep 13, 2018
1 parent 4023da5 commit 39bff34
Show file tree
Hide file tree
Showing 19 changed files with 228 additions and 167 deletions.
1 change: 0 additions & 1 deletion base_attendance/__init__.py
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).

from . import models
4 changes: 1 addition & 3 deletions base_attendance/__manifest__.py
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2004-2015 Odoo S.A.
# Copyright 2018 Kolushov Alexandr <https://it-projects.info/team/KolushovAlexandr>
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
Expand All @@ -19,7 +18,6 @@
"currency": "EUR",

"depends": [
'report',
'barcodes'
],
"external_dependencies": {"python": [], "bin": []},
Expand All @@ -36,6 +34,6 @@
'qweb': [
"static/src/xml/attendance.xml",
],
'installable': False,
'installable': True,
'auto_install': False,
}
1 change: 0 additions & 1 deletion base_attendance/models/__init__.py
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).

from . import res_attendance
Expand Down
1 change: 0 additions & 1 deletion base_attendance/models/res_attendance.py
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2004-2015 Odoo S.A.
# Copyright 2018 Kolushov Alexandr <https://it-projects.info/team/KolushovAlexandr>
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
Expand Down
3 changes: 1 addition & 2 deletions base_attendance/models/res_config.py
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2004-2015 Odoo S.A.
# Copyright 2018 Kolushov Alexandr <https://it-projects.info/team/KolushovAlexandr>
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
Expand All @@ -7,7 +6,7 @@


class BaseConfigSettings(models.TransientModel):
_inherit = 'base.config.settings'
_inherit = 'res.config.settings'

group_attendance_use_pin = fields.Selection([(0, 'Partners do not need to enter their PIN to check in manually in the "Kiosk Mode".'),
(1, 'Partners must enter their PIN to check in manually in the "Kiosk Mode".')],
Expand Down
1 change: 0 additions & 1 deletion base_attendance/models/res_partner.py
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2004-2015 Odoo S.A.
# Copyright 2018 Kolushov Alexandr <https://it-projects.info/team/KolushovAlexandr>
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
Expand Down
81 changes: 45 additions & 36 deletions base_attendance/static/src/js/greeting_message.js
@@ -1,19 +1,15 @@
/* Copyright (c) 2004-2015 Odoo S.A.
/* Copyright (c) 2004-2018 Odoo S.A.
Copyright 2018 Kolushov Alexandr <https://it-projects.info/team/KolushovAlexandr>
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). */
odoo.define('base_attendance.greeting_message', function (require) {
"use strict";

var BarcodeHandlerMixin = require('barcodes.BarcodeHandlerMixin');

var core = require('web.core');
var Model = require('web.Model');
var Widget = require('web.Widget');

var _t = core._t;


var GreetingMessage = Widget.extend(BarcodeHandlerMixin, {
var GreetingMessage = Widget.extend({
template: 'BaseAttendanceGreetingMessage',

events: {
Expand All @@ -25,13 +21,13 @@ var GreetingMessage = Widget.extend(BarcodeHandlerMixin, {
init: function(parent, action) {
var self = this;
this._super.apply(this, arguments);
BarcodeHandlerMixin.init.apply(this, arguments);
this.activeBarcode = true;

// if no correct action given (due to an erroneous back or refresh from the browser), we set the dismiss button to return
// to the (likely) appropriate menu, according to the user access rights
if(!action.attendance) {
this.stop_listening();
this.session.user_has_group('base_attendance.group_hr_attendance_user').then(function(has_group) {
this.activeBarcode = false;
this.getSession().user_has_group('base_attendance.group_hr_attendance_user').then(function(has_group) {
if(has_group) {
self.next_action = 'base_attendance.hr_attendance_action_kiosk_mode';
} else {
Expand All @@ -43,14 +39,22 @@ var GreetingMessage = Widget.extend(BarcodeHandlerMixin, {

this.next_action = action.next_action || 'base_attendance.hr_attendance_action_my_attendances';
// no listening to barcode scans if we aren't coming from the kiosk mode (and thus not going back to it with next_action)
if (this.next_action !== 'base_attendance.hr_attendance_action_kiosk_mode' && this.next_action.tag !== 'base_attendance_kiosk_mode') {
this.stop_listening();
if (this.next_action !== 'base_attendance.hr_attendance_action_kiosk_mode' && this.next_action.tag !== 'hr_attendance_kiosk_mode') {
this.activeBarcode = false;
}

this.attendance = action.attendance;
// We receive the check in/out times in UTC
// This widget only deals with display, which should be in browser's TimeZone
var moment = window.moment;
this.attendance.check_in = this.attendance.check_in && moment.utc(this.attendance.check_in).local();
this.attendance.check_out = this.attendance.check_out && moment.utc(this.attendance.check_out).local();
this.previous_attendance_change_date = action.previous_attendance_change_date && moment.utc(action.previous_attendance_change_date).local();

// check in/out times displayed in the greeting message template.
this.attendance.check_in_time = (new Date((new Date(this.attendance.check_in)).valueOf() - ((new Date()).getTimezoneOffset()*60*1000))).toTimeString().slice(0,8);
this.attendance.check_out_time = this.attendance.check_out && (new Date((new Date(this.attendance.check_out)).valueOf() - ((new Date()).getTimezoneOffset()*60*1000))).toTimeString().slice(0,8);
this.previous_attendance_change_date = action.previous_attendance_change_date;
this.format_time = 'HH:mm:ss';
this.attendance.check_in_time = this.attendance.check_in && this.attendance.check_in.format(this.format_time);
this.attendance.check_out_time = this.attendance.check_out && this.attendance.check_out.format(this.format_time);
this.partner_name = action.partner_name;
},

Expand All @@ -60,19 +64,22 @@ var GreetingMessage = Widget.extend(BarcodeHandlerMixin, {
? this.farewell_message()
: this.welcome_message();
}
if (this.activeBarcode) {
core.bus.on('barcode_scanned', this, this._onBarcodeScanned);
}
},

welcome_message: function() {
var self = this;
var now = new Date((new Date(this.attendance.check_in)).valueOf() - ((new Date()).getTimezoneOffset()*60*1000));
var now = this.attendance.check_in.clone();
this.return_to_main_menu = setTimeout( function() {
self.do_action(self.next_action, {clear_breadcrumbs: true});
}, 5000);

if (now.getHours() < 5) {
if (now.hours() < 5) {
this.$('.o_hr_attendance_message_message').append(_t("Good night"));
} else if (now.getHours() < 12) {
if (now.getHours() < 8 && Math.random() < 0.3) {
} else if (now.hours() < 12) {
if (now.hours() < 8 && Math.random() < 0.3) {
if (Math.random() < 0.75) {
this.$('.o_hr_attendance_message_message').append(_t("The early bird catches the worm"));
} else {
Expand All @@ -81,16 +88,16 @@ var GreetingMessage = Widget.extend(BarcodeHandlerMixin, {
} else {
this.$('.o_hr_attendance_message_message').append(_t("Good morning"));
}
} else if (now.getHours() < 17){
} else if (now.hours() < 17){
this.$('.o_hr_attendance_message_message').append(_t("Good afternoon"));
} else if (now.getHours() < 23){
} else if (now.hours() < 23){
this.$('.o_hr_attendance_message_message').append(_t("Good evening"));
} else {
this.$('.o_hr_attendance_message_message').append(_t("Good night"));
}
if(this.previous_attendance_change_date){
var last_check_out_date = new Date((new Date(this.previous_attendance_change_date)).valueOf() - ((new Date()).getTimezoneOffset()*60*1000));
if(now.valueOf() - last_check_out_date.valueOf() > 1000*60*60*24*7){
var last_check_out_date = this.previous_attendance_change_date.clone();
if(now - last_check_out_date > 24*7*60*60*1000){
this.$('.o_hr_attendance_random_message').html(_t("Glad to have you back, it's been a while!"));
} else if(Math.random() < 0.02){
this.$('.o_hr_attendance_random_message').html(_t("If a job is worth doing, it is worth doing well!"));
Expand All @@ -100,50 +107,51 @@ var GreetingMessage = Widget.extend(BarcodeHandlerMixin, {

farewell_message: function() {
var self = this;
var now = new Date((new Date(this.attendance.check_out)).valueOf() - ((new Date()).getTimezoneOffset()*60*1000));
var now = this.attendance.check_out.clone();
this.return_to_main_menu = setTimeout( function() {
self.do_action(self.next_action, {clear_breadcrumbs: true});
}, 5000);

if(this.previous_attendance_change_date){
var last_check_in_date = new Date((new Date(this.previous_attendance_change_date)).valueOf() - ((new Date()).getTimezoneOffset()*60*1000));
if(now.valueOf() - last_check_in_date.valueOf() > 1000*60*60*12){
var last_check_in_date = this.previous_attendance_change_date.clone();
if(now - last_check_in_date > 1000*60*60*12){
this.$('.o_hr_attendance_warning_message').append(_t("Warning! Last check in was over 12 hours ago.<br/>If this isn't right, please contact Human Resources."));
clearTimeout(this.return_to_main_menu);
this.stop_listening();
} else if(now.valueOf() - last_check_in_date.valueOf() > 1000*60*60*8){
this.activeBarcode = false;
} else if(now - last_check_in_date > 1000*60*60*8){
this.$('.o_hr_attendance_random_message').html(_t("Another good day's work! See you soon!"));
}
}

if (now.getHours() < 12) {
if (now.hours() < 12) {
this.$('.o_hr_attendance_message_message').append(_t("Have a good day!"));
} else if (now.getHours() < 14) {
} else if (now.hours() < 14) {
this.$('.o_hr_attendance_message_message').append(_t("Have a nice lunch!"));
if (Math.random() < 0.05) {
this.$('.o_hr_attendance_random_message').html(_t("Eat breakfast as a king, lunch as a merchant and supper as a beggar"));
} else if (Math.random() < 0.06) {
this.$('.o_hr_attendance_random_message').html(_t("An apple a day keeps the doctor away"));
}
} else if (now.getHours() < 17) {
} else if (now.hours() < 17) {
this.$('.o_hr_attendance_message_message').append(_t("Have a good afternoon"));
} else if (now.getHours() < 18 && Math.random() < 0.2) {
} else if (now.hours() < 18 && Math.random() < 0.2) {
this.$('.o_hr_attendance_message_message').append(_t("Early to bed and early to rise, makes a man healthy, wealthy and wise"));
} else {
this.$('.o_hr_attendance_message_message').append(_t("Have a good evening"));
}

},

on_barcode_scanned: function(barcode) {
_onBarcodeScanned: function(barcode) {
var self = this;
if (this.return_to_main_menu) {
// in case of multiple scans in the greeting message view, delete the timer, a new one will be created.
clearTimeout(this.return_to_main_menu);
}
var res_partner = new Model('res.partner');
res_partner.call('attendance_scan', [barcode, ]).
then(function (result) {
this._rpc({
model: 'res.partner',
method: 'attendance_scan',
args: [barcode, ],
}).then(function (result) {
if (result.action) {
self.do_action(result.action);
} else if (result.warning) {
Expand All @@ -153,6 +161,7 @@ var GreetingMessage = Widget.extend(BarcodeHandlerMixin, {
},

destroy: function () {
core.bus.off('barcode_scanned', this, this._onBarcodeScanned);
clearTimeout(this.return_to_main_menu);
this._super.apply(this, arguments);
},
Expand Down
59 changes: 30 additions & 29 deletions base_attendance/static/src/js/kiosk_confirm.js
@@ -1,15 +1,12 @@
/* Copyright (c) 2004-2015 Odoo S.A.
/* Copyright (c) 2004-2018 Odoo S.A.
Copyright 2018 Kolushov Alexandr <https://it-projects.info/team/KolushovAlexandr>
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). */
odoo.define('base_attendance.kiosk_confirm', function (require) {
"use strict";

var core = require('web.core');
var Model = require('web.Model');
var Widget = require('web.Widget');

var QWeb = core.qweb;
var _t = core._t;


var KioskConfirm = Widget.extend({
Expand All @@ -20,16 +17,18 @@ var KioskConfirm = Widget.extend({
"click .o_hr_attendance_sign_in_out_icon": function () {
var self = this;
this.$('.o_hr_attendance_sign_in_out_icon').attr("disabled", "disabled");
var hr_partner = new Model('res.partner');
hr_partner.call('attendance_manual', [[this.partner_id], this.next_action]).
then(function(result) {
if (result.action) {
self.do_action(result.action);
} else if (result.warning) {
self.do_warn(result.warning);
self.$('.o_hr_attendance_sign_in_out_icon').removeAttr("disabled");
}
});
this._rpc({
model: 'res.partner',
method: 'attendance_manual',
args: [[this.partner_id], this.next_action],
}).then(function(result) {
if (result.action) {
self.do_action(result.action);
} else if (result.warning) {
self.do_warn(result.warning);
self.$('.o_hr_attendance_sign_in_out_icon').removeAttr("disabled");
}
});
},
'click .o_hr_attendance_pin_pad_button_0': function() {
this.$('.o_hr_attendance_PINbox').val(this.$('.o_hr_attendance_PINbox').val() + 0);
Expand Down Expand Up @@ -67,18 +66,21 @@ var KioskConfirm = Widget.extend({
'click .o_hr_attendance_pin_pad_button_ok': function() {
var self = this;
this.$('.o_hr_attendance_pin_pad_button_ok').attr("disabled", "disabled");
var hr_partner = new Model('res.partner');
hr_partner.call('attendance_manual', [[this.partner_id], this.next_action, this.$('.o_hr_attendance_PINbox').val()]).
then(function(result) {
if (result.action) {
self.do_action(result.action);
} else if (result.warning) {
self.do_warn(result.warning);
setTimeout( function() {
self.$('.o_hr_attendance_pin_pad_button_ok').removeAttr("disabled");
}, 500);
}
});
this._rpc({
model: 'res.partner',
method: 'attendance_manual',
args: [[this.partner], this.next_action, this.$('.o_hr_attendance_PINbox').val()],
}).then(function(result) {
if (result.action) {
self.do_action(result.action);
} else if (result.warning) {
self.do_warn(result.warning);
self.$('.o_hr_attendance_PINbox').val('');
setTimeout( function() {
self.$('.o_hr_attendance_pin_pad_button_ok').removeAttr("disabled");
}, 500);
}
});
},
},

Expand All @@ -88,12 +90,11 @@ var KioskConfirm = Widget.extend({
this.partner_id = action.partner_id;
this.partner_name = action.partner_name;
this.partner_state = action.partner_state;
var self = this;
},

start: function () {
var self = this;
self.session.user_has_group('base_attendance.group_hr_attendance_use_pin').then(function(has_group){
this.getSession().user_has_group('base_attendance.group_hr_attendance_use_pin').then(function(has_group){
self.use_pin = has_group;
self.$el.html(QWeb.render("BaseAttendanceKioskConfirm", {widget: self}));
self.start_clock();
Expand All @@ -104,7 +105,7 @@ var KioskConfirm = Widget.extend({
start_clock: function () {
this.clock_start = setInterval(function() {
this.$(".o_hr_attendance_clock").text(new Date().toLocaleTimeString(navigator.language, {hour: '2-digit', minute:'2-digit'}));
}, 700);
}, 500);
// First clock refresh before interval to avoid delay
this.$(".o_hr_attendance_clock").text(new Date().toLocaleTimeString(navigator.language, {hour: '2-digit', minute:'2-digit'}));
},
Expand Down

0 comments on commit 39bff34

Please sign in to comment.