feat(outbound): 完善出库审批邮件通知逻辑,支持申请人与审批人同时收到邮件(带物料明细),审批通过后申请人和库管均收到带物料明细的通知
This commit is contained in:
@ -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 通知申请人(已驳回)
|
||||
|
||||
Reference in New Issue
Block a user