feat(sip): 实现供应商和合作伙伴邮件通知功能

- 启用邮件发送功能配置
- 添加预付款和预收款变动的邮件模板
- 实现在核销和恢复操作时自动发送邮件通知给供应商和合作伙伴
- 集成邮件工具类支持模板邮件发送
- 添加供应商信息批量查询功能
- 实现在预付款核销时发送余额变动通知
- 实现在预付款恢复时发送退款通知
- 实现在预收款处理时发送相应通知邮件
- 添加新的DTO类用于项目付款单数据传输
dev_1.0.1
chenhao 2026-01-05 20:57:34 +08:00
parent 357410c3e7
commit 3102a2c0a0
17 changed files with 337 additions and 24 deletions

View File

@ -68,4 +68,4 @@ unis:
# 执行单截止时间 # 执行单截止时间
endHour: 96 endHour: 96
mail: mail:
enabled: false enabled: true

View File

@ -0,0 +1,38 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="renderer" content="webkit">
</head>
<style>
tr td,th{
text-align: center;
border: 1px solid black;
padding: 5px 10px;
}
p{
margin-top: 20px;
}
</style>
<body>
<div>
<p>尊敬的[[${vendorName}]]:</p>
<p>因【[[${projectName}]]】计划变更,我司已将原划扣款项¥[[${paymentAmount}]]元,全额退回至贵司的预付款账户。</p>
<p>截至目前,预付款余额为¥[[${preResidueAmountAdd}]]元。</p>
<p> 特此函告。</p>
<p style="text-align: right">
紫光汇智信息技术有限公司
</p>
<p style="text-align: right">
[[${currentDate}]]
</p>
<!-- <div style="margin-top:50px">-->
<!-- <img src="cid:signature" style="width: 200px; height: auto;" />-->
<!-- <p>紫光汇智信息技术有限公司</p>-->
<!-- </div>-->
</div>
</body>
</html>

View File

@ -0,0 +1,38 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="renderer" content="webkit">
</head>
<style>
tr td,th{
text-align: center;
border: 1px solid black;
padding: 5px 10px;
}
p{
margin-top: 20px;
}
</style>
<body>
<div>
<p>尊敬的[[${vendorName}]]:</p>
<p>我司向贵公司发起的预付款(金额¥[[${preResidueAmount}]]元),因【[[${projectName}]]】结算,已按约扣除¥[[${paymentAmount}]]元。</p>
<p>截至目前,预付款余额为¥[[${preResidueAmountSub}]]元。</p>
<p> 特此函告。</p>
<p style="text-align: right;">
紫光汇智信息技术有限公司
</p>
<p style="text-align: right;">
[[${currentDate}]]
</p>
<!-- <div style="margin-top:50px">-->
<!-- <img src="cid:signature" style="width: 200px; height: auto;" />-->
<!-- <p>紫光汇智信息技术有限公司</p>-->
<!-- </div>-->
</div>
</body>
</html>

View File

@ -0,0 +1,38 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="renderer" content="webkit">
</head>
<style>
tr td,th{
text-align: center;
border: 1px solid black;
padding: 5px 10px;
}
p{
margin-top: 20px;
}
</style>
<body>
<div>
<p>尊敬的[[${vendorName}]]:</p>
<p>因【[[${projectName}]]】计划变更,我司已将原划扣款项¥[[${paymentAmount}]]元,全额退回至贵司的预收款账户。</p>
<p> 截至目前,预收款余额为¥[[${preResidueAmountAdd}]]元。</p>
<p> 特此函告。</p>
<p style="text-align: right">
紫光汇智信息技术有限公司
</p>
<p style="text-align: right">
[[${currentDate}]]
</p>
<!-- <div style="margin-top:50px">-->
<!-- <img src="cid:signature" style="width: 200px; height: auto;" />-->
<!-- <p>紫光汇智信息技术有限公司</p>-->
<!-- </div>-->
</div>
</body>
</html>

View File

