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.
		
		
		
		
		
			
		
			
				
					
					
						
							233 lines
						
					
					
						
							10 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							233 lines
						
					
					
						
							10 KiB
						
					
					
				| # -*- coding: utf-8 -*- | |
| ################################################################################ | |
| # | |
| #    Cybrosys Technologies Pvt. Ltd. | |
| # | |
| #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | |
| #    Author: THASNI CP (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/>. | |
| # | |
| ################################################################################ | |
| import pytz | |
| from collections import OrderedDict | |
| from datetime import datetime | |
| from dateutil.relativedelta import relativedelta | |
| from odoo import fields | |
| from odoo import http | |
| from odoo.http import request | |
| from odoo.tools import date_utils | |
| from odoo.addons.portal.controllers import portal | |
| from odoo.addons.portal.controllers.portal import pager | |
| 
 | |
| 
 | |
| class PortalAttendance(portal.CustomerPortal): | |
|     """To get the values of portal attendance""" | |
|     def _prepare_home_portal_values(self, counters): | |
|         """To get the count of the attendance in portal""" | |
|         values = super(PortalAttendance, self)._prepare_home_portal_values( | |
|             counters) | |
|         uid = request.session.uid | |
|         user_id = request.env['res.users'].browse(uid) | |
|         employee_id = request.env['hr.employee'].search( | |
|             [('user_id', '=', user_id.id)]) | |
|         attendance_count = request.env['hr.attendance'].search_count( | |
|             [('is_portal', '=', True), ('employee_id', '=', employee_id.id)]) | |
|         values.update({ | |
|             'attendance_count': attendance_count | |
|         }) | |
|         return values | |
| 
 | |
|     @http.route('/attendance/checkin', type='http', auth='user', website=True) | |
|     def attendance_checkin(self): | |
|         """When clicking the checkin button it will redirect to the check in | |
|         template""" | |
|         uid = request.session.uid | |
|         user_id = request.env['res.users'].browse(uid) | |
|         employee_id = request.env['hr.employee'].search( | |
|             [('user_id', '=', user_id.id)]) | |
|         values = { | |
|             'name': employee_id.name, | |
|             'image': employee_id.image_1920, | |
|             'check_in': datetime.now() | |
|         } | |
|         return request.render("web_portal_attendance.check_in_template", values) | |
| 
 | |
|     @http.route('/check/in', type='http', auth='user', website=True) | |
|     def attendance_creation(self): | |
|         """When clicking the checkin button it will create attendance to the | |
|         backend""" | |
|         uid = request.session.uid | |
|         user_id = request.env['res.users'].browse(uid) | |
|         employee_id = request.env['hr.employee'].search( | |
|             [('user_id', '=', user_id.id)]) | |
|         attendance = request.env['hr.attendance'].sudo().create({ | |
|             'employee_id': employee_id.id, | |
|             'check_in': datetime.now().strftime('%Y-%m-%d %H:%M:%S'), | |
|             'is_portal': True | |
|         }) | |
|         check_in = datetime.now() | |
|         user_tz = pytz.timezone( | |
|             request.env.context.get('tz') or request.env.user.tz) | |
|         date_today = pytz.utc.localize(check_in).astimezone(user_tz) | |
|         formatted_time = datetime.strftime(date_today, '%H:%M:%S') | |
|         values = { | |
|             'attendance': attendance, | |
|             'name': employee_id.name, | |
|             'image': employee_id.image_1920, | |
|             'check_out': False, | |
|             'formatted_time': formatted_time, | |
|         } | |
|         return request.render( | |
|             "web_portal_attendance.check_in_welcome_note_template", values) | |
| 
 | |
|     @http.route('/check/out', type='http', auth='user', website=True) | |
|     def attendance_checkout(self): | |
|         """When clicking the checkout button it will store the checkout time | |
|         and worked hours in the check in log """ | |
|         uid = request.session.uid | |
|         user_id = request.env['res.users'].browse(uid) | |
|         employee_id = request.env['hr.employee'].search( | |
|             [('user_id', '=', user_id.id)]) | |
|         values = { | |
|             'name': employee_id.name, | |
|             'image': employee_id.image_1920 | |
|         } | |
|         return request.render("web_portal_attendance.check_out_template", | |
|                               values) | |
| 
 | |
