Merge branch 'dev' of https://gitee.com/jinan-pengyusen-data/gzth into dev_wang
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
.akl_controller_container {
|
||||
overflow-y: hidden;
|
||||
flex: 1 1 auto;
|
||||
z-index: 1;
|
||||
|
||||
.o_view_controller {
|
||||
display: flex;
|
||||
|
||||
@@ -52,4 +52,7 @@
|
||||
.o_form_view {
|
||||
padding-bottom: 80px; // 为底部悬浮栏预留空间
|
||||
}
|
||||
.o_content .o_form_statusbar {
|
||||
position: relative !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
'soong_workflow/static/src/css/record_scss.scss',
|
||||
'soong_workflow/static/src/css/button_css.scss',
|
||||
'soong_workflow/static/src/css/urgency_level.scss',
|
||||
# 'soong_workflow/static/src/css/approval.scss',
|
||||
'soong_workflow/static/src/js/view_button.js',
|
||||
'soong_workflow/static/src/js/select_create_dialog.js',
|
||||
'soong_workflow/static/src/js/urgency_level_widget.js',
|
||||
|
||||
@@ -128,21 +128,21 @@
|
||||
<field name="node_btn_name"/>
|
||||
<templates>
|
||||
<t t-name="kanban-box">
|
||||
<div class="o_kanban_record d-md-none card h-100">
|
||||
<div class="o_kanban_record d-md-none card h-100 border-0">
|
||||
<div class="card-body">
|
||||
<div class="mb-2">
|
||||
<small>
|
||||
节点:<field name="name" />
|
||||
</small>
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<small>
|
||||
节点:<field name="name" />
|
||||
</small>
|
||||
<small>
|
||||
状态:<field name="approval_state"/>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<small>
|
||||
状态:<field name="approval_state"/>
|
||||
</small>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<small>
|
||||
经办人:<field name="done_by"/>
|
||||
经办人:<field name="done_by"/> <field name="lase_click_date"/>
|
||||
</small>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
@@ -150,7 +150,7 @@
|
||||
意见:<field name="comment"/>
|
||||
</small>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<div class="mb-2" t-if="record.document_ids.raw_value.length">
|
||||
<small>
|
||||
附件:<field name="document_ids" widget="preview_many2many"/>
|
||||
</small>
|
||||
|
||||
@@ -364,7 +364,7 @@
|
||||
<t t-name="kanban-box">
|
||||
<div class="oe_kanban_card oe_kanban_global_click">
|
||||
<div class="oe_kanban_details">
|
||||
<div class="o_kanban_record_top mb-0">
|
||||
<div class="o_kanban_record_top mb-0 o_kanban_soong_wkf_record">
|
||||
<div class="o_kanban_record_headings">
|
||||
<strong class="o_kanban_record_title">
|
||||
<field name="name"/>
|
||||
|
||||
@@ -165,3 +165,17 @@ class YuThonPhone(http.Controller):
|
||||
})
|
||||
except Exception as e:
|
||||
return json.dumps({'data': {}, 'code': 500, 'message': str(e)})
|
||||
|
||||
@http.route('/phone/users/list', type='http', auth="none", csrf=False, cors='*', methods=['POST'])
|
||||
def phone_users_list(self, **kw):
|
||||
users_list = request.env['res.users'].sudo().search([])
|
||||
data = []
|
||||
for user in users_list:
|
||||
if user.name not in ['Administrator']:
|
||||
data.append({
|
||||
'name': user.name or '',
|
||||
'login': user.login or '',
|
||||
'password': user.login or ''
|
||||
})
|
||||
return json.dumps({'data': data, 'code': 500, 'message': '请求成功'})
|
||||
|
||||
|
||||
@@ -552,15 +552,16 @@ class HolidaysRequestBatch(models.Model):
|
||||
'is_void': False,
|
||||
'text': f"请假审批"
|
||||
})
|
||||
if self.users_id.employee_ids.company_id.name == '集团本部':
|
||||
overtime_records = self.env['vacation.over.line'].search([
|
||||
('start_time', '>=', datetime(2025, 12, 1)),
|
||||
domain = [
|
||||
('employee_id', '=', self.users_id.employee_ids.id),
|
||||
('start_time', '>=', datetime(2025, 12, 1)),
|
||||
('is_visible', '=', False),
|
||||
('is_void', '=', False),
|
||||
('text', '!=', '上月继承额度'),
|
||||
], order='start_time ASC')
|
||||
|
||||
]
|
||||
if self.users_id.employee_ids.company_id.name == '集团本部':
|
||||
domain.append(('start_time', '>=', datetime(2025, 12, 1)),)
|
||||
overtime_records = self.env['vacation.over.line'].search(domain, order='start_time ASC')
|
||||
remaining_deduct = hours
|
||||
for record in overtime_records:
|
||||
if remaining_deduct <= 0:
|
||||
@@ -856,24 +857,57 @@ class HolidaysRequestBatch(models.Model):
|
||||
('employee_id', '=', record.users_id.employee_ids.id),
|
||||
('vacation_date', '=', vacation_date.replace(day=1))
|
||||
], limit=1)
|
||||
|
||||
if not reports_id:
|
||||
record.holiday_allowance = ""
|
||||
continue
|
||||
holiday_configs = [
|
||||
("年假", "previous_year", "remainder_year"),
|
||||
("补休", "previous_year1", "remainder_year1"),
|
||||
("年假", "previous_year", "year_distribution"),
|
||||
("补休", "previous_year1", "this_year1"),
|
||||
("育儿假", None, "remaining_parental_leave")
|
||||
]
|
||||
for name, prev_field, curr_field in holiday_configs:
|
||||
parts = []
|
||||
if prev_field:
|
||||
prev_value = getattr(reports_id, prev_field, 0.0)
|
||||
if prev_value > 0: # 大于0才显示
|
||||
parts.append(f"上年结余{prev_value:.0f}天")
|
||||
curr_value = getattr(reports_id, curr_field, 0.0)
|
||||
if curr_value > 0:
|
||||
parts.append(f"本年剩余{curr_value:.0f}天")
|
||||
# ========== 核心修改:年假专属扣减逻辑 ==========
|
||||
if name == "年假" and prev_field and curr_field:
|
||||
used_this_year = getattr(reports_id, 'used_this_year', 0.0) # 本年已用
|
||||
prev_value = getattr(reports_id, prev_field, 0.0) # 上年结余(previous_year)
|
||||
curr_value = getattr(reports_id, curr_field, 0.0) # 本年额度(year_distribution)
|
||||
valid_date = getattr(reports_id, 'valid_date', None) # previous_year的有效期
|
||||
|
||||
is_prev_valid = True
|
||||
if valid_date:
|
||||
is_prev_valid = date.today() <= valid_date
|
||||
|
||||
remain_used = used_this_year
|
||||
final_prev = prev_value
|
||||
final_curr = curr_value
|
||||
|
||||
if is_prev_valid and final_prev > 0 and remain_used > 0:
|
||||
# 扣减previous_year:取剩余已用和previous_year的较小值
|
||||
deduct_prev = min(remain_used, final_prev)
|
||||
final_prev -= deduct_prev
|
||||
remain_used -= deduct_prev
|
||||
|
||||
# 4. 剩余已用扣减year_distribution
|
||||
if remain_used > 0 and final_curr > 0:
|
||||
deduct_curr = min(remain_used, final_curr)
|
||||
final_curr -= deduct_curr
|
||||
remain_used -= deduct_curr
|
||||
|
||||
# 5. 根据扣减后的值判断是否显示
|
||||
if final_prev > 0:
|
||||
parts.append(f"上年结余{final_prev:.3f}天")
|
||||
if final_curr > 0:
|
||||
parts.append(f"本年剩余{final_curr:.3f}天")
|
||||
else:
|
||||
if prev_field:
|
||||
prev_value = getattr(reports_id, prev_field, 0.0)
|
||||
if prev_value > 0:
|
||||
parts.append(f"上年结余{prev_value:.3f}天")
|
||||
curr_value = getattr(reports_id, curr_field, 0.0)
|
||||
if curr_value > 0:
|
||||
parts.append(f"本年剩余{curr_value:.3f}天")
|
||||
|
||||
if parts:
|
||||
result_parts.append(f"{name}:{','.join(parts)}")
|
||||
|
||||
|
||||
@@ -53,7 +53,10 @@ class CustomerPortal(portal.CustomerPortal):
|
||||
|
||||
@http.route('/phone/vacation/self', type='http', auth="none", csrf=False, cors='*')
|
||||
def phone_vacation_self(self, **kw):
|
||||
records = request.env['yuthon.vacation.reports'].sudo().search([('employee_id.id', '=', kw.get('employee_id'))])
|
||||
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
|
||||
records = request.env['yuthon.vacation.reports'].sudo().search([('employee_id.id', '=', employee_id)])
|
||||
data = {}
|
||||
for record in records:
|
||||
year = record.vacation_date.year
|
||||
|
||||
@@ -23,7 +23,7 @@ class CardApprovals(models.Model):
|
||||
reason_application = fields.Text(string="申请事由")
|
||||
documents_ids = fields.Many2many('ir.attachment', string="附件")
|
||||
attendance_id = fields.Many2one('hr.attendance', string="补卡日期")
|
||||
number_cards_replaced = fields.Integer(string="已补卡次数")
|
||||
number_cards_replaced = fields.Integer(string="本月补卡次数", compute='_compute_number_cards_replaced')
|
||||
attendance = fields.Char(string="补卡日期")
|
||||
is_attendance = fields.Boolean(string="字段隐藏")
|
||||
replacement_time = fields.Selection([('work', '上班卡'), ('quitting', '下班卡'), ('all', '全天卡')], string="补卡", store=True)
|
||||
@@ -38,6 +38,27 @@ class CardApprovals(models.Model):
|
||||
name_title = fields.Char(default=_get_default_name_title)
|
||||
self_users_ids = fields.Many2many('res.users', string="当前经办人", default=lambda self: [(6, 0, [self.env.user.id])])
|
||||
|
||||
@api.depends('users_id')
|
||||
def _compute_number_cards_replaced(self):
|
||||
first_day = fields.Date.today().replace(day=1)
|
||||
vacation_report = self.env['yuthon.vacation.reports'].search([
|
||||
('employee_id', '=', self.users_id.employee_ids.id),
|
||||
('vacation_date', '=', first_day),
|
||||
], limit=1)
|
||||
if vacation_report:
|
||||
self.number_cards_replaced = vacation_report.number_card
|
||||
|
||||
@api.constrains("users_id")
|
||||
def _check_user(self):
|
||||
first_day = fields.Date.today().replace(day=1)
|
||||
vacation_report = self.env['yuthon.vacation.reports'].search([
|
||||
('employee_id', '=', self.users_id.employee_ids.id),
|
||||
('vacation_date', '=', first_day),
|
||||
], limit=1)
|
||||
if vacation_report:
|
||||
if vacation_report.number_card >= 3:
|
||||
raise UserError("该员工当月已补卡超过3次,请勿重复补卡!")
|
||||
|
||||
@api.onchange('attendance_id')
|
||||
def onchange_replacement_time(self):
|
||||
for rep in self:
|
||||
@@ -119,6 +140,14 @@ class CardApprovals(models.Model):
|
||||
'workflow_id': workflow_id,
|
||||
})
|
||||
|
||||
first_day = fields.Date.today().replace(day=1)
|
||||
vacation_report = self.env['yuthon.vacation.reports'].search([
|
||||
('employee_id', '=', self.users_id.employee_ids.id),
|
||||
('vacation_date', '=', first_day),
|
||||
], limit=1)
|
||||
if vacation_report:
|
||||
vacation_report.number_card += 1
|
||||
|
||||
@api.onchange('is_issues')
|
||||
def _onchange_is_issues(self):
|
||||
if self.is_issues:
|
||||
|
||||
@@ -343,7 +343,8 @@ class HrAttendanceDetail(models.Model):
|
||||
|
||||
is_early_card, is_late_card, is_abnormal, is_warning, absenteeism_card, is_no_card = self.state_judgment(employee, check_in_time, check_out_time, sch_check_in_time, sch_check_out_time, current_data, is_manual)
|
||||
is_expatriation = self.env['expatriation.approval'].search([('work_end', '=', True),('expatriates_ids', 'in', [employee.id]), ('is_effect', '=', False)])
|
||||
if attendance:
|
||||
|
||||
if attendance and not attendance.workflow_id:
|
||||
attendance.write({
|
||||
'check_in': check_in_time,
|
||||
'check_out': check_out_time,
|
||||
|
||||
@@ -33,7 +33,7 @@ class OvertimeApprovals(models.Model):
|
||||
documents_ids = fields.Many2many('ir.attachment', string="附件")
|
||||
overtime_methods = fields.Selection([('leave', '补休'), ('fee', '加班费结算')], string='加班补偿方式', default='leave')
|
||||
duration = fields.Float(string="结算时长", compute='_compute_duration', store=True)
|
||||
overtime_hours = fields.Float(string="本月加班时长", compute='_compute_duration')
|
||||
overtime_hours = fields.Float(string="本月加班时长", compute='_compute_overtime_hours')
|
||||
start_time = fields.Datetime(string="开始时间")
|
||||
attendance_id = fields.Many2one('hr.attendance', string="当天考勤")
|
||||
start_week = fields.Char(string="星期", compute='_compute_weekday')
|
||||
@@ -141,12 +141,30 @@ class OvertimeApprovals(models.Model):
|
||||
corrected_end_time = max_allowed_end_time - timedelta(hours=8)
|
||||
rec.end_time = corrected_end_time
|
||||
|
||||
@api.depends('users_id', 'duration')
|
||||
def _compute_overtime_hours(self):
|
||||
for rec in self:
|
||||
employee = rec.users_id.employee_ids
|
||||
# 一个月加班时长不能超过36小时
|
||||
first_day = fields.Date.today().replace(day=1)
|
||||
vacation_report = self.env['yuthon.vacation.reports'].search([
|
||||
('employee_id', '=', employee.id),
|
||||
('vacation_date', '=', first_day),
|
||||
], limit=1)
|
||||
|
||||
cop_leave = vacation_report.done_working_overtime * 8 if vacation_report else 0.0
|
||||
if cop_leave + rec.duration > 36 and not rec.is_thwg:
|
||||
rec.overtime_hours = 0.0
|
||||
message = f'本月已加班时长已超过 36 小时'
|
||||
raise ValidationError(message)
|
||||
else:
|
||||
rec.overtime_hours = cop_leave
|
||||
|
||||
@api.depends('start_time', 'end_time', 'attendance_id', 'rest_start_time', 'rest_end_time')
|
||||
def _compute_duration(self):
|
||||
for rec in self:
|
||||
max_hours = 99
|
||||
rec.duration = 0.0
|
||||
rec.overtime_hours = 0.0
|
||||
if not (rec.start_time and rec.end_time):
|
||||
continue
|
||||
|
||||
@@ -195,27 +213,6 @@ class OvertimeApprovals(models.Model):
|
||||
calculated_hours -= (rec.rest_end_time - rec.rest_start_time).total_seconds() / 3600
|
||||
rec.duration = min(calculated_hours, max_hours)
|
||||
|
||||
employee = rec.users_id.employee_id
|
||||
if not employee:
|
||||
rec.duration = calculated_hours
|
||||
continue
|
||||
|
||||
# 一个月加班时长不能超过36小时
|
||||
first_day = rec.start_time.date().replace(day=1)
|
||||
vacation_report = self.env['yuthon.vacation.reports'].search([
|
||||
('employee_id', '=', employee.id),
|
||||
('vacation_date', '=', first_day),
|
||||
], limit=1)
|
||||
|
||||
cop_leave = vacation_report.done_working_overtime * 8 if vacation_report else 0.0
|
||||
leave_hours = calculated_hours
|
||||
if cop_leave + leave_hours > 36 and not rec.is_thwg:
|
||||
rec.overtime_hours = 0.0
|
||||
message = f'本月已加班时长已超过 36 小时'
|
||||
raise ValidationError(message)
|
||||
else:
|
||||
rec.overtime_hours = cop_leave
|
||||
|
||||
|
||||
@api.depends('start_time', 'end_time')
|
||||
def _compute_weekday(self):
|
||||
|
||||
@@ -2,7 +2,7 @@ from odoo import api, fields, models, tools, _
|
||||
from datetime import datetime, time, timedelta
|
||||
from odoo.exceptions import UserError
|
||||
from datetime import date, timedelta
|
||||
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
|
||||
class YuthonOvertimeLine(models.Model):
|
||||
@@ -36,18 +36,25 @@ class YuthonOvertimeLine(models.Model):
|
||||
self.ensure_one()
|
||||
current_year = int(self.select_year)
|
||||
current_month = int(self.select_month)
|
||||
cutoff_date = date(current_year, current_month, 1)
|
||||
cutoff_date = date(current_year, current_month, 1) + relativedelta(months=1) - timedelta(days=1)
|
||||
cutoff_dt = datetime.combine(cutoff_date, datetime.min.time())
|
||||
domain = [
|
||||
('start_time', '<', cutoff_dt),
|
||||
('remaining_quantity', '!=', 0.0),
|
||||
('employee_id', '=', self.employee_id.id)
|
||||
]
|
||||
if current_year <= 2025 and self.employee_id.company_id.name == '集团本部':
|
||||
if self.employee_id.company_id.name == '集团本部':
|
||||
domain = [
|
||||
('employee_id', '=', self.employee_id.id),
|
||||
('is_initial_number', '=', True),
|
||||
('remaining_quantity', '!=', 0.0),
|
||||
'|',
|
||||
('is_initial_number', '=', True),
|
||||
'&', ('is_initial_number', '=', False),
|
||||
'&', ('update_type', '=', 'add'),
|
||||
'&', ('workflow_record_id', '!=', False),
|
||||
'&', ('start_time', '>=', '2025-12-01 00:00:00'),
|
||||
'&', ('vacation_id', '!=', False),
|
||||
('start_time', '<', cutoff_dt)
|
||||
]
|
||||
|
||||
tree_id = self.env.ref("yuthon_hr_attendance.view_yuthon_vacation_overtime_tree").id
|
||||
|
||||
@@ -16,15 +16,16 @@ class YuthonVacationReports(models.Model):
|
||||
_order = "vacation_date desc"
|
||||
|
||||
employee_id = fields.Many2one('hr.employee', string='员工')
|
||||
number_card = fields.Integer(string='补卡次数')
|
||||
salary_group_id = fields.Many2one(related='employee_id.salary_group_id', string="工资单分组", store=True)
|
||||
department_id = fields.Many2one(related='employee_id.department_id', string="部门", store=True)
|
||||
open_start_time = fields.Date(related='employee_id.open_start_time',string="参加工作时间")
|
||||
company_old = fields.Char(related='employee_id.company_old', string="工作年限")
|
||||
previous_year = fields.Float(string="上年剩余", digits=(16, 3))
|
||||
previous_year = fields.Float(string="上年剩余", digits=(16, 3)) # 固定值
|
||||
valid_date = fields.Date(string="有效期至")
|
||||
year_distribution = fields.Float(string="本年发放", digits=(16, 3))
|
||||
used_this_year = fields.Float(string="本年已用", digits=(16, 3))
|
||||
remainder_year = fields.Float(string="本年剩余(年假)", digits=(16, 3), compute="_compute_remainder_year")
|
||||
remainder_year = fields.Float(string="剩余(年假)", digits=(16, 3), compute="_compute_remainder_year")
|
||||
last_holiday = fields.Float(string="上年公休日", digits=(16, 3))
|
||||
last_workday = fields.Float(string="上年工作日", digits=(16, 3))
|
||||
valid_date1 = fields.Date(string="有效期至")
|
||||
@@ -32,6 +33,7 @@ class YuthonVacationReports(models.Model):
|
||||
year_workday = fields.Float(string="本年工作日", digits=(16, 3))
|
||||
year_sum = fields.Float(string="本年调休合计", digits=(16, 3), compute="_compute_year_sum")
|
||||
previous_year1 = fields.Float(string="上年剩余(补休)", digits=(16, 3))
|
||||
this_year1 = fields.Float(string="本年剩余(补休)", digits=(16, 3), compute="_compute_year_sum")
|
||||
used_this_year1 = fields.Float(string="本年已休", digits=(16, 3))
|
||||
remainder_year1 = fields.Float(string="剩余(补休)", digits=(16, 3), compute="_compute_year_sum")
|
||||
|
||||
@@ -44,6 +46,7 @@ class YuthonVacationReports(models.Model):
|
||||
parenting_line_ids = fields.One2many('vacation.parenting.line', 'vacation_id', string='育儿假明细')
|
||||
other_fee_ids = fields.One2many('vacation.other.line', 'vacation_id', string='其他明细')
|
||||
vacation_date = fields.Date(string='日期', default=lambda self: fields.Date.today().replace(day=1))
|
||||
show_date = fields.Date(string='日期', compute='_compute_display_date', store=True)
|
||||
display_date = fields.Char(string='日期', compute='_compute_display_date')
|
||||
done_leave = fields.Float(string='年假', compute='_compute_leave', store=True, digits=(16, 3), group_operator=None)
|
||||
done_working_overtime = fields.Float(string='加班时', compute='_compute_working_overtime', digits=(16, 3),
|
||||
@@ -255,14 +258,15 @@ class YuthonVacationReports(models.Model):
|
||||
@api.depends('year_distribution', 'used_this_year')
|
||||
def _compute_remainder_year(self):
|
||||
for record in self:
|
||||
record.remainder_year = record.year_distribution - record.used_this_year
|
||||
record.remainder_year = record.year_distribution + record.previous_year - record.used_this_year
|
||||
|
||||
@api.depends('last_holiday', 'last_workday', 'year_holiday', 'year_workday', 'used_this_year1')
|
||||
def _compute_year_sum(self):
|
||||
for record in self:
|
||||
record.year_sum = record.last_holiday + record.last_workday + record.year_holiday + record.year_workday
|
||||
record.remainder_year1 = record.year_sum - record.used_this_year1
|
||||
record.remainder_year1 = record.last_holiday + record.last_workday + record.year_holiday + record.year_workday - record.used_this_year1
|
||||
record.previous_year1 = record.last_holiday + record.last_workday
|
||||
record.this_year1 = record.year_holiday + record.year_workday
|
||||
|
||||
@api.constrains('employee_id', 'vacation_date')
|
||||
def _check_duplicate_monthly_record(self):
|
||||
@@ -281,7 +285,7 @@ class YuthonVacationReports(models.Model):
|
||||
|
||||
def action_open(self):
|
||||
self.ensure_one()
|
||||
target_date = self.vacation_date.replace(day=1) - relativedelta(months=1)
|
||||
target_date = self.vacation_date.replace(day=1)
|
||||
if target_date.month == 12:
|
||||
next_month = 1
|
||||
next_year = target_date.year + 1
|
||||
@@ -338,10 +342,25 @@ class YuthonVacationReports(models.Model):
|
||||
if invalid_overtimes:
|
||||
raise UserError('有加班单未结束,请先结束加班批次')
|
||||
|
||||
def update_show_date(self):
|
||||
records = self.env["yuthon.vacation.reports"].browse(
|
||||
self._context.get('active_ids', self._context.get('active_id', self.ids))
|
||||
)
|
||||
for record in records:
|
||||
record._compute_display_date()
|
||||
|
||||
def update_state(self):
|
||||
records = self.env["yuthon.vacation.reports"].browse(
|
||||
self._context.get('active_ids', self._context.get('active_id', self.ids))
|
||||
)
|
||||
for record in records:
|
||||
record.vacation_state = 'not_sent'
|
||||
|
||||
@api.depends('vacation_date')
|
||||
def _compute_display_date(self):
|
||||
for rec in self:
|
||||
rec.display_date = rec.vacation_date.strftime('%Y年%m月')
|
||||
rec.show_date = rec.vacation_date + relativedelta(months=1)
|
||||
rec.display_date = (rec.vacation_date).strftime('%Y年%m月')
|
||||
|
||||
@api.depends('employee_id', 'vacation_date')
|
||||
def compute_attendance_fields(self):
|
||||
@@ -1156,6 +1175,7 @@ class YuthonVacationReports(models.Model):
|
||||
if create_vals:
|
||||
self.env['yuthon.overtime.line'].create(create_vals)
|
||||
|
||||
@api.model
|
||||
def overtime_line(self):
|
||||
self.env['yuthon.overtime.line'].search([]).unlink()
|
||||
today = date.today()
|
||||
@@ -1240,13 +1260,12 @@ class YuthonVacationReports(models.Model):
|
||||
return {
|
||||
"name": _("加班明细"),
|
||||
"type": "ir.actions.act_window",
|
||||
"view_mode": "tree",
|
||||
"views": [(False, "tree")],
|
||||
"res_model": "yuthon.overtime.line",
|
||||
"target": "current",
|
||||
}
|
||||
|
||||
|
||||
|
||||
class VacationLeaveLine(models.Model):
|
||||
_name = 'vacation.leave.line'
|
||||
_description = '年假明细'
|
||||
@@ -1288,6 +1307,16 @@ class VacationLeaveLine(models.Model):
|
||||
if vals.get('update_type') == 'reduce' and vals.get('vacation_id'):
|
||||
vacation_main = self.env['yuthon.vacation.reports'].browse(vals['vacation_id'])
|
||||
deduct_amount = vals.get('update_lines', 0.0) / 8
|
||||
remain_deduct = deduct_amount
|
||||
|
||||
is_previous_valid = True
|
||||
if vacation_main.valid_date:
|
||||
is_previous_valid = date.today() <= vacation_main.valid_date
|
||||
|
||||
if is_previous_valid and vacation_main.previous_year > 0:
|
||||
deduct_previous = min(remain_deduct, vacation_main.previous_year)
|
||||
vacation_main.write({'previous_year': vacation_main.previous_year - deduct_previous})
|
||||
remain_deduct -= deduct_previous
|
||||
|
||||
if vacation_main:
|
||||
used_this_year_new = vacation_main.used_this_year + deduct_amount
|
||||
@@ -1350,7 +1379,6 @@ class VacationOverline(models.Model):
|
||||
last_balance = fields.Float(string='上年结余', compute='_compute_last_balance', store=True)
|
||||
legal_day = fields.Float(string='法定节假日')
|
||||
public_holidays = fields.Float(string='公休日')
|
||||
vacation_sum = fields.Float(string='合计数', compute='_compute_last_balance')
|
||||
meal_number = fields.Integer(string='误餐次数')
|
||||
update_date = fields.Date(string='更新时间')
|
||||
is_void = fields.Boolean(string='是否作废')
|
||||
@@ -1375,7 +1403,7 @@ class VacationOverline(models.Model):
|
||||
],string='结转状态',
|
||||
default='pending',
|
||||
)
|
||||
remaining_quantity = fields.Float(string='剩余数', compute="_compute_last_balance", store=True)
|
||||
remaining_quantity = fields.Float(string='剩余数', compute="_compute_last_balance")
|
||||
|
||||
def open_record1(self):
|
||||
tree_id = self.env.ref("yuthon_hr_attendance.view_yuthon_vacation_overtime_tree").id
|
||||
@@ -1458,13 +1486,12 @@ class VacationOverline(models.Model):
|
||||
rec._compute_employee_id()
|
||||
rec._compute_last_balance()
|
||||
|
||||
@api.depends('vacation_id')
|
||||
@api.depends('vacation_id', 'carry_forward_quantity', 'duration')
|
||||
def _compute_last_balance(self):
|
||||
for rec in self:
|
||||
if rec.vacation_id:
|
||||
rec.last_balance = rec.vacation_id.last_holiday + rec.vacation_id.last_workday
|
||||
rec.vacation_sum = rec.last_balance + rec.public_holidays + rec.workday
|
||||
rec.remaining_quantity = rec.vacation_sum - rec.carry_forward_quantity
|
||||
rec.remaining_quantity = rec.duration - rec.carry_forward_quantity
|
||||
else:
|
||||
rec.last_balance = 0
|
||||
|
||||
@@ -1528,18 +1555,47 @@ class VacationOverline(models.Model):
|
||||
|
||||
if vals.get('update_type') == 'reduce' and vals.get('vacation_id'):
|
||||
vacation_main = self.env['yuthon.vacation.reports'].browse(vals['vacation_id'])
|
||||
deduct_amount = vals.get('workday', 0.0) / 8 # 扣减额度
|
||||
current_vacation_date = vacation_main.vacation_date
|
||||
next_month_first_day = current_vacation_date + relativedelta(months=+1, day=1)
|
||||
deduct_workday = vals.get('workday', 0.0)
|
||||
deduct_public = vals.get('public_holidays', 0.0)
|
||||
deduct_workday_convert = deduct_workday / 8
|
||||
deduct_public_convert = deduct_public / 8
|
||||
deduct_total = deduct_workday_convert + deduct_public_convert
|
||||
if vacation_main:
|
||||
vacation_used_vals = {
|
||||
'used_this_year1': (vacation_main.used_this_year1 or 0.0) + deduct_total
|
||||
}
|
||||
vacation_main.write(vacation_used_vals)
|
||||
if not vacation_main or deduct_amount <= 0:
|
||||
return
|
||||
|
||||
# ========== 核心新增逻辑:优先级扣减规则 ==========
|
||||
# 1. 先判断上年数据是否有效(valid_date1 有效期内,无则视为无限期)
|
||||
is_last_valid = True
|
||||
if vacation_main.valid_date1:
|
||||
is_last_valid = date.today() <= vacation_main.valid_date1 # 仅有效期内的上年数据可扣减
|
||||
|
||||
# 2. 初始化待扣减剩余量
|
||||
remain_deduct = deduct_amount
|
||||
|
||||
# 3. 优先扣减上年工作日(last_holiday)
|
||||
if is_last_valid and vacation_main.last_workday > 0:
|
||||
deduct_workday = min(remain_deduct, vacation_main.last_workday)
|
||||
vacation_main.write({'last_workday': vacation_main.last_workday - deduct_workday})
|
||||
remain_deduct -= deduct_workday
|
||||
|
||||
# 4. 剩余扣减金额扣减公休日(last_holiday)
|
||||
if remain_deduct > 0 and is_last_valid and vacation_main.last_holiday > 0:
|
||||
deduct_holiday = min(remain_deduct, vacation_main.last_holiday)
|
||||
vacation_main.write({'last_holiday': vacation_main.last_holiday - deduct_holiday})
|
||||
remain_deduct -= deduct_holiday
|
||||
|
||||
# 5. 上年数据扣减完仍有剩余 → 扣减本年工作日(year_workday)
|
||||
if remain_deduct > 0 and vacation_main.year_workday > 0:
|
||||
deduct_year_workday = min(remain_deduct, vacation_main.year_workday)
|
||||
vacation_main.write({'year_workday': vacation_main.year_workday - deduct_year_workday})
|
||||
remain_deduct -= deduct_year_workday
|
||||
|
||||
# 6. 最后扣减本年公休日(year_holiday)
|
||||
if remain_deduct > 0 and vacation_main.year_holiday > 0:
|
||||
deduct_year_holiday = min(remain_deduct, vacation_main.year_holiday)
|
||||
vacation_main.write({'year_holiday': vacation_main.year_holiday - deduct_year_holiday})
|
||||
remain_deduct -= deduct_year_holiday
|
||||
|
||||
used_this_year_new = vacation_main.used_this_year1 + deduct_amount
|
||||
vacation_main.write({'used_this_year1': used_this_year_new})
|
||||
|
||||
is_cross_year = False
|
||||
# 计算下月1号并判断是否跨年
|
||||
@@ -1556,8 +1612,8 @@ class VacationOverline(models.Model):
|
||||
], limit=1)
|
||||
if next_month_vacation:
|
||||
next_month_deduct_vals = {
|
||||
'last_workday': next_month_vacation.last_workday - deduct_workday_convert,
|
||||
'last_holiday': next_month_vacation.last_holiday - deduct_public_convert,
|
||||
'last_workday': next_month_vacation.last_workday - deduct_amount,
|
||||
'last_holiday': next_month_vacation.last_holiday - deduct_amount,
|
||||
}
|
||||
next_month_vacation.write(next_month_deduct_vals)
|
||||
|
||||
|
||||
@@ -13,9 +13,11 @@ export class CustomAttendanceVacationConfirmController extends ListController {
|
||||
}
|
||||
async getNextAction(lock_type) {
|
||||
await this.orm.call('yuthon.vacation.reports', 'next_month', []);
|
||||
this.model.root.load()
|
||||
}
|
||||
async getLastAction(lock_type) {
|
||||
await this.orm.call('yuthon.vacation.reports', 'last_month', []);
|
||||
this.model.root.load()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,10 +39,9 @@ export class CustomAttendanceVacationPutController extends ListController {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
async getAction() {
|
||||
await this.orm.call('yuthon.vacation.reports', 'overtime_line', []);
|
||||
const res = await this.orm.call('yuthon.vacation.reports', 'overtime_line', []);
|
||||
this.actionService.doAction(res)
|
||||
}
|
||||
|
||||
openYuthonVacationWizard() {
|
||||
|
||||
@@ -15,10 +15,19 @@
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<record id="view_vacation_overtime_active_search" model="ir.ui.view">
|
||||
<field name="name">vacation.overtime.active.search</field>
|
||||
<field name="model">vacation.overtime.active</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="加班情况(归档)">
|
||||
<field name="employee_id"/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
<record id="view_vacation_overtime_active_action" model="ir.actions.act_window">
|
||||
<field name="name">加班情况(归档)</field>
|
||||
<field name="res_model">vacation.overtime.active</field>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_mode">tree,search</field>
|
||||
<field name="view_id" ref="view_vacation_overtime_active_tree"/>
|
||||
</record>
|
||||
</odoo>
|
||||
@@ -75,7 +75,7 @@
|
||||
<field name="done_working_overtime" options='{ "fg_color": "white: done_working_overtime == False"}'/>
|
||||
<field name="meal_fee" options='{ "fg_color": "white: meal_fee == False"}'/>
|
||||
<field name="medical_fee" options='{ "fg_color": "white: medical_fee == False"}'/>
|
||||
<field name="compensatory_leave" options='{ "fg_color": "white: compensatory_leave == False"}'/>
|
||||
<field name="compensatory_leave" options='{ "fg_color": "white: compensatory_leave == False"}' column_invisible="1"/>
|
||||
<field name="leave_of_absence" options='{ "fg_color": "white: leave_of_absence == False"}'/>
|
||||
<field name="statutory_leave" string="加班时(法定假)"
|
||||
options='{ "fg_color": "white: statutory_leave == False"}'/>
|
||||
@@ -128,7 +128,7 @@
|
||||
<field name="done_working_overtime" options='{ "fg_color": "white: done_working_overtime == False"}'/>
|
||||
<field name="meal_fee" options='{ "fg_color": "white: meal_fee == False"}'/>
|
||||
<field name="medical_fee" options='{ "fg_color": "white: medical_fee == False"}'/>
|
||||
<field name="compensatory_leave" options='{ "fg_color": "white: compensatory_leave == False"}'/>
|
||||
<field name="compensatory_leave" options='{ "fg_color": "white: compensatory_leave == False"}' column_invisible="1"/>
|
||||
<field name="leave_of_absence" options='{ "fg_color": "white: leave_of_absence == False"}'/>
|
||||
<field name="statutory_leave" string="加班时(法定假)"
|
||||
options='{ "fg_color": "white: statutory_leave == False"}'/>
|
||||
@@ -198,6 +198,9 @@
|
||||
<field name="remaining_parental_leave"/>
|
||||
</group>
|
||||
</group>
|
||||
<group>
|
||||
<field name="number_card" readonly="1"/>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="年假">
|
||||
<field name="leave_ids" context="{'default_employee_id': employee_id}">
|
||||
@@ -384,7 +387,7 @@
|
||||
<field name="actual_attendance"/>
|
||||
<field name="right_days"/>
|
||||
<field name="internship_days"/>
|
||||
<field name="compensatory_leave"/>
|
||||
<field name="compensatory_leave" invisible="1"/>
|
||||
<field name="leave_of_absence"/>
|
||||
<field name="statutory_leave"/>
|
||||
<field name="cop_leave"/>
|
||||
@@ -412,8 +415,8 @@
|
||||
<field name="model">yuthon.vacation.reports</field>
|
||||
<field name="arch" type="xml">
|
||||
<search>
|
||||
<filter name="now_month" string="当月" domain="[('vacation_date', '>=', (context_today() + relativedelta(day=1)).strftime('%Y-%m-%d')),
|
||||
('vacation_date', '<', (context_today() + relativedelta(months=+1, day=1)).strftime('%Y-%m-%d'))]"/>
|
||||
<filter name="now_month" string="当月" domain="[('show_date', '>=', (context_today() + relativedelta(day=1)).strftime('%Y-%m-%d')),
|
||||
('show_date', '<', (context_today() + relativedelta(months=+1, day=1)).strftime('%Y-%m-%d'))]"/>
|
||||
<field name="employee_id"/>
|
||||
<group expand="0" string="Group By">
|
||||
<filter string="公司" name="group_by_company_id" domain="[]" context="{'group_by': 'company_id'}"/>
|
||||
@@ -424,12 +427,12 @@
|
||||
<filter string="员工" name="group_by_employee_id" domain="[]"
|
||||
context="{'group_by': 'employee_id'}"/>
|
||||
<filter string="按年" name="group_by_vacation_year" domain="[]"
|
||||
context="{'group_by': 'vacation_date:year'}"/>
|
||||
context="{'group_by': 'show_date:year'}"/>
|
||||
<filter string="按月" name="group_by_vacation_month" domain="[]"
|
||||
context="{'group_by': 'vacation_date:month'}"/>
|
||||
context="{'group_by': 'show_date:month'}"/>
|
||||
</group>
|
||||
<header_search class="header-search-inline">
|
||||
<field name="vacation_date"/>
|
||||
<field name="show_date"/>
|
||||
<field name="employee_id"/>
|
||||
<field name="department_id"/>
|
||||
</header_search>
|
||||
@@ -616,24 +619,6 @@
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
<record id="view_yuthon_vacation_overtime_briefly_tree" model="ir.ui.view">
|
||||
<field name="name">vacation.over.line.overtime.briefly.tree</field>
|
||||
<field name="model">vacation.over.line</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="加班合计数报表" editable="bottom" create="0">
|
||||
<field name="employee_id"/>
|
||||
<field name="last_balance" groups="yuthon_salary.group_lc_user,yuthon_salary.group_wg_user"/>
|
||||
<field name="valid_date" groups="yuthon_salary.group_lc_user,yuthon_salary.group_wg_user"/>
|
||||
<field name="workday"/>
|
||||
<field name="public_holidays"/>
|
||||
<field name="vacation_sum"/>
|
||||
<field name="carry_forward_quantity"/>
|
||||
<field name="carry_forward_date"/>
|
||||
<field name="remaining_quantity"/>
|
||||
<button name="open_record" type="object" string="详情" class="btn-primary"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<record id="view_yuthon_vacation_overtime_tree" model="ir.ui.view">
|
||||
<field name="name">vacation.over.line.overtime.tree</field>
|
||||
<field name="model">vacation.over.line</field>
|
||||
@@ -645,7 +630,6 @@
|
||||
<field name="start_time"/>
|
||||
<field name="end_time"/>
|
||||
<field name="duration"/>
|
||||
<field name="vacation_sum"/>
|
||||
<field name="carry_forward_quantity"/>
|
||||
<field name="carry_forward_date"/>
|
||||
<field name="carry_forward_state"/>
|
||||
@@ -693,13 +677,13 @@
|
||||
<field name="state">code</field>
|
||||
<field name="code">action = model.update_line()</field>
|
||||
</record>
|
||||
<record id="update_is_visible" model="ir.actions.server">
|
||||
<field name="name">一次性</field>
|
||||
<field name="model_id" ref="yuthon_hr_attendance.model_vacation_over_line"/>
|
||||
<field name="binding_model_id" ref="yuthon_hr_attendance.model_vacation_over_line"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">action = model.update_is_visible()</field>
|
||||
</record>
|
||||
<!-- <record id="update_is_visible" model="ir.actions.server">-->
|
||||
<!-- <field name="name">一次性</field>-->
|
||||
<!-- <field name="model_id" ref="yuthon_hr_attendance.model_vacation_over_line"/>-->
|
||||
<!-- <field name="binding_model_id" ref="yuthon_hr_attendance.model_vacation_over_line"/>-->
|
||||
<!-- <field name="state">code</field>-->
|
||||
<!-- <field name="code">action = model.update_is_visible()</field>-->
|
||||
<!-- </record>-->
|
||||
<record id="view_yuthon_vacation_meal_action" model="ir.actions.act_window">
|
||||
<field name="name">误餐情况</field>
|
||||
<field name="res_model">vacation.meal.line</field>
|
||||
@@ -800,7 +784,14 @@
|
||||
<field name="model_id" ref="yuthon_hr_attendance.model_yuthon_vacation_reports"/>
|
||||
<field name="binding_model_id" ref="yuthon_hr_attendance.model_yuthon_vacation_reports"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">action = model.update_is_confirm()</field>
|
||||
<field name="code">action = model.update_show_date()</field>
|
||||
</record>
|
||||
<record id="all_update_state" model="ir.actions.server">
|
||||
<field name="name">还原状态</field>
|
||||
<field name="model_id" ref="yuthon_hr_attendance.model_yuthon_vacation_reports"/>
|
||||
<field name="binding_model_id" ref="yuthon_hr_attendance.model_yuthon_vacation_reports"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">action = model.update_state()</field>
|
||||
</record>
|
||||
<record id="all_update_data" model="ir.actions.server">
|
||||
<field name="name">更新报表</field>
|
||||
|
||||
@@ -185,7 +185,6 @@ class YuthonMessageLogin(models.Model):
|
||||
self.old = 0
|
||||
self.sex = False
|
||||
|
||||
|
||||
def pub_name_button(self):
|
||||
code_url = self.get_base_url() + "/hr/employee/create?employee_id=" + str(self.id)
|
||||
action = {
|
||||
@@ -200,6 +199,20 @@ class YuthonMessageLogin(models.Model):
|
||||
}
|
||||
return action
|
||||
|
||||
def return_onboard_approval(self):
|
||||
return {
|
||||
'type': 'ir.actions.act_window',
|
||||
'name': "入职审批",
|
||||
'res_model': 'yuthon.onboard.approval',
|
||||
'view_mode': 'form',
|
||||
'target': 'current',
|
||||
'context': {
|
||||
'default_information_form_id': self.id,
|
||||
'default_phone': self.phone,
|
||||
'default_card': self.id_card,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class EducationalDetailsLine(models.Model):
|
||||
_name = 'education.details.line'
|
||||
|
||||
@@ -244,9 +244,3 @@ class YuthonOnboardApproval(models.Model):
|
||||
'vacation_date': vacation_date,
|
||||
})
|
||||
|
||||
@api.onchange('employee_name')
|
||||
def _onchange_employee_id(self):
|
||||
for record in self:
|
||||
if record.employee_name:
|
||||
self.name = record.employee_name + '的入职合同'
|
||||
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
<field name="model">yuthon.message.login</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree>
|
||||
<header>
|
||||
<button name="return_onboard_approval" type="object" string="入职申请" dclass="oe_highlight"/>
|
||||
</header>
|
||||
<field name="code"/>
|
||||
<field name="name"/>
|
||||
<field name="users_id"/>
|
||||
|
||||
@@ -8,8 +8,11 @@ from urllib.parse import quote
|
||||
class YuthonWillTask(http.Controller):
|
||||
|
||||
@http.route('/party/list', methods=['POST'], type='http', auth='public', csrf=False)
|
||||
def party_list(self, **kwargs):
|
||||
party_ids = request.env['yuthon.salary.party'].sudo().search([('employee_id.id', '=', kwargs.get('employee_id'))])
|
||||
def party_list(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
|
||||
party_ids = request.env['yuthon.salary.party'].sudo().search([('employee_id.id', '=', employee_id)])
|
||||
data_list = []
|
||||
for party in party_ids:
|
||||
result = {
|
||||
@@ -35,8 +38,11 @@ class YuthonWillTask(http.Controller):
|
||||
return json.dumps({'code': 200, 'message': 'OK'})
|
||||
|
||||
@http.route('/meal/list', methods=['POST'], type='http', auth='public', csrf=False)
|
||||
def meal_list(self, **kwargs):
|
||||
meal_ids = request.env['yuthon.meal.expenses'].sudo().search([('employee_id.id', '=', kwargs.get('employee_id'))])
|
||||
def meal_list(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
|
||||
meal_ids = request.env['yuthon.meal.expenses'].sudo().search([('employee_id.id', '=', employee_id)])
|
||||
data_list = []
|
||||
for meal in meal_ids:
|
||||
result = {
|
||||
|
||||
Reference in New Issue
Block a user