feat(sip): 实现应付核销功能及相关服务优化

- 新增自动核销与手动核销逻辑,支持通过付款单自动触发核销流程
- 完善核销单号生成规则,确保唯一性和可追溯性
- 增强付款单与应付单之间的关联处理,包括核销后的反向操作
- 添加附件删除接口,支持按支付单ID及类型批量逻辑删除
- 扩展应付明细查询能力,新增根据核销ID列表查询相关应付明细
- 优化付款单状态更新机制,在核销撤销时同步更新付款状态及附件信息
- 引入WriteOffDetailDTO用于封装核销详情数据,提升前后端交互效率
dev_1.0.1
chenhao 2025-12-17 20:13:49 +08:00
parent f79150abc9
commit ed90f7ce87
23 changed files with 375 additions and 93 deletions

View File

@ -73,7 +73,7 @@ public class OmsPayableWriteOffController extends BaseController
@PostMapping
public AjaxResult add(@RequestBody WriteOffRequestDto writeOffRequestDto)
{
Long writeOffId = omsPayableWriteOffService.insertOmsPayableWriteOff(writeOffRequestDto);
Long writeOffId = omsPayableWriteOffService.userWriteOff(writeOffRequestDto);
return AjaxResult.success();
}

View File

@ -17,6 +17,7 @@ public class OmsPayablePaymentDetail extends BaseEntity {
private Long payableBillId;
private List<Long> payableBillIdList;
private String payableDetailType;
private List<Long> writeOffIdList;
private Date paymentTime;
private BigDecimal paymentAmount;
@ -40,6 +41,7 @@ public class OmsPayablePaymentDetail extends BaseEntity {
PREPAY_WRITE_OFF("2", "预付核销"),
REFUND("3", "退款"),
REFUND_WRITE_OFF("4", "反核销"),
WRITE_OFF("5", "核销"),
;

View File

@ -7,6 +7,7 @@ import java.util.List;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.sip.domain.dto.PaymentBillPayableDetailDTO;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter;
@ -79,6 +80,8 @@ public class OmsPayableWriteOff extends BaseEntity
/** 更新时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
private List<PaymentBillPayableDetailDTO> detailList;
private OmsPaymentBill paymentBill;
@Getter
public enum WriteOffTypeEnum {

View File

@ -2,6 +2,8 @@ package com.ruoyi.sip.domain;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.Getter;
@ -27,6 +29,7 @@ public class OmsPaymentBill extends BaseEntity
/** 付款单编号 */
@Excel(name = "付款单编号")
private String paymentBillCode;
private List<String> paymentBillCodeList;
/** 付款单类型 (FROM_PAYABLE, PRE_PAYMENT) */
@Excel(name = "付款单类型 (FROM_PAYABLE, PRE_PAYMENT)")

View File

@ -3,6 +3,7 @@ package com.ruoyi.sip.domain.dto;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
/**
* DTO
@ -31,4 +32,6 @@ public class PaymentBillPayableDetailDTO {
/** 本次付款比例 */
private BigDecimal paymentRate;
private String vendorName;
private Date createTime;
}

View File

@ -2,6 +2,7 @@ package com.ruoyi.sip.mapper;
import java.util.List;
import com.ruoyi.sip.domain.OmsFinAttachment;
import org.apache.ibatis.annotations.Param;
/**
* Mapper
@ -58,4 +59,7 @@ public interface OmsFinAttachmentMapper
* @return
*/
public int deleteOmsFinAttachmentByIds(Long[] ids);
void deleteOmsFinAttachmentByPayment(@Param("list") List<Long> paymentBillCodeList,@Param("type") String type);
}

View File

@ -16,4 +16,8 @@ public interface OmsPayablePaymentDetailMapper {
List<PaymentBillPayableDetailDTO> listPayableByPaymentCode(List<String> paymentBillCodeList);
List<OmsPayablePaymentDetail> selectByPaymentPlanIds(@Param("paymentPlanIds") List<Long> paymentPlanIds);
int deleteByWriteOffIds(@Param("ids") Long[] ids);
List<PaymentBillPayableDetailDTO> listPayableByWriteOffId(List<Long> writeOffIds);
}

View File

@ -58,4 +58,9 @@ public interface OmsPayableWriteOffMapper
* @return
*/
public int deleteOmsPayableWriteOffByIds(Long[] ids);
int selectMaxCodeByPrefix(String codePrefix);
List<OmsPayableWriteOff> listByIds(Long[] ids);
}

View File

