You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

129 lines
6.3 KiB

# -*- coding: utf-8 -*-
################################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Subina P (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
from geopy.geocoders import Nominatim
from odoo import exceptions, fields, models, _
class HrEmployee(models.AbstractModel):
"""Inherits HR Employee model to override functions to add the
location options """
_inherit = 'hr.employee'
def attendance_manual(self, next_action, entered_pin=None):
"""Override this method to add latitude and longitude"""
self.ensure_one()
latitudes = self.env.context.get('latitude', False)
longitudes = self.env.context.get('longitude', False)
attendance_user_and_no_pin = self.user_has_groups(
'hr_attendance.group_hr_attendance_user,'
'!hr_attendance.group_hr_attendance_use_pin')
can_check_without_pin = (attendance_user_and_no_pin or self.user_id ==
self.env.user and entered_pin is None)
if (can_check_without_pin or entered_pin is not None and entered_pin ==
self.sudo().pin):
return self._attendance_action(latitudes, longitudes,
next_action)
if not self.user_has_groups('hr_attendance.group_hr_attendance_user'):
return {'warning': _('To activate Kiosk mode without pin code, you '
'must have access right as an Officer or above'
'in the Attendance app. Please contact your '
'administrator.')}
return {'warning': _('Wrong PIN')}
def _attendance_action(self, latitudes, longitudes, next_action):
""" Changes the attendance of the employee.
Returns an action to the check in/out message,
next_action defines which menu the check in/out message should
return to. ("My Attendances" or "Kiosk Mode")
"""
self.ensure_one()
employee = self.sudo()
action_message = self.env['ir.actions.actions']._for_xml_id(
'hr_attendance.'
'hr_attendance_action_greeting_message')
action_message[
'previous_attendance_change_date'] = (employee.last_attendance_id
and (
employee.last_attendance_id.check_out
or employee.last_attendance_id.check_in) or False)
action_message['employee_name'] = employee.name
action_message['barcode'] = employee.barcode
action_message['next_action'] = next_action
action_message['hours_today'] = employee.hours_today
if employee.user_id:
modified_attendance = employee.with_user(
employee.user_id).sudo()._attendance_action_change(longitudes,
latitudes)
else:
modified_attendance = employee._attendance_action_change(longitudes,
latitudes)
action_message['attendance'] = modified_attendance.read()[0]
action_message['total_overtime'] = employee.total_overtime
# Overtime have a unique constraint on the day, no need for limit=1
action_message['overtime_today'] = \
self.env['hr.attendance.overtime'].sudo().search(
[('employee_id', '=', employee.id),
('date', '=', fields.Date.context_today(self)),
('adjustment', '=', False)]).duration or 0
return {'action': action_message}
def _attendance_action_change(self, longitudes, latitudes):
""" Check In/Check Out action
Check In: create a new attendance record
Check Out: modify check_out field of appropriate attendance record
"""
self.ensure_one()
action_date = fields.Datetime.now()
# Create a geolocator object
geolocator = Nominatim(user_agent='my-app')
# Get the location using the geolocator object
location = geolocator.reverse(str(latitudes) + ', ' + str(longitudes))
if self.attendance_state != 'checked_in':
vals = {
'employee_id': self.id,
'checkin_address': location.address,
'checkin_latitude': latitudes,
'checkin_longitude': longitudes,
'checkin_location': 'https://www.google.com/maps/place/'
+ location.address,
}
return self.env['hr.attendance'].create(vals)
attendance = self.env['hr.attendance'].search(
[('employee_id', '=', self.id), ('check_out', '=', False)], limit=1)
if attendance:
attendance.write({
'checkout_address': location.address,
'checkout_latitude': latitudes,
'checkout_longitude': longitudes,
'checkout_location': 'https://www.google.com/maps/place/'
+ location.address,
})
attendance.check_out = action_date
else:
raise exceptions.UserError(_('Cannot perform check out on '
'%(empl_name)s, could not find '
'corresponding check in.'
' Your attendances have probably been '
'modified manually by'
' human resources.') % {
'empl_name': self.sudo().name})
return attendance