fix(审批邮件): items_json序列化Bug修复 + 邮件方法出库/借库物理隔离

This commit is contained in:
DXC
2026-06-12 15:04:57 +08:00
parent 6f5652b90e
commit 5c0c1632c3
3 changed files with 170 additions and 61 deletions

View File

@ -136,7 +136,7 @@ class BorrowApprovalService:
"""发送新借库申请通知邮件给审批人和申请人(静默处理,不阻断主流程)"""
try:
from flask import current_app
from app.utils.email_service import send_new_request_notify
from app.utils.email_service import send_borrow_new_request_notify
from app.models.system import SysUser
applicant_name = ''
@ -176,7 +176,7 @@ class BorrowApprovalService:
# 4. 分别发送邮件
if applicant_emails:
try:
send_new_request_notify(
send_borrow_new_request_notify(
to_emails=applicant_emails,
request_no=approval.request_no,
applicant_name=applicant_name,
@ -189,7 +189,7 @@ class BorrowApprovalService:
if approver_emails:
try:
send_new_request_notify(
send_borrow_new_request_notify(
to_emails=approver_emails,
request_no=approval.request_no,
applicant_name=applicant_name,
@ -215,7 +215,7 @@ class BorrowApprovalService:
logger = logging.getLogger(__name__)
try:
from app.utils.email_service import send_approval_result_notify, send_warehouse_dispatch_notify
from app.utils.email_service import send_borrow_approval_result_notify, send_borrow_dispatch_notify
from app.models.system import SysUser as SU
# 1. 提取申请人信息
@ -229,17 +229,32 @@ class BorrowApprovalService:
applicant_emails.append(user.email)
# 2. 提取物料明细
items = approval.items_json if approval.items_json else []
items = approval.get_items() if approval else []
# 3. 分支逻辑
if action == 'approve':
# 3.1 通知库管(带明细
# 3.1 通知申请人(审批已通过,明确告知结果
if applicant_emails:
try:
send_borrow_approval_result_notify(
to_emails=applicant_emails,
request_no=approval.request_no,
is_passed=True,
reject_reason='',
applicant_name=applicant_name
)
except Exception as e:
logger.error(f"[Email] 通知申请人(通过)失败: {e}")
else:
logger.warning("[Email] 申请人无邮箱,无法发送审批通过通知")
# 3.2 通知库管(请备货)
warehouse_role_codes = ['WAREHOUSE_MGR', 'OUTBOUND']
warehouse_emails = BorrowApprovalService._get_emails_by_identifiers(role_codes=warehouse_role_codes)
if warehouse_emails:
try:
send_warehouse_dispatch_notify(
send_borrow_dispatch_notify(
to_emails=warehouse_emails,
request_no=approval.request_no,
applicant_name=applicant_name,
@ -247,24 +262,14 @@ class BorrowApprovalService:
)
except Exception as e:
logger.error(f"[Email] 通知库管失败: {e}")
# 3.2 通知申请人(审批通过,带完整物料清单)
if applicant_emails:
try:
send_warehouse_dispatch_notify(
to_emails=applicant_emails,
request_no=approval.request_no,
applicant_name=applicant_name,
items=items
)
except Exception as e:
logger.error(f"[Email] 通知申请人(通过)失败: {e}")
else:
logger.warning("[Email] 无库管角色邮箱,无法发送备货通知")
elif action == 'reject':
# 3.3 通知申请人(已驳回)
if applicant_emails:
try:
send_approval_result_notify(
send_borrow_approval_result_notify(
to_emails=applicant_emails,
request_no=approval.request_no,
is_passed=False,

View File

@ -709,7 +709,7 @@ class OutboundApprovalService:
"""发送新申请通知邮件给审批人和申请人(静默处理,不阻断主流程)"""
try:
from flask import current_app
from app.utils.email_service import send_new_request_notify
from app.utils.email_service import send_outbound_new_request_notify
from app.models.system import SysUser
applicant_name = ''
@ -749,7 +749,7 @@ class OutboundApprovalService:
# 4. 分别发送邮件
if applicant_emails:
try:
send_new_request_notify(
send_outbound_new_request_notify(
to_emails=applicant_emails,
request_no=approval.request_no,
applicant_name=applicant_name,
@ -762,7 +762,7 @@ class OutboundApprovalService:
if approver_emails:
try:
send_new_request_notify(
send_outbound_new_request_notify(
to_emails=approver_emails,
request_no=approval.request_no,
applicant_name=applicant_name,
@ -871,7 +871,7 @@ class OutboundApprovalService:
logger = logging.getLogger(__name__)
try:
from app.utils.email_service import send_approval_result_notify, send_warehouse_dispatch_notify
from app.utils.email_service import send_outbound_approval_result_notify, send_outbound_dispatch_notify
from app.models.system import SysUser as SU
# 1. 提取申请人信息(供两个分支使用)
@ -885,7 +885,7 @@ class OutboundApprovalService:
applicant_emails.append(user.email)
# 2. 提取物料明细(供通过分支使用)
items = approval.items_json if approval.items_json else []
items = approval.get_items() if approval else []
# 3. 分支逻辑
if action == 'approve':
@ -895,7 +895,7 @@ class OutboundApprovalService:
if warehouse_emails:
try:
send_warehouse_dispatch_notify(
send_outbound_dispatch_notify(
to_emails=warehouse_emails,
request_no=approval.request_no,
applicant_name=applicant_name,
@ -907,7 +907,7 @@ class OutboundApprovalService:
# 3.2 通知申请人(审批通过,带完整物料清单)
if applicant_emails:
try:
send_warehouse_dispatch_notify(
send_outbound_dispatch_notify(
to_emails=applicant_emails,
request_no=approval.request_no,
applicant_name=applicant_name,
@ -920,7 +920,7 @@ class OutboundApprovalService:
# 3.3 通知申请人(已驳回)
if applicant_emails:
try:
send_approval_result_notify(
send_outbound_approval_result_notify(
to_emails=applicant_emails,
request_no=approval.request_no,
is_passed=False,

View File

@ -118,24 +118,13 @@ def send_email(to_email: Union[str, List[str]], subject: str, content: str):
logger.error(f"[Email] 发送邮件时发生未知异常: {e}")
def send_new_request_notify(to_emails: List[str], request_no: str,
def send_outbound_new_request_notify(to_emails: List[str], request_no: str,
applicant_name: str = '', remark: str = '',
items: list = None, is_applicant_notify: bool = False):
"""
通知审批人有新的出库申请单待审批(可附带物料清单)
或通知申请人其申请已提交is_applicant_notify=True 时)
Args:
to_emails: 审批人邮箱列表
request_no: 审批单号
applicant_name: 申请人姓名
remark: 申请备注
items: 物料明细列表(可选)
is_applicant_notify: True=通知申请人标题您的出库申请已提交False=通知审批人(标题:您有一笔新的出库审批待处理)
"""
print(f"[DEBUG send_new_request_notify] 入参 items={items}, is_applicant_notify={is_applicant_notify}")
# 拼装物料表格
rows = []
rows.append("名称 | 规格 | 计划数量")
rows.append("-" * 40)
@ -194,21 +183,78 @@ https://172.16.0.198/outbound/approval
send_email(to_emails, subject, content)
def send_approval_result_notify(to_emails: List[str], request_no: str,
def send_borrow_new_request_notify(to_emails: List[str], request_no: str,
applicant_name: str = '', remark: str = '',
items: list = None, is_applicant_notify: bool = False):
"""
通知审批人有新的借库申请单待审批(可附带物料清单)
或通知申请人其申请已提交is_applicant_notify=True 时)
"""
rows = []
rows.append("名称 | 规格 | 计划数量")
rows.append("-" * 40)
if items:
for item in items:
name = item.get('name', '-') or '-'
spec = item.get('spec_model', '-') or '-'
qty = item.get('quantity', '-') or '-'
rows.append(f"{name} | {spec} | {qty}")
else:
rows.append("(无物料明细)")
if is_applicant_notify:
subject = f"【已提交】您的借库申请单 {request_no} 已提交"
content = f"""您好,
您的借库申请单 {request_no} 已成功提交,等待审批。
申请单号:{request_no}
申请人:{applicant_name or '未知'}
备注说明:{remark or ''}
物料清单如下:
{chr(10).join(rows)}
---
您可以点击下方链接查看申请状态:
https://172.16.0.198/operation/borrow_apply
---
此邮件由系统自动发送,请勿回复。
"""
else:
subject = f"【待审批】借库申请单 {request_no}"
content = f"""您好,
您有一笔新的借库审批申请待处理:
申请单号:{request_no}
申请人:{applicant_name or '未知'}
备注说明:{remark or ''}
物料清单如下:
{chr(10).join(rows)}
---
⚡ 快速通道:
请点击下方链接直接进入系统审批:
https://172.16.0.198/operation/borrow_approval
---
请登录仓库管理系统进行审批。
此邮件由系统自动发送,请勿回复。
"""
send_email(to_emails, subject, content)
def send_outbound_approval_result_notify(to_emails: List[str], request_no: str,
is_passed: bool, reject_reason: str = '',
applicant_name: str = ''):
"""
通知审批结果
Args:
to_emails: 收件人邮箱列表
request_no: 审批单号
is_passed: 是否通过(通过时发给库管,驳回时发给申请人)
reject_reason: 驳回原因(仅 is_passed=False 时使用)
applicant_name: 申请人姓名(仅驳回通知时使用)
通知出库审批结果
"""
if is_passed:
# ★ 发给申请人:告知已通过,去领料
subject = f"【已通过】出库申请单 {request_no}"
content = f"""{"尊敬的 " + applicant_name + ",您好" if applicant_name else "您好"}
@ -219,7 +265,6 @@ def send_approval_result_notify(to_emails: List[str], request_no: str,
此邮件由系统自动发送,请勿回复。
"""
else:
# ★ 发给申请人:告知被驳回
subject = f"【已驳回】出库申请单 {request_no}"
content = f"""{"尊敬的 " + applicant_name + ",您好" if applicant_name else "您好"}
@ -234,19 +279,43 @@ def send_approval_result_notify(to_emails: List[str], request_no: str,
send_email(to_emails, subject, content)
def send_warehouse_dispatch_notify(to_emails: List[str], request_no: str,
def send_borrow_approval_result_notify(to_emails: List[str], request_no: str,
is_passed: bool, reject_reason: str = '',
applicant_name: str = ''):
"""
通知借库审批结果
"""
if is_passed:
subject = f"【已通过】借库申请单 {request_no}"
content = f"""{"尊敬的 " + applicant_name + ",您好" if applicant_name else "您好"}
您的借库申请单 {request_no} 已审批通过,请前往仓库扫码借出。
请登录仓库管理系统查看详情。
此邮件由系统自动发送,请勿回复。
"""
else:
subject = f"【已驳回】借库申请单 {request_no}"
content = f"""{"尊敬的 " + applicant_name + ",您好" if applicant_name else "您好"}
借库申请单 {request_no} 已被审批驳回。
驳回原因:{reject_reason or '未填写'}
请登录仓库管理系统查看详情,并根据驳回原因调整后重新提交申请。
此邮件由系统自动发送,请勿回复。
"""
send_email(to_emails, subject, content)
def send_outbound_dispatch_notify(to_emails: List[str], request_no: str,
applicant_name: str = '', items: list = None):
"""
通知库管备货出库(包含完整物料清单)
Args:
to_emails: 库管邮箱列表
request_no: 审批单号
applicant_name: 申请人姓名
items: 物料明细列表,每个元素包含 name/spec_model/warehouse_location/quantity
"""
print(f"[DEBUG send_warehouse_dispatch_notify] 入参 items={items}")
print(f"[DEBUG send_warehouse_dispatch_notify] items 类型={type(items)}, 长度={len(items) if items else 0}")
print(f"[DEBUG send_outbound_dispatch_notify] 入参 items={items}")
rows = []
rows.append("名称 | 规格 | 库位 | 计划数量")
@ -275,4 +344,39 @@ def send_warehouse_dispatch_notify(to_emails: List[str], request_no: str,
此邮件由系统自动发送,请勿回复。
"""
send_email(to_emails, subject, content)
print(f"DEBUG: 准备向服务器提交发信请求,收件人: {to_emails}")
def send_borrow_dispatch_notify(to_emails: List[str], request_no: str,
applicant_name: str = '', items: list = None):
"""
通知库管备货借库(包含完整物料清单)
"""
print(f"[DEBUG send_borrow_dispatch_notify] 入参 items={items}")
rows = []
rows.append("名称 | 规格 | 库位 | 计划数量")
rows.append("-" * 50)
if items:
for item in items:
name = item.get('name', '-') or '-'
spec = item.get('spec_model', '-') or '-'
loc = item.get('warehouse_location', '-') or '-'
qty = item.get('quantity', '-') or '-'
rows.append(f"{name} | {spec} | {loc} | {qty}")
else:
rows.append("(无物料明细)")
subject = f"【待借库】借库申请单 {request_no} 已审批通过"
content = f"""您好,
借库申请单 {request_no} 已审批通过,请按以下清单准备备货:
{chr(10).join(rows)}
申请人:{applicant_name or '未知'}
请登录仓库管理系统执行"扫码借库"操作。
此邮件由系统自动发送,请勿回复。
"""
send_email(to_emails, subject, content)