diff --git a/yuthon_salary/__manifest__.py b/yuthon_salary/__manifest__.py
index 4d4ec6f2b..32ce24331 100644
--- a/yuthon_salary/__manifest__.py
+++ b/yuthon_salary/__manifest__.py
@@ -15,6 +15,8 @@
'security/ir.model.access.csv',
'security/salary_security_rule.xml',
'data/rank_log_time.xml',
+ 'data/meal_cron.xml',
+
'views/inherit_hr_payroll_structure_views.xml',
'views/inherit_hr_salary_rule_views.xml',
'views/inherit_hr_payslip_views.xml',
diff --git a/yuthon_salary/data/meal_cron.xml b/yuthon_salary/data/meal_cron.xml
new file mode 100644
index 000000000..70f16da63
--- /dev/null
+++ b/yuthon_salary/data/meal_cron.xml
@@ -0,0 +1,18 @@
+
+
+
+
+ 定时任务:餐费缴费提醒
+
+ code
+ model.cron_send_meal_reminder()
+
+
+ 1
+ days
+
+ -1
+
+
+
+
diff --git a/yuthon_salary/models/yuthon_meal_expenses.py b/yuthon_salary/models/yuthon_meal_expenses.py
index b1944cd90..c264729a2 100644
--- a/yuthon_salary/models/yuthon_meal_expenses.py
+++ b/yuthon_salary/models/yuthon_meal_expenses.py
@@ -109,6 +109,35 @@ class YuthonMealExpenses(models.Model):
to_update.write({'meal_state': 'done'})
return True
+ def cron_send_meal_reminder(self):
+ """定时任务:给状态为已发送且缴费状态为待缴的记录发送缴费提醒"""
+ # 找出所有 已发送 且 仍然 待缴 的餐费记录
+ meals = self.sudo().search([
+ ('meal_state', '=', 'done'),
+ ('toll_state', '=', 'to_do'),
+ ])
+ for meal in meals:
+ # 如果早餐次数和午餐次数都为0,则不发送提醒
+ if meal.number_breakfasts == 0 and meal.number_lunches == 0:
+ continue
+ employee = meal.employee_id
+ if not employee or not employee.user_id or not employee.wecom_userid:
+ continue
+ # 和现有手机端餐费链接保持一致
+ url = f'https://phone.thtzjt.com/phone/Meal/{employee.user_id.id}'
+ # 提示文案,按照要求修改
+ employee_name = employee.name or ''
+ description = (
+ f'{employee_name},您尚有餐费未缴纳,请及时登录系统查看并完成缴费,感谢配合。'
+ )
+ self.sudo().env["wecom.apps"].sync_send_message_textcard(
+ category='can',
+ user_id=employee.wecom_userid,
+ title="缴纳餐费提醒",
+ description=description,
+ url=url,
+ btntxt="详细信息",
+ )
def action_generate_missing_feb(self):
target_year = '2026'
@@ -159,3 +188,133 @@ class YuthonMealExpenses(models.Model):
('date', '>=', date_start),
('date', '<=', date_end)],
}
+
+ def action_send_reminder(self):
+ """一键催缴:手动发送缴费提醒"""
+ self.ensure_one()
+ # 如果早餐次数和午餐次数都为0,则不发送提醒
+ if self.number_breakfasts == 0 and self.number_lunches == 0:
+ return {
+ 'type': 'ir.actions.client',
+ 'tag': 'display_notification',
+ 'params': {
+ 'title': '提醒',
+ 'message': '该记录早餐和午餐次数都为0,无需发送提醒',
+ 'type': 'info',
+ 'sticky': False,
+ }
+ }
+ employee = self.employee_id
+ if not employee or not employee.user_id or not employee.wecom_userid:
+ return {
+ 'type': 'ir.actions.client',
+ 'tag': 'display_notification',
+ 'params': {
+ 'title': '错误',
+ 'message': '员工信息不完整,无法发送提醒',
+ 'type': 'danger',
+ 'sticky': False,
+ }
+ }
+ # 和现有手机端餐费链接保持一致
+ url = f'https://phone.thtzjt.com/phone/Meal/{employee.user_id.id}'
+ # 提示文案,按照要求修改
+ employee_name = employee.name or ''
+ description = (
+ f'{employee_name},您尚有餐费未缴纳,请及时登录系统查看并完成缴费,感谢配合。'
+ )
+ try:
+ self.sudo().env["wecom.apps"].sync_send_message_textcard(
+ category='can',
+ user_id=employee.wecom_userid,
+ title="缴纳餐费提醒",
+ description=description,
+ url=url,
+ btntxt="详细信息",
+ )
+ return {
+ 'type': 'ir.actions.client',
+ 'tag': 'display_notification',
+ 'params': {
+ 'title': '发送成功',
+ 'message': '提醒已发送给员工',
+ 'type': 'success',
+ 'sticky': False,
+ }
+ }
+ except Exception as e:
+ return {
+ 'type': 'ir.actions.client',
+ 'tag': 'display_notification',
+ 'params': {
+ 'title': '发送失败',
+ 'message': f'提醒发送失败:{str(e)}',
+ 'type': 'danger',
+ 'sticky': False,
+ }
+ }
+
+ def action_batch_send_reminder(self):
+ """批量催缴:发送提醒给所有符合条件的员工"""
+ # 查询所有缴费状态为待缴,状态为已发送的记录
+ meals = self.sudo().search([
+ ('meal_state', '=', 'done'),
+ ('toll_state', '=', 'to_do'),
+ ])
+
+ success_count = 0
+ skip_count = 0
+ error_count = 0
+
+ for meal in meals:
+ # 如果早餐次数和午餐次数都为0,则不发送提醒
+ if meal.number_breakfasts == 0 and meal.number_lunches == 0:
+ skip_count += 1
+ continue
+
+ employee = meal.employee_id
+ if not employee or not employee.user_id or not employee.wecom_userid:
+ error_count += 1
+ continue
+
+ # 和现有手机端餐费链接保持一致
+ url = f'https://phone.thtzjt.com/phone/Meal/{employee.user_id.id}'
+ # 提示文案,按照要求修改
+ employee_name = employee.name or ''
+ description = (
+ f'{employee_name},您尚有餐费未缴纳,请及时登录系统查看并完成缴费,感谢配合。'
+ )
+ try:
+ self.sudo().env["wecom.apps"].sync_send_message_textcard(
+ category='can',
+ user_id=employee.wecom_userid,
+ title="缴纳餐费提醒",
+ description=description,
+ url=url,
+ btntxt="详细信息",
+ )
+ success_count += 1
+ except Exception:
+ error_count += 1
+
+ # 构建返回消息
+ message_parts = []
+ if success_count > 0:
+ message_parts.append(f'成功发送{success_count}条提醒')
+ if skip_count > 0:
+ message_parts.append(f'跳过{skip_count}条记录(早餐和午餐次数都为0)')
+ if error_count > 0:
+ message_parts.append(f'失败{error_count}条记录(员工信息不完整)')
+
+ message = ';'.join(message_parts)
+
+ return {
+ 'type': 'ir.actions.client',
+ 'tag': 'display_notification',
+ 'params': {
+ 'title': '批量催缴完成',
+ 'message': message,
+ 'type': 'success' if success_count > 0 else 'info',
+ 'sticky': False,
+ }
+ }
diff --git a/yuthon_salary/views/yuthon_meal_expenses_views.xml b/yuthon_salary/views/yuthon_meal_expenses_views.xml
index 5591a763f..8bac3845d 100644
--- a/yuthon_salary/views/yuthon_meal_expenses_views.xml
+++ b/yuthon_salary/views/yuthon_meal_expenses_views.xml
@@ -27,6 +27,7 @@
@@ -41,6 +42,7 @@
+