@ -95,4 +95,7 @@ public interface OmsPaymentBillMapper
List<OmsPaymentBill> listApprove(@Param("entity") OmsPaymentBill omsPaymentBill, @Param("tableName")String buTodo);
void revoke(OmsPaymentBill paymentBill);
void updateReturnWriteOffBatch(List<OmsPaymentBill> updateBills);
}

View File

@ -72,4 +72,6 @@ public interface IOmsFinAttachmentService
public OmsFinAttachment uploadAttachment(MultipartFile file, Long invoiceReceiptBillId, OmsFinAttachment.RelatedBillTypeEnum type) throws Exception;
List<OmsFinAttachment> list(List<Long> ids, String type);
void deleteOmsFinAttachmentByPayment(List<Long> relatedIdList,String type);
}

View File

@ -14,12 +14,17 @@ public interface IOmsPayablePaymentDetailService {
void applyRefund(String payableBillCode, String payableBillCode1);
List<PaymentBillPayableDetailDTO> listPayableByPaymentCode(String paymentBillCode);
List<PaymentBillPayableDetailDTO> listPayableByWriteOffId(List<Long> writeOffIds);
List<OmsPayablePaymentDetail> selectByPaymentPlanIds(List<Long> paymentPlanIds);
List<OmsPayablePaymentDetail> listBypaymentCode(String paymentBillCode);
List<OmsPayablePaymentDetail> listByWriteOffIds(Long[] ids);
void insertBatch(List<OmsPayablePaymentDetail> detailList);
int deleteByWriteOffIds(Long[] ids);
// List<OmsPayableWriteOffDetail> listWriteOffByPaymentCode(List<String> );
}

View File

