diff --git a/yuthon_holiday/models/inherit_hr_leave.py b/yuthon_holiday/models/inherit_hr_leave.py
index b0a35037d..70a3e513c 100644
--- a/yuthon_holiday/models/inherit_hr_leave.py
+++ b/yuthon_holiday/models/inherit_hr_leave.py
@@ -353,7 +353,7 @@ class HolidaysRequestBatch(models.Model):
column1='leave_id',
column2='attachment_id'
)
- holiday_allowance = fields.Char(string="可用额度", compute='_compute_holiday_allowance', store=True)
+ holiday_allowance = fields.Text(string="可用额度", compute='_compute_holiday_allowance', store=True)
active = fields.Boolean('Active', default=True, tracking=True)
def _get_default_name_title(self):
@@ -365,7 +365,7 @@ class HolidaysRequestBatch(models.Model):
@api.onchange('is_day')
def _onchange_is_day(self):
if not self.is_day:
- self.leave_ids = [(5, 0, 0)] # 清空One2many字段
+ self.leave_ids = [(5, 0, 0)]
@api.onchange('is_hour')
def _onchange_is_hour(self):
@@ -411,7 +411,7 @@ class HolidaysRequestBatch(models.Model):
other_leave_types = [
'产假', '事假', '法定假', '调休', '补休', '值班调休',
'婚假', '陪产假', '计生假', '丧假', '探亲假',
- '家长会假', '病假(普通)', '病假(住院期)',
+ '家长会假', '病假(普通)', '病假(住院期)', '育儿假',
'病假(出院恢复期)', '考试假'
]
for leave_type in other_leave_types:
@@ -855,9 +855,9 @@ class HolidaysRequestBatch(models.Model):
('vacation_date', '=', vacation_date.replace(day=1))
], limit=1)
if reports_id:
- leave_days = reports_id.leave
- overtime_days = reports_id.working_overtime
- record.holiday_allowance = f"年假{leave_days:.3f}天, 补休{overtime_days:.3f}天"
+ record.holiday_allowance = (f"本年剩余(年假){reports_id.remainder_year:.3f}天, 上年剩余(年假){reports_id.previous_year:.3f}天\n"
+ f"本年剩余(补休){reports_id.remainder_year1:.3f}天, 上年剩余(补休){reports_id.previous_year1:.3f}天\n "
+ f"育儿假{reports_id.remaining_parental_leave:.3f}天")
def action_print_leave_batch(self):
"""按钮触发打印请假单"""
diff --git a/yuthon_hr_attendance/__manifest__.py b/yuthon_hr_attendance/__manifest__.py
index 4a41593da..f775b316b 100644
--- a/yuthon_hr_attendance/__manifest__.py
+++ b/yuthon_hr_attendance/__manifest__.py
@@ -58,6 +58,7 @@
'views/card_remind_form.xml',
'views/yuthon_customer_planning_views.xml',
'views/planning_slot_template_views.xml',
+ 'views/vacation_overtime_active_views.xml',
'views/hr_attendance_month_views.xml',
'views/wifi_message_view.xml',
'views/back_approval.xml',
@@ -65,6 +66,7 @@
'views/meal_approval.xml',
'views/applet_address_views.xml',
'views/yuthon_holiday_statement.xml',
+ 'views/yuthon_parenting_allocate_views.xml',
'views/all_attendance_menu.xml',
'views/overtime_approval_inherit_header.xml',
diff --git a/yuthon_hr_attendance/models/__init__.py b/yuthon_hr_attendance/models/__init__.py
index 3dfc96f27..c401c8c4e 100644
--- a/yuthon_hr_attendance/models/__init__.py
+++ b/yuthon_hr_attendance/models/__init__.py
@@ -34,7 +34,8 @@ from . import staff_dining_report
from . import message_reminder_tasks
from . import yuthon_holiday_statement
from . import yuthon_meal_case
-
+from . import yuthon_parenting_allocate
+from . import vacation_overtime_active
# from odoo.tools import SQL
# import odoo
# odoo.models.READ_GROUP_AGGREGATE.update({
diff --git a/yuthon_hr_attendance/models/vacation_overtime_active.py b/yuthon_hr_attendance/models/vacation_overtime_active.py
new file mode 100644
index 000000000..e9bed3cad
--- /dev/null
+++ b/yuthon_hr_attendance/models/vacation_overtime_active.py
@@ -0,0 +1,24 @@
+from datetime import datetime, timedelta, time
+from email.policy import default
+from operator import index
+from odoo import models, fields, api, _
+from odoo.exceptions import ValidationError
+import calendar
+from datetime import date
+from dateutil.relativedelta import relativedelta
+from odoo.exceptions import UserError, ValidationError
+
+
+class VacationOvertimeActive(models.Model):
+ _name = 'vacation.overtime.active'
+ _description = '加班情况归档'
+
+ employee_id = fields.Many2one('hr.employee', string='员工')
+ department_id = fields.Many2one('hr.department', related='employee_id.department_id', string="部门")
+ company_id = fields.Many2one('res.company', related='employee_id.company_id', string="公司")
+ workflow_record_id = fields.Many2one('soong.workflow.record', string='流程')
+ overtime_name = fields.Char(string="标题")
+ carry_forward_date = fields.Date(string="结转日期")
+ carry_forward_quantity = fields.Float(string="结转时长")
+ carry_result = fields.Selection([('success', '成功'), ('failed', '失败')], string="结转结果")
+ remaining_quantity = fields.Float(string="剩余数")
diff --git a/yuthon_hr_attendance/models/yuthon_parenting_allocate.py b/yuthon_hr_attendance/models/yuthon_parenting_allocate.py
new file mode 100644
index 000000000..b607a5108
--- /dev/null
+++ b/yuthon_hr_attendance/models/yuthon_parenting_allocate.py
@@ -0,0 +1,31 @@
+# -*- coding: utf-8 -*-
+from odoo import api, fields, models, tools, _
+from datetime import datetime, time, timedelta
+from odoo.exceptions import UserError
+
+
+class YuthonParentingAllocate(models.Model):
+ _name = 'yuthon.parenting.allocate'
+ _description = '育儿额度分配规则'
+
+ company_id = fields.Many2one("res.company", string="公司", default=lambda self: self.env.company)
+ cycle_years = fields.Integer(string='周期年数', default=1, help='按出生日计算的周期年数,如1表示1年')
+ cycle_unit = fields.Integer(string='周期单位', default=1, help='周期的描述单位,如“1”周期')
+ valid_limit = fields.Integer(string='有效期限(岁)', default=1, help='规则生效的截止条件')
+ distribute = fields.Integer(string='年/发放额度')
+ start_date = fields.Date(string="生效日期", copy=False, default=fields.Date.today())
+ end_date = fields.Date(string="失效日期", copy=False, default=fields.Date.from_string('2099-01-01'))
+ is_enable = fields.Boolean(string="是否启用", compute="compute_is_enable", store=True)
+ birth_certificate = fields.Text(string='备注', default='需要在花名册配置紧急联系人才能生效')
+
+ @api.depends('start_date', 'end_date')
+ def compute_is_enable(self):
+ for rec in self:
+ if not rec.end_date:
+ rec.is_enable = True
+ else:
+ if rec.start_date and rec.end_date:
+ if rec.start_date <= fields.Date.today() < rec.end_date:
+ rec.is_enable = True
+ else:
+ rec.is_enable = False
\ No newline at end of file
diff --git a/yuthon_hr_attendance/models/yuthon_vacation_reports.py b/yuthon_hr_attendance/models/yuthon_vacation_reports.py
index db17df426..acdb08682 100644
--- a/yuthon_hr_attendance/models/yuthon_vacation_reports.py
+++ b/yuthon_hr_attendance/models/yuthon_vacation_reports.py
@@ -31,6 +31,7 @@ class YuthonVacationReports(models.Model):
year_holiday = fields.Float(string="本年公休日", digits=(16, 3))
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))
used_this_year1 = fields.Float(string="本年已休", digits=(16, 3))
remainder_year1 = fields.Float(string="剩余(补休)", digits=(16, 3), compute="_compute_year_sum")
@@ -40,6 +41,7 @@ class YuthonVacationReports(models.Model):
overtime_ids = fields.One2many('vacation.over.line', 'vacation_id', string='加班明细')
meal_fee_ids = fields.One2many('vacation.meal.line', 'vacation_id', string='误餐明细')
medical_fee_ids = fields.One2many('vacation.medical.line', 'vacation_id', string='体检费明细')
+ 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))
display_date = fields.Char(string='日期', compute='_compute_display_date')
@@ -68,6 +70,8 @@ class YuthonVacationReports(models.Model):
general_sick_leave = fields.Float(string='病假(普通)', digits=(16, 3), compute='_compute_other_leave', store=True, group_operator=None)
hospital_sick_leave = fields.Float(string='病假(住院期)', digits=(16, 3), compute='_compute_other_leave', store=True, group_operator=None)
recovery_sick_leave = fields.Float(string='病假(出院恢复期)', digits=(16, 3), compute='_compute_other_leave', store=True, group_operator=None)
+ parental_leave = fields.Float(string='育儿假', digits=(16, 3), compute='_compute_parental_leave', store=True, group_operator=None)
+ remaining_parental_leave = fields.Float(string='剩余育儿假', digits=(16, 3), compute='_compute_parental_leave', store=True, group_operator=None)
exam_leave = fields.Integer(string='考试假', compute='_compute_other_leave', store=True, group_operator=None)
right_days = fields.Float(string='转正天数', group_operator=None, compute='compute_attendance_fields')
internship_days = fields.Float(string='实习天数', group_operator=None)
@@ -97,6 +101,33 @@ class YuthonVacationReports(models.Model):
tracking=3,
default='not_sent')
+ @api.depends('other_fee_ids', 'other_fee_ids.holiday_type', 'other_fee_ids.lines',
+ 'other_fee_ids.is_void', 'other_fee_ids.update_type', 'parenting_line_ids',
+ 'parenting_line_ids.update_date', 'parenting_line_ids.end_date', 'parenting_line_ids.lines')
+ def _compute_parental_leave(self):
+ today = date.today()
+ for rec in self:
+ used_amount = 0.0
+ deduct_fee_lines = rec.other_fee_ids.filtered(
+ lambda l:
+ l.holiday_type.name == '育儿假'
+ and l.update_type == 'reduce'
+ and not l.is_void
+ and l.lines > 0
+ )
+ if deduct_fee_lines:
+ used_amount = sum(line.lines for line in deduct_fee_lines)
+ rec.parental_leave = used_amount
+ total_amount = 0.0
+ valid_parenting_lines = rec.parenting_line_ids.filtered(
+ lambda l:
+ l.update_date <= today
+ and (l.end_date >= today if l.end_date else True)
+ )
+ if valid_parenting_lines:
+ total_amount = sum(line.lines for line in valid_parenting_lines)
+ rec.remaining_parental_leave = max(total_amount - used_amount, 0.0)
+
def update_vacation_state(self):
records = self.env["yuthon.vacation.reports"].browse(
self._context.get('active_ids', self._context.get('active_id', self.ids))
@@ -142,6 +173,7 @@ class YuthonVacationReports(models.Model):
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.previous_year1 = record.last_holiday + record.last_workday
@api.constrains('employee_id', 'vacation_date')
def _check_duplicate_monthly_record(self):
@@ -993,8 +1025,22 @@ class VacationOverline(models.Model):
)
remaining_quantity = fields.Float(string='剩余数', compute="_compute_remaining_quantity", store=True)
+ def open_record(self):
+ tree_id = self.env.ref("yuthon_vacation_reports.view_yuthon_vacation_overtime_tree").id
+ return {
+ 'type': 'ir.actions.act_window',
+ 'name': 'Overtime Record',
+ 'res_model': 'vacation.meal.line',
+ 'view_mode': 'tree',
+ 'views': [[tree_id, 'tree']],
+ 'domain': [('employee_id', '=', self.employee_id.id),
+ ('carry_forward_state', '=', 'pending')
+ ],
+ }
+
@api.model
def confirm(self):
+ # 1. 构建筛选域
domain = [
'|',
['is_initial_number', '=', True],
@@ -1012,11 +1058,39 @@ class VacationOverline(models.Model):
filtered_records = self.search(domain)
if not filtered_records:
return
- records_to_update = filtered_records.filtered(
- lambda r: fields.float_compare(r.duration, r.carry_forward_quantity) == 0
+
+ valid_records = filtered_records.filtered(
+ lambda r: r.carry_forward_quantity and r.carry_forward_quantity != 0.0
)
- if records_to_update:
- records_to_update.write({'is_filing': True})
+ if not valid_records:
+ return
+
+ active_model = self.env['vacation.overtime.active']
+ for rec in valid_records:
+ if rec.remaining_quantity == 0:
+ rec.is_filing = True
+
+ match_domain = [
+ ('employee_id', '=', rec.employee_id.id if rec.employee_id else False),
+ ('workflow_record_id', '=', rec.workflow_record_id.id if rec.workflow_record_id else False),
+ ('carry_forward_date', '=', rec.carry_forward_date or fields.Date.today()),
+ ('overtime_name', '=', rec.overtime_name or '')
+ ]
+ existing_active = active_model.search(match_domain, limit=1)
+ active_vals = {
+ 'employee_id': rec.employee_id.id if rec.employee_id else False,
+ 'workflow_record_id': rec.workflow_record_id.id if rec.workflow_record_id else False,
+ 'overtime_name': rec.overtime_name or '',
+ 'remaining_quantity': rec.remaining_quantity,
+ 'carry_forward_date': rec.carry_forward_date or fields.Date.today(),
+ 'carry_forward_quantity': rec.carry_forward_quantity,
+ 'carry_result': 'success'
+ }
+
+ if existing_active:
+ existing_active.write(active_vals)
+ else:
+ active_model.create(active_vals)
def update_is_visible(self):
over_ids = self.env["vacation.over.line"].browse(
@@ -1320,6 +1394,19 @@ class VacationMealLine(models.Model):
return super(VacationMealLine, self).unlink()
+class VacationParentingLine(models.Model):
+ _name = 'vacation.parenting.line'
+ _description = '育儿明细'
+
+ vacation_id = fields.Many2one('yuthon.vacation.reports', string='关联假期额度记录')
+ employee_id = fields.Many2one('hr.employee', string='员工')
+ update_date = fields.Date(string='发放日期')
+ end_date = fields.Date(string='失效日期')
+ lines = fields.Float(string='额度')
+ text = fields.Text(string='备注')
+ is_confirm = fields.Boolean(string="是否确认")
+
+
class VacationMedicalLine(models.Model):
_name = 'vacation.medical.line'
_description = '体检费明细'
diff --git a/yuthon_hr_attendance/security/ir.model.access.csv b/yuthon_hr_attendance/security/ir.model.access.csv
index cdc58f6eb..b6c9c65d3 100644
--- a/yuthon_hr_attendance/security/ir.model.access.csv
+++ b/yuthon_hr_attendance/security/ir.model.access.csv
@@ -85,4 +85,7 @@ access_applet_security_quick_perm_wizard,access_applet_security_quick_perm_wizar
access_vacation_reports_wizard,vacation.reports.wizard,model_vacation_reports_wizard,base.group_user,1,1,1,1
access_yuthon_holiday_statement,access_yuthon_holiday_statement,model_yuthon_holiday_statement,base.group_user,1,1,1,1
access_yuthon_meal_case,access_yuthon_meal_case,model_yuthon_meal_case,base.group_user,1,1,1,1
-access_pay_carryover_wizard,pay.carryover.wizard,model_pay_carryover_wizard,base.group_user,1,1,1,1
\ No newline at end of file
+access_pay_carryover_wizard,pay.carryover.wizard,model_pay_carryover_wizard,base.group_user,1,1,1,1
+access_vacation_parenting_line,vacation.parenting.line,model_vacation_parenting_line,base.group_user,1,1,1,1
+access_yuthon_parenting_allocate,yuthon.parenting.allocate,model_yuthon_parenting_allocate,base.group_user,1,1,1,1
+access_vacation_overtime_active,vacation.overtime.active,model_vacation_overtime_active,base.group_user,1,1,1,1
\ No newline at end of file
diff --git a/yuthon_hr_attendance/static/src/js/button_meal_confirm.js b/yuthon_hr_attendance/static/src/js/button_meal_confirm.js
index 3e3e82531..303a5fd09 100644
--- a/yuthon_hr_attendance/static/src/js/button_meal_confirm.js
+++ b/yuthon_hr_attendance/static/src/js/button_meal_confirm.js
@@ -7,17 +7,10 @@ export class CustomAttendanceMealConfirmController extends ListController {
setup() {
super.setup();
}
-
async getAction(lock_type) {
- const action = await this.orm.call('vacation.meal.line', 'confirm', [lock_type], {context: this.props.context});
- action["context"] = {
- ...action.context,
- ...this.model.root.context,
- }
- return action
+ await this.orm.call('vacation.meal.line', 'confirm', []);
}
}
-
registry.category("views").add("custom_vacation_meal_button", {
...listView,
Controller: CustomAttendanceMealConfirmController,
diff --git a/yuthon_hr_attendance/static/src/js/button_statement_confirm.js b/yuthon_hr_attendance/static/src/js/button_statement_confirm.js
index f598e288e..4c08e982e 100644
--- a/yuthon_hr_attendance/static/src/js/button_statement_confirm.js
+++ b/yuthon_hr_attendance/static/src/js/button_statement_confirm.js
@@ -8,13 +8,9 @@ export class CustomAttendanceStatementConfirmController extends ListController {
super.setup();
}
+
async getAction(lock_type) {
- const action = await this.orm.call('hr.leave', 'confirm', [lock_type], {context: this.props.context});
- action["context"] = {
- ...action.context,
- ...this.model.root.context,
- }
- return action
+ await this.orm.call('hr.leave', 'confirm', []);
}
}
diff --git a/yuthon_hr_attendance/static/src/js/button_vacation_confirm.js b/yuthon_hr_attendance/static/src/js/button_vacation_confirm.js
index 00223dbe0..d70f42708 100644
--- a/yuthon_hr_attendance/static/src/js/button_vacation_confirm.js
+++ b/yuthon_hr_attendance/static/src/js/button_vacation_confirm.js
@@ -9,12 +9,7 @@ export class CustomAttendanceVacationConfirmController extends ListController {
}
async getAction(lock_type) {
- const action = await this.orm.call('vacation.over.line', 'confirm', [lock_type], {context: this.props.context});
- action["context"] = {
- ...action.context,
- ...this.model.root.context,
- }
- return action
+ await this.orm.call('vacation.over.line', 'confirm', []);
}
}
diff --git a/yuthon_hr_attendance/views/vacation_overtime_active_views.xml b/yuthon_hr_attendance/views/vacation_overtime_active_views.xml
new file mode 100644
index 000000000..4f793552b
--- /dev/null
+++ b/yuthon_hr_attendance/views/vacation_overtime_active_views.xml
@@ -0,0 +1,24 @@
+
+
+
+ vacation.overtime.active.tree
+ vacation.overtime.active
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 加班情况(归档)
+ vacation.overtime.active
+ tree
+
+
+
\ No newline at end of file
diff --git a/yuthon_hr_attendance/views/yuthon_parenting_allocate_views.xml b/yuthon_hr_attendance/views/yuthon_parenting_allocate_views.xml
new file mode 100644
index 000000000..cd1105f19
--- /dev/null
+++ b/yuthon_hr_attendance/views/yuthon_parenting_allocate_views.xml
@@ -0,0 +1,22 @@
+
+
+
+ yuthon.parenting.allocate.tree
+ yuthon.parenting.allocate
+
+
+
+
+
+
+
+
+
+
+
+
+ 育儿假规则
+ yuthon.parenting.allocate
+ tree
+
+
\ No newline at end of file
diff --git a/yuthon_hr_attendance/views/yuthon_vacation_reports_views.xml b/yuthon_hr_attendance/views/yuthon_vacation_reports_views.xml
index 6fad46c79..9adc5a914 100644
--- a/yuthon_hr_attendance/views/yuthon_vacation_reports_views.xml
+++ b/yuthon_hr_attendance/views/yuthon_vacation_reports_views.xml
@@ -75,6 +75,7 @@
+
@@ -124,6 +125,7 @@
+
@@ -183,7 +185,9 @@
-
+
+
+
@@ -323,6 +327,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -486,6 +503,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -548,22 +578,7 @@
-
-
-
-
- vacation.over.line.overtime.tree
- vacation.over.line
-
-
-
-
-
-
-
-
-
-
+
@@ -615,15 +630,6 @@
{'search_default_now_month': 1, 'search_default_group_by_employee_id':1}
-
-
- 加班情况(归档)
- vacation.over.line
- tree
- ['|', ('workflow_record_id','!=', False), ('is_initial_number', '=', True), ('update_type', '=', 'add'), ('is_filing','=', True), ('is_visible', '=', False)]
- {'search_default_group_by_employee_id':1}
-
-
触发计算逻辑
diff --git a/yuthon_hr_attendance/wizard/pay_carryover_wizard.py b/yuthon_hr_attendance/wizard/pay_carryover_wizard.py
index b58c1fc8f..2d974c3b2 100644
--- a/yuthon_hr_attendance/wizard/pay_carryover_wizard.py
+++ b/yuthon_hr_attendance/wizard/pay_carryover_wizard.py
@@ -22,7 +22,7 @@ class PayCarryoverWizard(models.TransientModel):
is_2025_december = rec.vacation_date.year == 2026 and rec.vacation_date.month == 1
if rec.overtime_ids:
for overtime in rec.overtime_ids:
- if overtime.text == '上月额度继承' and overtime.total > 40:
+ if overtime.text == '上月额度继承' and overtime.duration > 40:
reduce_workday = overtime.workday - 40
new_overtime = self.env['vacation.over.line'].create([{
'vacation_id': rec.id,
diff --git a/yuthon_hr_employee/models/yuthon_hr_employee.py b/yuthon_hr_employee/models/yuthon_hr_employee.py
index 3ef8d826f..06866ba10 100644
--- a/yuthon_hr_employee/models/yuthon_hr_employee.py
+++ b/yuthon_hr_employee/models/yuthon_hr_employee.py
@@ -876,10 +876,15 @@ class YuthonHrEmployee(models.Model):
def update_parental_leave(self):
today = datetime.now().date()
active_contracts = self.env['hr.contract'].search([
+ ('employee_id.name','=', '和博延'),
('state', '=', 'open'),
('contract_type_id.name', 'ilike', '正式合同'),
('employee_id', '!=', False)
])
+ allocate_config = self.env['yuthon.parenting.allocate'].search([], limit=1)
+ valid_limit = allocate_config.valid_limit # 截至年龄(如3)
+ cycle_years = allocate_config.cycle_years # 周期年数(如1)
+ distribute = allocate_config.distribute #
if not active_contracts:
return
employees = active_contracts.mapped('employee_id')
@@ -905,50 +910,60 @@ class YuthonHrEmployee(models.Model):
except (ValueError, IndexError):
continue
- age_delta = today - birth_date
- if age_delta > timedelta(days=3 * 365):
+ valid_end_date = birth_date + relativedelta(years=valid_limit)
+ if today > valid_end_date:
continue
- cycle1_end = birth_date + relativedelta(years=1) # 第1年到期日
- cycle2_end = birth_date + relativedelta(years=2) # 第2年到期日
- cycle3_end = birth_date + relativedelta(years=3) # 第3年到期日(3岁生日)
+ cycle_list = []
+ current_cycle_start = birth_date
+ total_cycles = int(valid_limit / cycle_years)
- if today <= cycle1_end:
- date_from = birth_date
- date_to = cycle1_end - timedelta(days=1)
- elif today <= cycle2_end:
- date_from = cycle1_end
- date_to = cycle2_end - timedelta(days=1)
- else:
- date_from = cycle2_end
- date_to = cycle3_end - timedelta(days=1)
+ for i in range(1, total_cycles + 1):
+ current_cycle_end = current_cycle_start + relativedelta(years=cycle_years)
+ cycle_list.append({
+ 'cycle_num': i,
+ 'start': current_cycle_start,
+ 'end': current_cycle_end
+ })
+ current_cycle_start = current_cycle_end
+
+ date_from = birth_date
+ date_to = valid_end_date - timedelta(days=1)
+ for cycle in cycle_list:
+ if today <= cycle['end']:
+ date_from = cycle['start']
+ date_to = cycle['end'] - timedelta(days=1)
+ break
+
+ total_days = distribute
+ if total_days <= 0:
+ continue
- total_days = (date_to - date_from).days + 1
holiday_status_id = self.env['hr.leave.type'].search([('name', '=', '育儿假')], limit=1)
# 更新报表
- other_list = []
+ parenting_line_ids = []
reports_id = self.env['yuthon.vacation.reports'].search([
('employee_id', '=', employee.id),
('vacation_date', '=', fields.Date.today().replace(day=1))
], limit=1) #
if reports_id:
- existing_line = reports_id.other_fee_ids.search([
- ('holiday_type', '=', holiday_status_id.id),
+ existing_line = reports_id.parenting_line_ids.search([
+ ('vacation_id', '=', reports_id.id),
('employee_id', '=', employee.id),
('update_date', '=', date_from),
- ('update_type', '=', 'add')
+ ('end_date', '=', date_to),
+ ('text','=', '育儿假分配')
], limit=1)
if not existing_line:
- other_list.append([0, 0, {
+ parenting_line_ids.append([0, 0, {
'vacation_id': reports_id.id,
- 'holiday_type': holiday_status_id.id,
'employee_id': employee.id,
'update_date': date_from,
- 'update_type': 'add',
+ 'end_date': date_to,
'lines': total_days,
- 'text': '育儿假'
+ 'text': '育儿假分配'
}])
- if other_list:
- reports_id.write({'other_fee_ids': other_list})
+ if parenting_line_ids :
+ reports_id.write({'parenting_line_ids': parenting_line_ids})
# 6. 检查是否已存在相同分配记录,避免重复
existing_allocation = self.env['hr.leave.allocation'].search([
diff --git a/yuthon_salary/__manifest__.py b/yuthon_salary/__manifest__.py
index ff35a9fca..5151f650f 100644
--- a/yuthon_salary/__manifest__.py
+++ b/yuthon_salary/__manifest__.py
@@ -43,6 +43,7 @@
'wizard/temporary_payslip_wizard_views.xml',
'wizard/salary_import_wizard_views.xml',
'wizard/yuthon_payroll_wizard_views.xml',
+ 'wizard/salary_active_wizard_views.xml',
'wizard/basic_pension_wizard_views.xml',
'wizard/payroll_labor_wizard_views.xml',
'wizard/payroll_retired_wizard_views.xml',
diff --git a/yuthon_salary/models/yuthon_salary_active.py b/yuthon_salary/models/yuthon_salary_active.py
index b073b5a78..feb7b2511 100644
--- a/yuthon_salary/models/yuthon_salary_active.py
+++ b/yuthon_salary/models/yuthon_salary_active.py
@@ -99,14 +99,30 @@ class YuthonSalaryActive(models.Model):
self.write({'confirm_status': 'un_confirm'})
def open_archive_record(self):
- tree_id = self.env.ref("yuthon_salary.view_yuthon_salary_active_tree").id
+ self.ensure_one()
+ float_fields_with_value = []
+ for field_name, field in self._fields.items():
+ if field.type == 'float' and self[field_name] != 0 and self[field_name] is not False:
+ float_fields_with_value.append({
+ 'field_name': field_name,
+ 'field_string': field.string,
+ 'field_value': self[field_name]
+ })
return {
'name': '工资条',
'type': 'ir.actions.act_window',
- 'res_model': 'yuthon.salary.active',
- 'views': [[tree_id, 'tree']],
- 'view_mode': 'tree',
- 'domain': [('employee_id', '=', self.employee_id.id)],
+ 'res_model': 'salary.active.wizard',
+ 'view_mode': 'form',
+ 'target': 'new',
+ 'context': {
+ 'default_actual_wages': self.actual_paid_salary,
+ 'default_select_year': self.select_year,
+ 'default_select_time': self.select_time,
+ 'default_active_line': [(0, 0, {
+ 'name': item['field_string'],
+ 'amount': item['field_value']
+ }) for item in float_fields_with_value]
+ }
}
def _get_default_month(self):
diff --git a/yuthon_salary/security/ir.model.access.csv b/yuthon_salary/security/ir.model.access.csv
index 30abfad01..fd1c330c3 100644
--- a/yuthon_salary/security/ir.model.access.csv
+++ b/yuthon_salary/security/ir.model.access.csv
@@ -45,4 +45,7 @@ access_party_send_wizard,access_party_send_wizard,model_party_send_wizard,base.g
access_yuthon_meal_expenses,access_yuthon_meal_expenses,model_yuthon_meal_expenses,base.group_user,1,1,1,1
access_party_meal_wizard,access_party_meal_wizard,model_party_meal_wizard,base.group_user,1,1,1,1
access_salary_meal_wizard,access_salary_meal_wizard,model_salary_meal_wizard,base.group_user,1,1,1,1
-access_yuthon_salary_active,access_yuthon_salary_active,model_yuthon_salary_active,base.group_user,1,1,1,1
\ No newline at end of file
+access_yuthon_salary_active,access_yuthon_salary_active,model_yuthon_salary_active,base.group_user,1,1,1,1
+
+access_salary_active_wizard,access__salary_active_wizard,model_salary_active_wizard,base.group_user,1,1,1,1
+access_salary_active_line,access_salary_active_line,model_salary_active_line,base.group_user,1,1,1,1
\ No newline at end of file
diff --git a/yuthon_salary/wizard/__init__.py b/yuthon_salary/wizard/__init__.py
index 13f4bc72d..171ff8854 100644
--- a/yuthon_salary/wizard/__init__.py
+++ b/yuthon_salary/wizard/__init__.py
@@ -17,4 +17,5 @@ from . import salary_party_wizard
from . import salary_import_wizard
from . import party_send_wizard
from . import party_meal_wizard
-from . import salary_meal_wizard
\ No newline at end of file
+from . import salary_meal_wizard
+from . import salary_active_wizard
\ No newline at end of file
diff --git a/yuthon_salary/wizard/salary_active_wizard.py b/yuthon_salary/wizard/salary_active_wizard.py
new file mode 100644
index 000000000..0a45e3059
--- /dev/null
+++ b/yuthon_salary/wizard/salary_active_wizard.py
@@ -0,0 +1,43 @@
+# -*- coding: utf-8 -*-
+from dateutil.relativedelta import relativedelta
+
+from odoo import models, fields, api, _, SUPERUSER_ID
+from odoo.exceptions import ValidationError, UserError
+from odoo.exceptions import ValidationError
+import calendar
+from pypinyin import pinyin, Style
+import math
+import xlrd
+import base64
+import datetime
+from datetime import datetime, timedelta
+
+
+class SalaryActiveWizard(models.TransientModel):
+ _name = 'salary.active.wizard'
+ _description = '工资条查询'
+
+ active_line = fields.One2many('salary.active.line', 'active_id', string='明细')
+ select_time = fields.Selection([('1', '一月'), ('2', '二月'), ('3', '三月'), ('4', '四月'),
+ ('5', '五月'), ('6', '六月'), ('7', '七月'), ('8', '八月'),
+ ('9', '九月'), ('10', '十月'), ('11', '十一月'),
+ ('12', '十二月')], string='月份',
+ default=lambda self: self._get_default_month())
+ select_year = fields.Selection(selection=[(str(i), str(i)) for i in range(2024, 2040)], string='年份')
+ select_name = fields.Char(compute='_get_default_name')
+ actual_wages = fields.Float(string='实发工资')
+
+ @api.depends('select_year', 'select_time')
+ def _get_default_name(self):
+ for rec in self:
+ rec.select_name = rec.select_year + '年' + rec.select_time + '月'
+
+
+class SalaryActiveLine(models.TransientModel):
+ _name = 'salary.active.line'
+ _description = '明细'
+
+ sequence = fields.Char(string='序号', store=True)
+ active_id = fields.Many2one('salary.active.wizard', string='工资条')
+ name = fields.Char(string='工资条')
+ amount = fields.Float(string='金额')
\ No newline at end of file
diff --git a/yuthon_salary/wizard/salary_active_wizard_views.xml b/yuthon_salary/wizard/salary_active_wizard_views.xml
new file mode 100644
index 000000000..3bdb64f6b
--- /dev/null
+++ b/yuthon_salary/wizard/salary_active_wizard_views.xml
@@ -0,0 +1,33 @@
+
+
+
+ 工资条查询
+ salary.active.wizard
+
+
+
+
+
\ No newline at end of file
diff --git a/yuthon_work_brand/views/hr_menus.xml b/yuthon_work_brand/views/hr_menus.xml
index fb82d3c0f..45229df20 100644
--- a/yuthon_work_brand/views/hr_menus.xml
+++ b/yuthon_work_brand/views/hr_menus.xml
@@ -166,17 +166,17 @@
sequence="14"/>
@@ -311,6 +311,11 @@
parent="attendance_resources_setting_root_board"
action="hr_holidays.hr_leave_allocation_action_approve_department"
sequence="20"/>
+