feat(outbound): 完善出库审批邮件通知逻辑,支持申请人与审批人同时收到邮件(带物料明细),审批通过后申请人和库管均收到带物料明细的通知

This commit is contained in:
DXC
2026-05-12 13:42:15 +08:00
parent c86da38a70
commit 3dae206828
3 changed files with 85 additions and 37 deletions

View File

@ -688,18 +688,28 @@ class OutboundApprovalService:
@staticmethod
def _notify_new_request(approval, applicant_id, approver_id=None):
"""发送新申请通知邮件给审批人(静默处理,不阻断主流程)"""
"""发送新申请通知邮件给审批人和申请人(静默处理,不阻断主流程)"""
try:
from flask import current_app
from app.utils.email_service import send_new_request_notify
from app.models.system import SysUser
emails = []
applicant_name = ''
applicant_emails = []
# 1. 收集申请人信息
if applicant_id:
user = SysUser.query.get(int(applicant_id))
if user and user.email:
applicant_emails.append(user.email)
applicant_name = str(user.username).split('/')[0] if '/' in (user.username or '') else (user.username or str(applicant_id))
# 2. 收集审批人信息
approver_emails = []
if approver_id:
# ★ 精准通知模式:直接查询指定审批人
user = SysUser.query.get(int(approver_id))
if user and user.email:
emails.append(user.email)
approver_emails.append(user.email)
else:
# 兜底:按角色查询
approvers = approval.get_allowed_approvers()
@ -707,37 +717,49 @@ class OutboundApprovalService:
for a in approvers:
if a.get('type') == 'role':
role_codes.append(a.get('value', ''))
emails = OutboundApprovalService._get_emails_by_identifiers(role_codes=role_codes)
approver_emails = OutboundApprovalService._get_emails_by_identifiers(role_codes=role_codes)
if not emails:
current_app.logger.info(f"[Email] 审批单 {approval.request_no} 无审批人邮箱,跳过通知")
# 去重
all_emails = list(set(applicant_emails + approver_emails))
if not all_emails:
current_app.logger.info(f"[Email] 审批单 {approval.request_no} 无收件人邮箱,跳过通知")
return
# 获取申请人姓名
applicant_name = ''
if applicant_id:
u = SysUser.query.get(applicant_id)
if u:
# username 格式为 "姓名/账号",取姓名部分
applicant_name = str(u.username).split('/')[0] if '/' in u.username else (u.username or str(applicant_id))
# ★ 发送通知,附完整物料清单
# 3. 获取物料明细
items = approval.get_items()
send_new_request_notify(
to_emails=emails,
request_no=approval.request_no,
applicant_name=applicant_name,
remark=approval.remark or '',
items=items
)
# 4. 分别发送邮件
if applicant_emails:
try:
send_new_request_notify(
to_emails=applicant_emails,
request_no=approval.request_no,
applicant_name=applicant_name,
remark=f"您的出库申请已提交,等待审批。{approval.remark or ''}",
items=items,
is_applicant_notify=True
)
except Exception as e:
current_app.logger.error(f"[Email] 通知申请人失败: {e}")
if approver_emails:
try:
send_new_request_notify(
to_emails=approver_emails,
request_no=approval.request_no,
applicant_name=applicant_name,
remark=approval.remark or '',
items=items,
is_applicant_notify=False
)
except Exception as e:
current_app.logger.error(f"[Email] 通知审批人失败: {e}")
except Exception as e:
# ★ 捕获所有异常,确保邮件发送失败不阻断主流程
try:
from flask import current_app
current_app.logger.error(f"[Email] 发送新申请通知邮件失败: {e}")
except RuntimeError:
# 如果不在 Flask 应用上下文内,降级为标准日志
import logging
logging.getLogger(__name__).error(f"[Email] 发送新申请通知邮件失败: {e}")
@ -864,17 +886,17 @@ class OutboundApprovalService:
except Exception as e:
logger.error(f"[Email] 通知库管失败: {e}")
# 3.2 通知申请人(已通过
# 3.2 通知申请人(审批通过,带完整物料清单
if applicant_emails:
try:
send_approval_result_notify(
send_warehouse_dispatch_notify(
to_emails=applicant_emails,
request_no=approval.request_no,
is_passed=True,
applicant_name=applicant_name
applicant_name=applicant_name,
items=items
)
except Exception as e:
logger.error(f"[Email] 通知申请人通过失败: {e}")
logger.error(f"[Email] 通知申请人通过失败: {e}")
elif action == 'reject':
# 3.3 通知申请人(已驳回)