完善付款
This commit is contained in:
+14
@@ -29,6 +29,7 @@ public class FormalSettlementSaveRequest implements Serializable {
|
||||
private String attachmentsJson;
|
||||
private String remark;
|
||||
private List<SummaryFee> summaryFees;
|
||||
private List<Invoice> invoices;
|
||||
|
||||
@Data
|
||||
public static class SummaryFee implements Serializable {
|
||||
@@ -40,4 +41,17 @@ public class FormalSettlementSaveRequest implements Serializable {
|
||||
private String remark;
|
||||
private Integer manualFlag;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class Invoice implements Serializable {
|
||||
@Serial private static final long serialVersionUID = 1L;
|
||||
private String invoiceNo;
|
||||
private LocalDate invoiceDate;
|
||||
private String invoiceType;
|
||||
private BigDecimal taxRate;
|
||||
private BigDecimal invoiceAmount;
|
||||
private BigDecimal availableInvoiceAmount;
|
||||
private BigDecimal matchedAmount;
|
||||
private String attachmentJson;
|
||||
}
|
||||
}
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments from this software for such purposes.
|
||||
* Copyright of this software remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.transport.pojo.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
|
||||
/** 付款申请付款记录请求。 @author Chill */
|
||||
@Data
|
||||
public class PaymentApplicationRecordRequest implements Serializable {
|
||||
@Serial private static final long serialVersionUID = 1L;
|
||||
private BigDecimal paidAmount;
|
||||
private LocalDate paidDate;
|
||||
private String paymentNo;
|
||||
private String voucherJson;
|
||||
private String kingdeeBillNo;
|
||||
}
|
||||
+1
@@ -58,4 +58,5 @@ public class PaymentApplicationSaveRequest implements Serializable {
|
||||
private String attachmentsJson;
|
||||
private String remark;
|
||||
private List<PaymentApplicationInvoiceRequest> invoices;
|
||||
private List<PaymentApplicationRecordRequest> paymentRecords;
|
||||
}
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.transport.pojo.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.springblade.core.tenant.mp.TenantEntity;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/** 正式结算变更记录。 @author Chill */
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("blade_formal_settlement_change_record")
|
||||
public class FormalSettlementChangeRecord extends TenantEntity {
|
||||
@Serial private static final long serialVersionUID = 1L;
|
||||
private Long formalSettlementId;
|
||||
private String changeType;
|
||||
private Integer lineNo;
|
||||
private String operationType;
|
||||
private String changeContent;
|
||||
private String changeReason;
|
||||
private String operatorName;
|
||||
private LocalDateTime changeTime;
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.transport.pojo.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.springblade.core.tenant.mp.TenantEntity;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
|
||||
/**
|
||||
* 正式结算发票明细实体类
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("blade_formal_settlement_invoice")
|
||||
@Schema(description = "正式结算发票明细")
|
||||
public class FormalSettlementInvoice extends TenantEntity {
|
||||
@Serial private static final long serialVersionUID = 1L;
|
||||
private Long formalSettlementId;
|
||||
private Integer lineNo;
|
||||
private String invoiceNo;
|
||||
private LocalDate invoiceDate;
|
||||
private String invoiceType;
|
||||
private BigDecimal taxRate;
|
||||
private BigDecimal invoiceAmount;
|
||||
private BigDecimal availableInvoiceAmount;
|
||||
private BigDecimal matchedAmount;
|
||||
private String attachmentJson;
|
||||
}
|
||||
+6
@@ -12,7 +12,9 @@ import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.springblade.transport.pojo.entity.FormalSettlement;
|
||||
import org.springblade.transport.pojo.entity.FormalSettlementChangeRecord;
|
||||
import org.springblade.transport.pojo.entity.FormalSettlementDetail;
|
||||
import org.springblade.transport.pojo.entity.FormalSettlementInvoice;
|
||||
import org.springblade.transport.pojo.entity.FormalSettlementSource;
|
||||
import org.springblade.transport.pojo.entity.FormalSettlementPayment;
|
||||
import org.springblade.transport.pojo.entity.FormalSettlementSummaryFee;
|
||||
@@ -42,4 +44,8 @@ public class FormalSettlementVO extends FormalSettlement {
|
||||
@TableField(exist = false) private List<FormalSettlementDetail> details;
|
||||
@TableField(exist = false) private List<FormalSettlementSummaryFee> summaryFees;
|
||||
@TableField(exist = false) private List<FormalSettlementPayment> payments;
|
||||
@TableField(exist = false) private List<FormalSettlementInvoice> invoices;
|
||||
@TableField(exist = false) private List<PaymentApplicationVO> paymentApplications;
|
||||
@TableField(exist = false) private List<SettlementAdjustmentVO> adjustments;
|
||||
@TableField(exist = false) private List<FormalSettlementChangeRecord> changeRecords;
|
||||
}
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.transport.pojo.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 付款申请关联结算单金额视图
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "付款申请关联结算单金额")
|
||||
public class PaymentApplicationReferenceAmountVO implements Serializable {
|
||||
@Serial private static final long serialVersionUID = 1L;
|
||||
@Schema(description = "结算金额") private BigDecimal settlementAmount;
|
||||
@Schema(description = "累计申请付款金额") private BigDecimal cumulativeAppliedAmount;
|
||||
@Schema(description = "可付款金额") private BigDecimal payableAmount;
|
||||
}
|
||||
+1
@@ -17,6 +17,7 @@ public class SettlementAdjustmentVO extends SettlementAdjustment {
|
||||
private String approvalStatusName;
|
||||
private String settlementTypeName;
|
||||
private String createUserName;
|
||||
private String kingdeeBillNo;
|
||||
private List<SettlementAdjustmentDetail> details;
|
||||
private List<FormalSettlementDetail> formalDetails;
|
||||
}
|
||||
|
||||
+15
-7
@@ -31,6 +31,7 @@ import org.springblade.core.secure.annotation.PreAuth;
|
||||
import org.springblade.core.tool.api.R;
|
||||
import org.springblade.transport.pojo.dto.PaymentApplicationSaveRequest;
|
||||
import org.springblade.transport.pojo.dto.PaymentApplicationStatusRequest;
|
||||
import org.springblade.transport.pojo.vo.PaymentApplicationReferenceAmountVO;
|
||||
import org.springblade.transport.pojo.vo.PaymentApplicationVO;
|
||||
import org.springblade.transport.service.IPaymentApplicationService;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
@@ -56,32 +57,39 @@ public class PaymentApplicationController extends BladeController {
|
||||
@ApiOperationSupport(order = 2)
|
||||
@Operation(summary = "付款申请详情")
|
||||
public R<PaymentApplicationVO> detail(@RequestParam Long id) { return R.data(paymentApplicationService.detail(id)); }
|
||||
@PostMapping("/save")
|
||||
@GetMapping("/reference-amount")
|
||||
@ApiOperationSupport(order = 3)
|
||||
@Operation(summary = "动态计算结算单可付款金额")
|
||||
public R<PaymentApplicationReferenceAmountVO> referenceAmount(@RequestParam String paymentType,
|
||||
@RequestParam Long referenceId, @RequestParam(required = false) Long excludeId) {
|
||||
return R.data(paymentApplicationService.referenceAmount(paymentType, referenceId, excludeId));
|
||||
}
|
||||
@PostMapping("/save")
|
||||
@ApiOperationSupport(order = 4)
|
||||
@Operation(summary = "保存付款申请")
|
||||
public R<Long> save(@RequestBody PaymentApplicationSaveRequest request) { return R.data(paymentApplicationService.saveDraft(request)); }
|
||||
@PostMapping("/remove")
|
||||
@ApiOperationSupport(order = 4)
|
||||
@ApiOperationSupport(order = 5)
|
||||
@Operation(summary = "删除付款申请草稿")
|
||||
public R remove(@RequestParam Long id) { paymentApplicationService.removeDraft(id); return R.success("删除成功"); }
|
||||
@PostMapping("/submit")
|
||||
@ApiOperationSupport(order = 5)
|
||||
@ApiOperationSupport(order = 6)
|
||||
@Operation(summary = "提交付款申请")
|
||||
public R submit(@RequestBody PaymentApplicationStatusRequest request) { paymentApplicationService.submit(request); return R.success("提交成功"); }
|
||||
@PostMapping("/approve")
|
||||
@ApiOperationSupport(order = 6)
|
||||
@ApiOperationSupport(order = 7)
|
||||
@Operation(summary = "审批通过付款申请")
|
||||
public R approve(@RequestBody PaymentApplicationStatusRequest request) { paymentApplicationService.approve(request); return R.success("审批通过"); }
|
||||
@PostMapping("/return")
|
||||
@ApiOperationSupport(order = 7)
|
||||
@ApiOperationSupport(order = 8)
|
||||
@Operation(summary = "驳回付款申请")
|
||||
public R returnBill(@RequestBody PaymentApplicationStatusRequest request) { paymentApplicationService.returnBill(request); return R.success("已驳回"); }
|
||||
@PostMapping("/void")
|
||||
@ApiOperationSupport(order = 8)
|
||||
@ApiOperationSupport(order = 9)
|
||||
@Operation(summary = "作废付款申请")
|
||||
public R voidBill(@RequestBody PaymentApplicationStatusRequest request) { paymentApplicationService.voidBill(request); return R.success("作废成功"); }
|
||||
@PostMapping("/sync-kingdee")
|
||||
@ApiOperationSupport(order = 9)
|
||||
@ApiOperationSupport(order = 10)
|
||||
@Operation(summary = "生成金蝶付款单")
|
||||
public R<String> syncKingdee(@RequestParam Long id) { return R.data(paymentApplicationService.syncKingdee(id)); }
|
||||
}
|
||||
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.transport.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.springblade.transport.pojo.entity.FormalSettlementChangeRecord;
|
||||
|
||||
/** 正式结算变更记录 Mapper。 @author Chill */
|
||||
@Mapper
|
||||
public interface FormalSettlementChangeRecordMapper extends BaseMapper<FormalSettlementChangeRecord> {
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.transport.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.springblade.transport.pojo.entity.FormalSettlementInvoice;
|
||||
|
||||
/**
|
||||
* 正式结算发票明细 Mapper
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Mapper
|
||||
public interface FormalSettlementInvoiceMapper extends BaseMapper<FormalSettlementInvoice> {
|
||||
}
|
||||
+2
@@ -24,12 +24,14 @@ import org.springblade.core.mp.base.BaseService;
|
||||
import org.springblade.transport.pojo.dto.PaymentApplicationSaveRequest;
|
||||
import org.springblade.transport.pojo.dto.PaymentApplicationStatusRequest;
|
||||
import org.springblade.transport.pojo.entity.PaymentApplication;
|
||||
import org.springblade.transport.pojo.vo.PaymentApplicationReferenceAmountVO;
|
||||
import org.springblade.transport.pojo.vo.PaymentApplicationVO;
|
||||
|
||||
/** 付款申请服务。 @author Chill */
|
||||
public interface IPaymentApplicationService extends BaseService<PaymentApplication> {
|
||||
IPage<PaymentApplicationVO> selectPage(IPage<PaymentApplication> page, PaymentApplicationVO query);
|
||||
PaymentApplicationVO detail(Long id);
|
||||
PaymentApplicationReferenceAmountVO referenceAmount(String paymentType, Long referenceId, Long excludeId);
|
||||
Long saveDraft(PaymentApplicationSaveRequest request);
|
||||
void removeDraft(Long id);
|
||||
void submit(PaymentApplicationStatusRequest request);
|
||||
|
||||
+140
-2
@@ -19,7 +19,9 @@ import org.springblade.core.tool.utils.BeanUtil;
|
||||
import org.springblade.core.tool.utils.Func;
|
||||
import org.springblade.transport.mapper.FormalSettlementDetailMapper;
|
||||
import org.springblade.transport.mapper.FormalSettlementDetailFeeMapper;
|
||||
import org.springblade.transport.mapper.FormalSettlementChangeRecordMapper;
|
||||
import org.springblade.transport.mapper.FormalSettlementMapper;
|
||||
import org.springblade.transport.mapper.FormalSettlementInvoiceMapper;
|
||||
import org.springblade.transport.mapper.FormalSettlementSourceMapper;
|
||||
import org.springblade.transport.mapper.FormalSettlementSummaryFeeMapper;
|
||||
import org.springblade.transport.mapper.FormalSettlementPaymentMapper;
|
||||
@@ -27,15 +29,19 @@ import org.springblade.transport.mapper.PreSettlementDetailMapper;
|
||||
import org.springblade.transport.mapper.PreSettlementDetailFeeMapper;
|
||||
import org.springblade.transport.mapper.PreSettlementMapper;
|
||||
import org.springblade.transport.mapper.PreSettlementSummaryFeeMapper;
|
||||
import org.springblade.transport.mapper.PaymentApplicationMapper;
|
||||
import org.springblade.transport.mapper.ReceivablePayableDetailMapper;
|
||||
import org.springblade.transport.mapper.ReceivablePayableCargoFeeMapper;
|
||||
import org.springblade.transport.mapper.SettlementAdjustmentMapper;
|
||||
import org.springblade.transport.pojo.dto.FormalSettlementSaveRequest;
|
||||
import org.springblade.transport.pojo.dto.FormalSettlementPaymentRequest;
|
||||
import org.springblade.transport.pojo.dto.FormalSettlementStatusRequest;
|
||||
import org.springblade.transport.pojo.dto.PreSettlementDetailAdjustRequest;
|
||||
import org.springblade.transport.pojo.entity.FormalSettlement;
|
||||
import org.springblade.transport.pojo.entity.FormalSettlementChangeRecord;
|
||||
import org.springblade.transport.pojo.entity.FormalSettlementDetail;
|
||||
import org.springblade.transport.pojo.entity.FormalSettlementDetailFee;
|
||||
import org.springblade.transport.pojo.entity.FormalSettlementInvoice;
|
||||
import org.springblade.transport.pojo.entity.FormalSettlementSource;
|
||||
import org.springblade.transport.pojo.entity.FormalSettlementSummaryFee;
|
||||
import org.springblade.transport.pojo.entity.FormalSettlementPayment;
|
||||
@@ -44,11 +50,14 @@ import org.springblade.transport.pojo.entity.PreSettlement;
|
||||
import org.springblade.transport.pojo.entity.PreSettlementDetail;
|
||||
import org.springblade.transport.pojo.entity.PreSettlementDetailFee;
|
||||
import org.springblade.transport.pojo.entity.PreSettlementSummaryFee;
|
||||
import org.springblade.transport.pojo.entity.PaymentApplication;
|
||||
import org.springblade.transport.pojo.entity.ReceivablePayableDetail;
|
||||
import org.springblade.transport.pojo.entity.ReceivablePayableCargoFee;
|
||||
import org.springblade.transport.pojo.entity.SettlementAdjustment;
|
||||
import org.springblade.transport.pojo.entity.Waybill;
|
||||
import org.springblade.transport.pojo.vo.FormalSettlementVO;
|
||||
import org.springblade.transport.pojo.vo.PreSettlementVO;
|
||||
import org.springblade.transport.pojo.vo.SettlementAdjustmentVO;
|
||||
import org.springblade.transport.service.IFormalSettlementService;
|
||||
import org.springblade.transport.service.IContractManageService;
|
||||
import org.springblade.transport.service.IPreSettlementService;
|
||||
@@ -56,6 +65,8 @@ import org.springblade.transport.service.IWaybillService;
|
||||
import org.springblade.transport.wrapper.PreSettlementWrapper;
|
||||
import org.springblade.core.tool.jackson.JsonUtil;
|
||||
import org.springblade.transport.wrapper.FormalSettlementWrapper;
|
||||
import org.springblade.transport.wrapper.PaymentApplicationWrapper;
|
||||
import org.springblade.system.cache.UserCache;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@@ -91,6 +102,8 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
||||
private final FormalSettlementSourceMapper sourceMapper;
|
||||
private final FormalSettlementSummaryFeeMapper summaryFeeMapper;
|
||||
private final FormalSettlementPaymentMapper paymentMapper;
|
||||
private final FormalSettlementInvoiceMapper invoiceMapper;
|
||||
private final FormalSettlementChangeRecordMapper changeRecordMapper;
|
||||
private final FormalSettlementDetailMapper detailMapper;
|
||||
private final FormalSettlementDetailFeeMapper detailFeeMapper;
|
||||
private final PreSettlementMapper preSettlementMapper;
|
||||
@@ -99,6 +112,8 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
||||
private final PreSettlementDetailFeeMapper preDetailFeeMapper;
|
||||
private final ReceivablePayableDetailMapper receivablePayableMapper;
|
||||
private final ReceivablePayableCargoFeeMapper receivablePayableCargoFeeMapper;
|
||||
private final PaymentApplicationMapper paymentApplicationMapper;
|
||||
private final SettlementAdjustmentMapper settlementAdjustmentMapper;
|
||||
private final IContractManageService contractManageService;
|
||||
private final IPreSettlementService preSettlementService;
|
||||
private final IWaybillService waybillService;
|
||||
@@ -172,13 +187,34 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
||||
public FormalSettlementVO detail(Long id) {
|
||||
FormalSettlement settlement = existing(id);
|
||||
FormalSettlementVO vo = toVO(settlement);
|
||||
vo.setSources(sourceMapper.selectList(Wrappers.<FormalSettlementSource>lambdaQuery()
|
||||
.eq(FormalSettlementSource::getFormalSettlementId, id).orderByAsc(FormalSettlementSource::getCreateTime)));
|
||||
List<FormalSettlementSource> sources = sourceMapper.selectList(Wrappers.<FormalSettlementSource>lambdaQuery()
|
||||
.eq(FormalSettlementSource::getFormalSettlementId, id).orderByAsc(FormalSettlementSource::getCreateTime));
|
||||
vo.setSources(sources);
|
||||
vo.setDetails(detailMapper.selectList(Wrappers.<FormalSettlementDetail>lambdaQuery()
|
||||
.eq(FormalSettlementDetail::getFormalSettlementId, id).orderByAsc(FormalSettlementDetail::getLineNo)));
|
||||
vo.setSummaryFees(listSummaryFees(id));
|
||||
vo.setPayments(paymentMapper.selectList(Wrappers.<FormalSettlementPayment>lambdaQuery()
|
||||
.eq(FormalSettlementPayment::getFormalSettlementId, id).orderByDesc(FormalSettlementPayment::getCreateTime)));
|
||||
vo.setInvoices(invoiceMapper.selectList(Wrappers.<FormalSettlementInvoice>lambdaQuery()
|
||||
.eq(FormalSettlementInvoice::getFormalSettlementId, id).orderByAsc(FormalSettlementInvoice::getLineNo)));
|
||||
List<Long> preSettlementIds = sources.stream().map(FormalSettlementSource::getPreSettlementId).toList();
|
||||
LambdaQueryWrapper<PaymentApplication> paymentApplicationQuery = Wrappers.<PaymentApplication>lambdaQuery();
|
||||
if (preSettlementIds.isEmpty()) {
|
||||
paymentApplicationQuery.eq(PaymentApplication::getSettlementId, id);
|
||||
} else {
|
||||
paymentApplicationQuery.and(query -> query.eq(PaymentApplication::getSettlementId, id)
|
||||
.or().in(PaymentApplication::getPreSettlementId, preSettlementIds));
|
||||
}
|
||||
vo.setPaymentApplications(paymentApplicationMapper.selectList(paymentApplicationQuery
|
||||
.orderByDesc(PaymentApplication::getCreateTime)).stream()
|
||||
.map(item -> PaymentApplicationWrapper.build().entityVO(item)).toList());
|
||||
vo.setAdjustments(settlementAdjustmentMapper.selectList(Wrappers.<SettlementAdjustment>lambdaQuery()
|
||||
.eq(SettlementAdjustment::getFormalSettlementId, id)
|
||||
.orderByDesc(SettlementAdjustment::getCreateTime)).stream()
|
||||
.map(item -> toAdjustmentVO(item, settlement.getKingdeeBillNo())).toList());
|
||||
vo.setChangeRecords(changeRecordMapper.selectList(Wrappers.<FormalSettlementChangeRecord>lambdaQuery()
|
||||
.eq(FormalSettlementChangeRecord::getFormalSettlementId, id)
|
||||
.orderByDesc(FormalSettlementChangeRecord::getChangeTime)));
|
||||
return vo;
|
||||
}
|
||||
|
||||
@@ -189,6 +225,7 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
||||
throw new ServiceException("请至少选择一张预结算单或一条应收应付明细");
|
||||
}
|
||||
FormalSettlement settlement = request.getId() == null ? new FormalSettlement() : editable(request.getId());
|
||||
boolean creating = settlement.getId() == null;
|
||||
if (settlement.getId() != null) releaseSources(settlement);
|
||||
List<PreSettlement> sources = Func.isEmpty(request.getSourcePreSettlementIds()) ? List.of()
|
||||
: request.getSourcePreSettlementIds().stream().distinct().map(this::availableSource).toList();
|
||||
@@ -241,6 +278,9 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
||||
rebuildSummaryFees(settlement.getId());
|
||||
applySummaryRequest(settlement.getId(), request.getSummaryFees());
|
||||
refreshSettlementAmount(settlement);
|
||||
rebuildInvoices(settlement, request.getInvoices());
|
||||
saveChange(settlement.getId(), "结算单基本信息", null, creating ? "新增" : "调整",
|
||||
(creating ? "创建" : "保存") + "正式结算单" + settlement.getFormalSettlementNo(), request.getRemark());
|
||||
return settlement.getId();
|
||||
}
|
||||
|
||||
@@ -256,6 +296,10 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
||||
detailMapper.delete(Wrappers.<FormalSettlementDetail>lambdaQuery().eq(FormalSettlementDetail::getFormalSettlementId, id));
|
||||
summaryFeeMapper.delete(Wrappers.<FormalSettlementSummaryFee>lambdaQuery()
|
||||
.eq(FormalSettlementSummaryFee::getFormalSettlementId, id));
|
||||
invoiceMapper.delete(Wrappers.<FormalSettlementInvoice>lambdaQuery()
|
||||
.eq(FormalSettlementInvoice::getFormalSettlementId, id));
|
||||
changeRecordMapper.delete(Wrappers.<FormalSettlementChangeRecord>lambdaQuery()
|
||||
.eq(FormalSettlementChangeRecord::getFormalSettlementId, id));
|
||||
removeById(id);
|
||||
}
|
||||
|
||||
@@ -271,6 +315,7 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
||||
settlement.setCurrentProcessor(AuthUtil.getUserName());
|
||||
settlement.setApprovedTime(LocalDateTime.now());
|
||||
updateById(settlement);
|
||||
saveChange(settlement.getId(), "结算单基本信息", null, "调整", "正式结算审批通过", request.getReason());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -282,6 +327,7 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
||||
settlement.setCurrentNode("已作废");
|
||||
settlement.setVoidReason(required(limit(request.getReason(), 200), "作废原因"));
|
||||
updateById(settlement);
|
||||
saveChange(settlement.getId(), "结算单基本信息", null, "调整", "作废正式结算单", request.getReason());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -294,6 +340,7 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
||||
settlement.setKingdeeSyncStatus("synced");
|
||||
settlement.setSyncedTime(LocalDateTime.now());
|
||||
updateById(settlement);
|
||||
saveChange(settlement.getId(), "结算单基本信息", null, "调整", "同步金蝶单据" + kingdeeNo, "");
|
||||
return kingdeeNo;
|
||||
}
|
||||
|
||||
@@ -340,9 +387,11 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
||||
Map<Long, FormalSettlementDetailFee> existing = detailFees(detail.getId()).stream()
|
||||
.collect(Collectors.toMap(FormalSettlementDetailFee::getId, item -> item));
|
||||
if (existing.size() != request.getRows().size()) throw new ServiceException("费用调整行数据不完整");
|
||||
List<String> changes = new java.util.ArrayList<>();
|
||||
for (PreSettlementDetailAdjustRequest.FeeRow row : request.getRows()) {
|
||||
FormalSettlementDetailFee fee = existing.get(row.getId());
|
||||
if (fee == null) throw new ServiceException("存在无效的货物费用行");
|
||||
BigDecimal beforeAmount = money(fee.getSettlementAmountTax());
|
||||
fee.setTransportQuantity(nonNegative(row.getTransportQuantity(), "运输总量"));
|
||||
fee.setMileage(nonNegative(row.getMileage(), "里程"));
|
||||
fee.setUnitPrice(nonNegative(row.getUnitPrice(), "运输单价"));
|
||||
@@ -353,6 +402,11 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
||||
fee.setAdjustAmount(fee.getSettlementAmountTax().subtract(money(fee.getOriginalAmount())));
|
||||
fee.setRemark(limit(row.getRemark(), 200));
|
||||
detailFeeMapper.updateById(fee);
|
||||
if (beforeAmount.compareTo(fee.getSettlementAmountTax()) != 0) {
|
||||
changes.add("【" + firstNotEmpty(fee.getCargoName(), fee.getLineNo())
|
||||
+ "】结算金额(含税)从【" + beforeAmount + "】调整为【"
|
||||
+ fee.getSettlementAmountTax() + "】");
|
||||
}
|
||||
}
|
||||
List<FormalSettlementDetailFee> rows = detailFees(detail.getId());
|
||||
detail.setTransportQuantity(rows.stream().map(FormalSettlementDetailFee::getTransportQuantity).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
|
||||
@@ -365,6 +419,8 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
||||
detailMapper.updateById(detail);
|
||||
rebuildSummaryFees(settlement.getId());
|
||||
refreshSettlementAmount(settlement);
|
||||
saveChange(settlement.getId(), "结算明细项", detail.getLineNo(), "调整",
|
||||
changes.isEmpty() ? "调整结算明细费用" : String.join(";", changes), reason);
|
||||
}
|
||||
|
||||
private void rebuildSummaryFees(Long settlementId) {
|
||||
@@ -512,6 +568,51 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
||||
renumberSummaryFees(settlementId);
|
||||
}
|
||||
|
||||
private void rebuildInvoices(FormalSettlement settlement, List<FormalSettlementSaveRequest.Invoice> requestRows) {
|
||||
List<FormalSettlementSaveRequest.Invoice> invoices = requestRows == null ? List.of() : requestRows;
|
||||
Set<String> invoiceNumbers = new LinkedHashSet<>();
|
||||
BigDecimal matchedTotal = BigDecimal.ZERO;
|
||||
for (FormalSettlementSaveRequest.Invoice requestRow : invoices) {
|
||||
String invoiceNo = requiredText(requestRow.getInvoiceNo(), "发票号");
|
||||
if (invoiceNo.length() > 32) throw new ServiceException("发票号不能超过32个字");
|
||||
if (!invoiceNumbers.add(invoiceNo)) throw new ServiceException("发票号" + invoiceNo + "重复");
|
||||
BigDecimal invoiceAmount = nonNegative(requestRow.getInvoiceAmount(), "发票金额");
|
||||
BigDecimal availableAmount = nonNegative(requestRow.getAvailableInvoiceAmount(), "可匹配发票金额");
|
||||
BigDecimal matchedAmount = nonNegative(requestRow.getMatchedAmount(), "匹配结算单金额");
|
||||
if (availableAmount.compareTo(invoiceAmount) > 0) {
|
||||
throw new ServiceException("发票" + invoiceNo + "的可匹配金额不能超过发票金额");
|
||||
}
|
||||
if (matchedAmount.compareTo(availableAmount) > 0) {
|
||||
throw new ServiceException("发票" + invoiceNo + "的匹配结算单金额不能超过可匹配金额");
|
||||
}
|
||||
if (requestRow.getTaxRate() != null && (requestRow.getTaxRate().signum() < 0
|
||||
|| requestRow.getTaxRate().compareTo(BigDecimal.valueOf(100)) > 0)) {
|
||||
throw new ServiceException("发票" + invoiceNo + "的税率必须在0-100之间");
|
||||
}
|
||||
matchedTotal = matchedTotal.add(matchedAmount);
|
||||
}
|
||||
if (matchedTotal.compareTo(money(settlement.getSettlementAmount())) > 0) {
|
||||
throw new ServiceException("发票匹配结算单金额合计不能超过结算金额");
|
||||
}
|
||||
invoiceMapper.delete(Wrappers.<FormalSettlementInvoice>lambdaQuery()
|
||||
.eq(FormalSettlementInvoice::getFormalSettlementId, settlement.getId()));
|
||||
int lineNo = 1;
|
||||
for (FormalSettlementSaveRequest.Invoice requestRow : invoices) {
|
||||
FormalSettlementInvoice invoice = new FormalSettlementInvoice();
|
||||
invoice.setFormalSettlementId(settlement.getId());
|
||||
invoice.setLineNo(lineNo++);
|
||||
invoice.setInvoiceNo(requestRow.getInvoiceNo().trim());
|
||||
invoice.setInvoiceDate(requestRow.getInvoiceDate());
|
||||
invoice.setInvoiceType(limit(requestRow.getInvoiceType(), 50));
|
||||
invoice.setTaxRate(requestRow.getTaxRate());
|
||||
invoice.setInvoiceAmount(money(requestRow.getInvoiceAmount()));
|
||||
invoice.setAvailableInvoiceAmount(money(requestRow.getAvailableInvoiceAmount()));
|
||||
invoice.setMatchedAmount(money(requestRow.getMatchedAmount()));
|
||||
invoice.setAttachmentJson(requestRow.getAttachmentJson());
|
||||
invoiceMapper.insert(invoice);
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshSettlementAmount(FormalSettlement settlement) {
|
||||
BigDecimal amount = listSummaryFees(settlement.getId()).stream()
|
||||
.map(FormalSettlementSummaryFee::getSettlementAmount).map(this::money)
|
||||
@@ -707,6 +808,27 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
||||
return vo;
|
||||
}
|
||||
|
||||
private SettlementAdjustmentVO toAdjustmentVO(SettlementAdjustment entity, String kingdeeBillNo) {
|
||||
SettlementAdjustmentVO vo = Objects.requireNonNull(
|
||||
BeanUtil.copyProperties(entity, SettlementAdjustmentVO.class));
|
||||
vo.setCreateUserName(UserCache.getUserRealName(entity.getCreateUser()));
|
||||
vo.setApprovalStatusName(approvalStatusName(entity.getApprovalStatus()));
|
||||
vo.setSettlementTypeName("receivable".equals(entity.getSettlementType()) ? "应收" : "应付");
|
||||
vo.setKingdeeBillNo(kingdeeBillNo);
|
||||
return vo;
|
||||
}
|
||||
|
||||
private String approvalStatusName(String value) {
|
||||
return switch (value == null ? "" : value) {
|
||||
case DRAFT -> "草稿";
|
||||
case REVIEWING -> "审批中";
|
||||
case APPROVED -> "审批通过";
|
||||
case RETURNED -> "已驳回";
|
||||
case VOIDED -> "已作废";
|
||||
default -> value;
|
||||
};
|
||||
}
|
||||
|
||||
private PreSettlement availableSource(Long id) {
|
||||
PreSettlement source = preSettlementMapper.selectById(id);
|
||||
if (source == null || Objects.equals(source.getIsDeleted(), 1)) throw new ServiceException("预结算单不存在");
|
||||
@@ -742,6 +864,21 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
||||
settlement.setApprovalStatus(target); settlement.setCurrentNode(node); settlement.setCurrentProcessor(AuthUtil.getUserName());
|
||||
if (RETURNED.equals(target)) settlement.setVoidReason(limit(reason, 200));
|
||||
updateById(settlement);
|
||||
saveChange(settlement.getId(), "结算单基本信息", null, "调整", node, reason);
|
||||
}
|
||||
|
||||
private void saveChange(Long settlementId, String changeType, Integer lineNo, String operationType,
|
||||
String content, String reason) {
|
||||
FormalSettlementChangeRecord record = new FormalSettlementChangeRecord();
|
||||
record.setFormalSettlementId(settlementId);
|
||||
record.setChangeType(changeType);
|
||||
record.setLineNo(lineNo);
|
||||
record.setOperationType(operationType);
|
||||
record.setChangeContent(content);
|
||||
record.setChangeReason(reason);
|
||||
record.setOperatorName(Func.isEmpty(AuthUtil.getUserName()) ? "system" : AuthUtil.getUserName());
|
||||
record.setChangeTime(LocalDateTime.now());
|
||||
changeRecordMapper.insert(record);
|
||||
}
|
||||
|
||||
private void copyHeader(PreSettlement source, FormalSettlement target) {
|
||||
@@ -771,5 +908,6 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
||||
private BigDecimal nonNegative(BigDecimal value, String field) { if (value == null || value.signum() < 0) throw new ServiceException(field + "不能小于0"); return value; }
|
||||
private BigDecimal positive(BigDecimal value, String field) { if (value == null || value.signum() <= 0) throw new ServiceException(field + "必须大于0"); return value; }
|
||||
private String required(String value, String field) { if (Func.isEmpty(value)) throw new ServiceException("请填写" + field); return value; }
|
||||
private String firstNotEmpty(Object first, Object second) { return Func.isNotEmpty(first) ? String.valueOf(first) : String.valueOf(second); }
|
||||
private String limit(String value, int max) { if (value != null && value.length() > max) throw new ServiceException("内容不能超过" + max + "个字"); return value; }
|
||||
}
|
||||
|
||||
+184
-20
@@ -35,10 +35,13 @@ import org.springblade.transport.mapper.BillLedgerUsageMapper;
|
||||
import org.springblade.transport.mapper.PreSettlementMapper;
|
||||
import org.springblade.transport.mapper.ProjectApplyMapper;
|
||||
import org.springblade.transport.mapper.CustomerArchiveMapper;
|
||||
import org.springblade.transport.mapper.ContractManageMapper;
|
||||
import org.springblade.transport.mapper.PaymentApplicationInvoiceMapper;
|
||||
import org.springblade.transport.mapper.PaymentApplicationMapper;
|
||||
import org.springblade.transport.mapper.PaymentApplicationRecordMapper;
|
||||
import org.springblade.transport.mapper.TemporaryCreditLimitMapper;
|
||||
import org.springblade.transport.pojo.dto.PaymentApplicationInvoiceRequest;
|
||||
import org.springblade.transport.pojo.dto.PaymentApplicationRecordRequest;
|
||||
import org.springblade.transport.pojo.dto.PaymentApplicationSaveRequest;
|
||||
import org.springblade.transport.pojo.dto.PaymentApplicationStatusRequest;
|
||||
import org.springblade.transport.pojo.entity.FormalSettlement;
|
||||
@@ -47,9 +50,13 @@ import org.springblade.transport.pojo.entity.BillLedgerUsage;
|
||||
import org.springblade.transport.pojo.entity.PreSettlement;
|
||||
import org.springblade.transport.pojo.entity.ProjectApply;
|
||||
import org.springblade.transport.pojo.entity.CustomerArchive;
|
||||
import org.springblade.transport.pojo.entity.ContractManage;
|
||||
import org.springblade.transport.pojo.entity.PaymentApplication;
|
||||
import org.springblade.transport.pojo.entity.PaymentApplicationInvoice;
|
||||
import org.springblade.transport.pojo.entity.PaymentApplicationRecord;
|
||||
import org.springblade.transport.pojo.entity.TemporaryCreditLimit;
|
||||
import org.springblade.transport.pojo.vo.PaymentApplicationVO;
|
||||
import org.springblade.transport.pojo.vo.PaymentApplicationReferenceAmountVO;
|
||||
import org.springblade.transport.service.IPaymentApplicationService;
|
||||
import org.springblade.transport.wrapper.PaymentApplicationWrapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -61,7 +68,9 @@ import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/** 付款申请服务实现。 @author Chill */
|
||||
@Service
|
||||
@@ -78,9 +87,11 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
|
||||
private final PreSettlementMapper preSettlementMapper;
|
||||
private final FormalSettlementMapper formalSettlementMapper;
|
||||
private final ProjectApplyMapper projectApplyMapper;
|
||||
private final ContractManageMapper contractManageMapper;
|
||||
private final CustomerArchiveMapper customerArchiveMapper;
|
||||
private final BillLedgerMapper billLedgerMapper;
|
||||
private final BillLedgerUsageMapper billLedgerUsageMapper;
|
||||
private final TemporaryCreditLimitMapper temporaryCreditLimitMapper;
|
||||
|
||||
@Override
|
||||
public IPage<PaymentApplicationVO> selectPage(IPage<PaymentApplication> page, PaymentApplicationVO query) {
|
||||
@@ -114,6 +125,39 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
|
||||
return vo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PaymentApplicationReferenceAmountVO referenceAmount(String paymentType, Long referenceId, Long excludeId) {
|
||||
if (referenceId == null) throw new ServiceException("结算单不能为空");
|
||||
BigDecimal settlementAmount;
|
||||
if ("settlement_payment".equals(paymentType)) {
|
||||
FormalSettlement settlement = formalSettlementMapper.selectById(referenceId);
|
||||
if (settlement == null || Objects.equals(settlement.getIsDeleted(), 1)) {
|
||||
throw new ServiceException("正式结算单不存在");
|
||||
}
|
||||
if (!APPROVED.equals(settlement.getApprovalStatus())) {
|
||||
throw new ServiceException("只能选择审批通过、未作废的正式结算单");
|
||||
}
|
||||
settlementAmount = money(settlement.getSettlementAmount());
|
||||
} else if ("progress_advance".equals(paymentType)) {
|
||||
PreSettlement settlement = preSettlementMapper.selectById(referenceId);
|
||||
if (settlement == null || Objects.equals(settlement.getIsDeleted(), 1)) {
|
||||
throw new ServiceException("预结算单不存在");
|
||||
}
|
||||
if (!APPROVED.equals(settlement.getApprovalStatus())) {
|
||||
throw new ServiceException("只能选择审批通过、未作废的预结算单");
|
||||
}
|
||||
settlementAmount = money(settlement.getSettlementAmount());
|
||||
} else {
|
||||
throw new ServiceException("付款类型不支持关联结算单");
|
||||
}
|
||||
BigDecimal cumulativeAppliedAmount = cumulativeAppliedAmount(paymentType, referenceId, excludeId);
|
||||
PaymentApplicationReferenceAmountVO amount = new PaymentApplicationReferenceAmountVO();
|
||||
amount.setSettlementAmount(settlementAmount);
|
||||
amount.setCumulativeAppliedAmount(cumulativeAppliedAmount);
|
||||
amount.setPayableAmount(settlementAmount.subtract(cumulativeAppliedAmount));
|
||||
return amount;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Long saveDraft(PaymentApplicationSaveRequest request) {
|
||||
@@ -139,6 +183,14 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
|
||||
entity.setRemark(limit(request.getRemark(), 200));
|
||||
entity.setApplyDate(entity.getApplyDate() == null ? LocalDate.now() : entity.getApplyDate());
|
||||
entity.setApplicantName(Func.isEmpty(entity.getApplicantName()) ? AuthUtil.getUserName() : entity.getApplicantName());
|
||||
List<PaymentApplicationInvoiceRequest> invoiceRequests = ("project_advance".equals(request.getPaymentType())
|
||||
|| request.getInvoices() == null) ? List.of() : request.getInvoices();
|
||||
BigDecimal matchedInvoiceAmount = BigDecimal.ZERO;
|
||||
for (PaymentApplicationInvoiceRequest item : invoiceRequests) {
|
||||
validateInvoice(item);
|
||||
matchedInvoiceAmount = matchedInvoiceAmount.add(money(item.getMatchedAmount()));
|
||||
}
|
||||
entity.setMatchedInvoiceAmount(matchedInvoiceAmount);
|
||||
fillReference(entity, request);
|
||||
fillBillLedger(entity, request);
|
||||
validateQuota(entity);
|
||||
@@ -146,27 +198,38 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
|
||||
invoiceMapper.delete(Wrappers.<PaymentApplicationInvoice>lambdaQuery()
|
||||
.eq(PaymentApplicationInvoice::getPaymentApplicationId, entity.getId()));
|
||||
int lineNo = 1;
|
||||
BigDecimal matchedInvoiceAmount = BigDecimal.ZERO;
|
||||
for (PaymentApplicationInvoiceRequest item : request.getInvoices() == null ? List.<PaymentApplicationInvoiceRequest>of() : request.getInvoices()) {
|
||||
validateInvoice(item);
|
||||
for (PaymentApplicationInvoiceRequest item : invoiceRequests) {
|
||||
PaymentApplicationInvoice invoice = Objects.requireNonNull(BeanUtil.copyProperties(item, PaymentApplicationInvoice.class));
|
||||
invoice.setId(null);
|
||||
invoice.setPaymentApplicationId(entity.getId());
|
||||
invoice.setLineNo(lineNo++);
|
||||
invoiceMapper.insert(invoice);
|
||||
matchedInvoiceAmount = matchedInvoiceAmount.add(money(item.getMatchedAmount()));
|
||||
}
|
||||
if (matchedInvoiceAmount.compareTo(money(entity.getAppliedAmount())) > 0) {
|
||||
throw new ServiceException("发票匹配金额合计不能超过申请付款金额");
|
||||
recordMapper.delete(Wrappers.<PaymentApplicationRecord>lambdaQuery()
|
||||
.eq(PaymentApplicationRecord::getPaymentApplicationId, entity.getId()));
|
||||
BigDecimal paidAmount = BigDecimal.ZERO;
|
||||
List<PaymentApplicationRecordRequest> recordRequests = ("project_advance".equals(request.getPaymentType())
|
||||
|| request.getPaymentRecords() == null) ? List.of() : request.getPaymentRecords();
|
||||
for (PaymentApplicationRecordRequest item : recordRequests) {
|
||||
validatePaymentRecord(item);
|
||||
PaymentApplicationRecord record = Objects.requireNonNull(BeanUtil.copyProperties(item, PaymentApplicationRecord.class));
|
||||
record.setId(null);
|
||||
record.setPaymentApplicationId(entity.getId());
|
||||
recordMapper.insert(record);
|
||||
paidAmount = paidAmount.add(money(item.getPaidAmount()));
|
||||
}
|
||||
if (paidAmount.compareTo(money(entity.getAppliedAmount())) > 0) {
|
||||
throw new ServiceException("付款记录金额合计不能超过申请付款金额");
|
||||
}
|
||||
entity.setMatchedInvoiceAmount(matchedInvoiceAmount);
|
||||
entity.setInvoiceStatus(matchedInvoiceAmount.compareTo(BigDecimal.ZERO) > 0 ? "matched" : "unmatched");
|
||||
entity.setPaidAmount(paidAmount);
|
||||
updateById(entity);
|
||||
return entity.getId();
|
||||
}
|
||||
|
||||
@Override @Transactional(rollbackFor = Exception.class)
|
||||
public void removeDraft(Long id) { PaymentApplication entity = editable(id); invoiceMapper.delete(Wrappers.<PaymentApplicationInvoice>lambdaQuery().eq(PaymentApplicationInvoice::getPaymentApplicationId, id)); removeById(entity); }
|
||||
public void removeDraft(Long id) { PaymentApplication entity = editable(id); invoiceMapper.delete(Wrappers.<PaymentApplicationInvoice>lambdaQuery().eq(PaymentApplicationInvoice::getPaymentApplicationId, id)); recordMapper.delete(Wrappers.<PaymentApplicationRecord>lambdaQuery().eq(PaymentApplicationRecord::getPaymentApplicationId, id)); removeById(entity); }
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void submit(PaymentApplicationStatusRequest request) {
|
||||
@@ -174,7 +237,9 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
|
||||
if (!List.of(DRAFT, RETURNED).contains(entity.getApprovalStatus())) {
|
||||
throw new ServiceException("当前状态不允许提交");
|
||||
}
|
||||
validateProjectAdvanceContractFile(entity);
|
||||
validateSelectedBill(entity, false);
|
||||
validateQuota(entity);
|
||||
entity.setApprovalStatus(REVIEWING);
|
||||
entity.setCurrentNode("财务审核");
|
||||
entity.setCurrentProcessor(AuthUtil.getUserName());
|
||||
@@ -228,6 +293,16 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
|
||||
}
|
||||
|
||||
private void validateInvoice(PaymentApplicationInvoiceRequest invoice) {
|
||||
if (invoice == null) throw new ServiceException("发票信息不能为空");
|
||||
if (invoice.getSettlementNo() != null && invoice.getSettlementNo().length() > 100) {
|
||||
throw new ServiceException("结算单号不能超过100个字符");
|
||||
}
|
||||
if (invoice.getInvoiceNo() != null && invoice.getInvoiceNo().length() > 100) {
|
||||
throw new ServiceException("发票号不能超过100个字符");
|
||||
}
|
||||
if (invoice.getInvoiceType() != null && invoice.getInvoiceType().length() > 30) {
|
||||
throw new ServiceException("发票类型不能超过30个字符");
|
||||
}
|
||||
BigDecimal invoiceAmount = money(invoice.getInvoiceAmount());
|
||||
BigDecimal matchedAmount = money(invoice.getMatchedAmount());
|
||||
if (invoiceAmount.compareTo(BigDecimal.ZERO) < 0) {
|
||||
@@ -245,18 +320,66 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
|
||||
}
|
||||
}
|
||||
|
||||
private void validatePaymentRecord(PaymentApplicationRecordRequest record) {
|
||||
if (record == null) throw new ServiceException("付款记录不能为空");
|
||||
if (record.getPaidAmount() == null || record.getPaidAmount().compareTo(BigDecimal.ZERO) < 0) {
|
||||
throw new ServiceException("付款记录金额不能小于0");
|
||||
}
|
||||
if (record.getPaymentNo() != null && record.getPaymentNo().length() > 100) {
|
||||
throw new ServiceException("付款单号不能超过100个字符");
|
||||
}
|
||||
if (record.getKingdeeBillNo() != null && record.getKingdeeBillNo().length() > 100) {
|
||||
throw new ServiceException("付款凭证不能超过100个字符");
|
||||
}
|
||||
}
|
||||
|
||||
private void validateProjectAdvanceContractFile(PaymentApplication entity) {
|
||||
if (!"project_advance".equals(entity.getPaymentType())) return;
|
||||
ContractManage contract = entity.getContractId() == null ? null : contractManageMapper.selectById(entity.getContractId());
|
||||
if (contract == null || Objects.equals(contract.getIsDeleted(), 1)) {
|
||||
throw new ServiceException("项目预付必须选择有效合同");
|
||||
}
|
||||
if (!hasDownloadableFile(contract.getContractFileJson())
|
||||
&& !hasDownloadableFile(entity.getAttachmentsJson(), "contract")) {
|
||||
throw new ServiceException("请上传合同签章文件");
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasDownloadableFile(String value) {
|
||||
return hasDownloadableFile(value, null);
|
||||
}
|
||||
|
||||
private boolean hasDownloadableFile(String value, String attachmentType) {
|
||||
if (Func.isEmpty(value)) return false;
|
||||
try {
|
||||
Object parsed = JsonUtil.parse(value, List.class);
|
||||
if (!(parsed instanceof List<?> files)) return false;
|
||||
return files.stream().anyMatch(file -> file instanceof Map<?, ?> fields
|
||||
&& (attachmentType == null || Objects.equals(attachmentType, fields.get("attachmentType")))
|
||||
&& List.of("url", "link", "fileUrl", "downloadUrl", "src", "domain").stream()
|
||||
.anyMatch(key -> Func.isNotEmpty(fields.get(key))));
|
||||
} catch (Exception exception) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void fillReference(PaymentApplication entity, PaymentApplicationSaveRequest request) {
|
||||
if (request.getSettlementId() != null) {
|
||||
if ("project_advance".equals(request.getPaymentType())) {
|
||||
ProjectApply project = projectApplyMapper.selectById(request.getProjectId());
|
||||
if (project == null || Objects.equals(project.getIsDeleted(), 1)) throw new ServiceException("所属项目不存在");
|
||||
entity.setSettlementId(null); entity.setSettlementNo(null); entity.setPreSettlementId(null); entity.setPreSettlementNo(null);
|
||||
entity.setProjectId(request.getProjectId()); entity.setProjectName(request.getProjectName()); entity.setDeptId(request.getDeptId()); entity.setDeptName(request.getDeptName()); entity.setContractId(request.getContractId()); entity.setContractNo(request.getContractNo()); entity.setContractName(request.getContractName()); entity.setPayerName(request.getPayerName()); entity.setPayeeName(request.getPayeeName()); entity.setSettlementAmount(request.getSettlementAmount()); entity.setPayableAmount(money(project.getFundDemand()).multiply(BigDecimal.valueOf(10000))); entity.setBillType(Func.isEmpty(project.getSettlementMode()) ? null : "项目预付");
|
||||
} else if (request.getSettlementId() != null) {
|
||||
FormalSettlement source = formalSettlementMapper.selectById(request.getSettlementId());
|
||||
if (source == null) throw new ServiceException("正式结算单不存在");
|
||||
if (!APPROVED.equals(source.getApprovalStatus())) throw new ServiceException("只能选择审批通过、未作废的正式结算单");
|
||||
entity.setSettlementId(source.getId()); entity.setSettlementNo(source.getFormalSettlementNo()); entity.setPreSettlementId(null); entity.setPreSettlementNo(null);
|
||||
entity.setProjectId(source.getProjectId()); entity.setProjectName(source.getProjectName()); entity.setDeptId(source.getDeptId()); entity.setDeptName(source.getDeptName()); entity.setContractId(source.getContractId()); entity.setContractNo(source.getContractNo()); entity.setContractName(source.getContractName()); entity.setPayerName(source.getPayerName()); entity.setPayeeName(source.getPayeeName()); entity.setSettlementAmount(source.getSettlementAmount()); entity.setPayableAmount(money(source.getSettlementAmount()).subtract(money(source.getAppliedPaymentAmount()))); entity.setBillType("正式结算单");
|
||||
entity.setProjectId(source.getProjectId()); entity.setProjectName(source.getProjectName()); entity.setDeptId(source.getDeptId()); entity.setDeptName(source.getDeptName()); entity.setContractId(source.getContractId()); entity.setContractNo(source.getContractNo()); entity.setContractName(source.getContractName()); entity.setPayerName(source.getPayerName()); entity.setPayeeName(source.getPayeeName()); entity.setSettlementAmount(source.getSettlementAmount()); entity.setPayableAmount(money(source.getSettlementAmount()).subtract(cumulativeAppliedAmount(request.getPaymentType(), source.getId(), entity.getId()))); entity.setBillType("正式结算单");
|
||||
} else if (request.getPreSettlementId() != null) {
|
||||
PreSettlement source = preSettlementMapper.selectById(request.getPreSettlementId());
|
||||
if (source == null) throw new ServiceException("预结算单不存在");
|
||||
if (!APPROVED.equals(source.getApprovalStatus())) throw new ServiceException("只能选择审批通过、未作废的预结算单");
|
||||
entity.setPreSettlementId(source.getId()); entity.setPreSettlementNo(source.getPreSettlementNo()); entity.setSettlementId(null); entity.setSettlementNo(null); entity.setProjectId(source.getProjectId()); entity.setProjectName(source.getProjectName()); entity.setDeptId(source.getDeptId()); entity.setDeptName(source.getDeptName()); entity.setContractId(source.getContractId()); entity.setContractNo(source.getContractNo()); entity.setContractName(source.getContractName()); entity.setPayerName(source.getPayerName()); entity.setPayeeName(source.getPayeeName()); entity.setSettlementAmount(source.getSettlementAmount()); entity.setPayableAmount(money(source.getSettlementAmount()).subtract(money(source.getAdvanceAppliedAmount()))); entity.setBillType("预结算单");
|
||||
entity.setPreSettlementId(source.getId()); entity.setPreSettlementNo(source.getPreSettlementNo()); entity.setSettlementId(null); entity.setSettlementNo(null); entity.setProjectId(source.getProjectId()); entity.setProjectName(source.getProjectName()); entity.setDeptId(source.getDeptId()); entity.setDeptName(source.getDeptName()); entity.setContractId(source.getContractId()); entity.setContractNo(source.getContractNo()); entity.setContractName(source.getContractName()); entity.setPayerName(source.getPayerName()); entity.setPayeeName(source.getPayeeName()); entity.setSettlementAmount(source.getSettlementAmount()); entity.setPayableAmount(money(source.getSettlementAmount()).subtract(cumulativeAppliedAmount(request.getPaymentType(), source.getId(), entity.getId()))); entity.setBillType("预结算单");
|
||||
} else {
|
||||
entity.setProjectId(request.getProjectId()); entity.setProjectName(request.getProjectName()); entity.setDeptId(request.getDeptId()); entity.setDeptName(request.getDeptName()); entity.setContractId(request.getContractId()); entity.setContractNo(request.getContractNo()); entity.setContractName(request.getContractName()); entity.setPayerName(request.getPayerName()); entity.setPayeeName(request.getPayeeName()); entity.setSettlementAmount(request.getSettlementAmount()); entity.setPayableAmount(request.getPayableAmount()); entity.setBillType(request.getBillType());
|
||||
}
|
||||
@@ -264,32 +387,73 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
|
||||
}
|
||||
|
||||
private void validateQuota(PaymentApplication entity) {
|
||||
BigDecimal usedByProject = sumApplied(Wrappers.<PaymentApplication>lambdaQuery()
|
||||
.eq(entity.getProjectId() != null, PaymentApplication::getProjectId, entity.getProjectId())
|
||||
.ne(entity.getId() != null, PaymentApplication::getId, entity.getId()));
|
||||
ProjectApply project = entity.getProjectId() == null ? null : projectApplyMapper.selectById(entity.getProjectId());
|
||||
ProjectApply project = entity.getProjectId() == null ? null : projectApplyMapper.selectOne(
|
||||
Wrappers.<ProjectApply>lambdaQuery().eq(ProjectApply::getId, entity.getProjectId()).last("FOR UPDATE"));
|
||||
if (project != null && project.getFundLimit() != null) {
|
||||
BigDecimal projectLimit = project.getFundLimit().multiply(BigDecimal.valueOf(10000));
|
||||
if (usedByProject.add(money(entity.getAppliedAmount())).compareTo(projectLimit) > 0) throw new ServiceException("申请付款金额超过项目剩余资金使用额度");
|
||||
BigDecimal projectLimit = projectFundLimit(project);
|
||||
BigDecimal projectOccupiedAmount = quotaOccupiedAmount(Wrappers.<PaymentApplication>lambdaQuery()
|
||||
.eq(PaymentApplication::getProjectId, entity.getProjectId())
|
||||
.ne(entity.getId() != null, PaymentApplication::getId, entity.getId()), entity);
|
||||
if (projectOccupiedAmount.compareTo(projectLimit) > 0) {
|
||||
throw new ServiceException("申请付款金额超过项目剩余资金使用额度(已扣减收票金额并包含在途申请)");
|
||||
}
|
||||
}
|
||||
if (Func.isNotEmpty(entity.getPayeeName())) {
|
||||
CustomerArchive customer = customerArchiveMapper.selectOne(Wrappers.<CustomerArchive>lambdaQuery()
|
||||
.and(wrapper -> wrapper.eq(CustomerArchive::getFullName, entity.getPayeeName()).or().eq(CustomerArchive::getShortName, entity.getPayeeName()))
|
||||
.eq(CustomerArchive::getIsDeleted, 0).last("limit 1"));
|
||||
.eq(CustomerArchive::getIsDeleted, 0).last("limit 1 FOR UPDATE"));
|
||||
if (customer != null && customer.getMaxCreditLimit() != null) {
|
||||
BigDecimal customerLimit = customer.getMaxCreditLimit().multiply(BigDecimal.valueOf(10000));
|
||||
BigDecimal usedByCustomer = sumApplied(Wrappers.<PaymentApplication>lambdaQuery()
|
||||
.eq(PaymentApplication::getPayeeName, entity.getPayeeName()).ne(entity.getId() != null, PaymentApplication::getId, entity.getId()));
|
||||
if (usedByCustomer.add(money(entity.getAppliedAmount())).compareTo(customerLimit) > 0) throw new ServiceException("申请付款金额超过客户剩余资金使用额度");
|
||||
List<String> customerNames = Stream.of(customer.getFullName(), customer.getShortName())
|
||||
.filter(Func::isNotEmpty).map(String::trim).distinct().toList();
|
||||
BigDecimal customerOccupiedAmount = quotaOccupiedAmount(Wrappers.<PaymentApplication>lambdaQuery()
|
||||
.in(PaymentApplication::getPayeeName, customerNames)
|
||||
.ne(entity.getId() != null, PaymentApplication::getId, entity.getId()), entity);
|
||||
if (customerOccupiedAmount.compareTo(customerLimit) > 0) {
|
||||
throw new ServiceException("申请付款金额超过客户剩余资金使用额度(已扣减收票金额并包含在途申请)");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private BigDecimal projectFundLimit(ProjectApply project) {
|
||||
BigDecimal temporaryLimit = temporaryCreditLimitMapper.selectList(Wrappers.<TemporaryCreditLimit>lambdaQuery()
|
||||
.eq(TemporaryCreditLimit::getProjectId, project.getId())
|
||||
.eq(TemporaryCreditLimit::getApprovalStatus, APPROVED)
|
||||
.ge(TemporaryCreditLimit::getValidUntil, LocalDate.now())
|
||||
.eq(TemporaryCreditLimit::getStatus, 1)
|
||||
.eq(TemporaryCreditLimit::getIsDeleted, 0)).stream()
|
||||
.map(TemporaryCreditLimit::getApplyLimit).map(this::money)
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
return money(project.getFundLimit()).add(temporaryLimit).multiply(BigDecimal.valueOf(10000));
|
||||
}
|
||||
|
||||
private BigDecimal quotaOccupiedAmount(LambdaQueryWrapper<PaymentApplication> wrapper,
|
||||
PaymentApplication currentApplication) {
|
||||
List<PaymentApplication> applications = list(wrapper.ne(PaymentApplication::getApprovalStatus, VOIDED)
|
||||
.last("FOR UPDATE"));
|
||||
BigDecimal appliedAmount = applications.stream().map(PaymentApplication::getAppliedAmount)
|
||||
.map(this::money).reduce(BigDecimal.ZERO, BigDecimal::add)
|
||||
.add(money(currentApplication.getAppliedAmount()));
|
||||
BigDecimal receivedInvoiceAmount = applications.stream().map(PaymentApplication::getMatchedInvoiceAmount)
|
||||
.map(this::money).reduce(BigDecimal.ZERO, BigDecimal::add)
|
||||
.add(money(currentApplication.getMatchedInvoiceAmount()));
|
||||
return appliedAmount.subtract(receivedInvoiceAmount).max(BigDecimal.ZERO);
|
||||
}
|
||||
|
||||
private BigDecimal sumApplied(LambdaQueryWrapper<PaymentApplication> wrapper) {
|
||||
return list(wrapper.ne(PaymentApplication::getApprovalStatus, VOIDED)).stream()
|
||||
.map(PaymentApplication::getAppliedAmount).map(this::money).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
}
|
||||
|
||||
private BigDecimal cumulativeAppliedAmount(String paymentType, Long referenceId, Long excludeId) {
|
||||
LambdaQueryWrapper<PaymentApplication> wrapper = Wrappers.<PaymentApplication>lambdaQuery()
|
||||
.eq("settlement_payment".equals(paymentType), PaymentApplication::getSettlementId, referenceId)
|
||||
.eq("progress_advance".equals(paymentType), PaymentApplication::getPreSettlementId, referenceId)
|
||||
.ne(excludeId != null, PaymentApplication::getId, excludeId);
|
||||
return sumApplied(wrapper);
|
||||
}
|
||||
|
||||
private void fillBillLedger(PaymentApplication entity, PaymentApplicationSaveRequest request) {
|
||||
if (!isBillPayment(request.getPaymentMethod())) {
|
||||
entity.setBillLedgerId(null);
|
||||
|
||||
+12
-1
@@ -56,6 +56,7 @@ import org.springblade.transport.pojo.entity.PreSettlementChangeRecord;
|
||||
import org.springblade.transport.pojo.entity.PreSettlementDetail;
|
||||
import org.springblade.transport.pojo.entity.PreSettlementDetailFee;
|
||||
import org.springblade.transport.pojo.entity.PreSettlementSummaryFee;
|
||||
import org.springblade.transport.pojo.entity.ProjectApply;
|
||||
import org.springblade.transport.pojo.entity.ReceivablePayableCargoFee;
|
||||
import org.springblade.transport.pojo.entity.ReceivablePayableDetail;
|
||||
import org.springblade.transport.pojo.entity.Waybill;
|
||||
@@ -183,7 +184,15 @@ public class PreSettlementServiceImpl extends BaseServiceImpl<PreSettlementMappe
|
||||
.and(Func.isNotEmpty(keyword), query -> query.like(ContractManage::getContractName, keyword)
|
||||
.or().like(ContractManage::getContractNo, keyword))
|
||||
.orderByDesc(ContractManage::getCreateTime);
|
||||
return contractManageService.list(wrapper).stream().filter(this::isAvailableContract).map(contract -> {
|
||||
List<ContractManage> contracts = contractManageService.list(wrapper).stream()
|
||||
.filter(this::isAvailableContract).toList();
|
||||
Set<Long> projectIds = contracts.stream().map(ContractManage::getProjectId)
|
||||
.filter(Objects::nonNull).collect(Collectors.toSet());
|
||||
Map<Long, ProjectApply> projectById = Func.isEmpty(projectIds) ? Map.of()
|
||||
: projectApplyService.listByIds(projectIds).stream()
|
||||
.collect(Collectors.toMap(ProjectApply::getId, Function.identity()));
|
||||
return contracts.stream().map(contract -> {
|
||||
ProjectApply project = projectById.get(contract.getProjectId());
|
||||
Map<String, Object> result = new LinkedHashMap<>();
|
||||
result.put("id", contract.getId());
|
||||
result.put("contractNo", contract.getContractNo());
|
||||
@@ -194,6 +203,8 @@ public class PreSettlementServiceImpl extends BaseServiceImpl<PreSettlementMappe
|
||||
result.put("deptName", contract.getOrganizationName());
|
||||
result.put("partyA", contract.getPartyA());
|
||||
result.put("partyB", contract.getPartyB());
|
||||
result.put("fundDemand", project == null ? null : project.getFundDemand());
|
||||
result.put("settlementMode", project == null ? null : project.getSettlementMode());
|
||||
result.put("settlementType", contractSettlementType(contract));
|
||||
return result;
|
||||
}).toList();
|
||||
|
||||
+26
@@ -11,12 +11,14 @@ import org.springblade.core.tool.utils.Func;
|
||||
import org.springblade.system.cache.UserCache;
|
||||
import org.springblade.transport.mapper.FormalSettlementDetailFeeMapper;
|
||||
import org.springblade.transport.mapper.FormalSettlementDetailMapper;
|
||||
import org.springblade.transport.mapper.FormalSettlementChangeRecordMapper;
|
||||
import org.springblade.transport.mapper.FormalSettlementMapper;
|
||||
import org.springblade.transport.mapper.SettlementAdjustmentDetailMapper;
|
||||
import org.springblade.transport.mapper.SettlementAdjustmentMapper;
|
||||
import org.springblade.transport.pojo.dto.SettlementAdjustmentSaveRequest;
|
||||
import org.springblade.transport.pojo.dto.SettlementAdjustmentStatusRequest;
|
||||
import org.springblade.transport.pojo.entity.FormalSettlement;
|
||||
import org.springblade.transport.pojo.entity.FormalSettlementChangeRecord;
|
||||
import org.springblade.transport.pojo.entity.FormalSettlementDetail;
|
||||
import org.springblade.transport.pojo.entity.FormalSettlementDetailFee;
|
||||
import org.springblade.transport.pojo.entity.SettlementAdjustment;
|
||||
@@ -48,6 +50,7 @@ public class SettlementAdjustmentServiceImpl extends BaseServiceImpl<SettlementA
|
||||
private final FormalSettlementMapper formalMapper;
|
||||
private final FormalSettlementDetailMapper formalDetailMapper;
|
||||
private final FormalSettlementDetailFeeMapper formalFeeMapper;
|
||||
private final FormalSettlementChangeRecordMapper formalChangeRecordMapper;
|
||||
|
||||
@Override
|
||||
public IPage<SettlementAdjustmentVO> selectPage(IPage<SettlementAdjustment> page, SettlementAdjustmentVO query) {
|
||||
@@ -178,9 +181,15 @@ public class SettlementAdjustmentServiceImpl extends BaseServiceImpl<SettlementA
|
||||
if (formal == null || !APPROVED.equals(formal.getApprovalStatus())) throw new ServiceException("关联正式结算单状态已变化,无法审批");
|
||||
for (SettlementAdjustmentDetail item : detailMapper.selectList(Wrappers.<SettlementAdjustmentDetail>lambdaQuery().eq(SettlementAdjustmentDetail::getAdjustmentId, adjustment.getId()))) {
|
||||
FormalSettlementDetailFee fee = validateFee(formal.getId(), item.getFormalSettlementDetailId(), item.getFormalSettlementDetailFeeId());
|
||||
BigDecimal beforeAmount = money(fee.getSettlementAmountTax());
|
||||
fee.setSettlementAmountTax(money(fee.getSettlementAmountTax()).add(money(item.getAdjustmentAmountTax())));
|
||||
if (item.getAdjustmentAmountNoTax() != null) fee.setSettlementAmountNoTax(money(fee.getSettlementAmountNoTax()).add(item.getAdjustmentAmountNoTax()));
|
||||
fee.setAdjustAmount(money(fee.getAdjustAmount()).add(item.getAdjustmentAmountTax())); formalFeeMapper.updateById(fee);
|
||||
FormalSettlementDetail formalDetail = formalDetailMapper.selectById(item.getFormalSettlementDetailId());
|
||||
saveFormalChange(formal.getId(), "结算明细项", formalDetail == null ? null : formalDetail.getLineNo(),
|
||||
"调整", "【" + (Func.isEmpty(item.getFeeItem()) ? "结算费用" : item.getFeeItem())
|
||||
+ "】从【" + beforeAmount + "】调整为【" + fee.getSettlementAmountTax() + "】",
|
||||
Func.isEmpty(item.getRemark()) ? adjustment.getRemark() : item.getRemark());
|
||||
}
|
||||
for (FormalSettlementDetail detail : formalDetailMapper.selectList(Wrappers.<FormalSettlementDetail>lambdaQuery().eq(FormalSettlementDetail::getFormalSettlementId, formal.getId()))) {
|
||||
List<FormalSettlementDetailFee> fees = formalFeeMapper.selectList(Wrappers.<FormalSettlementDetailFee>lambdaQuery().eq(FormalSettlementDetailFee::getFormalSettlementDetailId, detail.getId()));
|
||||
@@ -190,9 +199,26 @@ public class SettlementAdjustmentServiceImpl extends BaseServiceImpl<SettlementA
|
||||
}
|
||||
BigDecimal amount = formalDetailMapper.selectList(Wrappers.<FormalSettlementDetail>lambdaQuery().eq(FormalSettlementDetail::getFormalSettlementId, formal.getId())).stream().map(FormalSettlementDetail::getSettlementAmountTax).map(this::money).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
formal.setSettlementAmount(amount); formal.setLocalSettlementAmount(amount.multiply(formal.getExchangeRate() == null ? BigDecimal.ONE : formal.getExchangeRate())); formalMapper.updateById(formal);
|
||||
saveFormalChange(formal.getId(), "合计费用项", null, "调整",
|
||||
"调整单" + adjustment.getAdjustmentNo() + "调整金额【" + money(adjustment.getAdjustmentAmount()) + "】",
|
||||
adjustment.getRemark());
|
||||
adjustment.setKingdeeSyncStatus(formal.getKingdeeSyncStatus()); adjustment.setApprovalStatus(APPROVED); adjustment.setCurrentNode("审批通过"); adjustment.setCurrentProcessor(AuthUtil.getUserName()); adjustment.setApprovedTime(LocalDateTime.now()); updateById(adjustment);
|
||||
}
|
||||
|
||||
private void saveFormalChange(Long settlementId, String changeType, Integer lineNo,
|
||||
String operationType, String content, String reason) {
|
||||
FormalSettlementChangeRecord record = new FormalSettlementChangeRecord();
|
||||
record.setFormalSettlementId(settlementId);
|
||||
record.setChangeType(changeType);
|
||||
record.setLineNo(lineNo);
|
||||
record.setOperationType(operationType);
|
||||
record.setChangeContent(content);
|
||||
record.setChangeReason(reason);
|
||||
record.setOperatorName(Func.isEmpty(AuthUtil.getUserName()) ? "system" : AuthUtil.getUserName());
|
||||
record.setChangeTime(LocalDateTime.now());
|
||||
formalChangeRecordMapper.insert(record);
|
||||
}
|
||||
|
||||
private void changeStatus(Long id, String from, String to, String node, String reason) { SettlementAdjustment item = existing(id); if (!from.equals(item.getApprovalStatus())) throw new ServiceException("当前状态不允许此操作"); item.setApprovalStatus(to); item.setCurrentNode(node); if (reason != null) item.setRemark(reason); updateById(item); }
|
||||
private SettlementAdjustment existing(Long id) { SettlementAdjustment item = getById(id); if (item == null || Objects.equals(item.getIsDeleted(), 1)) throw new ServiceException("结算调整单不存在"); return item; }
|
||||
private SettlementAdjustment editable(Long id) { SettlementAdjustment item = existing(id); if (!(DRAFT.equals(item.getApprovalStatus()) || RETURNED.equals(item.getApprovalStatus()))) throw new ServiceException("仅草稿或驳回的调整单可编辑"); return item; }
|
||||
|
||||
@@ -23,6 +23,33 @@ CREATE TABLE IF NOT EXISTS `blade_formal_settlement` (
|
||||
KEY `idx_formal_contract` (`contract_id`), KEY `idx_formal_approval` (`approval_status`), KEY `idx_formal_create_time` (`create_time`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='正式结算单';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `blade_formal_settlement_invoice` (
|
||||
`id` bigint(20) NOT NULL COMMENT '主键', `tenant_id` varchar(12) NOT NULL DEFAULT '000000' COMMENT '租户ID',
|
||||
`create_user` bigint(20) DEFAULT NULL, `create_dept` bigint(20) DEFAULT NULL, `create_time` datetime DEFAULT NULL,
|
||||
`update_user` bigint(20) DEFAULT NULL, `update_time` datetime DEFAULT NULL, `status` int(11) DEFAULT '1', `is_deleted` int(11) DEFAULT '0',
|
||||
`formal_settlement_id` bigint(20) NOT NULL COMMENT '正式结算单ID', `line_no` int(11) NOT NULL COMMENT '行号',
|
||||
`invoice_no` varchar(32) NOT NULL COMMENT '发票号', `invoice_date` date DEFAULT NULL COMMENT '开票日期',
|
||||
`invoice_type` varchar(50) DEFAULT NULL COMMENT '发票类型', `tax_rate` decimal(8,4) DEFAULT NULL COMMENT '税率',
|
||||
`invoice_amount` decimal(18,2) NOT NULL DEFAULT '0.00' COMMENT '发票金额(含税)',
|
||||
`available_invoice_amount` decimal(18,2) NOT NULL DEFAULT '0.00' COMMENT '可匹配发票金额(含税)',
|
||||
`matched_amount` decimal(18,2) NOT NULL DEFAULT '0.00' COMMENT '匹配结算单金额(含税)',
|
||||
`attachment_json` longtext COMMENT '发票附件JSON', PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_formal_settlement_invoice_no` (`tenant_id`,`formal_settlement_id`,`invoice_no`),
|
||||
KEY `idx_formal_settlement_invoice` (`formal_settlement_id`,`line_no`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='正式结算发票明细';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `blade_formal_settlement_change_record` (
|
||||
`id` bigint(20) NOT NULL COMMENT '主键', `tenant_id` varchar(12) NOT NULL DEFAULT '000000' COMMENT '租户ID',
|
||||
`create_user` bigint(20) DEFAULT NULL, `create_dept` bigint(20) DEFAULT NULL, `create_time` datetime DEFAULT NULL,
|
||||
`update_user` bigint(20) DEFAULT NULL, `update_time` datetime DEFAULT NULL, `status` int(11) DEFAULT '1', `is_deleted` int(11) DEFAULT '0',
|
||||
`formal_settlement_id` bigint(20) NOT NULL COMMENT '正式结算单ID', `change_type` varchar(50) NOT NULL COMMENT '变更类型',
|
||||
`line_no` int(11) DEFAULT NULL COMMENT '行号', `operation_type` varchar(30) NOT NULL COMMENT '操作类型',
|
||||
`change_content` text NOT NULL COMMENT '变更内容', `change_reason` varchar(200) DEFAULT NULL COMMENT '变更原因',
|
||||
`operator_name` varchar(100) DEFAULT NULL COMMENT '操作人', `change_time` datetime NOT NULL COMMENT '变更时间',
|
||||
PRIMARY KEY (`id`), KEY `idx_formal_settlement_change_bill` (`formal_settlement_id`),
|
||||
KEY `idx_formal_settlement_change_time` (`change_time`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='正式结算变更记录';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `blade_formal_settlement_source` (
|
||||
`id` bigint(20) NOT NULL, `tenant_id` varchar(12) NOT NULL DEFAULT '000000', `create_user` bigint(20) DEFAULT NULL,
|
||||
`create_dept` bigint(20) DEFAULT NULL, `create_time` datetime DEFAULT NULL, `update_user` bigint(20) DEFAULT NULL,
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
-- 正式结算详情增加变更记录模块。
|
||||
CREATE TABLE IF NOT EXISTS `blade_formal_settlement_change_record` (
|
||||
`id` bigint(20) NOT NULL COMMENT '主键',
|
||||
`tenant_id` varchar(12) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '000000' COMMENT '租户ID',
|
||||
`create_user` bigint(20) DEFAULT NULL COMMENT '创建人',
|
||||
`create_dept` bigint(20) DEFAULT NULL COMMENT '创建部门',
|
||||
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||
`update_user` bigint(20) DEFAULT NULL COMMENT '修改人',
|
||||
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
|
||||
`status` int(11) DEFAULT '1' COMMENT '状态',
|
||||
`is_deleted` int(11) DEFAULT '0' COMMENT '是否已删除',
|
||||
`formal_settlement_id` bigint(20) NOT NULL COMMENT '正式结算单ID',
|
||||
`change_type` varchar(50) COLLATE utf8mb4_general_ci NOT NULL COMMENT '变更类型',
|
||||
`line_no` int(11) DEFAULT NULL COMMENT '行号',
|
||||
`operation_type` varchar(30) COLLATE utf8mb4_general_ci NOT NULL COMMENT '操作类型',
|
||||
`change_content` text COLLATE utf8mb4_general_ci NOT NULL COMMENT '变更内容',
|
||||
`change_reason` varchar(200) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '变更原因',
|
||||
`operator_name` varchar(100) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '操作人',
|
||||
`change_time` datetime NOT NULL COMMENT '变更时间',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
KEY `idx_formal_settlement_change_bill` (`formal_settlement_id`) USING BTREE,
|
||||
KEY `idx_formal_settlement_change_time` (`change_time`) USING BTREE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='正式结算变更记录';
|
||||
@@ -0,0 +1,26 @@
|
||||
-- 正式结算单增加认领发票明细
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `blade_formal_settlement_invoice` (
|
||||
`id` bigint(20) NOT NULL COMMENT '主键',
|
||||
`tenant_id` varchar(12) NOT NULL DEFAULT '000000' COMMENT '租户ID',
|
||||
`create_user` bigint(20) DEFAULT NULL COMMENT '创建人',
|
||||
`create_dept` bigint(20) DEFAULT NULL COMMENT '创建部门',
|
||||
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||
`update_user` bigint(20) DEFAULT NULL COMMENT '修改人',
|
||||
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
|
||||
`status` int(11) DEFAULT '1' COMMENT '状态',
|
||||
`is_deleted` int(11) DEFAULT '0' COMMENT '是否删除',
|
||||
`formal_settlement_id` bigint(20) NOT NULL COMMENT '正式结算单ID',
|
||||
`line_no` int(11) NOT NULL COMMENT '行号',
|
||||
`invoice_no` varchar(32) NOT NULL COMMENT '发票号',
|
||||
`invoice_date` date DEFAULT NULL COMMENT '开票日期',
|
||||
`invoice_type` varchar(50) DEFAULT NULL COMMENT '发票类型',
|
||||
`tax_rate` decimal(8,4) DEFAULT NULL COMMENT '税率',
|
||||
`invoice_amount` decimal(18,2) NOT NULL DEFAULT '0.00' COMMENT '发票金额(含税)',
|
||||
`available_invoice_amount` decimal(18,2) NOT NULL DEFAULT '0.00' COMMENT '可匹配发票金额(含税)',
|
||||
`matched_amount` decimal(18,2) NOT NULL DEFAULT '0.00' COMMENT '匹配结算单金额(含税)',
|
||||
`attachment_json` longtext COMMENT '发票附件JSON',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_formal_settlement_invoice_no` (`tenant_id`,`formal_settlement_id`,`invoice_no`),
|
||||
KEY `idx_formal_settlement_invoice` (`formal_settlement_id`,`line_no`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='正式结算发票明细';
|
||||
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE `blade_payment_application`
|
||||
ADD KEY `idx_payment_application_project_quota` (`tenant_id`, `project_id`, `is_deleted`, `approval_status`),
|
||||
ADD KEY `idx_payment_application_payee_quota` (`tenant_id`, `payee_name`(100), `is_deleted`, `approval_status`);
|
||||
Reference in New Issue
Block a user