调整结算
This commit is contained in:
+15
@@ -0,0 +1,15 @@
|
|||||||
|
package org.springblade.transport.pojo.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/** 正式结算发票认领请求。 */
|
||||||
|
@Data
|
||||||
|
public class FormalSettlementInvoiceClaimRequest implements Serializable {
|
||||||
|
@Serial private static final long serialVersionUID = 1L;
|
||||||
|
private Long formalSettlementId;
|
||||||
|
private List<FormalSettlementSaveRequest.Invoice> invoices;
|
||||||
|
}
|
||||||
+6
@@ -47,6 +47,12 @@ public class PreSettlementChangeRecord extends TenantEntity {
|
|||||||
@Schema(description = "变更内容")
|
@Schema(description = "变更内容")
|
||||||
private String changeContent;
|
private String changeContent;
|
||||||
|
|
||||||
|
@Schema(description = "变更前数据JSON")
|
||||||
|
private String beforeData;
|
||||||
|
|
||||||
|
@Schema(description = "变更后数据JSON")
|
||||||
|
private String afterData;
|
||||||
|
|
||||||
@Schema(description = "操作人")
|
@Schema(description = "操作人")
|
||||||
private String operatorName;
|
private String operatorName;
|
||||||
|
|
||||||
|
|||||||
+9
@@ -22,6 +22,7 @@ import org.springblade.transport.pojo.dto.FormalSettlementSaveRequest;
|
|||||||
import org.springblade.transport.pojo.dto.FormalSettlementPaymentRequest;
|
import org.springblade.transport.pojo.dto.FormalSettlementPaymentRequest;
|
||||||
import org.springblade.transport.pojo.dto.FormalSettlementBatchPaymentRequest;
|
import org.springblade.transport.pojo.dto.FormalSettlementBatchPaymentRequest;
|
||||||
import org.springblade.transport.pojo.dto.FormalSettlementStatusRequest;
|
import org.springblade.transport.pojo.dto.FormalSettlementStatusRequest;
|
||||||
|
import org.springblade.transport.pojo.dto.FormalSettlementInvoiceClaimRequest;
|
||||||
import org.springblade.transport.pojo.dto.PreSettlementDetailAdjustRequest;
|
import org.springblade.transport.pojo.dto.PreSettlementDetailAdjustRequest;
|
||||||
import org.springblade.transport.pojo.entity.FormalSettlementDetailFee;
|
import org.springblade.transport.pojo.entity.FormalSettlementDetailFee;
|
||||||
import org.springblade.transport.pojo.vo.FormalSettlementVO;
|
import org.springblade.transport.pojo.vo.FormalSettlementVO;
|
||||||
@@ -169,6 +170,14 @@ public class FormalSettlementController extends BladeController {
|
|||||||
return R.data(formalSettlementService.applyPayments(request));
|
return R.data(formalSettlementService.applyPayments(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/claim-invoices")
|
||||||
|
@ApiOperationSupport(order = 18)
|
||||||
|
@Operation(summary = "认领发票并同步付款申请")
|
||||||
|
public R claimInvoices(@RequestBody FormalSettlementInvoiceClaimRequest request) {
|
||||||
|
formalSettlementService.claimInvoices(request);
|
||||||
|
return R.success("发票认领成功");
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping("/receipt-claims")
|
@GetMapping("/receipt-claims")
|
||||||
@ApiOperationSupport(order = 19)
|
@ApiOperationSupport(order = 19)
|
||||||
@Operation(summary = "应收正式结算单收款认领信息")
|
@Operation(summary = "应收正式结算单收款认领信息")
|
||||||
|
|||||||
+2
@@ -21,6 +21,7 @@ import org.springblade.transport.pojo.entity.FormalSettlementDetailFee;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.springblade.transport.pojo.dto.FormalSettlementPaymentRequest;
|
import org.springblade.transport.pojo.dto.FormalSettlementPaymentRequest;
|
||||||
import org.springblade.transport.pojo.dto.FormalSettlementBatchPaymentRequest;
|
import org.springblade.transport.pojo.dto.FormalSettlementBatchPaymentRequest;
|
||||||
|
import org.springblade.transport.pojo.dto.FormalSettlementInvoiceClaimRequest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 正式结算单服务
|
* 正式结算单服务
|
||||||
@@ -45,4 +46,5 @@ public interface IFormalSettlementService extends BaseService<FormalSettlement>
|
|||||||
void refreshPaymentSummariesForPreSettlement(Long preSettlementId);
|
void refreshPaymentSummariesForPreSettlement(Long preSettlementId);
|
||||||
String applyPayment(FormalSettlementPaymentRequest request);
|
String applyPayment(FormalSettlementPaymentRequest request);
|
||||||
List<String> applyPayments(FormalSettlementBatchPaymentRequest request);
|
List<String> applyPayments(FormalSettlementBatchPaymentRequest request);
|
||||||
|
void claimInvoices(FormalSettlementInvoiceClaimRequest request);
|
||||||
}
|
}
|
||||||
|
|||||||
+84
-5
@@ -32,6 +32,7 @@ import org.springblade.transport.mapper.PreSettlementDetailFeeMapper;
|
|||||||
import org.springblade.transport.mapper.PreSettlementMapper;
|
import org.springblade.transport.mapper.PreSettlementMapper;
|
||||||
import org.springblade.transport.mapper.PreSettlementSummaryFeeMapper;
|
import org.springblade.transport.mapper.PreSettlementSummaryFeeMapper;
|
||||||
import org.springblade.transport.mapper.PaymentApplicationMapper;
|
import org.springblade.transport.mapper.PaymentApplicationMapper;
|
||||||
|
import org.springblade.transport.mapper.PaymentApplicationInvoiceMapper;
|
||||||
import org.springblade.transport.mapper.PaymentApplicationSettlementMapper;
|
import org.springblade.transport.mapper.PaymentApplicationSettlementMapper;
|
||||||
import org.springblade.transport.mapper.ReceiptClaimSettlementMapper;
|
import org.springblade.transport.mapper.ReceiptClaimSettlementMapper;
|
||||||
import org.springblade.transport.mapper.ReceivablePayableDetailMapper;
|
import org.springblade.transport.mapper.ReceivablePayableDetailMapper;
|
||||||
@@ -40,6 +41,7 @@ import org.springblade.transport.mapper.SettlementAdjustmentMapper;
|
|||||||
import org.springblade.transport.pojo.dto.FormalSettlementSaveRequest;
|
import org.springblade.transport.pojo.dto.FormalSettlementSaveRequest;
|
||||||
import org.springblade.transport.pojo.dto.FormalSettlementPaymentRequest;
|
import org.springblade.transport.pojo.dto.FormalSettlementPaymentRequest;
|
||||||
import org.springblade.transport.pojo.dto.FormalSettlementBatchPaymentRequest;
|
import org.springblade.transport.pojo.dto.FormalSettlementBatchPaymentRequest;
|
||||||
|
import org.springblade.transport.pojo.dto.FormalSettlementInvoiceClaimRequest;
|
||||||
import org.springblade.transport.pojo.dto.FormalSettlementStatusRequest;
|
import org.springblade.transport.pojo.dto.FormalSettlementStatusRequest;
|
||||||
import org.springblade.transport.pojo.dto.PreSettlementDetailAdjustRequest;
|
import org.springblade.transport.pojo.dto.PreSettlementDetailAdjustRequest;
|
||||||
import org.springblade.transport.pojo.entity.FormalSettlement;
|
import org.springblade.transport.pojo.entity.FormalSettlement;
|
||||||
@@ -58,6 +60,7 @@ import org.springblade.transport.pojo.entity.PreSettlementDetail;
|
|||||||
import org.springblade.transport.pojo.entity.PreSettlementDetailFee;
|
import org.springblade.transport.pojo.entity.PreSettlementDetailFee;
|
||||||
import org.springblade.transport.pojo.entity.PreSettlementSummaryFee;
|
import org.springblade.transport.pojo.entity.PreSettlementSummaryFee;
|
||||||
import org.springblade.transport.pojo.entity.PaymentApplication;
|
import org.springblade.transport.pojo.entity.PaymentApplication;
|
||||||
|
import org.springblade.transport.pojo.entity.PaymentApplicationInvoice;
|
||||||
import org.springblade.transport.pojo.entity.PaymentApplicationSettlement;
|
import org.springblade.transport.pojo.entity.PaymentApplicationSettlement;
|
||||||
import org.springblade.transport.pojo.entity.ReceiptClaimSettlement;
|
import org.springblade.transport.pojo.entity.ReceiptClaimSettlement;
|
||||||
import org.springblade.transport.pojo.entity.ReceivablePayableDetail;
|
import org.springblade.transport.pojo.entity.ReceivablePayableDetail;
|
||||||
@@ -125,6 +128,7 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
|||||||
private final ReceivablePayableDetailMapper receivablePayableMapper;
|
private final ReceivablePayableDetailMapper receivablePayableMapper;
|
||||||
private final ReceivablePayableCargoFeeMapper receivablePayableCargoFeeMapper;
|
private final ReceivablePayableCargoFeeMapper receivablePayableCargoFeeMapper;
|
||||||
private final PaymentApplicationMapper paymentApplicationMapper;
|
private final PaymentApplicationMapper paymentApplicationMapper;
|
||||||
|
private final PaymentApplicationInvoiceMapper paymentApplicationInvoiceMapper;
|
||||||
private final PaymentApplicationSettlementMapper paymentApplicationSettlementMapper;
|
private final PaymentApplicationSettlementMapper paymentApplicationSettlementMapper;
|
||||||
private final ReceiptClaimSettlementMapper receiptClaimSettlementMapper;
|
private final ReceiptClaimSettlementMapper receiptClaimSettlementMapper;
|
||||||
private final SettlementAdjustmentMapper settlementAdjustmentMapper;
|
private final SettlementAdjustmentMapper settlementAdjustmentMapper;
|
||||||
@@ -458,6 +462,81 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
|||||||
return paymentNos;
|
return paymentNos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void claimInvoices(FormalSettlementInvoiceClaimRequest request) {
|
||||||
|
if (request == null || request.getFormalSettlementId() == null || Func.isEmpty(request.getInvoices())) {
|
||||||
|
throw new ServiceException("请选择需要认领的发票");
|
||||||
|
}
|
||||||
|
FormalSettlement settlement = existing(request.getFormalSettlementId());
|
||||||
|
List<FormalSettlementSaveRequest.Invoice> invoices = request.getInvoices();
|
||||||
|
Set<String> invoiceNumbers = new LinkedHashSet<>();
|
||||||
|
BigDecimal matchedTotal = BigDecimal.ZERO;
|
||||||
|
for (FormalSettlementSaveRequest.Invoice item : invoices) {
|
||||||
|
String invoiceNo = item == null ? "" : requiredText(item.getInvoiceNo(), "发票号");
|
||||||
|
if (!invoiceNumbers.add(invoiceNo)) throw new ServiceException("发票号" + invoiceNo + "重复");
|
||||||
|
matchedTotal = matchedTotal.add(money(item.getMatchedAmount()));
|
||||||
|
}
|
||||||
|
if (matchedTotal.compareTo(money(settlement.getSettlementAmount())) > 0) {
|
||||||
|
throw new ServiceException("发票匹配结算单金额合计不能超过结算金额");
|
||||||
|
}
|
||||||
|
List<FormalSettlementInvoice> existingInvoices = invoiceMapper.selectList(
|
||||||
|
Wrappers.<FormalSettlementInvoice>lambdaQuery().eq(FormalSettlementInvoice::getFormalSettlementId, settlement.getId()));
|
||||||
|
Set<String> existingNumbers = existingInvoices.stream().map(FormalSettlementInvoice::getInvoiceNo)
|
||||||
|
.filter(Objects::nonNull).collect(Collectors.toSet());
|
||||||
|
int lineNo = existingInvoices.stream().map(FormalSettlementInvoice::getLineNo).filter(Objects::nonNull)
|
||||||
|
.max(Integer::compareTo).orElse(0) + 1;
|
||||||
|
BigDecimal insertedMatchedTotal = BigDecimal.ZERO;
|
||||||
|
for (FormalSettlementSaveRequest.Invoice item : invoices) {
|
||||||
|
if (existingNumbers.contains(item.getInvoiceNo())) continue;
|
||||||
|
FormalSettlementInvoice invoice = new FormalSettlementInvoice();
|
||||||
|
invoice.setFormalSettlementId(settlement.getId()); invoice.setLineNo(lineNo++);
|
||||||
|
invoice.setInvoiceNo(item.getInvoiceNo()); invoice.setInvoiceDate(item.getInvoiceDate());
|
||||||
|
invoice.setInvoiceType(item.getInvoiceType()); invoice.setTaxRate(item.getTaxRate());
|
||||||
|
invoice.setInvoiceAmount(money(item.getInvoiceAmount()));
|
||||||
|
invoice.setAvailableInvoiceAmount(money(item.getAvailableInvoiceAmount()));
|
||||||
|
invoice.setMatchedAmount(money(item.getMatchedAmount())); invoice.setAttachmentJson(item.getAttachmentJson());
|
||||||
|
invoiceMapper.insert(invoice);
|
||||||
|
insertedMatchedTotal = insertedMatchedTotal.add(money(item.getMatchedAmount()));
|
||||||
|
}
|
||||||
|
List<PaymentApplicationSettlement> relations = paymentApplicationSettlementMapper.selectList(
|
||||||
|
Wrappers.<PaymentApplicationSettlement>lambdaQuery().eq(PaymentApplicationSettlement::getFormalSettlementId, settlement.getId())
|
||||||
|
.eq(PaymentApplicationSettlement::getIsDeleted, 0));
|
||||||
|
Set<Long> paymentApplicationIds = new LinkedHashSet<>(relations.stream()
|
||||||
|
.map(PaymentApplicationSettlement::getPaymentApplicationId).filter(Objects::nonNull).toList());
|
||||||
|
paymentApplicationIds.addAll(paymentApplicationMapper.selectList(Wrappers.<PaymentApplication>lambdaQuery()
|
||||||
|
.eq(PaymentApplication::getSettlementId, settlement.getId()).eq(PaymentApplication::getIsDeleted, 0))
|
||||||
|
.stream().map(PaymentApplication::getId).toList());
|
||||||
|
for (Long paymentApplicationId : paymentApplicationIds) {
|
||||||
|
List<PaymentApplicationInvoice> old = paymentApplicationInvoiceMapper.selectList(
|
||||||
|
Wrappers.<PaymentApplicationInvoice>lambdaQuery().eq(PaymentApplicationInvoice::getPaymentApplicationId, paymentApplicationId));
|
||||||
|
Set<String> nums = old.stream().map(PaymentApplicationInvoice::getInvoiceNo).filter(Objects::nonNull).collect(Collectors.toSet());
|
||||||
|
BigDecimal paymentMatchedTotal = old.stream().map(PaymentApplicationInvoice::getMatchedAmount).map(this::money)
|
||||||
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
|
int paymentLine = old.stream().map(PaymentApplicationInvoice::getLineNo).filter(Objects::nonNull).max(Integer::compareTo).orElse(0) + 1;
|
||||||
|
for (FormalSettlementSaveRequest.Invoice item : invoices) {
|
||||||
|
if (nums.contains(item.getInvoiceNo())) continue;
|
||||||
|
PaymentApplicationInvoice invoice = new PaymentApplicationInvoice();
|
||||||
|
invoice.setPaymentApplicationId(paymentApplicationId); invoice.setLineNo(paymentLine++);
|
||||||
|
invoice.setSettlementNo(settlement.getFormalSettlementNo()); invoice.setInvoiceNo(item.getInvoiceNo());
|
||||||
|
invoice.setInvoiceDate(item.getInvoiceDate()); invoice.setInvoiceType(item.getInvoiceType());
|
||||||
|
invoice.setTaxRate(item.getTaxRate()); invoice.setInvoiceAmount(money(item.getInvoiceAmount()));
|
||||||
|
invoice.setMatchedAmount(money(item.getMatchedAmount())); invoice.setAttachmentJson(item.getAttachmentJson());
|
||||||
|
paymentApplicationInvoiceMapper.insert(invoice);
|
||||||
|
paymentMatchedTotal = paymentMatchedTotal.add(money(item.getMatchedAmount()));
|
||||||
|
}
|
||||||
|
PaymentApplication payment = paymentApplicationMapper.selectById(paymentApplicationId);
|
||||||
|
if (payment != null) {
|
||||||
|
payment.setMatchedInvoiceAmount(paymentMatchedTotal);
|
||||||
|
payment.setInvoiceStatus(paymentMatchedTotal.compareTo(BigDecimal.ZERO) > 0 ? "matched" : "unmatched");
|
||||||
|
paymentApplicationMapper.updateById(payment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
settlement.setInvoiceAmount(money(settlement.getInvoiceAmount()).add(insertedMatchedTotal));
|
||||||
|
settlement.setInvoiceStatus(invoiceStatus(settlement.getInvoiceAmount(), settlement.getSettlementAmount()));
|
||||||
|
updateById(settlement);
|
||||||
|
}
|
||||||
|
|
||||||
private String createPayment(FormalSettlement settlement, BigDecimal appliedAmount, String remark) {
|
private String createPayment(FormalSettlement settlement, BigDecimal appliedAmount, String remark) {
|
||||||
if (!APPROVED.equals(settlement.getApprovalStatus())) throw new ServiceException("仅审批通过的正式结算单允许发起付款申请");
|
if (!APPROVED.equals(settlement.getApprovalStatus())) throw new ServiceException("仅审批通过的正式结算单允许发起付款申请");
|
||||||
if (!"payable".equals(settlement.getSettlementType())) throw new ServiceException("仅应付正式结算单允许发起付款申请");
|
if (!"payable".equals(settlement.getSettlementType())) throw new ServiceException("仅应付正式结算单允许发起付款申请");
|
||||||
@@ -808,8 +887,8 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
|||||||
settlement.setSettlementAmount(amount);
|
settlement.setSettlementAmount(amount);
|
||||||
settlement.setLocalSettlementAmount(amount.multiply(
|
settlement.setLocalSettlementAmount(amount.multiply(
|
||||||
settlement.getExchangeRate() == null ? BigDecimal.ONE : settlement.getExchangeRate()));
|
settlement.getExchangeRate() == null ? BigDecimal.ONE : settlement.getExchangeRate()));
|
||||||
settlement.setRemainingPayableAmount(amount.subtract(money(settlement.getAppliedPaymentAmount()))
|
settlement.setRemainingPayableAmount(amount.subtract(money(settlement.getPaidAmount()))
|
||||||
.subtract(money(settlement.getPaidAmount())).max(BigDecimal.ZERO));
|
.max(BigDecimal.ZERO));
|
||||||
updateById(settlement);
|
updateById(settlement);
|
||||||
refreshPaymentSummary(settlement.getId());
|
refreshPaymentSummary(settlement.getId());
|
||||||
}
|
}
|
||||||
@@ -822,7 +901,7 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
|||||||
settlement.setAppliedPaymentAmount(summary.appliedAmount());
|
settlement.setAppliedPaymentAmount(summary.appliedAmount());
|
||||||
settlement.setPaidAmount(summary.paidAmount());
|
settlement.setPaidAmount(summary.paidAmount());
|
||||||
settlement.setRemainingPayableAmount(money(settlement.getSettlementAmount())
|
settlement.setRemainingPayableAmount(money(settlement.getSettlementAmount())
|
||||||
.subtract(summary.appliedAmount()).subtract(summary.paidAmount()).max(BigDecimal.ZERO));
|
.subtract(summary.paidAmount()).max(BigDecimal.ZERO));
|
||||||
settlement.setPaymentStatus(paymentStatus(summary.paidAmount(), settlement.getSettlementAmount()));
|
settlement.setPaymentStatus(paymentStatus(summary.paidAmount(), settlement.getSettlementAmount()));
|
||||||
updateById(settlement);
|
updateById(settlement);
|
||||||
}
|
}
|
||||||
@@ -1024,8 +1103,8 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
|||||||
PaymentSummary summary = calculatePaymentSummary(entity);
|
PaymentSummary summary = calculatePaymentSummary(entity);
|
||||||
vo.setAppliedPaymentAmount(summary.appliedAmount());
|
vo.setAppliedPaymentAmount(summary.appliedAmount());
|
||||||
vo.setPaidAmount(summary.paidAmount());
|
vo.setPaidAmount(summary.paidAmount());
|
||||||
vo.setRemainingPayableAmount(money(entity.getSettlementAmount()).subtract(summary.appliedAmount())
|
vo.setRemainingPayableAmount(money(entity.getSettlementAmount()).subtract(summary.paidAmount())
|
||||||
.subtract(summary.paidAmount()).max(BigDecimal.ZERO));
|
.max(BigDecimal.ZERO));
|
||||||
vo.setPreSettlementNos(sourceMapper.selectList(Wrappers.<FormalSettlementSource>lambdaQuery().eq(FormalSettlementSource::getFormalSettlementId, entity.getId())).stream().map(FormalSettlementSource::getPreSettlementNo).collect(Collectors.joining(",")));
|
vo.setPreSettlementNos(sourceMapper.selectList(Wrappers.<FormalSettlementSource>lambdaQuery().eq(FormalSettlementSource::getFormalSettlementId, entity.getId())).stream().map(FormalSettlementSource::getPreSettlementNo).collect(Collectors.joining(",")));
|
||||||
return vo;
|
return vo;
|
||||||
}
|
}
|
||||||
|
|||||||
+40
-9
@@ -605,6 +605,8 @@ public class PreSettlementServiceImpl extends BaseServiceImpl<PreSettlementMappe
|
|||||||
throw new ServiceException("费用调整行数据不完整");
|
throw new ServiceException("费用调整行数据不完整");
|
||||||
}
|
}
|
||||||
List<String> changes = new ArrayList<>();
|
List<String> changes = new ArrayList<>();
|
||||||
|
Map<String, Object> beforeData = new LinkedHashMap<>();
|
||||||
|
Map<String, Object> afterData = new LinkedHashMap<>();
|
||||||
for (PreSettlementDetailAdjustRequest.FeeRow requestRow : request.getRows()) {
|
for (PreSettlementDetailAdjustRequest.FeeRow requestRow : request.getRows()) {
|
||||||
PreSettlementDetailFee fee = existingMap.get(requestRow.getId());
|
PreSettlementDetailFee fee = existingMap.get(requestRow.getId());
|
||||||
if (fee == null) {
|
if (fee == null) {
|
||||||
@@ -632,19 +634,19 @@ public class PreSettlementServiceImpl extends BaseServiceImpl<PreSettlementMappe
|
|||||||
fee.setRemark(limitRemark(requestRow.getRemark(), 200));
|
fee.setRemark(limitRemark(requestRow.getRemark(), 200));
|
||||||
detailFeeMapper.updateById(fee);
|
detailFeeMapper.updateById(fee);
|
||||||
String prefix = "【" + firstNotEmpty(fee.getCargoName(), fee.getLineNo()) + "】";
|
String prefix = "【" + firstNotEmpty(fee.getCargoName(), fee.getLineNo()) + "】";
|
||||||
appendChange(changes, prefix + "运输总量", beforeQuantity, fee.getTransportQuantity());
|
appendChange(changes, beforeData, afterData, prefix + "运输总量", beforeQuantity, fee.getTransportQuantity());
|
||||||
appendChange(changes, prefix + "里程", beforeMileage, fee.getMileage());
|
appendChange(changes, beforeData, afterData, prefix + "里程", beforeMileage, fee.getMileage());
|
||||||
appendChange(changes, prefix + "运输单价", beforeUnitPrice, fee.getUnitPrice());
|
appendChange(changes, beforeData, afterData, prefix + "运输单价", beforeUnitPrice, fee.getUnitPrice());
|
||||||
appendChange(changes, prefix + "运费", beforeFreight, fee.getFreightAmount());
|
appendChange(changes, beforeData, afterData, prefix + "运费", beforeFreight, fee.getFreightAmount());
|
||||||
Map<String, BigDecimal> afterFeeItems = parseFeeItems(fee.getFeeItemsJson());
|
Map<String, BigDecimal> afterFeeItems = parseFeeItems(fee.getFeeItemsJson());
|
||||||
Set<String> feeItemNames = new LinkedHashSet<>(beforeFeeItems.keySet());
|
Set<String> feeItemNames = new LinkedHashSet<>(beforeFeeItems.keySet());
|
||||||
feeItemNames.addAll(afterFeeItems.keySet());
|
feeItemNames.addAll(afterFeeItems.keySet());
|
||||||
feeItemNames.forEach(name -> appendChange(changes, prefix + name,
|
feeItemNames.forEach(name -> appendChange(changes, beforeData, afterData, prefix + name,
|
||||||
beforeFeeItems.get(name), afterFeeItems.get(name)));
|
beforeFeeItems.get(name), afterFeeItems.get(name)));
|
||||||
appendChange(changes, prefix + "结算金额(含税)", beforeAmount, afterAmount);
|
appendChange(changes, beforeData, afterData, prefix + "结算金额(含税)", beforeAmount, afterAmount);
|
||||||
appendChange(changes, prefix + "结算金额(不含税)", beforeNoTaxAmount,
|
appendChange(changes, beforeData, afterData, prefix + "结算金额(不含税)", beforeNoTaxAmount,
|
||||||
fee.getSettlementAmountNoTax());
|
fee.getSettlementAmountNoTax());
|
||||||
appendTextChange(changes, prefix + "备注", beforeRemark, fee.getRemark());
|
appendTextChange(changes, beforeData, afterData, prefix + "备注", beforeRemark, fee.getRemark());
|
||||||
}
|
}
|
||||||
if (changes.isEmpty()) {
|
if (changes.isEmpty()) {
|
||||||
throw new ServiceException("未修改任何结算明细费用");
|
throw new ServiceException("未修改任何结算明细费用");
|
||||||
@@ -653,7 +655,7 @@ public class PreSettlementServiceImpl extends BaseServiceImpl<PreSettlementMappe
|
|||||||
rebuildSummaryFees(settlement.getId(), true);
|
rebuildSummaryFees(settlement.getId(), true);
|
||||||
refreshSettlementAmount(settlement);
|
refreshSettlementAmount(settlement);
|
||||||
saveChange(settlement.getId(), "结算明细项", detail.getLineNo(), "调整",
|
saveChange(settlement.getId(), "结算明细项", detail.getLineNo(), "调整",
|
||||||
String.join(";", changes), changeReason);
|
String.join(";", changes), changeReason, beforeData, afterData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -1313,12 +1315,19 @@ public class PreSettlementServiceImpl extends BaseServiceImpl<PreSettlementMappe
|
|||||||
|
|
||||||
private void saveChange(Long settlementId, String changeType, Integer lineNo, String operationType,
|
private void saveChange(Long settlementId, String changeType, Integer lineNo, String operationType,
|
||||||
String content, String reason) {
|
String content, String reason) {
|
||||||
|
saveChange(settlementId, changeType, lineNo, operationType, content, reason, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveChange(Long settlementId, String changeType, Integer lineNo, String operationType,
|
||||||
|
String content, String reason, Map<String, Object> beforeData, Map<String, Object> afterData) {
|
||||||
PreSettlementChangeRecord record = new PreSettlementChangeRecord();
|
PreSettlementChangeRecord record = new PreSettlementChangeRecord();
|
||||||
record.setPreSettlementId(settlementId);
|
record.setPreSettlementId(settlementId);
|
||||||
record.setChangeType(changeType);
|
record.setChangeType(changeType);
|
||||||
record.setLineNo(lineNo);
|
record.setLineNo(lineNo);
|
||||||
record.setOperationType(operationType);
|
record.setOperationType(operationType);
|
||||||
record.setChangeContent(content);
|
record.setChangeContent(content);
|
||||||
|
record.setBeforeData(beforeData == null ? null : JsonUtil.toJson(beforeData));
|
||||||
|
record.setAfterData(afterData == null ? null : JsonUtil.toJson(afterData));
|
||||||
record.setOperatorName(Func.isEmpty(AuthUtil.getUserName()) ? "system" : AuthUtil.getUserName());
|
record.setOperatorName(Func.isEmpty(AuthUtil.getUserName()) ? "system" : AuthUtil.getUserName());
|
||||||
record.setChangeReason(reason);
|
record.setChangeReason(reason);
|
||||||
record.setChangeTime(LocalDateTime.now());
|
record.setChangeTime(LocalDateTime.now());
|
||||||
@@ -1476,6 +1485,17 @@ public class PreSettlementServiceImpl extends BaseServiceImpl<PreSettlementMappe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void appendChange(List<String> changes, Map<String, Object> beforeData, Map<String, Object> afterData,
|
||||||
|
String fieldName, BigDecimal before, BigDecimal after) {
|
||||||
|
BigDecimal oldValue = money(before);
|
||||||
|
BigDecimal newValue = money(after);
|
||||||
|
if (oldValue.compareTo(newValue) != 0) {
|
||||||
|
changes.add("【" + fieldName + "】从【" + oldValue + "】调整为【" + newValue + "】");
|
||||||
|
beforeData.put(fieldName, before);
|
||||||
|
afterData.put(fieldName, after);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void appendTextChange(List<String> changes, String fieldName, String before, String after) {
|
private void appendTextChange(List<String> changes, String fieldName, String before, String after) {
|
||||||
String oldValue = before == null ? "" : before;
|
String oldValue = before == null ? "" : before;
|
||||||
String newValue = after == null ? "" : after;
|
String newValue = after == null ? "" : after;
|
||||||
@@ -1484,6 +1504,17 @@ public class PreSettlementServiceImpl extends BaseServiceImpl<PreSettlementMappe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void appendTextChange(List<String> changes, Map<String, Object> beforeData, Map<String, Object> afterData,
|
||||||
|
String fieldName, String before, String after) {
|
||||||
|
String oldValue = before == null ? "" : before;
|
||||||
|
String newValue = after == null ? "" : after;
|
||||||
|
if (!Objects.equals(oldValue, newValue)) {
|
||||||
|
changes.add("【" + fieldName + "】从【" + oldValue + "】调整为【" + newValue + "】");
|
||||||
|
beforeData.put(fieldName, before);
|
||||||
|
afterData.put(fieldName, after);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private String firstNotEmpty(String first, String second) {
|
private String firstNotEmpty(String first, String second) {
|
||||||
return Func.isNotEmpty(first) ? first : second;
|
return Func.isNotEmpty(first) ? first : second;
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-1
@@ -1447,7 +1447,25 @@ public class ReceivablePayableDetailServiceImpl
|
|||||||
fee.setBillingType(stringValue(rule, "billingType", ""));
|
fee.setBillingType(stringValue(rule, "billingType", ""));
|
||||||
fee.setTransportQuantity(measure(rule, feeWaybill));
|
fee.setTransportQuantity(measure(rule, feeWaybill));
|
||||||
fee.setPriceUnit(stringValue(rule, "billingUnit", feeWaybill.getPriceUnit()));
|
fee.setPriceUnit(stringValue(rule, "billingUnit", feeWaybill.getPriceUnit()));
|
||||||
fee.setUnitPrice(decimal(rule.get("unitPrice")));
|
fee.setUnitPrice(resolveCalculatedUnitPrice(rule, feeWaybill));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析费用行展示用的实际命中单价。
|
||||||
|
* 区间计费的规则默认单价仅用于兜底,费用行应展示当前计费量命中的区间单价。
|
||||||
|
*/
|
||||||
|
private BigDecimal resolveCalculatedUnitPrice(Map<String, Object> rule, Waybill waybill) {
|
||||||
|
BigDecimal defaultUnitPrice = decimal(rule.get("unitPrice"));
|
||||||
|
String billingType = stringValue(rule, "billingType", "");
|
||||||
|
if (!"区间单价".equals(billingType) && !"区间阶梯一口价".equals(billingType)) {
|
||||||
|
return defaultUnitPrice;
|
||||||
|
}
|
||||||
|
Optional<Map<String, Object>> matchedRange = range(ranges(rule), measure(rule, waybill));
|
||||||
|
if (matchedRange.isEmpty()) {
|
||||||
|
return defaultUnitPrice;
|
||||||
|
}
|
||||||
|
BigDecimal rangeUnitPrice = decimal(matchedRange.get().get("unitPrice"));
|
||||||
|
return rangeUnitPrice.signum() == 0 ? defaultUnitPrice : rangeUnitPrice;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<String> cargoFeeKey(Waybill waybill, Map<String, String> feeGoods) {
|
private List<String> cargoFeeKey(Waybill waybill, Map<String, String> feeGoods) {
|
||||||
|
|||||||
+2
-2
@@ -255,8 +255,8 @@ public class SettlementAdjustmentServiceImpl extends BaseServiceImpl<SettlementA
|
|||||||
BigDecimal amount = money(formal.getSettlementAmount()).add(money(adjustment.getAdjustmentAmount()));
|
BigDecimal amount = money(formal.getSettlementAmount()).add(money(adjustment.getAdjustmentAmount()));
|
||||||
formal.setSettlementAmount(amount);
|
formal.setSettlementAmount(amount);
|
||||||
formal.setLocalSettlementAmount(amount.multiply(formal.getExchangeRate() == null ? BigDecimal.ONE : formal.getExchangeRate()));
|
formal.setLocalSettlementAmount(amount.multiply(formal.getExchangeRate() == null ? BigDecimal.ONE : formal.getExchangeRate()));
|
||||||
formal.setRemainingPayableAmount(amount.subtract(money(formal.getAppliedPaymentAmount()))
|
formal.setRemainingPayableAmount(amount.subtract(money(formal.getPaidAmount()))
|
||||||
.subtract(money(formal.getPaidAmount())).max(BigDecimal.ZERO));
|
.max(BigDecimal.ZERO));
|
||||||
formalMapper.updateById(formal);
|
formalMapper.updateById(formal);
|
||||||
saveFormalChange(formal.getId(), "合计费用项", null, "调整",
|
saveFormalChange(formal.getId(), "合计费用项", null, "调整",
|
||||||
"调整单" + adjustment.getAdjustmentNo() + "调整金额【" + money(adjustment.getAdjustmentAmount()) + "】",
|
"调整单" + adjustment.getAdjustmentNo() + "调整金额【" + money(adjustment.getAdjustmentAmount()) + "】",
|
||||||
|
|||||||
+1
-2
@@ -32,9 +32,8 @@ public class FormalSettlementWrapper extends BaseEntityWrapper<FormalSettlement,
|
|||||||
public FormalSettlementVO entityVO(FormalSettlement entity) {
|
public FormalSettlementVO entityVO(FormalSettlement entity) {
|
||||||
FormalSettlementVO vo = Objects.requireNonNull(BeanUtil.copyProperties(entity, FormalSettlementVO.class));
|
FormalSettlementVO vo = Objects.requireNonNull(BeanUtil.copyProperties(entity, FormalSettlementVO.class));
|
||||||
BigDecimal settlementAmount = entity.getSettlementAmount() == null ? BigDecimal.ZERO : entity.getSettlementAmount();
|
BigDecimal settlementAmount = entity.getSettlementAmount() == null ? BigDecimal.ZERO : entity.getSettlementAmount();
|
||||||
BigDecimal appliedPaymentAmount = entity.getAppliedPaymentAmount() == null ? BigDecimal.ZERO : entity.getAppliedPaymentAmount();
|
|
||||||
BigDecimal paidAmount = entity.getPaidAmount() == null ? BigDecimal.ZERO : entity.getPaidAmount();
|
BigDecimal paidAmount = entity.getPaidAmount() == null ? BigDecimal.ZERO : entity.getPaidAmount();
|
||||||
vo.setRemainingPayableAmount(settlementAmount.subtract(appliedPaymentAmount).subtract(paidAmount).max(BigDecimal.ZERO));
|
vo.setRemainingPayableAmount(settlementAmount.subtract(paidAmount).max(BigDecimal.ZERO));
|
||||||
vo.setInvoiceAmount(entity.getInvoiceAmount() == null ? BigDecimal.ZERO : entity.getInvoiceAmount());
|
vo.setInvoiceAmount(entity.getInvoiceAmount() == null ? BigDecimal.ZERO : entity.getInvoiceAmount());
|
||||||
vo.setCreateUserName(UserCache.getUserRealName(entity.getCreateUser()));
|
vo.setCreateUserName(UserCache.getUserRealName(entity.getCreateUser()));
|
||||||
vo.setSettlementTypeName("receivable".equals(entity.getSettlementType()) ? "应收" : "应付");
|
vo.setSettlementTypeName("receivable".equals(entity.getSettlementType()) ? "应收" : "应付");
|
||||||
|
|||||||
@@ -182,6 +182,8 @@ CREATE TABLE IF NOT EXISTS `blade_pre_settlement_change_record` (
|
|||||||
`line_no` int(11) DEFAULT NULL COMMENT '行号',
|
`line_no` int(11) DEFAULT NULL COMMENT '行号',
|
||||||
`operation_type` varchar(30) COLLATE utf8mb4_general_ci NOT NULL COMMENT '操作类型',
|
`operation_type` varchar(30) COLLATE utf8mb4_general_ci NOT NULL COMMENT '操作类型',
|
||||||
`change_content` text COLLATE utf8mb4_general_ci NOT NULL COMMENT '变更内容',
|
`change_content` text COLLATE utf8mb4_general_ci NOT NULL COMMENT '变更内容',
|
||||||
|
`before_data` longtext COLLATE utf8mb4_general_ci COMMENT '变更前数据JSON',
|
||||||
|
`after_data` longtext COLLATE utf8mb4_general_ci COMMENT '变更后数据JSON',
|
||||||
`operator_name` varchar(100) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '操作人',
|
`operator_name` varchar(100) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '操作人',
|
||||||
`change_reason` varchar(200) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '变更原因',
|
`change_reason` varchar(200) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '变更原因',
|
||||||
`change_time` datetime NOT NULL COMMENT '变更时间',
|
`change_time` datetime NOT NULL COMMENT '变更时间',
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
-- 预结算变更记录补充前后值明细,供调整弹窗“查看详情”展示。
|
||||||
|
-- 兼容 MySQL 5.7(ADD COLUMN 不支持 IF NOT EXISTS),并支持重复执行。
|
||||||
|
SET @before_data_exists := (
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM information_schema.COLUMNS
|
||||||
|
WHERE TABLE_SCHEMA = DATABASE()
|
||||||
|
AND TABLE_NAME = 'blade_pre_settlement_change_record'
|
||||||
|
AND COLUMN_NAME = 'before_data'
|
||||||
|
);
|
||||||
|
SET @before_data_sql := IF(
|
||||||
|
@before_data_exists = 0,
|
||||||
|
'ALTER TABLE `blade_pre_settlement_change_record` ADD COLUMN `before_data` longtext COLLATE utf8mb4_general_ci COMMENT ''变更前数据JSON'' AFTER `change_content`',
|
||||||
|
'SELECT 1'
|
||||||
|
);
|
||||||
|
PREPARE before_data_stmt FROM @before_data_sql;
|
||||||
|
EXECUTE before_data_stmt;
|
||||||
|
DEALLOCATE PREPARE before_data_stmt;
|
||||||
|
|
||||||
|
SET @after_data_exists := (
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM information_schema.COLUMNS
|
||||||
|
WHERE TABLE_SCHEMA = DATABASE()
|
||||||
|
AND TABLE_NAME = 'blade_pre_settlement_change_record'
|
||||||
|
AND COLUMN_NAME = 'after_data'
|
||||||
|
);
|
||||||
|
SET @after_data_sql := IF(
|
||||||
|
@after_data_exists = 0,
|
||||||
|
'ALTER TABLE `blade_pre_settlement_change_record` ADD COLUMN `after_data` longtext COLLATE utf8mb4_general_ci COMMENT ''变更后数据JSON'' AFTER `before_data`',
|
||||||
|
'SELECT 1'
|
||||||
|
);
|
||||||
|
PREPARE after_data_stmt FROM @after_data_sql;
|
||||||
|
EXECUTE after_data_stmt;
|
||||||
|
DEALLOCATE PREPARE after_data_stmt;
|
||||||
Reference in New Issue
Block a user