diff --git a/yuthon_holiday/models/inherit_hr_leave_allocation.py b/yuthon_holiday/models/inherit_hr_leave_allocation.py
index 42e40b6b7..9f86c829a 100644
--- a/yuthon_holiday/models/inherit_hr_leave_allocation.py
+++ b/yuthon_holiday/models/inherit_hr_leave_allocation.py
@@ -6,6 +6,20 @@ import calendar
class HrLeaveAllocation(models.Model):
_inherit = 'hr.leave.allocation'
+ HOURS_PER_DAY = 8.0
+
+ @api.depends('holiday_status_id', 'allocation_type', 'number_of_hours_display', 'number_of_days_display', 'date_to')
+ def _compute_from_holiday_status_id(self):
+ super()._compute_from_holiday_status_id()
+ for allocation in self:
+ if allocation._get_request_unit() == 'hour':
+ allocation.number_of_days = allocation.number_of_hours_display / self.HOURS_PER_DAY
+
+ @api.depends('number_of_days', 'holiday_status_id', 'employee_id', 'holiday_type')
+ def _compute_number_of_hours_display(self):
+ for allocation in self:
+ allocation.number_of_hours_display = allocation.number_of_days * self.HOURS_PER_DAY
+
holiday_type = fields.Selection([
('employee', '按员工角色'),
('company', 'By Company'),
diff --git a/yuthon_hr_attendance/models/planning_template_inherit.py b/yuthon_hr_attendance/models/planning_template_inherit.py
index 34f412956..ab243ca82 100644
--- a/yuthon_hr_attendance/models/planning_template_inherit.py
+++ b/yuthon_hr_attendance/models/planning_template_inherit.py
@@ -124,6 +124,10 @@ class Planning(models.Model):
if att_id:
att_id.compute_attend()
+ vacation_id = self.env['yuthon.vacation.reports'].search([('employee_id', '=', slot.resource_id.employee_id.id), ('vacation_date', '=', new_start_datetime.date().replace(day=1))])
+ if vacation_id:
+ vacation_id.update_line()
+
@api.depends('template_id.color')
def _compute_color(self):
diff --git a/yuthon_hr_attendance/models/yuthon_vacation_reports.py b/yuthon_hr_attendance/models/yuthon_vacation_reports.py
index 30f212fe7..43fb8e9cb 100644
--- a/yuthon_hr_attendance/models/yuthon_vacation_reports.py
+++ b/yuthon_hr_attendance/models/yuthon_vacation_reports.py
@@ -1506,6 +1506,30 @@ class YuthonVacationReports(models.Model):
else:
return True
+ def _process_shift_days1(self, current_data):
+ """
+ 只判断:是否为法定节假日
+ 返回:True = 法定节假日
+ False = 非法定节假日
+ """
+ current_year = current_data.year
+ query_start = datetime(current_year, 1, 1)
+ query_end = datetime(current_year, 12, 31, 23, 59, 59)
+ # 只取法定节假日配置
+ calendar_leaves = self.env['resource.calendar.leaves'].sudo().search([
+ ("calendar_id.name", "=", "行政考勤工作日"),
+ ("date_from", ">=", query_start),
+ ("date_from", "<=", query_end)
+ ])
+
+ holidays_list = []
+ for leave in calendar_leaves:
+ if leave.holidays:
+ holidays_list.extend(leave.holidays.split(','))
+ holidays_list = [self.remove_leading_zero(date) for date in holidays_list]
+ current_date_str = f"{current_data.month}月{current_data.day}日"
+ return current_date_str in holidays_list
+
def all_put(self):
vacation_ids = self.env["yuthon.vacation.reports"].browse(self._context.get('active_ids', self._context.get('active_id')))
for rec in vacation_ids:
@@ -1798,18 +1822,21 @@ class YuthonVacationReports(models.Model):
'overtime_ids.is_void',
'overtime_ids.workflow_record_id',
'other_fee_ids.holiday_type',
- 'other_fee_ids.lines'
+ 'other_fee_ids.lines',
+ 'employee_id',
+ 'vacation_date'
)
def _compute_working_overtime(self):
for record in self:
- total_add1 = 0.0 # 加班时
- total_add2 = 0.0 # (已用补休)
- total_add = 0.0 # (剩余补休)
+ # ===================== 原有逻辑 开始 =====================
+ total_add1 = 0.0
+ total_add2 = 0.0
+ total_add = 0.0
legal_total = 0.0
+
for line in record.overtime_ids:
if line.is_void:
continue
-
line_total = (line.workday or 0) + (line.public_holidays or 0)
legal_total += (line.legal_day or 0)
if line.update_type == 'add':
@@ -1819,7 +1846,6 @@ class YuthonVacationReports(models.Model):
if line.workflow_record_id and line.update_type == 'add' and line.overtime_methods == 'leave':
total_add1 += line_total
-
if line.workflow_record_id and line.update_type == 'reduce':
total_add2 += line_total
@@ -1827,10 +1853,105 @@ class YuthonVacationReports(models.Model):
for other_line in record.other_fee_ids:
if other_line.holiday_type and other_line.holiday_type.name == '调休':
adjust_holiday_days += other_line.lines or 0
+ # ===================== 原有逻辑 结束 =====================
- record.working_overtime = (total_add / 8) + adjust_holiday_days
+ # ===================== 新增:排班加班逻辑(含你的新规则) =====================
+ employee = record.employee_id
+ vacation_date = record.vacation_date
+
+ if employee and vacation_date:
+ # 1. 获取【当前员工最新一条排班】
+ shift_planning = self.env['yuthon.shift.planning'].search([], order='start_date desc', limit=1)
+ rest_weekday = None
+ if shift_planning:
+ # 2. 查5个排班表,取固定休息日
+ shift_models = [
+ 'yuthon.shift.planning.a.line',
+ 'yuthon.shift.planning.b.line',
+ 'yuthon.shift.planning.c.line',
+ 'yuthon.shift.ever.white.line',
+ 'yuthon.shift.ever.noon.line',
+
+ ]
+ rest_code = False
+ for model in shift_models:
+ line = self.env[model].search([
+ ('shift_planning_id', '=', shift_planning.id),
+ ('employee_id', '=', employee.id)
+ ], limit=1)
+ if line:
+ rest_code = line.regular_holidays
+ break
+
+ week_map = {'one': 0, 'two': 1, 'three': 2, 'four': 3, 'five': 4, 'six': 5, 'seven': 6}
+ rest_weekday = week_map.get(rest_code)
+
+ # 3. 遍历当月所有天
+ dt = fields.Date.from_string(vacation_date)
+ year, month = dt.year, dt.month
+ _, days = calendar.monthrange(year, month)
+
+ for day in range(1, days + 1):
+ curr_date = datetime(year, month, day).date()
+ date_str = fields.Date.to_string(curr_date)
+ prev_date_str = fields.Date.to_string(curr_date - timedelta(days=1))
+
+ slot = self.env['planning.slot'].search([
+ ('employee_id', '=', employee.id),
+ ('start_datetime', '<=', date_str + ' 16:00:00'),
+ ('end_datetime', '>=', prev_date_str + ' 16:00:00'),
+ ], limit=1)
+ plan_name = slot.display_name or '' # 修正:用 name 不是 plan_name
+
+ # 日期类型判断
+ is_legal_holiday = self._process_shift_days1(curr_date)
+
+ # ===================== 规则1:固定休息日前一天 =====================
+ if rest_weekday is not None and curr_date.weekday() == rest_weekday - 1:
+ if not slot:
+ continue
+ work_hours = 0.0
+ if plan_name in ('旧白', '旧晚'):
+ work_hours = 12.0 if is_legal_holiday else 4.0
+ elif plan_name in ('旧白固加', '旧晚固加'):
+ work_hours = 12.0
+ else:
+ # 不属于以上班次 → 固定算8小时
+ work_hours = 8.0
+
+ # 计入加班
+ if is_legal_holiday:
+ legal_total += work_hours
+ else:
+ total_add += work_hours
+ total_add1 += work_hours
+
+ if slot:
+ work_hours = 0.0
+ is_special_shift = any(key in plan_name for key in ['旧白', '旧晚', '旧固加白', '旧固加晚', '全天班', '固加早', '固加夜', '固加中'])
+ if is_special_shift:
+ if '旧固加白' in plan_name or '旧固加晚' in plan_name:
+ work_hours = 12.0
+ elif '全天班' in plan_name:
+ work_hours = 24.0 if is_legal_holiday else 8.0
+ elif '旧白' in plan_name or '旧晚' in plan_name:
+ work_hours = 12.0 if is_legal_holiday else 4.0
+ elif '固加早' in plan_name or '固加夜' in plan_name or '固加中' in plan_name:
+ work_hours = 8.0
+ else:
+ if is_legal_holiday:
+ work_hours = 8.0
+
+ if is_legal_holiday:
+ legal_total += work_hours
+ else:
+ total_add += work_hours
+ total_add1 += work_hours
+
+ record.working_overtime = (total_add / 8) + adjust_holiday_days
+ record.this_year1 = total_add / 8
record.done_working_overtime = total_add1
- record.statutory_leave = legal_total/8
+ record.statutory_leave = legal_total
record.cop_leave = total_add2 / 8
@api.depends('overtime_ids.workday', 'overtime_ids.legal_day', 'overtime_ids.public_holidays', 'overtime_ids.update_type', 'overtime_ids.is_void')
diff --git a/yuthon_issue/models/inherit_room_booking.py b/yuthon_issue/models/inherit_room_booking.py
index 98d0448dd..85d2ea2ca 100644
--- a/yuthon_issue/models/inherit_room_booking.py
+++ b/yuthon_issue/models/inherit_room_booking.py
@@ -66,33 +66,33 @@ class RoomBooking(models.Model):
if '党' in meeting_type_name:
if meet.issue_library_id.is_party and not meet.issue_library_id.is_party_passed:
party_value = str(record.start_datetime.date()) + record.meeting_type_id.name
- meet.issue_library_id.party_char = f'{party_value}'
+ meet.issue_library_id.party_char = party_value
meet.issue_library_id.issue_state_party = 'meeting'
meet.issue_library_id.issue_state = False
if '班子' in meeting_type_name:
if meet.issue_library_id.is_class and not meet.issue_library_id.is_class_passed:
class_value = str(record.start_datetime.date()) + f'第{record.number_of_meetings}次' + record.meeting_type_id.name
- meet.issue_library_id.class_char = f'{class_value}'
+ meet.issue_library_id.class_char = class_value
meet.issue_library_id.issue_state_class = 'meeting'
meet.issue_library_id.issue_state = False
if '董事' in meeting_type_name:
if meet.issue_library_id.is_boss and not meet.issue_library_id.is_boss_passed:
boss_value = str(record.start_datetime.date()) + record.meeting_type_id.name
- meet.issue_library_id.boss_char = f'{boss_value}'
+ meet.issue_library_id.boss_char = boss_value
meet.issue_library_id.issue_state_boss = 'meeting'
meet.issue_library_id.issue_state = False
elif '套' in meeting_type_name:
if meet.issue_library_id.is_party and (meet.issue_library_id.is_party_passed == 'reject' or not meet.issue_library_id.is_party_passed):
party_value = str(record.start_datetime.date()) + record.meeting_type_id.name
- meet.issue_library_id.party_char = f'{party_value}'
+ meet.issue_library_id.party_char = party_value
meet.issue_library_id.issue_state_party = 'meeting'
meet.issue_library_id.issue_state = False
elif meet.issue_library_id.is_class and (meet.issue_library_id.is_class_passed == 'r eject' or not meet.issue_library_id.is_class_passed):
class_value = str(record.start_datetime.date()) + f'第{record.number_of_meetings}次' + record.meeting_type_id.name
- meet.issue_library_id.class_char = f'{class_value}'
+ meet.issue_library_id.class_char = class_value
meet.issue_library_id.issue_state_class = 'meeting'
meet.issue_library_id.issue_state = False
@@ -372,7 +372,7 @@ class IssueMeetingLine(models.Model):
for suffix in suffix_list:
clean_party_char = clean_party_char.removesuffix(suffix)
clean_party_char = clean_party_char.replace('', '').replace('', '')
- record.issue_library_id.party_char = f'{clean_party_char + agree_name}'
+ record.issue_library_id.party_char = clean_party_char + agree_name
record.issue_library_id.issue_state_party = 'on_meet'
# 3. 班子会相关
@@ -385,7 +385,7 @@ class IssueMeetingLine(models.Model):
for suffix in suffix_list:
clean_class_char = clean_class_char.removesuffix(suffix)
clean_class_char = clean_class_char.replace('', '').replace('', '')
- record.issue_library_id.class_char = f'{clean_class_char + agree_name}'
+ record.issue_library_id.class_char = clean_class_char + agree_name
record.issue_library_id.issue_state_class = 'on_meet'
# 4. 董事会相关
@@ -397,7 +397,7 @@ class IssueMeetingLine(models.Model):
for suffix in suffix_list:
clean_boss_char = clean_boss_char.removesuffix(suffix)
clean_boss_char = clean_boss_char.replace('', '').replace('', '')
- record.issue_library_id.boss_char = f'{clean_boss_char + agree_name}'
+ record.issue_library_id.boss_char = clean_boss_char + agree_name
record.issue_library_id.issue_state_boss = 'on_meet'
# 套开相关
@@ -414,7 +414,7 @@ class IssueMeetingLine(models.Model):
for suffix in suffix_list:
clean_party_char = clean_party_char.removesuffix(suffix)
clean_party_char = clean_party_char.replace('', '').replace('', '')
- record.issue_library_id.party_char = f'{clean_party_char + agree_name}'
+ record.issue_library_id.party_char = clean_party_char + agree_name
record.issue_library_id.issue_state_party = 'on_meet' if is_push else 'will'
elif (record.issue_library_id.is_class and
@@ -427,7 +427,7 @@ class IssueMeetingLine(models.Model):
for suffix in suffix_list:
clean_class_char = clean_class_char.removesuffix(suffix)
clean_class_char = clean_class_char.replace('', '').replace('', '')
- record.issue_library_id.class_char = f'{clean_class_char + agree_name}'
+ record.issue_library_id.class_char = clean_class_char + agree_name
record.issue_library_id.issue_state_class = 'on_meet' if is_push else 'will'
def unlink(self):
diff --git a/yuthon_issue/models/issue_library.py b/yuthon_issue/models/issue_library.py
index fd1eedd7f..3b3e1c4b0 100644
--- a/yuthon_issue/models/issue_library.py
+++ b/yuthon_issue/models/issue_library.py
@@ -141,12 +141,18 @@ class IssueLibrary(models.Model):
records = self.env['issue.library'].browse(active_ids)
count = 0
for record in records:
- # 只清理party_char的HTML标签
+ # 清理party_char的HTML标签
if record.party_char:
clean_value = re.sub(r'<[^>]+>', '', record.party_char)
if clean_value != record.party_char:
record.party_char = clean_value
count += 1
+ # 清理class_char的HTML标签
+ if record.class_char:
+ clean_value = re.sub(r'<[^>]+>', '', record.class_char)
+ if clean_value != record.class_char:
+ record.class_char = clean_value
+ count += 1
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
diff --git a/yuthon_issue/views/issue_library_views.xml b/yuthon_issue/views/issue_library_views.xml
index def33a6d7..d5507f318 100644
--- a/yuthon_issue/views/issue_library_views.xml
+++ b/yuthon_issue/views/issue_library_views.xml
@@ -466,6 +466,7 @@
diff --git a/yuthon_official/models/yuthon_official.py b/yuthon_official/models/yuthon_official.py
index 941f1658d..3a7aea583 100644
--- a/yuthon_official/models/yuthon_official.py
+++ b/yuthon_official/models/yuthon_official.py
@@ -37,6 +37,14 @@ class YuthonOfficial(models.Model):
'flat_id',
string="抄送单位"
)
+ main_unit_type = fields.Selection([
+ ('gov', '行政事业单位'),
+ ('other', '其他单位')
+ ], string='主送单位类型')
+ copy_unit_type = fields.Selection([
+ ('gov', '行政事业单位'),
+ ('other', '其他单位')
+ ], string='抄送单位类型')
department_ids = fields.Many2many('hr.department', string='部门范围')
employee_ids = fields.Many2many('hr.employee', string='人员范围')
users_role_ids = fields.Many2many('soong.user.role', string='角色范围')
@@ -183,6 +191,20 @@ class YuthonOfficial(models.Model):
else:
self.reference_cold = False
+ @api.onchange('main_flats_ids')
+ def _onchange_main_flats_ids(self):
+ if self.main_flats_ids:
+ self.main_unit_type = self.main_flats_ids[0].unit_type
+ else:
+ self.main_unit_type = False
+
+ @api.onchange('copy_flats_ids')
+ def _onchange_copy_flats_ids(self):
+ if self.copy_flats_ids:
+ self.copy_unit_type = self.copy_flats_ids[0].unit_type
+ else:
+ self.copy_unit_type = False
+
@api.onchange('company_id1')
def onchange_company_id1(self):
current_year = fields.Date.today().year
@@ -422,6 +444,20 @@ class YuthonPropertyOfficial(models.Model):
else:
self.reference_cold = False
+ @api.onchange('main_flats_ids')
+ def _onchange_main_flats_ids(self):
+ if self.main_flats_ids:
+ self.main_unit_type = self.main_flats_ids[0].unit_type
+ else:
+ self.main_unit_type = False
+
+ @api.onchange('copy_flats_ids')
+ def _onchange_copy_flats_ids(self):
+ if self.copy_flats_ids:
+ self.copy_unit_type = self.copy_flats_ids[0].unit_type
+ else:
+ self.copy_unit_type = False
+
@api.onchange('company_id1')
def onchange_company_id1(self):
current_year = fields.Date.today().year
diff --git a/yuthon_official/views/yuthon_official_views.xml b/yuthon_official/views/yuthon_official_views.xml
index b169585ae..55c1bd818 100644
--- a/yuthon_official/views/yuthon_official_views.xml
+++ b/yuthon_official/views/yuthon_official_views.xml
@@ -78,6 +78,8 @@
+
+
diff --git a/yuthon_property_approval/__manifest__.py b/yuthon_property_approval/__manifest__.py
index 30db0c254..60447fd0d 100644
--- a/yuthon_property_approval/__manifest__.py
+++ b/yuthon_property_approval/__manifest__.py
@@ -115,7 +115,9 @@
'report/property_lease_contract_print_report.xml',
'report/property_lease_contract_print_templates.xml',
'report/property_supervising_approval_print_report.xml',
- 'report/property_supervising_approval_print_templates.xml'
+ 'report/property_supervising_approval_print_templates.xml',
+ 'report/property_open_rent_print_report.xml',
+ 'report/property_open_rent_print_templates.xml'
],
diff --git a/yuthon_property_approval/models/property_open_rent.py b/yuthon_property_approval/models/property_open_rent.py
index e3f2ddb04..79977e40d 100644
--- a/yuthon_property_approval/models/property_open_rent.py
+++ b/yuthon_property_approval/models/property_open_rent.py
@@ -271,6 +271,13 @@ class PropertyOpenRent(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])])
+
+ def action_print_property_open_rent(self):
+ """打印公开招租审批"""
+ self.ensure_one()
+ report_ref = self.env.ref('yuthon_property_approval.action_property_open_rent_print_report')
+ return report_ref.sudo().report_action(self)
+
#
#
# class PropertyOpenRentLine(models.Model):
diff --git a/yuthon_property_approval/report/property_open_rent_print_report.xml b/yuthon_property_approval/report/property_open_rent_print_report.xml
new file mode 100644
index 000000000..a0286050b
--- /dev/null
+++ b/yuthon_property_approval/report/property_open_rent_print_report.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+ Open Rent Small Top Margin
+ A4
+ 5
+ Portrait
+
+
+
+ 公开招租审批
+
+ property.open.rent
+ qweb-pdf
+ yuthon_property_approval.property_open_rent_print_template
+ yuthon_property_approval.property_open_rent_print_template
+ '公开招租审批%s_%s_%s' % (object.display_name or object.code or '', object.user_id.name or '', ((object.log_ids.filtered(lambda l: l.name == '归档')[-1].lase_click_date or object.log_ids.filtered(lambda l: l.name == '归档')[-1].date_create).strftime('%Y-%m-%d') if object.log_ids.filtered(lambda l: l.name == '归档') else ''))
+
+ report
+
+
+
\ No newline at end of file
diff --git a/yuthon_property_approval/report/property_open_rent_print_templates.xml b/yuthon_property_approval/report/property_open_rent_print_templates.xml
new file mode 100644
index 000000000..5b20ae9d4
--- /dev/null
+++ b/yuthon_property_approval/report/property_open_rent_print_templates.xml
@@ -0,0 +1,94 @@
+
+
+
+
+
+
+
+
+
+
+
公开招租审批
+
+
+
+
+ 流水号:
+
+
+
+
+
+ | 标题 |
+ |
+ 申请人 |
+ |
+
+
+ | 紧急度 |
+ |
+ 是否用章 |
+ |
+
+
+ | 经办意见 |
+ |
+
+
+
+
+
租赁期限
+
+
+ | 租期 |
+ |
+ 总面积 (㎡) |
+ |
+
+
+ | 月租金 (元) |
+ |
+ 单价 (元/㎡) |
+ |
+
+
+ | 总租金 (元) |
+ |
+
+
+
+
+
审批详情
+
+
+
+
+ |
+ |
+
+
+
+
+ |
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/yuthon_property_approval/views/property_open_rent_views.xml b/yuthon_property_approval/views/property_open_rent_views.xml
index aaa579e81..d24a83edd 100644
--- a/yuthon_property_approval/views/property_open_rent_views.xml
+++ b/yuthon_property_approval/views/property_open_rent_views.xml
@@ -16,6 +16,12 @@
property.open.rent