@ -0,0 +1,38 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="renderer" content="webkit">
</head>
<style>
tr td,th{
text-align: center;
border: 1px solid black;
padding: 5px 10px;
}
p{
margin-top: 20px;
}
</style>
<body>
<div>
<p>尊敬的[[${partnerName}]]:</p>
<p>我司向贵公司发起的预收款(金额¥[[${preResidueAmount}]]元),因【[[${projectName}]]】结算,已按约扣除¥[[${paymentAmount}]]元。</p>
<p>截至目前,预收款余额为¥[[${preResidueAmountSub}]]元。</p>
<p> 特此函告。</p>
<p style="text-align: right">
紫光汇智信息技术有限公司
</p>
<p style="text-align: right">
[[${currentDate}]]
</p>
<!-- <div style="margin-top:50px">-->
<!-- <img src="cid:signature" style="width: 200px; height: auto;" />-->
<!-- <p>紫光汇智信息技术有限公司</p>-->
<!-- </div>-->
</div>
</body>
</html>

View File

@ -42,10 +42,18 @@ public class TemplateMailUtil {
* @Date 2025/07/29 09:55 * @Date 2025/07/29 09:55
*/ */
public static void sendTemplateMail(List<String> toEmail, String title, MailTemplate path, Dict dict) { public static void sendTemplateMail(List<String> toEmail, String title, MailTemplate path, Dict dict) {
sendTemplateMail(toEmail, title, path, dict, null); sendTemplateMail(toEmail, title, path, dict, null, true);
} }
public static void sendTemplateMail(List<String> toEmail, String title, MailTemplate path, Dict dict, List<String> toCssEmail) { public static void sendTemplateMail(List<String> toEmail, String title, MailTemplate path, Dict dict, List<String> toCssEmail) {
sendTemplateMail(toEmail, title, path, dict, toCssEmail, true);
}
public static void sendTemplateMailNotImage(List<String> toEmail, String title, MailTemplate path, Dict dict) {
sendTemplateMail(toEmail, title, path, dict, null, false);
}
public static void sendTemplateMail(List<String> toEmail, String title, MailTemplate path, Dict dict, List<String> toCssEmail, Boolean addImage) {
String enabled = SpringUtils.getProperty("unis.mail.enabled", "false"); String enabled = SpringUtils.getProperty("unis.mail.enabled", "false");
if (!Boolean.parseBoolean(enabled)) { if (!Boolean.parseBoolean(enabled)) {
log.warn("邮件发送开关未开启"); log.warn("邮件发送开关未开启");
@ -58,9 +66,7 @@ public class TemplateMailUtil {
String result = template.render(dict); String result = template.render(dict);
try{ try{
org.springframework.core.io.Resource resource = SpringUtils.getResource("classpath:static/img/companyLogo.png");
// 使用 InputStreamResource 包装输入流
InputStreamResource imageResource = new InputStreamResource(resource.getInputStream());
Mail mail = Mail.create() Mail mail = Mail.create()
.setTos(toEmail.toArray(new String[0])) .setTos(toEmail.toArray(new String[0]))
.setTitle(title) .setTitle(title)
@ -69,7 +75,12 @@ public class TemplateMailUtil {
if (CollUtil.isNotEmpty(toCssEmail)) { if (CollUtil.isNotEmpty(toCssEmail)) {
mail.setCcs(toCssEmail.toArray(new String[0])); mail.setCcs(toCssEmail.toArray(new String[0]));
} }
mail.addImage("signature",imageResource.getStream()); if (addImage != null && addImage) {
org.springframework.core.io.Resource resource = SpringUtils.getResource("classpath:static/img/companyLogo.png");
// 使用 InputStreamResource 包装输入流
InputStreamResource imageResource = new InputStreamResource(resource.getInputStream());
mail.addImage("signature", imageResource.getStream());
}
mail.send(); mail.send();
} catch (Exception e) { } catch (Exception e) {
log.error("发送邮件失败,错误原因:{},错误详情:{}",e.getMessage(),e.getStackTrace()); log.error("发送邮件失败,错误原因:{},错误详情:{}",e.getMessage(),e.getStackTrace());
@ -86,6 +97,10 @@ public class TemplateMailUtil {
ORDER_PARTNER("mailPartnerTemplate.html","代理商商通知"), ORDER_PARTNER("mailPartnerTemplate.html","代理商商通知"),
PASSWORD_RESET("passwordTemplate.html", "密码重置"), PASSWORD_RESET("passwordTemplate.html", "密码重置"),
REJECT_EMAIL("rejectTemplate.html", "董事长驳回订单审批流程"), REJECT_EMAIL("rejectTemplate.html", "董事长驳回订单审批流程"),
PAYABLE_EMAIL("payableTemplate.html", "预付款变动通知"),
PAYABLE_REFUNDED_EMAIL("payableRefundedTemplate.html", "董事长驳回订单审批流程"),
RECEIPT_EMAIL("receiptTemplate.html", "董事长驳回订单审批流程"),
RECEIPT_REFUNDED_EMAIL("receiptRefundedTemplate.html", "董事长驳回订单审批流程"),
; ;

View File

@ -32,6 +32,7 @@ public class VendorInfo extends BaseEntity
/** 制造商编码 */ /** 制造商编码 */
@Excel(name = "制造商编码") @Excel(name = "制造商编码")
private String vendorCode; private String vendorCode;
private List<String> vendorCodeList;
/** 制造商名称 */ /** 制造商名称 */
@Excel(name = "制造商名称") @Excel(name = "制造商名称")

View File

@ -0,0 +1,24 @@
package com.ruoyi.sip.domain.dto;
import lombok.Data;
/**
* @author : ch
* @version : 1.0
* @ClassName : ProjectPaymentBillDto
* @Description :
* @DATE : Created in 20:05 2026/1/5
* <pre> Copyright: Copyright(c) 2026 </pre>
* <pre> Company : </pre>
* Modification History:
* Date Author Version Discription
* --------------------------------------------------------------------------
* 2026/01/05 ch 1.0 Why & What is modified: <> *
*/
@Data
public class ProjectPaymentBillDto {
private String projectCode;
private String projectName;
private String paymentBillCode;
}

View File

@ -2,6 +2,7 @@ package com.ruoyi.sip.mapper;
import com.ruoyi.sip.domain.OmsPayablePaymentDetail; import com.ruoyi.sip.domain.OmsPayablePaymentDetail;
import com.ruoyi.sip.domain.dto.PaymentBillPayableDetailDTO; import com.ruoyi.sip.domain.dto.PaymentBillPayableDetailDTO;
import com.ruoyi.sip.domain.dto.ProjectPaymentBillDto;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
import java.util.Date; import java.util.Date;

View File

@ -2,6 +2,7 @@ package com.ruoyi.sip.service;
import com.ruoyi.sip.domain.OmsPayablePaymentDetail; import com.ruoyi.sip.domain.OmsPayablePaymentDetail;
import com.ruoyi.sip.domain.dto.PaymentBillPayableDetailDTO; import com.ruoyi.sip.domain.dto.PaymentBillPayableDetailDTO;
import com.ruoyi.sip.domain.dto.ProjectPaymentBillDto;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;

View File

@ -6,6 +6,7 @@ import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.sip.domain.OmsFinAttachment; import com.ruoyi.sip.domain.OmsFinAttachment;
import com.ruoyi.sip.domain.OmsPayablePaymentDetail; import com.ruoyi.sip.domain.OmsPayablePaymentDetail;
import com.ruoyi.sip.domain.dto.PaymentBillPayableDetailDTO; import com.ruoyi.sip.domain.dto.PaymentBillPayableDetailDTO;
import com.ruoyi.sip.domain.dto.ProjectPaymentBillDto;
import com.ruoyi.sip.mapper.OmsPayablePaymentDetailMapper; import com.ruoyi.sip.mapper.OmsPayablePaymentDetailMapper;
import com.ruoyi.sip.service.IOmsFinAttachmentService; import com.ruoyi.sip.service.IOmsFinAttachmentService;
import com.ruoyi.sip.service.IOmsPayablePaymentDetailService; import com.ruoyi.sip.service.IOmsPayablePaymentDetailService;

View File

@ -3,21 +3,18 @@ package com.ruoyi.sip.service.impl;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern; import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ShiroUtils; import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.sip.domain.OmsPayablePaymentDetail; import com.ruoyi.common.utils.mail.TemplateMailUtil;
import com.ruoyi.sip.domain.OmsPayableWriteOff; import com.ruoyi.sip.domain.*;
import com.ruoyi.sip.domain.OmsPayableWriteOffDetail;
import com.ruoyi.sip.domain.OmsPaymentBill;
import com.ruoyi.sip.domain.dto.PaymentBillPayableDetailDTO; import com.ruoyi.sip.domain.dto.PaymentBillPayableDetailDTO;
import com.ruoyi.sip.dto.WriteOffDetailResultDto; import com.ruoyi.sip.dto.WriteOffDetailResultDto;
import com.ruoyi.sip.dto.WriteOffRequestDto; import com.ruoyi.sip.dto.WriteOffRequestDto;
import com.ruoyi.sip.mapper.OmsPayableWriteOffMapper; import com.ruoyi.sip.mapper.OmsPayableWriteOffMapper;
import com.ruoyi.sip.service.IOmsPayableBillService; import com.ruoyi.sip.service.*;
import com.ruoyi.sip.service.IOmsPayablePaymentDetailService;
import com.ruoyi.sip.service.IOmsPayableWriteOffService;
import com.ruoyi.sip.service.IOmsPaymentBillService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -46,6 +43,8 @@ public class OmsPayableWriteOffServiceImpl implements IOmsPayableWriteOffService
private IOmsPayablePaymentDetailService omsPayablePaymentDetailService; private IOmsPayablePaymentDetailService omsPayablePaymentDetailService;
@Autowired @Autowired
private IOmsPayableBillService payableBillService; private IOmsPayableBillService payableBillService;
@Autowired
private IVendorInfoService vendorInfoService;
/** /**
@ -146,7 +145,24 @@ public class OmsPayableWriteOffServiceImpl implements IOmsPayableWriteOffService
omsPayablePaymentDetail.setWriteOffId(writeOff.getId()); omsPayablePaymentDetail.setWriteOffId(writeOff.getId());
} }
omsPayablePaymentDetailService.insertBatch( writeOffRequestDto.getDetailList()); omsPayablePaymentDetailService.insertBatch( writeOffRequestDto.getDetailList());
payableBillService.updatePaymentAmount(writeOffRequestDto.getDetailList().stream().map(OmsPayablePaymentDetail::getPayableBillId).distinct().collect(Collectors.toList())); List<Long> collect = writeOffRequestDto.getDetailList().stream().map(OmsPayablePaymentDetail::getPayableBillId).distinct().collect(Collectors.toList());
payableBillService.updatePaymentAmount(collect);
VendorInfo vendorInfo = vendorInfoService.selectVendorInfoByVendorCode(writeOffRequestDto.getVendorCode());
if (vendorInfo!=null && StrUtil.isNotEmpty(vendorInfo.getVendorEmail())){
OmsPayableBill queryBill = new OmsPayableBill();
queryBill.setIdList( collect);
List<OmsPayableBill> omsPayableBills = payableBillService.selectOmsPayableBillList(queryBill);
String title = "预付款变动通知";
Dict dict = Dict.create();
dict.put("vendorName", vendorInfo.getVendorName());
dict.put("preResidueAmount", paymentBill.getPreResidueAmount());
dict.put("preResidueAmountSub", decimal);
dict.put("projectName", omsPayableBills.stream().map(OmsPayableBill::getProjectName).filter(StrUtil::isNotEmpty).distinct().collect(Collectors.joining(",")));
dict.put("paymentAmount", totalAmount);
dict.put("currentDate", DateUtils.parseDateToStr(DatePattern.CHINESE_DATE_PATTERN,DateUtils.getNowDate()));
TemplateMailUtil.sendTemplateMailNotImage(Collections.singletonList(vendorInfo.getVendorEmail()), title,
TemplateMailUtil.MailTemplate.PAYABLE_EMAIL, dict);
}
return writeOff.getId(); return writeOff.getId();
} }

View File

@ -2,11 +2,13 @@ package com.ruoyi.sip.service.impl;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.*; import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern; import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.config.RuoYiConfig; import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.config.flow.ProcessConfig; import com.ruoyi.common.config.flow.ProcessConfig;
@ -16,9 +18,11 @@ import com.ruoyi.common.enums.ApproveStatusEnum;
import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ShiroUtils; import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.common.utils.file.FileUploadUtils; import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.mail.TemplateMailUtil;
import com.ruoyi.sip.domain.*; import com.ruoyi.sip.domain.*;
import com.ruoyi.sip.domain.dto.PaymentBillDetailDTO; import com.ruoyi.sip.domain.dto.PaymentBillDetailDTO;
import com.ruoyi.sip.domain.dto.PaymentBillPayableDetailDTO; import com.ruoyi.sip.domain.dto.PaymentBillPayableDetailDTO;
import com.ruoyi.sip.domain.dto.ProjectPaymentBillDto;
import com.ruoyi.sip.dto.WriteOffRequestDto; import com.ruoyi.sip.dto.WriteOffRequestDto;
import com.ruoyi.sip.flowable.domain.Todo; import com.ruoyi.sip.flowable.domain.Todo;
import com.ruoyi.sip.flowable.service.TodoCommonTemplate; import com.ruoyi.sip.flowable.service.TodoCommonTemplate;
@ -573,10 +577,14 @@ public class OmsPaymentBillServiceImpl implements IOmsPaymentBillService , TodoC
if (increaseAmount.compareTo(BigDecimal.ZERO) > 0) { if (increaseAmount.compareTo(BigDecimal.ZERO) > 0) {
OmsPaymentBill updateBill = new OmsPaymentBill(); OmsPaymentBill updateBill = new OmsPaymentBill();
updateBill.setId(prePaymentBill.getId()); updateBill.setId(prePaymentBill.getId());
updateBill.setVendorCode(prePaymentBill.getVendorCode());
updateBill.setPaymentBillCode(prePaymentBill.getPaymentBillCode());
// 在原剩余额度基础上加回本次核销金额 // 在原剩余额度基础上加回本次核销金额
BigDecimal newResidueAmount = prePaymentBill.getPreResidueAmount() BigDecimal newResidueAmount = prePaymentBill.getPreResidueAmount()
.add(increaseAmount); .add(increaseAmount);
updateBill.setPreResidueAmount(newResidueAmount); updateBill.setPreResidueAmount(newResidueAmount);
return updateBill; return updateBill;
} }
return null; return null;
@ -585,8 +593,39 @@ public class OmsPaymentBillServiceImpl implements IOmsPaymentBillService , TodoC
.collect(Collectors.toList()); .collect(Collectors.toList());
if (CollUtil.isNotEmpty(updateBills)) { if (CollUtil.isNotEmpty(updateBills)) {
VendorInfo queryVendor = new VendorInfo();
queryVendor.setVendorCodeList(updateBills.stream().map(OmsPaymentBill::getVendorCode).distinct().collect(Collectors.toList()));
List<VendorInfo> vendorInfos = vendorInfoService.selectVendorInfoList(queryVendor);
Map<String, VendorInfo> vendorInfoMap = vendorInfos.stream().collect(Collectors.toMap(VendorInfo::getVendorCode, Function.identity(), (v1, v2) -> v1));
List<Long> payableBillIdList = omsPayablePaymentDetails.stream().map(OmsPayablePaymentDetail::getPayableBillId).collect(Collectors.toList());
OmsPayableBill query = new OmsPayableBill();
query.setIdList(payableBillIdList);
List<OmsPayableBill> omsPayableBills = payableBillService.selectOmsPayableBillList(query);
Map<Long, String> projectNameMap = omsPayableBills.stream().collect(Collectors.toMap(OmsPayableBill::getId, OmsPayableBill::getProjectName));
Map<String, Set<String>> projectNamePaymentCodeMapSet = omsPayablePaymentDetails.stream().collect(Collectors.groupingBy(OmsPayablePaymentDetail::getPaymentBillCode,
Collectors.mapping(item -> {
return projectNameMap.get(item.getPayableBillId());
},
Collectors.toSet())));
for (OmsPaymentBill bill : updateBills) { for (OmsPaymentBill bill : updateBills) {
updateOmsPaymentBill(bill); updateOmsPaymentBill(bill);
VendorInfo vendorInfo = vendorInfoMap.get(bill.getVendorCode());
if (vendorInfo != null && StrUtil.isNotEmpty(vendorInfo.getVendorEmail())) {
BigDecimal increaseAmount = paymentBillWriteOffAmountMap.getOrDefault(
bill.getPaymentBillCode(), BigDecimal.ZERO);
String title = "预付款恢复通知";
Dict dict = Dict.create();
dict.put("vendorName", vendorInfo.getVendorName());
dict.put("preResidueAmount", bill.getPreResidueAmount().subtract(increaseAmount));
dict.put("preResidueAmountAdd", bill.getPreResidueAmount());
dict.put("projectName", projectNamePaymentCodeMapSet.getOrDefault(bill.getPaymentBillCode(),Collections.emptySet()).stream().filter(StrUtil::isNotEmpty).collect(Collectors.joining(",")));
dict.put("paymentAmount", increaseAmount);
dict.put("currentDate", DateUtils.parseDateToStr(DatePattern.CHINESE_DATE_PATTERN, DateUtils.getNowDate()));
TemplateMailUtil.sendTemplateMailNotImage(Collections.singletonList(vendorInfo.getVendorEmail()), title,
TemplateMailUtil.MailTemplate.PAYABLE_REFUNDED_EMAIL, dict);
}
} }
} }
} }

View File

@ -3,6 +3,7 @@ package com.ruoyi.sip.service.impl;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern; import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.config.RuoYiConfig; import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.config.flow.ProcessConfig; import com.ruoyi.common.config.flow.ProcessConfig;
@ -13,6 +14,7 @@ import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ShiroUtils; import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils; import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.mail.TemplateMailUtil;
import com.ruoyi.sip.domain.*; import com.ruoyi.sip.domain.*;
import com.ruoyi.sip.domain.dto.ReceiptDetailDTO; import com.ruoyi.sip.domain.dto.ReceiptDetailDTO;
import com.ruoyi.sip.dto.WriteOffReceiptRequestDto; import com.ruoyi.sip.dto.WriteOffReceiptRequestDto;
@ -32,6 +34,7 @@ import java.io.IOException;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.rmi.ServerException; import java.rmi.ServerException;
import java.util.*; import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
@ -53,6 +56,8 @@ public class OmsReceiptBillServiceImpl implements IOmsReceiptBillService, TodoCo
@Autowired @Autowired
private IOmsFinAttachmentService attachmentService; private IOmsFinAttachmentService attachmentService;
@Autowired
private IPartnerInfoService partnerInfoService;
@Autowired @Autowired
private IOmsReceivableWriteOffService omsReceivableWriteOffService; private IOmsReceivableWriteOffService omsReceivableWriteOffService;
@ -385,6 +390,8 @@ public class OmsReceiptBillServiceImpl implements IOmsReceiptBillService, TodoCo
if (increaseAmount.compareTo(BigDecimal.ZERO) > 0) { if (increaseAmount.compareTo(BigDecimal.ZERO) > 0) {
OmsReceiptBill updateBill = new OmsReceiptBill(); OmsReceiptBill updateBill = new OmsReceiptBill();
updateBill.setId(prePaymentBill.getId()); updateBill.setId(prePaymentBill.getId());
updateBill.setPartnerCode(prePaymentBill.getPartnerCode());
updateBill.setReceiptBillCode(prePaymentBill.getReceiptBillCode());
// 在原剩余额度基础上加回本次核销金额 // 在原剩余额度基础上加回本次核销金额
BigDecimal newResidueAmount = prePaymentBill.getRemainingAmount() BigDecimal newResidueAmount = prePaymentBill.getRemainingAmount()
.add(increaseAmount); .add(increaseAmount);
@ -397,8 +404,35 @@ public class OmsReceiptBillServiceImpl implements IOmsReceiptBillService, TodoCo
.collect(Collectors.toList()); .collect(Collectors.toList());
if (CollUtil.isNotEmpty(updateBills)) { if (CollUtil.isNotEmpty(updateBills)) {
List<PartnerInfo> partnerInfos = partnerInfoService.selectPartnerInfoByCode(updateBills.stream().map(OmsReceiptBill::getPartnerCode).collect(Collectors.toList()));
Map<String, PartnerInfo> partnerInfoMap = partnerInfos.stream().collect(Collectors.toMap(PartnerInfo::getPartnerCode, Function.identity(), (v1, v2) -> v1));
OmsReceivableBill queryBill = new OmsReceivableBill();
queryBill.setIdList(omsReceivableReceiptDetails.stream().map(OmsReceivableReceiptDetail::getReceivableBillId).distinct().collect(Collectors.toList()));
List<OmsReceivableBill> receivableBillList = receivableBillService.selectOmsReceivableBillList(queryBill);
Map<Long, String> projectNameMap = receivableBillList.stream().collect(Collectors.toMap(OmsReceivableBill::getId, OmsReceivableBill::getProjectName, (v1, v2) -> v1));
Map<String, Set<String>> projectNameBillCodeMap = omsReceivableReceiptDetails.stream().collect(Collectors.groupingBy(OmsReceivableReceiptDetail::getReceiptBillCode,
Collectors.mapping(item -> projectNameMap.get(item.getReceivableBillId()), Collectors.toSet())));
for (OmsReceiptBill bill : updateBills) { for (OmsReceiptBill bill : updateBills) {
update(bill); update(bill);
PartnerInfo partnerInfo = partnerInfoMap.get(bill.getPartnerCode());
if (partnerInfo != null && StrUtil.isNotEmpty(partnerInfo.getContactEmail())) {
BigDecimal increaseAmount = paymentBillWriteOffAmountMap.getOrDefault(
bill.getReceiptBillCode(), BigDecimal.ZERO);
String title = "预付款恢复通知";
Dict dict = Dict.create();
dict.put("partnerName", partnerInfo.getPartnerName());
dict.put("preResidueAmount", bill.getRemainingAmount().subtract(increaseAmount));
dict.put("preResidueAmountAdd", bill.getRemainingAmount());
dict.put("projectName", projectNameBillCodeMap.getOrDefault(bill.getReceiptBillCode(),Collections.emptySet()).stream().filter(StrUtil::isNotEmpty).collect(Collectors.joining(",")));
dict.put("paymentAmount", increaseAmount);
dict.put("currentDate", DateUtils.parseDateToStr(DatePattern.CHINESE_DATE_PATTERN, DateUtils.getNowDate()));
TemplateMailUtil.sendTemplateMailNotImage(Collections.singletonList(partnerInfo.getContactEmail()), title,
TemplateMailUtil.MailTemplate.RECEIPT_REFUNDED_EMAIL, dict);
}
} }
} }
//预收单的detail直接删除 //预收单的detail直接删除

View File

@ -3,22 +3,18 @@ package com.ruoyi.sip.service.impl;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern; import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ShiroUtils; import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.sip.domain.OmsPayablePaymentDetail; import com.ruoyi.common.utils.mail.TemplateMailUtil;
import com.ruoyi.sip.domain.OmsReceiptBill; import com.ruoyi.sip.domain.*;
import com.ruoyi.sip.domain.OmsReceivableReceiptDetail;
import com.ruoyi.sip.domain.OmsReceivableWriteOff;
import com.ruoyi.sip.domain.dto.ReceiptDetailDTO; import com.ruoyi.sip.domain.dto.ReceiptDetailDTO;
import com.ruoyi.sip.dto.WriteOffDetailResultDto; import com.ruoyi.sip.dto.WriteOffDetailResultDto;
import com.ruoyi.sip.dto.WriteOffReceiptRequestDto; import com.ruoyi.sip.dto.WriteOffReceiptRequestDto;
import com.ruoyi.sip.mapper.OmsReceivableWriteOffMapper; import com.ruoyi.sip.mapper.OmsReceivableWriteOffMapper;
import com.ruoyi.sip.service.IOmsReceiptBillService; import com.ruoyi.sip.service.*;
import com.ruoyi.sip.service.IOmsReceivableBillService;
import com.ruoyi.sip.service.IOmsReceivableReceiptDetailService;
import com.ruoyi.sip.service.IOmsReceivableWriteOffService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -47,6 +43,8 @@ public class OmsReceivableWriteOffServiceImpl implements IOmsReceivableWriteOffS
private IOmsReceivableReceiptDetailService omsReceivableReceiptDetailService; private IOmsReceivableReceiptDetailService omsReceivableReceiptDetailService;
@Autowired @Autowired
private IOmsReceivableBillService receivableBillService; private IOmsReceivableBillService receivableBillService;
@Autowired
private IPartnerInfoService partnerInfoService;
/** /**
* *
@ -153,6 +151,31 @@ public class OmsReceivableWriteOffServiceImpl implements IOmsReceivableWriteOffS
omsReceivableReceiptDetailService.insertOmsReceivableReceiptDetail(detail); omsReceivableReceiptDetailService.insertOmsReceivableReceiptDetail(detail);
} }
receivableBillService.updateReceiptAmount(writeOffRequestDto.getDetailList().stream().map(OmsReceivableReceiptDetail::getReceivableBillId).distinct().collect(Collectors.toList())); receivableBillService.updateReceiptAmount(writeOffRequestDto.getDetailList().stream().map(OmsReceivableReceiptDetail::getReceivableBillId).distinct().collect(Collectors.toList()));
String title = "预收款变动通知";
List<PartnerInfo> partnerInfos = partnerInfoService.selectPartnerInfoByCode(Collections.singletonList(writeOffRequestDto.getPartnerCode()));
if (CollUtil.isNotEmpty(partnerInfos)){
PartnerInfo partnerInfo = partnerInfos.get(0);
if (partnerInfo!=null && StrUtil.isNotEmpty(partnerInfo.getContactEmail())){
OmsReceivableBill queryBill = new OmsReceivableBill();
queryBill.setIdList(writeOffRequestDto.getDetailList().stream().map(OmsReceivableReceiptDetail::getReceivableBillId).distinct().collect(Collectors.toList()));
List<OmsReceivableBill> receivableBillList = receivableBillService.selectOmsReceivableBillList(queryBill);
Dict dict = Dict.create();
dict.put("partnerName", writeOffRequestDto.getPartnerName());
dict.put("preResidueAmount", receiptBill.getRemainingAmount());
dict.put("preResidueAmountSub", decimal);
dict.put("projectName", receivableBillList.stream().map(OmsReceivableBill::getProjectName).collect(Collectors.joining(", ")));
dict.put("paymentAmount", totalAmount);
dict.put("currentDate", DateUtils.parseDateToStr(DatePattern.CHINESE_DATE_PATTERN,DateUtils.getNowDate()));
TemplateMailUtil.sendTemplateMailNotImage(Collections.singletonList(partnerInfo.getContactEmail()), title,
TemplateMailUtil.MailTemplate.RECEIPT_EMAIL, dict);
}
}
return writeOff.getId(); return writeOff.getId();
} }

View File

@ -181,7 +181,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
update oms_payable_payment_detail set write_off_id=null WHERE write_off_id IN update oms_payable_payment_detail set write_off_id=null WHERE write_off_id IN
<foreach collection="array" item="item" open="(" separator="," close=")" index=""> <foreach collection="array" item="item" open="(" separator="," close=")" index="">
#{item} #{item}
</foreach> </foreach>;
delete from oms_payable_payment_detail where write_off_id is null and payable_detail_type='2';
</update> </update>
</mapper> </mapper>

View File

@ -43,6 +43,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<include refid="selectVendorInfoVo"/> <include refid="selectVendorInfoVo"/>
<where> <where>
<if test="vendorCode != null and vendorCode != ''"> and t1.vendor_code like concat('%', #{vendorCode}, '%')</if> <if test="vendorCode != null and vendorCode != ''"> and t1.vendor_code like concat('%', #{vendorCode}, '%')</if>
<if test="vendorCodeList != null and vendorCodeList.size>0"> and t1.vendor_code in
<foreach item="item" index="index" collection="vendorCodeList" separator="," open="(" close=")">
#{item}
</foreach>
</if>
<if test="vendorName != null and vendorName != ''"> and t1.vendor_name like concat('%', #{vendorName}, '%')</if> <if test="vendorName != null and vendorName != ''"> and t1.vendor_name like concat('%', #{vendorName}, '%')</if>
<if test="vendorAddress != null and vendorAddress != ''"> and t1.vendor_address like concat('%', #{vendorAddress}, '%')</if> <if test="vendorAddress != null and vendorAddress != ''"> and t1.vendor_address like concat('%', #{vendorAddress}, '%')</if>
<if test="vendorUser != null and vendorUser != ''"> and t1.vendor_user = #{vendorUser}</if> <if test="vendorUser != null and vendorUser != ''"> and t1.vendor_user = #{vendorUser}</if>