|
|
|
@ -616,6 +616,9 @@ public class ErfExpApplyServiceImpl extends ServiceImpl<ErfExpApplyMapper, ErfEx |
|
|
|
erfFlowEngineService.moveToNextNode(data.getApplyNo(), "计划员排产", null); |
|
|
|
log.info("排产完成,已自动流转到下一节点"); |
|
|
|
|
|
|
|
// 排产完成后向仓库角色用户发送邮件通知 |
|
|
|
sendWarehouseNotification(entity); |
|
|
|
|
|
|
|
log.info("计划员排产完成"); |
|
|
|
} |
|
|
|
|
|
|
|
@ -1528,6 +1531,113 @@ public class ErfExpApplyServiceImpl extends ServiceImpl<ErfExpApplyMapper, ErfEx |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 排产完成后向仓库角色用户发送邮件通知 |
|
|
|
* 邮件内容包含试验单信息表格和原材料清单 |
|
|
|
* |
|
|
|
* @param entity 试验单实体 |
|
|
|
*/ |
|
|
|
private void sendWarehouseNotification(ErfExpApply entity) { |
|
|
|
try { |
|
|
|
MailSendAddressData mailSendData = qcMapper.getSendMailFromAddress(); |
|
|
|
if (mailSendData == null) { |
|
|
|
log.error("邮件发送配置未设置,无法发送仓库通知邮件"); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// 查询角色名称为"仓库"且备注为"工程实验申请"的用户邮箱列表 |
|
|
|
List<UserEmailInfoDto> warehouseUsers = sysUserDao.getUserEmailListByRoleNameAndRemark("仓库", "工程实验申请"); |
|
|
|
if (warehouseUsers == null || warehouseUsers.isEmpty()) { |
|
|
|
log.warn("未找到仓库角色(备注=工程实验申请)的用户,跳过发送邮件"); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
String todayStr = DateTimeFormatter.ofPattern("yyyy-MM-dd").format(LocalDateTime.now()); |
|
|
|
String expectedFinishDateStr = entity.getExpectedFinishDate() != null |
|
|
|
? DateTimeFormatter.ofPattern("yyyy-MM-dd") |
|
|
|
.format(entity.getExpectedFinishDate().toInstant().atZone(java.time.ZoneId.systemDefault()).toLocalDateTime()) |
|
|
|
: ""; |
|
|
|
|
|
|
|
// 构建试验单信息表格 |
|
|
|
String mainTable = buildPlannerNotificationTable(entity, todayStr, expectedFinishDateStr); |
|
|
|
|
|
|
|
// 构建原材料清单表格 |
|
|
|
List<ErfExpRawMaterial> rawMaterials = erfExpRawMaterialService.getRawMaterialListByApplyNo(entity.getApplyNo()); |
|
|
|
String rawMaterialTable = buildRawMaterialTable(rawMaterials); |
|
|
|
|
|
|
|
String subject = String.format("【排产通知】%s - %s", |
|
|
|
entity.getApplyNo(), entity.getTitle() != null ? entity.getTitle() : ""); |
|
|
|
|
|
|
|
List<String> successEmails = new ArrayList<>(); |
|
|
|
|
|
|
|
for (UserEmailInfoDto warehouseUser : warehouseUsers) { |
|
|
|
try { |
|
|
|
String body = "<html><body>" |
|
|
|
+ "<h3>尊敬的 " + warehouseUser.getUsername() + ":</h3>" |
|
|
|
+ "<p>您好!以下工程实验试验单已完成排产,请做好相应备料准备。</p>" |
|
|
|
+ "<hr/>" + mainTable |
|
|
|
+ "<br/><h4>原材料清单:</h4>" + rawMaterialTable |
|
|
|
+ "<br/><p style='color:#888;'>发送时间:" |
|
|
|
+ LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) |
|
|
|
+ "</p></body></html>"; |
|
|
|
|
|
|
|
MailUtil.sendMail(subject, body, new String[]{warehouseUser.getEmail()}, mailSendData); |
|
|
|
successEmails.add(warehouseUser.getEmail()); |
|
|
|
log.info("已向仓库用户 {} ({}) 发送排产通知邮件,试验单: {}", |
|
|
|
warehouseUser.getUsername(), warehouseUser.getEmail(), entity.getApplyNo()); |
|
|
|
} catch (Exception e) { |
|
|
|
log.error("向仓库用户 {} 发送邮件失败: {}", warehouseUser.getEmail(), e.getMessage()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (!successEmails.isEmpty()) { |
|
|
|
SendMailRecord mailRecord = new SendMailRecord(); |
|
|
|
mailRecord.setType("工程实验申请排产通知"); |
|
|
|
mailRecord.setDocumentNo(entity.getApplyNo()); |
|
|
|
mailRecord.setRecipient(String.join(";", successEmails)); |
|
|
|
mailRecord.setSendDate(new Date()); |
|
|
|
qcMapper.saveSendMailRecord(mailRecord); |
|
|
|
} |
|
|
|
|
|
|
|
} catch (Exception e) { |
|
|
|
log.error("发送仓库排产通知邮件失败,试验单: {}, 错误: {}", entity.getApplyNo(), e.getMessage(), e); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 构建原材料清单 HTML 表格 |
|
|
|
* |
|
|
|
* @param rawMaterials 原材料清单列表 |
|
|
|
* @return HTML 表格字符串 |
|
|
|
*/ |
|
|
|
private String buildRawMaterialTable(List<ErfExpRawMaterial> rawMaterials) { |
|
|
|
StringBuilder sb = new StringBuilder(); |
|
|
|
sb.append("<table border='1' cellpadding='6' cellspacing='0' ") |
|
|
|
.append("style='border-collapse:collapse; width:100%; font-size:13px;'>") |
|
|
|
.append("<thead style='background-color:#4CAF50; color:white;'><tr>") |
|
|
|
.append("<th>序号</th><th>物料编码</th><th>物料描述</th><th>数量</th><th>计量单位</th><th>备注</th>") |
|
|
|
.append("</tr></thead><tbody>"); |
|
|
|
|
|
|
|
if (rawMaterials == null || rawMaterials.isEmpty()) { |
|
|
|
sb.append("<tr><td colspan='6' style='text-align:center;'>暂无原材料</td></tr>"); |
|
|
|
} else { |
|
|
|
int index = 1; |
|
|
|
for (ErfExpRawMaterial rm : rawMaterials) { |
|
|
|
sb.append("<tr>") |
|
|
|
.append("<td>").append(index++).append("</td>") |
|
|
|
.append("<td>").append(rm.getPartNo() != null ? rm.getPartNo() : "").append("</td>") |
|
|
|
.append("<td>").append(rm.getPartDesc() != null ? rm.getPartDesc() : "").append("</td>") |
|
|
|
.append("<td>").append(rm.getQuantity() != null ? rm.getQuantity().toPlainString() : "").append("</td>") |
|
|
|
.append("<td>").append(rm.getUmid() != null ? rm.getUmid() : "").append("</td>") |
|
|
|
.append("<td>").append(rm.getRemark() != null ? rm.getRemark() : "").append("</td>") |
|
|
|
.append("</tr>"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
sb.append("</tbody></table>"); |
|
|
|
return sb.toString(); |
|
|
|
} |
|
|
|
|
|
|
|
private String buildPlannerNotificationTable(ErfExpApply entity, String todayStr, String expectedFinishDateStr) { |
|
|
|
return "<table border='1' cellpadding='6' cellspacing='0' " |
|
|
|
+ "style='border-collapse:collapse; width:100%; font-size:13px;'>" |
|
|
|
|