Files
gzth/yuthon_hr_attendance/controllers/portal.py
T
2026-08-14 15:50:57 +08:00

159 lines
8.3 KiB
Python

# -*- coding: utf-8 -*-
import binascii, json
from odoo import fields, http, SUPERUSER_ID, _
from odoo.exceptions import AccessError, MissingError, ValidationError
from odoo.http import request
from ....addons.portal.controllers import portal
from datetime import datetime, date, time, timedelta
from dateutil.relativedelta import relativedelta
class CustomerPortal(portal.CustomerPortal):
@http.route(['/my/attendance/month/detail/<int:attendance_id>'], type='http', auth="public", website=True)
def portal_attendance_month_detail_page(self, attendance_id, report_type=None, access_token=None, message=False, download=False, **kw):
# 后期有需求的话可以进行加密处理数据,包括请求地址进行加密处理数据
try:
attendance_sudo = self._document_check_access('hr.attendance.month.detail', attendance_id, access_token=access_token)
except (AccessError, MissingError):
return request.redirect('/my')
values = {
'attendance_month': attendance_sudo,
'message': message,
'report_type': 'html',
'res_company': attendance_sudo.employee_id.user_id.company_id,
}
return request.render('yuthon_hr_attendance.attendance_month_portal_template', values)
@http.route(['/my/attendance/month/detail/<int:attendance_id>/accept'], type='json', auth="public", website=True)
def portal_attendance_month_detail_quote_accept(self, attendance_id, access_token=None, name=None, signature=None):
# 后期有需求的话可以进行加密处理数据,包括请求地址进行加密处理数据
access_token = access_token or request.httprequest.args.get('access_token')
try:
attendance_sudo = self._document_check_access('hr.attendance.month.detail', attendance_id, access_token=access_token)
except (AccessError, MissingError):
return {'error': _('无效的信息')}
try:
attendance_sudo.write({
'signed_by': name,
'signed_on': fields.Datetime.now(),
'signature': signature,
'state': "confirmed"
})
request.env.cr.commit()
except (TypeError, binascii.Error) as e:
return {'error': _('无效的签名.')}
query_string = '&message=sign_ok'
return {
'force_refresh': True,
'redirect_url': attendance_sudo.get_portal_url(query_string=query_string),
}
@http.route('/phone/vacation/self', type='http', auth="none", csrf=False, cors='*')
def phone_vacation_self(self, **kw):
users_id = int(kw.get('users_id'))
user = request.env['res.users'].sudo().browse(int(users_id))
employee_id = user.with_company(user.company_id.id).employee_id.id
employee = request.env['hr.employee'].sudo().browse(employee_id)
records = request.env['yuthon.vacation.reports'].sudo().search([('employee_id.id', '=', employee_id)])
data = {}
for record in records:
year = record.vacation_date.year
key = f'{year}年'
if key not in data:
data[key] = []
vacation_state = '已确认' if record.vacation_state == 'confirmed' else '待确认'
# 检查是否有未办结的人力流程
has_pending, pending_tip = record._has_pending_hr_workflow(employee_id, record.vacation_date)
can_confirm = record.vacation_state != 'confirmed' and not has_pending
data[key].append({
'id': record.id,
'state': vacation_state,
'month': record.vacation_date.month,
# 'can_confirm': can_confirm,
# 'pending_tip': pending_tip if has_pending else '',
})
return json.dumps({'data': data, 'code': 200, 'message': ''})
@http.route('/phone/vacation/self/detail', type='http', auth="none", csrf=False, cors='*')
def phone_vacation_self_detail(self, **kw):
record = request.env['yuthon.vacation.reports'].sudo().search([('id', '=', kw.get('id'))])
def format_vacation_value(value, unit, multiply=1):
num = float(value or 0) * multiply
if num == 0:
return "0"
if unit == "小时":
return f"{round(num, 1)}{unit}"
return f"{num}{unit}"
# 检查是否有未办结的人力流程
employee_id = record.employee_id.id
has_pending, pending_tip = record._has_pending_hr_workflow(employee_id, record.vacation_date)
can_confirm = record.vacation_state != 'confirmed' and not has_pending
data = {
'state': '已确认' if record.vacation_state == 'confirmed' else '待确认',
# 'can_confirm': can_confirm,
# 'pending_tip': pending_tip if has_pending else '',
'日期': record.display_date,
'应到': format_vacation_value(record.should_attendance, '天'),
'实到': format_vacation_value(record.actual_attendance, '天'),
'外派': format_vacation_value(record.expatriation, '天'),
'迟到': format_vacation_value(record.is_late_card, '次'),
'早退': format_vacation_value(record.is_early_card, '次'),
'缺卡': format_vacation_value(record.is_no_card, '次'),
'旷工': format_vacation_value(record.is_work, '次'),
'异常': format_vacation_value(record.is_abnormal, '次'),
'年假': format_vacation_value(record.done_leave, '天'),
'加班时': format_vacation_value(record.done_working_overtime, '小时'),
'补休': format_vacation_value(record.cop_leave, '小时', 8),
'调休': format_vacation_value(record.compensatory_leave, '天'),
'事假': format_vacation_value(record.leave_of_absence, '天'),
'加班时(法定假)': format_vacation_value(record.statutory_leave, '小时'),
'育儿假': format_vacation_value(record.parental_leave, '天'),
'值班调休': format_vacation_value(record.duty_off_leave, '天'),
'婚假': format_vacation_value(record.marriage_leave, '天'),
'产假': format_vacation_value(record.maternity_leave, '天'),
'陪产假': format_vacation_value(record.paternity_leave, '天'),
'计生假': format_vacation_value(record.family_planning_leave, '天'),
'丧假': format_vacation_value(record.bereavement_leave, '天'),
'探亲假': format_vacation_value(record.home_visit_leave, '天'),
'家长会假': format_vacation_value(record.parents_meeting_leave, '天'),
'病假(普通)': format_vacation_value(record.general_sick_leave, '天'),
'病假(住院期)': format_vacation_value(record.hospital_sick_leave, '天'),
'病假(出院恢复期)': format_vacation_value(record.recovery_sick_leave, '天'),
'考试假': format_vacation_value(record.exam_leave, '天'),
}
return json.dumps({'data': data, 'code': 200, 'message': ''})
@http.route('/phone/vacation/self/status', type='http', auth="none", csrf=False, cors='*')
def phone_vacation_self_status(self, **kw):
record_id = request.env['yuthon.vacation.reports'].sudo().search([('id', '=', kw.get('id'))])
if not record_id:
return json.dumps({'code': 400, 'message': '记录不存在'})
# 检查是否有未办结的人力流程
has_pending, pending_tip = record_id._has_pending_hr_workflow(
record_id.employee_id.id, record_id.vacation_date)
if has_pending:
return json.dumps({'code': 403, 'message': pending_tip})
record_id.write({'vacation_state': 'confirmed'})
return json.dumps({'code': 200, 'message': 'OK'})
@http.route('/phone/attendance_summary/btn_list', type='http', auth="none", csrf=False, cors='*')
def phone_attendance_summary_btn_list(self, **kw):
approvals = request.env['soong.workflow'].sudo().search([('name', 'in', ['补卡', '请假', '外出'])])
menu_id = request.env.ref('soong_workflow.menu_workflow_approval_request_new').sudo()
data = {
'records': {a.name: a.id for a in approvals},
'menu_id': menu_id.id,
'action_id': menu_id.action.id
}
return json.dumps({'code': 200, 'message': 'OK', 'data': data})