@ -36,7 +36,7 @@ public interface IOmsPayableWriteOffService
* @param writeOffRequestDto
* @return
*/
public Long insertOmsPayableWriteOff(WriteOffRequestDto writeOffRequestDto);
public Long userWriteOff(WriteOffRequestDto writeOffRequestDto);
/**
*
@ -71,4 +71,6 @@ public interface IOmsPayableWriteOffService
public List<WriteOffDetailResultDto> selectWriteOffDetailsByWriteOffId(Long writeOffId);
List<OmsPayableWriteOff> listByPaymentBillCodeList(List<String> collect);
void autoWriteOff(WriteOffRequestDto writeOffRequestDto);
}

View File

@ -4,6 +4,7 @@ import java.util.List;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.sip.domain.OmsFinAttachment;
import com.ruoyi.sip.domain.OmsPayablePaymentDetail;
import com.ruoyi.sip.domain.OmsPaymentBill;
import com.ruoyi.sip.domain.dto.PaymentBillDetailDTO;
import org.springframework.web.multipart.MultipartFile;
@ -105,4 +106,8 @@ public interface IOmsPaymentBillService
AjaxResult applyRefundApprove(OmsPaymentBill paymentBill);
List<OmsPaymentBill> listWriteOff(OmsPaymentBill omsPaymentBill);
void returnWriteOff(List<String> collect,List<OmsPayablePaymentDetail> omsPayablePaymentDetails);
OmsPaymentBill selectOmsPaymentBillByCode(String paymentBillCode);
}

View File

@ -53,6 +53,11 @@ public class OmsFinAttachmentServiceImpl implements IOmsFinAttachmentService
return omsFinAttachmentMapper.selectOmsFinAttachmentList(omsFinAttachment);
}
@Override
public void deleteOmsFinAttachmentByPayment(List<Long> relatedIdList,String type) {
omsFinAttachmentMapper.deleteOmsFinAttachmentByPayment(relatedIdList,type);
}
/**
*
*

View File

@ -276,6 +276,8 @@ public class OmsPayableBillServiceImpl implements IOmsPayableBillService {
detail.setPaymentPlanId(paymentPlanDto.getId());
detail.setPaymentBillCode(paymentBill.getPaymentBillCode());
detail.setPaymentAmount(paymentPlanDto.getPlanAmount());
detail.setPaymentAmountWithoutTax(paymentPlanDto.getPlanAmount().divide(BigDecimal.ONE.add(paymentPlanDto.getPlanRate()), 2, java.math.RoundingMode.HALF_UP));
detail.setPaymentAmountTax(detail.getPaymentAmount().subtract(detail.getPaymentAmountWithoutTax()));
detail.setPaymentRate(paymentPlanDto.getPlanRate());
detail.setPaymentTime(paymentPlanDto.getPlanPaymentDate());
detail.setRemark(paymentPlanDto.getRemark());

View File

@ -101,6 +101,20 @@ public class OmsPayablePaymentDetailServiceImpl implements IOmsPayablePaymentDet
}
@Override
public List<PaymentBillPayableDetailDTO> listPayableByWriteOffId(List<Long> writeOffIds) {
if (writeOffIds == null || writeOffIds.size() == 0){
return Collections.emptyList();
}
List<PaymentBillPayableDetailDTO> paymentBillPayableDetailDTOS = omsPayablePaymentDetailMapper.listPayableByWriteOffId(writeOffIds);
for (PaymentBillPayableDetailDTO paymentBillPayableDetailDTO : paymentBillPayableDetailDTOS) {
paymentBillPayableDetailDTO.setPaymentRate(paymentBillPayableDetailDTO.getPaymentAmount()
.divide(paymentBillPayableDetailDTO.getTotalPriceWithTax(),4,java.math.RoundingMode.HALF_UP)
.multiply(new BigDecimal("100")));
}
return paymentBillPayableDetailDTOS;
}
@Override
public List<OmsPayablePaymentDetail> selectByPaymentPlanIds(List<Long> paymentPlanIds) {
return omsPayablePaymentDetailMapper.selectByPaymentPlanIds(paymentPlanIds);
@ -117,4 +131,22 @@ public class OmsPayablePaymentDetailServiceImpl implements IOmsPayablePaymentDet
public void insertBatch(List<OmsPayablePaymentDetail> detailList) {
omsPayablePaymentDetailMapper.insertBatch(detailList);
}
@Override
public List<OmsPayablePaymentDetail> listByWriteOffIds(Long[] ids) {
if (ids == null || ids.length == 0) {
return new ArrayList<>();
}
OmsPayablePaymentDetail omsPayablePaymentDetail = new OmsPayablePaymentDetail();
omsPayablePaymentDetail.setWriteOffIdList(java.util.Arrays.asList(ids));
return omsPayablePaymentDetailMapper.list(omsPayablePaymentDetail);
}
@Override
public int deleteByWriteOffIds(Long[] ids) {
if (ids == null || ids.length == 0) {
return 0;
}
return omsPayablePaymentDetailMapper.deleteByWriteOffIds(ids);
}
}

View File

@ -1,6 +1,8 @@
package com.ruoyi.sip.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ShiroUtils;
@ -8,6 +10,7 @@ import com.ruoyi.sip.domain.OmsPayablePaymentDetail;
import com.ruoyi.sip.domain.OmsPayableWriteOff;
import com.ruoyi.sip.domain.OmsPayableWriteOffDetail;
import com.ruoyi.sip.domain.OmsPaymentBill;
import com.ruoyi.sip.domain.dto.PaymentBillPayableDetailDTO;
import com.ruoyi.sip.dto.WriteOffDetailResultDto;
import com.ruoyi.sip.dto.WriteOffRequestDto;
import com.ruoyi.sip.mapper.OmsPayableWriteOffMapper;
@ -15,14 +18,13 @@ import com.ruoyi.sip.mapper.OmsPaymentBillMapper;
import com.ruoyi.sip.service.IOmsPayableBillService;
import com.ruoyi.sip.service.IOmsPayablePaymentDetailService;
import com.ruoyi.sip.service.IOmsPayableWriteOffService;
import com.ruoyi.sip.utils.WriteOffCodeGenerator;
import com.ruoyi.sip.service.IOmsPaymentBillService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
/**
@ -40,7 +42,7 @@ public class OmsPayableWriteOffServiceImpl implements IOmsPayableWriteOffService
@Autowired
private OmsPaymentBillMapper omsPaymentBillMapper;
private IOmsPaymentBillService omsPaymentBillService;
@Autowired
private IOmsPayablePaymentDetailService omsPayablePaymentDetailService;
@Autowired
@ -56,7 +58,12 @@ public class OmsPayableWriteOffServiceImpl implements IOmsPayableWriteOffService
@Override
public OmsPayableWriteOff selectOmsPayableWriteOffById(Long id)
{
return omsPayableWriteOffMapper.selectOmsPayableWriteOffById(id);
OmsPayableWriteOff omsPayableWriteOff = omsPayableWriteOffMapper.selectOmsPayableWriteOffById(id);
OmsPaymentBill omsPaymentBill = omsPaymentBillService.selectOmsPaymentBillByCode(omsPayableWriteOff.getPaymentBillCode());
omsPayableWriteOff.setPaymentBill(omsPaymentBill);
List<PaymentBillPayableDetailDTO> detailDTOList = omsPayablePaymentDetailService.listPayableByWriteOffId(Collections.singletonList(id));
omsPayableWriteOff.setDetailList(detailDTOList);
return omsPayableWriteOff;
}
/**
@ -79,20 +86,20 @@ public class OmsPayableWriteOffServiceImpl implements IOmsPayableWriteOffService
*/
@Override
@Transactional
public Long insertOmsPayableWriteOff(WriteOffRequestDto writeOffRequestDto)
public Long userWriteOff(WriteOffRequestDto writeOffRequestDto)
{
if (CollUtil.isEmpty(writeOffRequestDto.getDetailList())){
throw new ServiceException("请选择核销明细");
}
// 获取付款单信息
OmsPaymentBill paymentBill = omsPaymentBillMapper.selectOmsPaymentBillById(writeOffRequestDto.getPaymentBillId());
OmsPaymentBill paymentBill = omsPaymentBillService.selectOmsPaymentBillById(writeOffRequestDto.getPaymentBillId());
if (paymentBill == null) {
throw new ServiceException("付款单不存在");
}
// 创建核销主记录
OmsPayableWriteOff writeOff = new OmsPayableWriteOff();
writeOff.setWriteOffCode(WriteOffCodeGenerator.generateWriteOffCode());
writeOff.setWriteOffCode(generateWriteOffCode());
// 默认为用户手动核销
writeOff.setWriteOffType(OmsPayableWriteOff.WriteOffTypeEnum.USER.getCode());
writeOff.setPaymentBillCode(paymentBill.getPaymentBillCode());
@ -123,7 +130,7 @@ public class OmsPayableWriteOffServiceImpl implements IOmsPayableWriteOffService
}
updateBill.setPreResidueAmount(decimal);
updateBill.setId(paymentBill.getId());
omsPaymentBillMapper.updateOmsPaymentBill(updateBill);
omsPaymentBillService.updateOmsPaymentBill(updateBill);
// 设置创建时间
writeOff.setCreateTime(new Date());
writeOff.setCreateBy(ShiroUtils.getUserId().toString());
@ -138,10 +145,22 @@ public class OmsPayableWriteOffServiceImpl implements IOmsPayableWriteOffService
omsPayablePaymentDetail.setWriteOffId(writeOff.getId());
}
omsPayablePaymentDetailService.insertBatch( writeOffRequestDto.getDetailList());
payableBillService.updatePaymentAmount(writeOffRequestDto.getDetailList().stream().map(OmsPayablePaymentDetail::getPayableBillId).collect(Collectors.toList()));
payableBillService.updatePaymentAmount(writeOffRequestDto.getDetailList().stream().map(OmsPayablePaymentDetail::getPayableBillId).distinct().collect(Collectors.toList()));
return writeOff.getId();
}
private String generateWriteOffCode() {
String prefix = "HX";
// 查询当天已有的最大序列号
String codePrefix = prefix + DateUtil.format(DateUtil.date(), DatePattern.PURE_DATE_PATTERN);
int maxSequence = omsPayableWriteOffMapper.selectMaxCodeByPrefix(codePrefix);
// 生成新的序列号
int newSequence = maxSequence + 1;
// 序列号补零到4位
String sequenceStr = String.format("%04d", newSequence);
return codePrefix + sequenceStr;
}
/**
*
*
@ -164,12 +183,38 @@ public class OmsPayableWriteOffServiceImpl implements IOmsPayableWriteOffService
@Transactional
public int deleteOmsPayableWriteOffByIds(Long[] ids)
{
//反核销逻辑 todo
// 反核销逻辑
List<OmsPayableWriteOff> omsPayableWriteOffs = omsPayableWriteOffMapper.listByIds(ids);
if (CollUtil.isEmpty(omsPayableWriteOffs)) {
return 0;
}
// 通过writeOffId获取对应的支付详情记录
List<OmsPayablePaymentDetail> omsPayablePaymentDetails =
omsPayablePaymentDetailService.listByWriteOffIds(ids);
// 先删除明细记录
// omsPayablePaymentDetailService.deleteOmsPayableWriteOffDetailByWriteOffIds(ids);
// 再删除主记录
// 处理付款单
omsPaymentBillService.returnWriteOff(omsPayableWriteOffs.stream()
.map(OmsPayableWriteOff::getPaymentBillCode).collect(Collectors.toList()),omsPayablePaymentDetails);
// 批量删除对应的支付详情记录
if (ids != null && ids.length > 0) {
// 使用专门的方法删除
omsPayablePaymentDetailService.deleteByWriteOffIds(ids);
}
// 获取涉及的应付单ID用于后续更新应付单的支付金额
List<Long> payableBillIds = omsPayablePaymentDetails.stream()
.map(OmsPayablePaymentDetail::getPayableBillId)
.distinct()
.collect(Collectors.toList());
// 根据对应的应付单id更新对应的数据
if (CollUtil.isNotEmpty(payableBillIds)) {
payableBillService.updatePaymentAmount(payableBillIds);
}
// 最后删除主记录
return omsPayableWriteOffMapper.deleteOmsPayableWriteOffByIds(ids);
}
@ -208,6 +253,60 @@ public class OmsPayableWriteOffServiceImpl implements IOmsPayableWriteOffService
return omsPayableWriteOffMapper.selectOmsPayableWriteOffList(omsPayableWriteOff);
}
@Override
public void autoWriteOff(WriteOffRequestDto writeOffRequestDto) {
if (CollUtil.isEmpty(writeOffRequestDto.getDetailList())){
throw new ServiceException("请选择核销明细");
}
// 获取付款单信息
OmsPaymentBill paymentBill = omsPaymentBillService.selectOmsPaymentBillById(writeOffRequestDto.getPaymentBillId());
if (paymentBill == null) {
throw new ServiceException("付款单不存在");
}
// 创建核销主记录
OmsPayableWriteOff writeOff = new OmsPayableWriteOff();
writeOff.setWriteOffCode(generateWriteOffCode());
// 默认为用户手动核销
writeOff.setWriteOffType(OmsPayableWriteOff.WriteOffTypeEnum.AUTO.getCode());
writeOff.setPaymentBillCode(paymentBill.getPaymentBillCode());
writeOff.setVendorCode(writeOffRequestDto.getVendorCode());
writeOff.setWriteOffTime(new Date());
writeOff.setRemark(writeOffRequestDto.getRemark());
// 计算总金额和相关税额
BigDecimal totalAmount = BigDecimal.ZERO;
BigDecimal totalAmountWithoutTax = BigDecimal.ZERO;
BigDecimal totalTaxAmount = BigDecimal.ZERO;
for (OmsPayablePaymentDetail item : writeOffRequestDto.getDetailList()) {
totalAmount = totalAmount.add(item.getPaymentAmount());
totalAmountWithoutTax = totalAmountWithoutTax.add(item.getPaymentAmountWithoutTax());
totalTaxAmount = totalTaxAmount.add(item.getPaymentAmountTax());
}
writeOff.setWriteOffAmount(totalAmount);
writeOff.setWriteOffAmountWithoutTax(totalAmountWithoutTax);
writeOff.setWriteOffTaxAmount(totalTaxAmount);
// 设置创建时间
writeOff.setCreateTime(new Date());
writeOff.setCreateBy(ShiroUtils.getUserId().toString());
writeOff.setUpdateTime(new Date());
// 保存核销主记录
omsPayableWriteOffMapper.insertOmsPayableWriteOff(writeOff);
// 保存核销明细
for (OmsPayablePaymentDetail omsPayablePaymentDetail : writeOffRequestDto.getDetailList()) {
omsPayablePaymentDetail.setPayableDetailType(OmsPayablePaymentDetail.PayableDetailTypeEnum.WRITE_OFF.getCode());
omsPayablePaymentDetail.setPaymentTime(DateUtils.getNowDate());
omsPayablePaymentDetail.setCreateBy(ShiroUtils.getUserId().toString());
omsPayablePaymentDetail.setWriteOffId(writeOff.getId());
}
omsPayablePaymentDetailService.insertBatch( writeOffRequestDto.getDetailList());
payableBillService.updatePaymentAmount(writeOffRequestDto.getDetailList().stream().map(OmsPayablePaymentDetail::getPayableBillId).distinct().collect(Collectors.toList()));
}
/**
* OmsPayableWriteOffDetailWriteOffDetailResultDto
*

View File

@ -1,15 +1,13 @@
package com.ruoyi.sip.service.impl;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.config.flow.ProcessConfig;
import com.ruoyi.common.core.domain.AjaxResult;
@ -21,6 +19,7 @@ import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.sip.domain.*;
import com.ruoyi.sip.domain.dto.PaymentBillDetailDTO;
import com.ruoyi.sip.domain.dto.PaymentBillPayableDetailDTO;
import com.ruoyi.sip.dto.WriteOffRequestDto;
import com.ruoyi.sip.flowable.domain.Todo;
import com.ruoyi.sip.flowable.service.DeleteFlowableProcessInstanceCmd;
import com.ruoyi.sip.flowable.service.TodoCommonTemplate;
@ -342,7 +341,17 @@ public class OmsPaymentBillServiceImpl implements IOmsPaymentBillService , TodoC
paymentBill.setActualPaymentTime(DateUtils.getNowDate());
paymentBill.setPaymentStatus(OmsPaymentBill.PaymentStatusEnum.PAYMENT.getCode());
updateOmsPaymentBill(paymentBill);
if (!paymentBill.getPaymentBillType().equals(OmsPaymentBill.PaymentBillTypeEnum.PRE_PAYMENT.getCode())) {
List<OmsPayablePaymentDetail> omsPayablePaymentDetails = detailService.listBypaymentCode(paymentBill.getPaymentBillCode());
WriteOffRequestDto writeOffRequestDto = new WriteOffRequestDto();
writeOffRequestDto.setPaymentBillId(paymentBill.getId());
writeOffRequestDto.setDetailList(omsPayablePaymentDetails);
writeOffRequestDto.setVendorCode(paymentBill.getVendorCode());
writeOffRequestDto.setRemark(StrUtil.format("{}自动核销数据:{}", DateUtils.getTime(), paymentBill.getPaymentBillCode()));
// 新增核销记录
writeOffService.autoWriteOff(writeOffRequestDto);
}
return AjaxResult.success(attachment);
}
@ -425,6 +434,17 @@ public class OmsPaymentBillServiceImpl implements IOmsPaymentBillService , TodoC
paymentBill.setPaymentStatus(OmsPaymentBill.PaymentStatusEnum.PAYMENT.getCode());
paymentBill.setActualPaymentTime(DateUtils.getNowDate());
updateOmsPaymentBill(paymentBill);
if (!paymentBill.getPaymentBillType().equals(OmsPaymentBill.PaymentBillTypeEnum.PRE_PAYMENT.getCode())) {
List<OmsPayablePaymentDetail> omsPayablePaymentDetails = detailService.listBypaymentCode(paymentBill.getPaymentBillCode());
WriteOffRequestDto writeOffRequestDto = new WriteOffRequestDto();
writeOffRequestDto.setPaymentBillId(paymentBillId);
writeOffRequestDto.setDetailList(omsPayablePaymentDetails);
writeOffRequestDto.setVendorCode(paymentBill.getVendorCode());
writeOffRequestDto.setRemark(StrUtil.format("{}自动核销数据:{}", DateUtils.getTime(), paymentBill.getPaymentBillCode()));
// 新增核销记录
writeOffService.autoWriteOff(writeOffRequestDto);
}
return AjaxResult.success(attachment);
}
@ -495,4 +515,90 @@ public class OmsPaymentBillServiceImpl implements IOmsPaymentBillService , TodoC
return omsPaymentBills;
}
@Override
public void returnWriteOff(List<String> collect, List<OmsPayablePaymentDetail> omsPayablePaymentDetails) {
OmsPaymentBill omsPaymentBill = new OmsPaymentBill();
omsPaymentBill.setPaymentBillCodeList(collect);
List<OmsPaymentBill> omsPaymentBills = selectOmsPaymentBillList(omsPaymentBill);
Map<String, List<OmsPaymentBill>> listMap = omsPaymentBills.stream()
.collect(Collectors.groupingBy(OmsPaymentBill::getPaymentBillType));
// 处理预付
List<OmsPaymentBill> prePaymentBillList = listMap.remove(OmsPaymentBill.PaymentBillTypeEnum.PRE_PAYMENT.getCode());
// 预付处理逻辑
// 1:通过omsPayablePaymentDetailService查询对应的详情然后根据paymentBillCode分组
// 将含税金额总和计算出来,加在预付单的剩余额度上
if (CollUtil.isNotEmpty(prePaymentBillList)) {
// 按付款单code分组核销详情
Map<String, List<OmsPayablePaymentDetail>> groupedDetails =
omsPayablePaymentDetails.stream()
.filter(detail -> detail.getPaymentBillCode() != null)
.collect(Collectors.groupingBy(OmsPayablePaymentDetail::getPaymentBillCode));
// 计算每个付款单的核销金额合计
Map<String, BigDecimal> paymentBillWriteOffAmountMap = groupedDetails.entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
entry -> entry.getValue().stream()
.map(OmsPayablePaymentDetail::getPaymentAmount)
.reduce(BigDecimal.ZERO, BigDecimal::add)
));
// 更新预付单的剩余额度 - 批量操作
List<OmsPaymentBill> updateBills = prePaymentBillList.stream()
.map(prePaymentBill -> {
BigDecimal increaseAmount = paymentBillWriteOffAmountMap.getOrDefault(
prePaymentBill.getPaymentBillCode(), BigDecimal.ZERO);
if (increaseAmount.compareTo(BigDecimal.ZERO) > 0) {
OmsPaymentBill updateBill = new OmsPaymentBill();
updateBill.setId(prePaymentBill.getId());
// 在原剩余额度基础上加回本次核销金额
BigDecimal newResidueAmount = prePaymentBill.getPreResidueAmount()
.add(increaseAmount);
updateBill.setPreResidueAmount(newResidueAmount);
return updateBill;
}
return null;
})
.filter(Objects::nonNull)
.collect(Collectors.toList());
if (CollUtil.isNotEmpty(updateBills)) {
for (OmsPaymentBill bill : updateBills) {
updateOmsPaymentBill(bill);
}
}
}
//处理其余数据
if (CollUtil.isNotEmpty(listMap.values())) {
List<OmsPaymentBill> updateBills = new ArrayList<>();
for (List<OmsPaymentBill> omsPaymentBillList : listMap.values()) {
for (OmsPaymentBill paymentBill : omsPaymentBillList) {
OmsPaymentBill updateBill = new OmsPaymentBill();
updateBill.setId(paymentBill.getId());
updateBill.setPaymentStatus(OmsPaymentBill.PaymentStatusEnum.WAIT_PAYMENT.getCode());
updateBill.setActualPaymentTime(null);
updateBills.add(updateBill);
}
}
if (CollUtil.isNotEmpty(updateBills)) {
omsPaymentBillMapper.updateReturnWriteOffBatch(updateBills);
omsFinAttachmentService.deleteOmsFinAttachmentByPayment(updateBills.stream().map(OmsPaymentBill::getId).collect(Collectors.toList()), OmsFinAttachment.RelatedBillTypeEnum.PAYMENT.getCode());
}
}
}
@Override
public OmsPaymentBill selectOmsPaymentBillByCode(String paymentBillCode) {
return omsPaymentBillMapper.selectOmsPaymentBillByCode(paymentBillCode);
}
}

View File

@ -1,67 +0,0 @@
package com.ruoyi.sip.utils;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
*
*
* HX + YYMMDD +
*
* @author zghz
* @date 2025-12-16
*/
public class WriteOffCodeGenerator {
private static final String PREFIX = "HX";
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyMMdd");
// 用于生成序列号的锁和计数器
private static final Object lock = new Object();
private static int sequenceNumber = 0;
/**
*
*
* @return
*/
public static String generateWriteOffCode() {
synchronized (lock) {
// 获取当前日期
String dateStr = DATE_FORMAT.format(new Date());
// 递增序列号
sequenceNumber++;
// 重置序列号 如果超过四位数则重置(实际使用中可能需要更复杂的逻辑来处理)
if (sequenceNumber > 9999) {
sequenceNumber = 1;
}
// 格式化四位序列号
String sequenceStr = String.format("%04d", sequenceNumber);
return PREFIX + dateStr + sequenceStr;
}
}
/**
*
*/
public static void resetSequence() {
synchronized (lock) {
sequenceNumber = 0;
}
}
/**
*
*
* @param number
*/
public static void setSequenceNumber(int number) {
synchronized (lock) {
sequenceNumber = number;
}
}
}

