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
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							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
 | |
| 
 |