|     @http.route('/check/out/last', type='http', auth='user', website=True) | |
|     def attendance_final_checkout(self): | |
|         """To display the final checkout template """ | |
|         uid = request.session.uid | |
|         user_id = request.env['res.users'].browse(uid) | |
|         employee_id = request.env['hr.employee'].search( | |
|             [('user_id', '=', user_id.id)]) | |
|         check_out = datetime.now() | |
|         user_tz = pytz.timezone( | |
|             request.env.context.get('tz') or request.env.user.tz) | |
|         date_today = pytz.utc.localize(check_out).astimezone(user_tz) | |
|         formatted_time = datetime.strftime(date_today, '%H:%M:%S') | |
|         attendance = request.env['hr.attendance'].search( | |
|             [('employee_id', '=', employee_id.id), ('check_out', '=', False), | |
|              ('is_portal', '=', True)], | |
|             order="check_in desc", limit=1) | |
|         # If there is an attendance record with no check-out time, | |
|         # update it with the current time | |
|         if attendance: | |
|             check_out = datetime.now() | |
|             check_in = attendance.check_in | |
|             worked_hours = check_out - check_in | |
|             total_seconds = worked_hours.total_seconds() | |
|             hours = int(total_seconds / 3600) | |
|             minutes = int((total_seconds % 3600) / 60) | |
|             worked_hours_str = "{:02d}:{:02d}".format(hours, minutes) | |
|             hours, minutes = map(int, worked_hours_str.split(':')) | |
|             worked_hours_float = hours + minutes / 60.0 | |
|             attendance.write({ | |
|                 'check_out': check_out.strftime('%Y-%m-%d %H:%M:%S'), | |
|                 'worked_hours': worked_hours_float | |
|             }) | |
|         values = { | |
|             'name': employee_id.name, | |
|             'image': employee_id.image_1920, | |
|             'formatted_time': formatted_time | |
|         } | |
|         return request.render("web_portal_attendance.portal_last_checkout", | |
|                               values) | |
| 
 | |
|     @http.route(['/attendance/list', '/attendance/list/page/<int:page>'], | |
|                 type='http', website=True) | |
|     def attendance_search_sort_view(self, page=1, search=None, | |
|                                     search_in="Check In", | |
|                                     filterby="all", **kwargs): | |
|         """To search and filter in the list view of attendance""" | |
|         uid = request.session.uid | |
|         user_id = request.env['res.users'].browse(uid) | |
|         employee_id = request.env['hr.employee'].search( | |
|             [('user_id', '=', user_id.id)]) | |
|         search_list = { | |
|             'Work Hour': {'label': 'Work Hour', 'input': 'Work Hour', | |
|                           'domain': [('worked_hours', 'ilike', search)]}, | |
|             'Check In': {'label': 'Check In', 'input': 'Check In', | |
|                          'domain': [('check_in', 'ilike', search)]}, | |
|             'Check Out': {'label': 'Check Out', 'input': 'Check Out', | |
|                           'domain': [('check_out', 'ilike', search)]}, } | |
|         today = fields.Date.today() | |
|         last_week = today + relativedelta(weeks=-1) | |
|         last_month = today + relativedelta(months=-1) | |
|         last_year = today + relativedelta(years=-1) | |
|         searchbar_filters = { | |
|             'all': {'label': 'All', 'domain': []}, | |
|             'today': { | |
|                 'label': 'Today', | |
|                 'domain': [("check_in", ">=", | |
|                             fields.Datetime.to_string(fields.Datetime.today())), | |
|                            ("check_in", "<=", fields.Datetime.to_string( | |
|                                fields.Datetime.today().replace(hour=23, | |
|                                                                minute=59, | |
|                                                                second=59)))]}, | |
|             'week': { | |
|                 'label': 'Last Week', | |
|                 'domain': [ | |
|                     ('check_in', '>=', date_utils.start_of(last_week, "week")), | |
|                     ('check_in', '<=', date_utils.end_of(last_week, 'week'))]}, | |
|             'month': { | |
|                 'label': 'Last Month', | |
|                 'domain': [('check_in', '>=', | |
|                             date_utils.start_of(last_month, 'month')), | |
|                            ('check_in', '<=', | |
|                             date_utils.end_of(last_month, 'month'))]}, | |
|             'year': { | |
|                 'label': 'Last Year', | |
|                 'domain': [ | |
|                     ('check_in', '>=', date_utils.start_of(last_year, 'year')), | |
|                     ('check_in', '<=', date_utils.end_of(last_year, 'year'))]}} | |
|         search_domain = search_list[search_in]['domain'] | |
|         filter_domain = searchbar_filters[filterby]['domain'] | |
|         attendance_obj = request.env['hr.attendance'].search( | |
|             [('is_portal', '=', True), ('employee_id', '=', employee_id.id)]) | |
|         total_attendance = attendance_obj.search_count( | |
|             [('is_portal', '=', True), | |
|              ('employee_id', '=', | |
|               employee_id.id)] + search_domain + filter_domain) | |
|         page_detail = pager(url='/attendance/list', | |
|                             total=total_attendance, | |
|                             page=page, | |
|                             step=10, | |
|                             url_args={'search': search, | |
|                                       'search_in': search_in, | |
|                                       'filterby': filterby}) | |
|         attendance_domain = [('is_portal', '=', True), | |
|                              ('employee_id', '=', employee_id.id)] | |
|         if search_domain: | |
|             attendance_domain += search_domain | |
|         if filter_domain: | |
|             attendance_domain += filter_domain | |
|         attendance = attendance_obj.search( | |
|             attendance_domain, | |
|             limit=10, | |
|             offset=page_detail['offset']) | |
|         vals = { | |
|             'attendance': attendance, | |
|             'page_name': 'attendance', | |
|             'pager': page_detail, | |
|             'search': search, | |
|             'search_in': search_in, | |
|             'searchbar_inputs': search_list, | |
|             'default_url': '/attendance/list', | |
|             'searchbar_filters': OrderedDict(sorted(searchbar_filters.items())), | |
|             'filterby': filterby, | |
|         } | |
|         return request.render( | |
|             "web_portal_attendance.portal_list_attendance_order", vals)
 | |
| 
 |