View File

@ -33,23 +33,35 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="selectOmsPayableWriteOffById" parameterType="Long" resultMap="OmsPayableWriteOffResult">
<include refid="selectOmsPayableWriteOffVo"/>
where id = #{id}
where t1.id = #{id}
</select>
<select id="selectOmsPayableWriteOffList" parameterType="com.ruoyi.sip.domain.OmsPayableWriteOff" resultMap="OmsPayableWriteOffResult">
<include refid="selectOmsPayableWriteOffVo"/>
<where>
<if test="writeOffCode != null and writeOffCode != ''"> and write_off_code = #{writeOffCode}</if>
<if test="writeOffType != null and writeOffType != ''"> and write_off_type = #{writeOffType}</if>
<if test="paymentBillCode != null and paymentBillCode != ''"> and payment_bill_code = #{paymentBillCode}</if>
<if test="paymentBillCodeList != null and paymentBillCodeList.size>0"> and payment_bill_code in
<if test="writeOffCode != null and writeOffCode != ''"> and t1.write_off_code = #{writeOffCode}</if>
<if test="writeOffType != null and writeOffType != ''"> and t1.write_off_type = #{writeOffType}</if>
<if test="paymentBillCode != null and paymentBillCode != ''"> and t1.payment_bill_code = #{paymentBillCode}</if>
<if test="paymentBillCodeList != null and paymentBillCodeList.size>0"> and t1.payment_bill_code in
<foreach index="index" collection="paymentBillCodeList" item="paymentBillCode" separator="," open="(" close=")">
#{paymentBillCode}
</foreach>
</if>
<if test="vendorCode != null and vendorCode != ''"> and vendor_code = #{vendorCode}</if>
<if test="vendorCode != null and vendorCode != ''"> and t1.vendor_code = #{vendorCode}</if>
</where>
</select>
<select id="selectMaxCodeByPrefix" resultType="java.lang.Integer">
select ifnull(max(SUBSTR(write_off_code FROM LENGTH(#{prefix}) + 1 FOR 4)), 0)
from oms_payable_write_off
where write_off_code like concat(#{prefix}, '%')
</select>
<select id="listByIds" resultType="com.ruoyi.sip.domain.OmsPayableWriteOff">
<include refid="selectOmsPayableWriteOffVo"/>
where t1.id in
<foreach item="item" index="index" collection="array" open="(" separator="," close=")" >
#{item}
</foreach>
</select>
<insert id="insertOmsPayableWriteOff" parameterType="com.ruoyi.sip.domain.OmsPayableWriteOff" useGeneratedKeys="true" keyProperty="id">
insert into oms_payable_write_off

View File

@ -112,5 +112,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
#{id}
</foreach>
</delete>
<update id="deleteOmsFinAttachmentByPayment">
update oms_fin_attachment set del_flag = 2 where related_bill_type = #{type} and del_flag=0 and
related_bill_id in
<foreach item="id" collection="list" open="(" separator="," close=")">
#{id}
</foreach>
</update>
</mapper>

View File

@ -86,6 +86,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
#{item}
</foreach>
</if>
<if test="writeOffIdList != null and writeOffIdList.size>0">
and t1.write_off_id in
<foreach item="item" collection="writeOffIdList" separator="," open="(" close=")" index="">
#{item}
</foreach>
</if>
</where>
order by t1.create_time desc
</select>
@ -117,5 +123,28 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
left join project_order_info t3 on t2.order_code = t3.order_code
left join project_info t4 on t3.project_id = t4.id
</select>
<select id="listPayableByWriteOffId" resultType="com.ruoyi.sip.domain.dto.PaymentBillPayableDetailDTO">
select t1.payment_amount, t2.payable_bill_code, t4.project_name, t4.project_code, t2.total_price_with_tax,t5.vendor_name,t2.create_time
from (SELECT sum(payment_amount) payment_amount,
payable_bill_id
FROM oms_payable_payment_detail
WHERE write_off_id in
<foreach item="item" collection="list" separator="," open="(" close=")" index="">
#{item}
</foreach>
group by payable_bill_id) t1
left join oms_payable_bill t2 on t1.payable_bill_id = t2.id
left join project_order_info t3 on t2.order_code = t3.order_code
left join project_info t4 on t3.project_id = t4.id
left join oms_vendor_info t5 on t2.vendor_code = t5.vendor_code
</select>
<delete id="deleteByWriteOffIds" parameterType="java.lang.Long">
DELETE FROM oms_payable_payment_detail WHERE write_off_id IN
<foreach collection="ids" item="item" open="(" separator="," close=")" index="">
#{item}
</foreach>
</delete>
</mapper>

View File

@ -114,6 +114,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="paymentBillCode != null and paymentBillCode != ''">and pb.payment_bill_code like concat('%',
#{paymentBillCode}, '%')
</if>
<if test="paymentBillCodeList != null and paymentBillCodeList.size>0">and pb.payment_bill_code in
<foreach item="item" collection="paymentBillCodeList" separator="," open="(" close=")" index="">
#{item}
</foreach>
</if>
<if test="paymentBillType != null and paymentBillType != ''">and pb.payment_bill_type =
#{paymentBillType}
</if>
@ -308,6 +313,17 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
update_time=now()
where id = #{id}
</update>
<update id="updateReturnWriteOffBatch">
<foreach collection="list" item="item" separator=";">
update oms_payment_bill
set actual_payment_time=null,
payment_status=#{item.paymentStatus},
update_time=now()
where id = #{item.id}
</foreach>
</update>
<delete id="deleteOmsPaymentBillById" parameterType="Long">
delete from oms_payment_bill where id = #{id}