Commit ff2841eb authored by zhangfeng's avatar zhangfeng

feat(wealth): 创建/批量创建银行收款明细

parent 146c3c91
......@@ -4,9 +4,12 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.AbstractMapper;
import cn.iocoder.yudao.module.wealth.dal.dataobject.receivable.ReceivableWriteOffRecord;
import org.apache.ibatis.annotations.Mapper;
import java.math.BigDecimal;
/**
* 应收明细核销记录 Mapper
*/
@Mapper
public interface ReceivableWriteOffRecordMapper extends AbstractMapper<ReceivableWriteOffRecord> {
BigDecimal getTotalAmountForReceivable(Long id);
}
......@@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.wealth.listener.event.ReceiptItemWriteOffEvent;
import cn.iocoder.yudao.module.wealth.service.receiptItem.ReceiptItemService;
import lombok.AllArgsConstructor;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
/**
* 银行收款明细审核通过监听
......@@ -18,6 +19,7 @@ public class ReceiptItemWriteOffListener {
* @param event 编号记录
*/
@EventListener(ReceiptItemWriteOffEvent.class)
@Async
public void onReceiptItemWriteOff(ReceiptItemWriteOffEvent event) {
receiptItemService.verification(event.getId(), event.getBpmResult());
}
......
......@@ -46,6 +46,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
......@@ -231,13 +232,16 @@ public class ReceiptItemServiceImpl extends AbstractService<ReceiptItemMapper, R
// 更新收款单
ReceiptDO receiptDO = receiptMapper.selectById(receiptItemDO.getReceiptId());
if (null == receiptDO) {
throw exception(RECEIPT_NOT_EXISTS);
}
//判断收款单状态如果是待核销状态-变成部分核销状态,其它 状态不变
if (null != receiptDO && receiptDO.getState().equals(ReceiptStatusEnum.WRITE_OFF_WAITING.getValue())) {
if (receiptDO.getState().equals(ReceiptStatusEnum.WRITE_OFF_WAITING.getValue())) {
receiptDO.setState(ReceiptStatusEnum.WRITE_OFF_PART_ING.getValue());
}
// TODO 是否更新核销金额,核销比例
BigDecimal writeOffAmount = receiptItemMapper.getWriteOffAmountByReceiptId(receiptDO.getId());
if (null != receiptDO.getReceivableTotalAmount() && receiptDO.getReceivableTotalAmount().compareTo(BigDecimal.ZERO) == 1) {
if (null != receiptDO.getReceivableTotalAmount() && receiptDO.getReceivableTotalAmount().compareTo(BigDecimal.ZERO) > 0) {
receiptDO.setWriteOffProportion(writeOffAmount.divide(receiptDO.getReceivableTotalAmount(), 8, RoundingMode.HALF_UP).multiply(new BigDecimal("100")).setScale(6, BigDecimal.ROUND_HALF_UP));
}
receiptService.updateById(receiptDO);
......@@ -594,13 +598,51 @@ public class ReceiptItemServiceImpl extends AbstractService<ReceiptItemMapper, R
if (!respVOS.isEmpty()) {
return respVOS;
}
// 计算每条应收明细的核销金额
for (ReceiptItemCreateReqVO receiptItemCreateReqVO : receiptItemCreateReqVOS) {
List<ReceivableInItemVO> listForCreateReceiptItem = receivableService.getListForCreateReceiptItem(receiptItemCreateReqVO.getReceiptId());
List<ReceivableWriteOffReqVO> receivableWriteOffList = getReceiptItemDetail(listForCreateReceiptItem, receiptItemCreateReqVO);
receiptItemCreateReqVO.setReceivableWriteOffList(receivableWriteOffList);
}
// 插入数据
receiptItemCreateReqVOS.forEach(this::createReceiptItem);
// 校验收款明细自动审核,发事件
return respVOS;
}
/**
* 自动填写收款明细核销金额
*/
public List<ReceivableWriteOffReqVO> getReceiptItemDetail(List<ReceivableInItemVO> listForCreateReceiptItem, ReceiptItemCreateReqVO receiptItemCreateReqVO) {
List<ReceivableInItemVO> receivableInItemVOS = listForCreateReceiptItem.stream()
.filter(receivableInItemVO -> receivableInItemVO.getNotWriteOffAmountUsd().compareTo(BigDecimal.ZERO) >= 0)
.sorted(Comparator.comparing(ReceivableInItemVO::getNotWriteOffAmountUsd))
.collect(Collectors.toList());
ArrayList<ReceivableWriteOffReqVO> receivableWriteOffReqVOS = new ArrayList<>();
// 当剩余核销金额<未填写核销金额,默认本次核销金额=剩余核销金额,依次填写应收明细
// 当填充到最后一个应收,默认把剩余未填写核销金额填充到本次核销金额(允许本次核销金额>剩余核销金额)
BigDecimal writeOffAmount = receiptItemCreateReqVO.getWriteOffAmount();
for (ReceivableInItemVO receivableInItemVO : receivableInItemVOS) {
if (writeOffAmount.compareTo(receivableInItemVO.getNotWriteOffAmountUsd()) > 0) {
ReceivableWriteOffReqVO writeOffReqVO = ReceivableWriteOffReqVO.builder()
.receivableId(receivableInItemVO.getId())
.writeOffAmount(receivableInItemVO.getNotWriteOffAmountUsd())
.build();
receivableWriteOffReqVOS.add(writeOffReqVO);
writeOffAmount = writeOffAmount.subtract(receivableInItemVO.getNotWriteOffAmountUsd());
continue;
}
if (writeOffAmount.compareTo(receivableInItemVO.getNotWriteOffAmountUsd()) <= 0) {
ReceivableWriteOffReqVO writeOffReqVO = ReceivableWriteOffReqVO.builder()
.receivableId(receivableInItemVO.getId())
.writeOffAmount(writeOffAmount)
.build();
receivableWriteOffReqVOS.add(writeOffReqVO);
break;
}
}
return receivableWriteOffReqVOS;
}
@Override
public ReceiptItemBackVO getReceiptItemDetail(Long id) {
ReceiptItemDO receiptItemDO = receiptItemMapper.selectById(id);
......@@ -637,8 +679,8 @@ public class ReceiptItemServiceImpl extends AbstractService<ReceiptItemMapper, R
}
ReceiptItemReviewPageResult<ReceiptItemReviewPageVO> pageResult = ReceiptItemReviewPageResult.of(mpPage);
List<ReceiptItemActualAmount> actualAmount = receiptItemMapper.getReceiptItemActualAmount(pageReqVO);
List<ReceiptItemActualAmount> totalActualAmount= receiptItemMapper.countTotalActualAmount();
List<ReceiptItemActualAmount> totalWriteOffAmount= receiptItemMapper.countTotalWriteOffAmount();
List<ReceiptItemActualAmount> totalActualAmount = receiptItemMapper.countTotalActualAmount();
List<ReceiptItemActualAmount> totalWriteOffAmount = receiptItemMapper.countTotalWriteOffAmount();
pageResult.setActualAmount(actualAmount);
pageResult.setTotalActualAmount(totalActualAmount);
pageResult.setTotalWriteOffAmount(totalWriteOffAmount);
......@@ -695,6 +737,14 @@ public class ReceiptItemServiceImpl extends AbstractService<ReceiptItemMapper, R
return feeStatistics;
}
/**
* 批量创建收款单校验
*
* @param batchCreateReqVO
* @param ignoreItem
* @param receiptItemCreateReqVOS
* @return
*/
private ReceiptItemBatchRespVO validateBatchReceiptItem(ReceiptItemBatchCreateReqVO batchCreateReqVO, Boolean ignoreItem, ArrayList<ReceiptItemCreateReqVO> receiptItemCreateReqVOS) {
// 校验单个字段合法性
ReceiptItemBatchRespVO commonFieldRes = validateBatchReceiptItemCommonField(batchCreateReqVO);
......@@ -706,12 +756,24 @@ public class ReceiptItemServiceImpl extends AbstractService<ReceiptItemMapper, R
if (null == orderByNo) {
return new ReceiptItemBatchRespVO(batchCreateReqVO.getOrderNo(), batchCreateReqVO.getPayer(), 0, "订单不存在");
}
// 根据订单号或提单号匹配状态≠已核销/草稿状态的收款单是否存在,存在多条匹配创建时间最晚的一条
List<ReceivableDO> receivableDOS = receivableService.selectList("order_id", orderByNo.getOrderId());
// 根据订单号或提单号+付款人匹配状态≠已核销/草稿状态的收款单是否存在,存在多条匹配创建时间最晚的一条
List<ReceivableDO> receivableDOS = receivableService.selectList(Wrappers.lambdaQuery(ReceivableDO.class)
.eq(ReceivableDO::getOrderId, orderByNo.getOrderId())
.eq(ReceivableDO::getPaymentUser, "发货人".equals(batchCreateReqVO.getPayer()) ? 1 : 2));
if (receivableDOS == null || receivableDOS.isEmpty()) {
return new ReceiptItemBatchRespVO(batchCreateReqVO.getOrderNo(), batchCreateReqVO.getPayer(), 0, "无匹配收款单");
}
Map<Long, List<ReceivableDO>> receivableCollect = receivableDOS.stream().filter(receivableDO -> receivableDO.getReceiptId() != null).collect(Collectors.groupingBy(ReceivableDO::getReceiptId));
// 查询订单是否存在多条银行收款数据
if (!ignoreItem) {
LambdaQueryWrapper<ReceiptItemDO> queryWrapper = Wrappers.lambdaQuery(ReceiptItemDO.class).in(ReceiptItemDO::getReceiptId, receivableCollect.keySet());
if (receiptItemMapper.selectList(queryWrapper).size() > 1) {
return new ReceiptItemBatchRespVO(batchCreateReqVO.getOrderNo(), batchCreateReqVO.getPayer(), 1, "订单存在多条银行收款数据");
}
}
ReceiptDO matchReceiptDO = receivableCollect.keySet().stream()
.map(receiptId -> receiptService.selectOne("id", receiptId))
.filter(receivableDO -> !Objects.equals(receivableDO.getState(), ReceiptStatusEnum.DRAFT.getValue()) && !Objects.equals(receivableDO.getState(), ReceiptStatusEnum.WRITE_OFF_ALL_SUCCESS.getValue()))
.filter(receivableDO -> !Objects.equals(receivableDO.getState(), ReceiptStatusEnum.DRAFT.getValue()) && !Objects.equals(receivableDO.getState(), ReceiptStatusEnum.WRITE_OFF_ALL_SUCCESS.getValue()) && !Objects.equals(receivableDO.getState(), ReceiptStatusEnum.WRITE_OFF_ALL_OPENING.getValue()))
.max(Comparator.comparingLong(r -> r.getCreateTime().getTime()))
.orElse(null);
if (null == matchReceiptDO) {
......@@ -731,6 +793,7 @@ public class ReceiptItemServiceImpl extends AbstractService<ReceiptItemMapper, R
receiptItemCreateReqVO.setAmount(new BigDecimal(batchCreateReqVO.getPayAmount()));
receiptItemCreateReqVO.setCurrencyId(matchReceiptDO.getCurrencyId());
receiptItemCreateReqVO.setRate(batchCreateReqVO.getSettleRate());
receiptItemCreateReqVO.setRemark(batchCreateReqVO.getRemark());
try {
receiptItemCreateReqVO.setAmountDate(DateUtils.parseDate(batchCreateReqVO.getPayDate(), FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND));
} catch (Exception e) {
......
......@@ -274,4 +274,6 @@ public interface ReceivableService extends IService<ReceivableDO> {
void createWriteOffRecord(ReceivableWriteOffReqVO receivableWriteOffReqVO, ReceiptItemDO receiptItem);
ReceivableWriteOffRecord getReceivableWriteOffRecord(Long receivableId, Long receiptItemId);
List<ReceivableInItemVO> getListForCreateReceiptItem(Long receiptId);
}
......@@ -595,4 +595,20 @@ public class ReceivableServiceImpl extends AbstractService<ReceivableMapper, Rec
public ReceivableWriteOffRecord getReceivableWriteOffRecord(Long receivableId, Long receiptItemId) {
return receivableWriteOffRecordMapper.selectOne("receivable_id", receivableId, "receipt_item_id", receiptItemId);
}
@Override
public List<ReceivableInItemVO> getListForCreateReceiptItem(Long receiptId) {
List<ReceivableDO> receivableDOS = this.selectList("receipt_id", receiptId);
List<ReceivableInItemVO> receivableInItemVOS = ReceivableConvert.INSTANCE.convertToItemVOList(receivableDOS);
for (ReceivableInItemVO receivableInItemVO : receivableInItemVOS) {
receivableInItemVO.setActualAmount(receivableInItemVO.getTaxAmount().subtract(receivableInItemVO.getDiscountTotal() == null ? BigDecimal.ZERO : receivableInItemVO.getDiscountTotal()));
BigDecimal totalWriteOffAmount = receivableWriteOffRecordMapper.getTotalAmountForReceivable(receivableInItemVO.getId());
if (totalWriteOffAmount == null) {
totalWriteOffAmount = BigDecimal.ZERO;
}
receivableInItemVO.setWriteOffAmountUsd(totalWriteOffAmount);
receivableInItemVO.setNotWriteOffAmountUsd(receivableInItemVO.getBaseAmount().subtract(totalWriteOffAmount));
}
return receivableInItemVOS;
}
}
\ No newline at end of file
......@@ -3,11 +3,11 @@ package cn.iocoder.yudao.module.wealth.vo.receiptAccount;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Builder;
import lombok.Data;
import java.util.Date;
@Data
@Builder
@ApiModel("管理后台 - 批量收款信息创建 Request VO")
public class ReceiptItemBatchCreateReqVO {
@ApiModelProperty(value = "订单号/提单号")
......
......@@ -28,8 +28,11 @@ public class ReceivableInItemVO {
@ApiModelProperty(value = "货币id")
private Long currencyId;
@ApiModelProperty(value = "总金额")
private BigDecimal totalAmount;
@ApiModelProperty(value = "折扣金额")
private BigDecimal discountTotal;
@ApiModelProperty(value = "含税金额")
private BigDecimal taxAmount;
@ApiModelProperty(value = "收款状态(0未收款,1收款中,2已收款)")
private Integer state;
......
......@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.wealth.vo.receivable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Builder;
import lombok.Data;
import javax.validation.constraints.NotNull;
......@@ -9,6 +10,7 @@ import java.math.BigDecimal;
@Data
@ApiModel("管理后台 - 应收款核销 Request VO")
@Builder
public class ReceivableWriteOffReqVO {
@ApiModelProperty(value = "主键", required = true)
......
......@@ -34,9 +34,11 @@ import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
......@@ -278,6 +280,28 @@ public class ReceiptItemController {
return success(true);
}
@GetMapping("/import/template")
@ApiOperation("导入模板下载")
public void importTemplate(HttpServletResponse response) throws IOException {
// 手动创建导出 demo
List<ReceiptItemBatchCreateReqVO> list = Arrays.asList(
ReceiptItemBatchCreateReqVO.builder()
.orderNo("订单号/提单号给其一")
.payer("发货人/收货人")
.payDate("格式:2024-01-01 11:22:33")
.payAccount("8110901012501586556")
.payAmount("99.99")
.payCurrency("$")
.settleCurrency("¥")
.settleRate("0.877193")
.waterNo("非必填")
.submitter("提交人")
.remark("非必填")
.build());
// 输出
ExcelUtils.write(response, "批量银行收款信息导入模板.xls", "银行收款信息", ReceiptItemBatchCreateReqVO.class, list);
}
@PostMapping(value = "/import", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@ApiOperation("批量银行收款信息导入")
@ApiImplicitParams({
......
......@@ -110,6 +110,12 @@ public class ReceivableController {
public CommonResult<PageResult<BatchGenReceiptPageVO>> batchGenReceiptPage(@Valid @RequestBody BatchGenReceiptPageQueryVO query, PageVO page) {
return success(receivableService.batchGenReceiptPage(query, page));
}
@GetMapping("/getListForReceiptItem")
@ApiOperation("财务-创建收款明细获取应收明细")
public CommonResult<List<ReceivableInItemVO>> getListForCreateReceiptItem(Long receiptId) {
return success(receivableService.getListForCreateReceiptItem(receiptId));
}
/*
@GetMapping("/list")
@ApiOperation("根据id集合获得应收款列表")
......
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.iocoder.yudao.module.wealth.dal.mysql.receivable.ReceivableWriteOffRecordMapper">
<select id="getTotalAmountForReceivable" resultType="java.math.BigDecimal">
SELECT SUM(erwor.write_off_amount)
FROM ecw_receivable_write_off_record erwor
LEFT JOIN ecw_receipt_item eri ON erwor.receipt_item_id = eri.id
WHERE
erwor.receivable_id = #{id}
AND erwor.deleted = 0
AND eri.deleted = 0
AND (eri.status = 0 OR eri.status = 1)
</select>
</mapper>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment