1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.service.common import exp_version
from odoo import http, _
from odoo.http import request
from odoo.osv import expression
from odoo.tools import float_round, py_to_js_locale, SQL
from odoo.tools.image import image_data_uri
import datetime
class HrAttendance(http.Controller):
@staticmethod
def _get_company(token):
company = request.env['res.company'].sudo().search([('attendance_kiosk_key', '=', token)])
return company
@staticmethod
def _get_user_attendance_data(employee):
response = {}
if employee:
response = {
'id': employee.id,
'hours_today': float_round(employee.hours_today, precision_digits=2),
'hours_previously_today': float_round(employee.hours_previously_today, precision_digits=2),
'last_attendance_worked_hours': float_round(employee.last_attendance_worked_hours, precision_digits=2),
'last_check_in': employee.last_check_in,
'attendance_state': employee.attendance_state,
'display_systray': employee.company_id.attendance_from_systray,
}
return response
@staticmethod
def _get_employee_info_response(employee):
response = {}
if employee:
response = {
**HrAttendance._get_user_attendance_data(employee),
'employee_name': employee.name,
'employee_avatar': employee.image_256 and image_data_uri(employee.image_256),
'total_overtime': float_round(employee.total_overtime, precision_digits=2),
'kiosk_delay': employee.company_id.attendance_kiosk_delay * 1000,
'attendance': {'check_in': employee.last_attendance_id.check_in,
'check_out': employee.last_attendance_id.check_out},
'overtime_today': request.env['hr.attendance.overtime'].sudo().search([
('employee_id', '=', employee.id), ('date', '=', datetime.date.today()),
('adjustment', '=', False)]).duration or 0,
'use_pin': employee.company_id.attendance_kiosk_use_pin,
'display_overtime': employee.company_id.hr_attendance_display_overtime
}
return response
@staticmethod
def _get_geoip_response(mode, latitude=False, longitude=False):
return {
'city': request.geoip.city.name or _('Unknown'),
'country_name': request.geoip.country.name or request.geoip.continent.name or _('Unknown'),
'latitude': latitude or request.geoip.location.latitude or False,
'longitude': longitude or request.geoip.location.longitude or False,
'ip_address': request.geoip.ip,
'browser': request.httprequest.user_agent.browser,
'mode': mode
}
@http.route('/hr_attendance/kiosk_mode_menu/<int:company_id>', auth='user', type='http')
def kiosk_menu_item_action(self, company_id):
if request.env.user.has_group("hr_attendance.group_hr_attendance_manager"):
# Auto log out will prevent users from forgetting to log out of their session
# before leaving the kiosk mode open to the public. This is a prevention security
# measure.
if self.has_password():
request.session.logout(keep_db=True)
return request.redirect(request.env['res.company'].browse(company_id).attendance_kiosk_url)
else:
return request.not_found()
@http.route('/hr_attendance/kiosk_keepalive', auth='user', type='json')
def kiosk_keepalive(self):
request.session.touch()
return {}
@http.route(["/hr_attendance/<token>"], type='http', auth='public', website=True, sitemap=True)
def open_kiosk_mode(self, token, from_trial_mode=False):
company = self._get_company(token)
if not company:
return request.not_found()
else:
department_list = [{'id': dep["id"],
'name': dep["name"],
'count': dep["total_employee"]
} for dep in request.env['hr.department'].sudo().search_read(domain=[('company_id', '=', company.id)],
fields=["id",
"name",
"total_employee"])]
has_password = self.has_password()
if not from_trial_mode and has_password:
request.session.logout(keep_db=True)
if (from_trial_mode or not has_password):
kiosk_mode = "settings"
else:
kiosk_mode = company.attendance_kiosk_mode
version_info = exp_version()
return request.render(
'hr_attendance.public_kiosk_mode',
{
'kiosk_backend_info': {
'token': token,
'company_id': company.id,
'company_name': company.name,
'departments': department_list,
'kiosk_mode': kiosk_mode,
'from_trial_mode': from_trial_mode,
'barcode_source': company.attendance_barcode_source,
'lang': py_to_js_locale(company.partner_id.lang),
'server_version_info': version_info.get('server_version_info'),
},
}
)
@http.route('/hr_attendance/attendance_employee_data', type="json", auth="public")
def employee_attendance_data(self, token, employee_id):
company = self._get_company(token)
if company:
employee = request.env['hr.employee'].sudo().browse(employee_id)
if employee.company_id == company:
return self._get_employee_info_response(employee)
return {}
@http.route('/hr_attendance/attendance_barcode_scanned', type="json", auth="public")
def scan_barcode(self, token, barcode):
company = self._get_company(token)
if company:
employee = request.env['hr.employee'].sudo().search([('barcode', '=', barcode), ('company_id', '=', company.id)], limit=1)
if employee:
employee._attendance_action_change(self._get_geoip_response('kiosk'))
return self._get_employee_info_response(employee)
return {}
def manual_selection(self, token, employee_id, pin_code):
return self.manual_selection_with_geolocation(token, employee_id, pin_code)
@http.route('/hr_attendance/manual_selection', type="json", auth="public")
def manual_selection_with_geolocation(self, token, employee_id, pin_code, latitude=False, longitude=False):
company = self._get_company(token)
if company:
employee = request.env['hr.employee'].sudo().browse(employee_id)
if employee.company_id == company and ((not company.attendance_kiosk_use_pin) or (employee.pin == pin_code)):
employee.sudo()._attendance_action_change(self._get_geoip_response('kiosk', latitude=latitude, longitude=longitude))
return self._get_employee_info_response(employee)
return {}
@http.route('/hr_attendance/employees_infos', type="json", auth="public")
def employees_infos(self, token, limit, offset, domain):
company = self._get_company(token)
if company:
domain = expression.AND([domain, [('company_id', '=', company.id)]])
employees = request.env['hr.employee'].sudo().search_fetch(domain, ['id', 'display_name', 'job_id'],
limit=limit, offset=offset, order="name, id")
employees_data = [{
'id': employee.id,
'display_name': employee.display_name,
'job_id': employee.job_id.name,
'avatar': image_data_uri(employee.avatar_128)
} for employee in employees]
return {'records': employees_data, 'length': request.env['hr.employee'].sudo().search_count(domain)}
return []
@http.route('/hr_attendance/systray_check_in_out', type="json", auth="user")
def systray_attendance(self, latitude=False, longitude=False):
employee = request.env.user.employee_id
geo_ip_response = self._get_geoip_response(mode='systray',
latitude=latitude,
longitude=longitude)
employee._attendance_action_change(geo_ip_response)
return self._get_employee_info_response(employee)
@http.route('/hr_attendance/attendance_user_data', type="json", auth="user", readonly=True)
def user_attendance_data(self):
employee = request.env.user.employee_id
return self._get_user_attendance_data(employee)
def has_password(self):
# With this method we try to know whether it's the user is on trial mode or not.
# We assume that in trial, people have not configured their password yet and their password should be empty.
request.env.cr.execute(
SQL('''
SELECT COUNT(password)
FROM res_users
WHERE id=%(user_id)s
AND password IS NOT NULL
LIMIT 1
''', user_id=request.env.user.id))
return bool(request.env.cr.fetchone()[0])
@http.route('/hr_attendance/is_fresh_db', type="json", auth="public")
def is_fresh_db(self, token):
company = self._get_company(token)
if company:
users = request.env['res.users'].sudo().search([])
return len(users) == 1 and not users[0].employee_id.barcode
return False
@http.route('/hr_attendance/set_user_barcode', type="json", auth="public")
def set_user_barcode(self, token, barcode):
company = self._get_company(token)
if company and self.is_fresh_db(token):
request.env.user.employee_id.barcode = barcode
return True
return False
@http.route('/hr_attendance/set_settings', type="json", auth="public")
def set_attendance_settings(self, token, mode):
company = self._get_company(token)
if company:
request.env.user.company_id.attendance_kiosk_mode = mode
|