✨ 结算付款与汇票校验优化,完善变更记录与菜单拆分
付款可付款占用、汇票仅可选未到期收票、正式结算计费方式与金蝶同步、导入运单删除校验,并补充结算菜单与变更明细 SQL。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+1
-1
@@ -33,7 +33,7 @@ public class PreSettlementDetailAdjustRequest implements Serializable {
|
|||||||
@Schema(description = "预结算明细ID")
|
@Schema(description = "预结算明细ID")
|
||||||
private Long detailId;
|
private Long detailId;
|
||||||
|
|
||||||
@Schema(description = "调整原因")
|
@Schema(description = "备注(写入结算明细备注,非必填)")
|
||||||
private String changeReason;
|
private String changeReason;
|
||||||
|
|
||||||
@Schema(description = "明细费用行")
|
@Schema(description = "明细费用行")
|
||||||
|
|||||||
+4
@@ -25,6 +25,10 @@ public class FormalSettlementChangeRecord extends TenantEntity {
|
|||||||
private Integer lineNo;
|
private Integer lineNo;
|
||||||
private String operationType;
|
private String operationType;
|
||||||
private String changeContent;
|
private String changeContent;
|
||||||
|
/** 变更前数据JSON */
|
||||||
|
private String beforeData;
|
||||||
|
/** 变更后数据JSON */
|
||||||
|
private String afterData;
|
||||||
private String changeReason;
|
private String changeReason;
|
||||||
private String operatorName;
|
private String operatorName;
|
||||||
private LocalDateTime changeTime;
|
private LocalDateTime changeTime;
|
||||||
|
|||||||
+8
@@ -8,7 +8,9 @@
|
|||||||
*/
|
*/
|
||||||
package org.springblade.transport.pojo.entity;
|
package org.springblade.transport.pojo.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import org.springblade.core.tenant.mp.TenantEntity;
|
import org.springblade.core.tenant.mp.TenantEntity;
|
||||||
@@ -123,6 +125,12 @@ public class FormalSettlementDetail extends TenantEntity {
|
|||||||
* 批次号
|
* 批次号
|
||||||
*/
|
*/
|
||||||
private String batchNo;
|
private String batchNo;
|
||||||
|
/**
|
||||||
|
* 计费方式(来源应收应付货物费用计费类型,非本表字段)
|
||||||
|
*/
|
||||||
|
@TableField(exist = false)
|
||||||
|
@Schema(description = "计费方式")
|
||||||
|
private String billingType;
|
||||||
/**
|
/**
|
||||||
* 运输单价
|
* 运输单价
|
||||||
*/
|
*/
|
||||||
|
|||||||
+8
@@ -8,7 +8,9 @@
|
|||||||
*/
|
*/
|
||||||
package org.springblade.transport.pojo.entity;
|
package org.springblade.transport.pojo.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import org.springblade.core.tenant.mp.TenantEntity;
|
import org.springblade.core.tenant.mp.TenantEntity;
|
||||||
@@ -70,6 +72,12 @@ public class FormalSettlementDetailFee extends TenantEntity {
|
|||||||
* 费用项JSON
|
* 费用项JSON
|
||||||
*/
|
*/
|
||||||
private String feeItemsJson;
|
private String feeItemsJson;
|
||||||
|
/**
|
||||||
|
* 命中计费规则JSON(来源费用带回,非本表字段)
|
||||||
|
*/
|
||||||
|
@TableField(exist = false)
|
||||||
|
@Schema(description = "命中计费规则JSON")
|
||||||
|
private String billingRulesJson;
|
||||||
/**
|
/**
|
||||||
* 原金额
|
* 原金额
|
||||||
*/
|
*/
|
||||||
|
|||||||
+2
@@ -27,4 +27,6 @@ public class PaymentApplicationReferenceAmountVO implements Serializable {
|
|||||||
@Schema(description = "结算金额") private BigDecimal settlementAmount;
|
@Schema(description = "结算金额") private BigDecimal settlementAmount;
|
||||||
@Schema(description = "累计申请付款金额") private BigDecimal cumulativeAppliedAmount;
|
@Schema(description = "累计申请付款金额") private BigDecimal cumulativeAppliedAmount;
|
||||||
@Schema(description = "可付款金额") private BigDecimal payableAmount;
|
@Schema(description = "可付款金额") private BigDecimal payableAmount;
|
||||||
|
/** 该结算单当前为第几次付款(含本次,已作废不计) */
|
||||||
|
@Schema(description = "付款次序") private Integer paymentSequence;
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-1
@@ -104,12 +104,17 @@ public class BillLedgerServiceImpl extends BaseServiceImpl<BillLedgerMapper, Bil
|
|||||||
}
|
}
|
||||||
|
|
||||||
private List<BillLedgerVO> availableList(String keyword, Long deptId, Long selectedId) {
|
private List<BillLedgerVO> availableList(String keyword, Long deptId, Long selectedId) {
|
||||||
|
LocalDate today = LocalDate.now();
|
||||||
|
// 付款申请仅可选:收票类型、未到期、有可用余额;已选中的汇票始终带回以便回显
|
||||||
return list(Wrappers.<BillLedger>lambdaQuery()
|
return list(Wrappers.<BillLedger>lambdaQuery()
|
||||||
.and(Func.isNotEmpty(keyword), wrapper -> wrapper.like(BillLedger::getBillNo, keyword)
|
.and(Func.isNotEmpty(keyword), wrapper -> wrapper.like(BillLedger::getBillNo, keyword)
|
||||||
.or().like(BillLedger::getIssuerName, keyword)
|
.or().like(BillLedger::getIssuerName, keyword)
|
||||||
.or().like(BillLedger::getReceiverName, keyword))
|
.or().like(BillLedger::getReceiverName, keyword))
|
||||||
.and(wrapper -> wrapper
|
.and(wrapper -> wrapper
|
||||||
.gt(BillLedger::getAvailableBalance, BigDecimal.ZERO)
|
.and(available -> available
|
||||||
|
.eq(BillLedger::getBillType, "received")
|
||||||
|
.ge(BillLedger::getMaturityDate, today)
|
||||||
|
.gt(BillLedger::getAvailableBalance, BigDecimal.ZERO))
|
||||||
.or(selectedId != null, child -> child.eq(BillLedger::getId, selectedId)))
|
.or(selectedId != null, child -> child.eq(BillLedger::getId, selectedId)))
|
||||||
.orderByAsc(BillLedger::getMaturityDate)
|
.orderByAsc(BillLedger::getMaturityDate)
|
||||||
.orderByDesc(BillLedger::getCreateTime)).stream()
|
.orderByDesc(BillLedger::getCreateTime)).stream()
|
||||||
|
|||||||
+174
-9
@@ -315,6 +315,7 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
|||||||
.eq(FormalSettlementDetail::getFormalSettlementId, id).orderByAsc(FormalSettlementDetail::getLineNo));
|
.eq(FormalSettlementDetail::getFormalSettlementId, id).orderByAsc(FormalSettlementDetail::getLineNo));
|
||||||
fillDetailWaybillAddresses(details);
|
fillDetailWaybillAddresses(details);
|
||||||
fillDetailCargoNames(details);
|
fillDetailCargoNames(details);
|
||||||
|
fillDetailBillingTypes(details);
|
||||||
vo.setDetails(details);
|
vo.setDetails(details);
|
||||||
vo.setSummaryFees(listSummaryFees(id));
|
vo.setSummaryFees(listSummaryFees(id));
|
||||||
vo.setPayments(paymentMapper.selectList(Wrappers.<FormalSettlementPayment>lambdaQuery()
|
vo.setPayments(paymentMapper.selectList(Wrappers.<FormalSettlementPayment>lambdaQuery()
|
||||||
@@ -352,6 +353,36 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
|||||||
return vo;
|
return vo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 明细展示计费方式:按来源应收应付货物费用的计费类型汇总(去重后顿号拼接)。
|
||||||
|
*/
|
||||||
|
private void fillDetailBillingTypes(List<FormalSettlementDetail> details) {
|
||||||
|
if (details == null || details.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
List<Long> sourceDetailIds = details.stream()
|
||||||
|
.map(FormalSettlementDetail::getSourceDetailId)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.distinct()
|
||||||
|
.toList();
|
||||||
|
if (sourceDetailIds.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Map<Long, String> billingTypeMap = receivablePayableCargoFeeMapper.selectList(
|
||||||
|
Wrappers.<ReceivablePayableCargoFee>lambdaQuery()
|
||||||
|
.in(ReceivablePayableCargoFee::getDetailId, sourceDetailIds)
|
||||||
|
.orderByAsc(ReceivablePayableCargoFee::getLineNo))
|
||||||
|
.stream()
|
||||||
|
.filter(fee -> Func.isNotEmpty(fee.getBillingType()))
|
||||||
|
.collect(Collectors.groupingBy(ReceivablePayableCargoFee::getDetailId,
|
||||||
|
Collectors.mapping(ReceivablePayableCargoFee::getBillingType,
|
||||||
|
Collectors.collectingAndThen(Collectors.toCollection(LinkedHashSet::new),
|
||||||
|
values -> String.join("、", values)))));
|
||||||
|
for (FormalSettlementDetail detail : details) {
|
||||||
|
detail.setBillingType(billingTypeMap.getOrDefault(detail.getSourceDetailId(), ""));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 为历史正式结算明细补充运单收发货信息,保留明细中已有的快照值。
|
* 为历史正式结算明细补充运单收发货信息,保留明细中已有的快照值。
|
||||||
*/
|
*/
|
||||||
@@ -1090,9 +1121,23 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
|||||||
public List<FormalSettlementDetailFee> detailFees(Long detailId) {
|
public List<FormalSettlementDetailFee> detailFees(Long detailId) {
|
||||||
FormalSettlementDetail detail = detailMapper.selectById(detailId);
|
FormalSettlementDetail detail = detailMapper.selectById(detailId);
|
||||||
if (detail == null || Objects.equals(detail.getIsDeleted(), 1)) throw new ServiceException("正式结算明细不存在");
|
if (detail == null || Objects.equals(detail.getIsDeleted(), 1)) throw new ServiceException("正式结算明细不存在");
|
||||||
return detailFeeMapper.selectList(Wrappers.<FormalSettlementDetailFee>lambdaQuery()
|
List<FormalSettlementDetailFee> fees = detailFeeMapper.selectList(Wrappers.<FormalSettlementDetailFee>lambdaQuery()
|
||||||
.eq(FormalSettlementDetailFee::getFormalSettlementDetailId, detailId)
|
.eq(FormalSettlementDetailFee::getFormalSettlementDetailId, detailId)
|
||||||
.orderByAsc(FormalSettlementDetailFee::getLineNo));
|
.orderByAsc(FormalSettlementDetailFee::getLineNo));
|
||||||
|
List<Long> sourceFeeIds = fees.stream().map(FormalSettlementDetailFee::getSourceFeeId)
|
||||||
|
.filter(Objects::nonNull).toList();
|
||||||
|
if (sourceFeeIds.isEmpty()) {
|
||||||
|
return fees;
|
||||||
|
}
|
||||||
|
Map<Long, ReceivablePayableCargoFee> sourceFeeMap = receivablePayableCargoFeeMapper.selectBatchIds(sourceFeeIds).stream()
|
||||||
|
.collect(Collectors.toMap(ReceivablePayableCargoFee::getId, Function.identity(), (left, right) -> left));
|
||||||
|
fees.forEach(fee -> {
|
||||||
|
ReceivablePayableCargoFee sourceFee = sourceFeeMap.get(fee.getSourceFeeId());
|
||||||
|
if (sourceFee != null) {
|
||||||
|
fee.setBillingRulesJson(sourceFee.getBillingRulesJson());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return fees;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -1102,11 +1147,15 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
|||||||
if (detail == null || Objects.equals(detail.getIsDeleted(), 1)) throw new ServiceException("正式结算明细不存在");
|
if (detail == null || Objects.equals(detail.getIsDeleted(), 1)) throw new ServiceException("正式结算明细不存在");
|
||||||
FormalSettlement settlement = editable(detail.getFormalSettlementId());
|
FormalSettlement settlement = editable(detail.getFormalSettlementId());
|
||||||
if (Func.isEmpty(request.getRows())) throw new ServiceException("请填写需要调整的货物费用行");
|
if (Func.isEmpty(request.getRows())) throw new ServiceException("请填写需要调整的货物费用行");
|
||||||
String reason = required(limit(request.getChangeReason(), 200), "调整原因");
|
// 弹窗底部备注非必填,写入结算明细备注
|
||||||
|
String detailRemark = limit(request.getChangeReason(), 200);
|
||||||
|
String beforeDetailRemark = detail.getRemark() == null ? "" : detail.getRemark();
|
||||||
Map<Long, FormalSettlementDetailFee> existing = detailFees(detail.getId()).stream()
|
Map<Long, FormalSettlementDetailFee> existing = detailFees(detail.getId()).stream()
|
||||||
.collect(Collectors.toMap(FormalSettlementDetailFee::getId, item -> item));
|
.collect(Collectors.toMap(FormalSettlementDetailFee::getId, item -> item));
|
||||||
if (existing.size() != request.getRows().size()) throw new ServiceException("费用调整行数据不完整");
|
if (existing.size() != request.getRows().size()) throw new ServiceException("费用调整行数据不完整");
|
||||||
List<String> changes = new java.util.ArrayList<>();
|
List<String> changes = new java.util.ArrayList<>();
|
||||||
|
Map<String, Object> beforeData = new LinkedHashMap<>();
|
||||||
|
Map<String, Object> afterData = new LinkedHashMap<>();
|
||||||
for (PreSettlementDetailAdjustRequest.FeeRow row : request.getRows()) {
|
for (PreSettlementDetailAdjustRequest.FeeRow row : request.getRows()) {
|
||||||
FormalSettlementDetailFee fee = existing.get(row.getId());
|
FormalSettlementDetailFee fee = existing.get(row.getId());
|
||||||
if (fee == null) throw new ServiceException("存在无效的货物费用行");
|
if (fee == null) throw new ServiceException("存在无效的货物费用行");
|
||||||
@@ -1119,7 +1168,6 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
|||||||
fee.setSettlementAmountTax(nonNegative(row.getSettlementAmountTax(), "结算金额(含税)"));
|
fee.setSettlementAmountTax(nonNegative(row.getSettlementAmountTax(), "结算金额(含税)"));
|
||||||
fee.setSettlementAmountNoTax(row.getSettlementAmountNoTax() == null ? null : nonNegative(row.getSettlementAmountNoTax(), "结算金额(不含税)"));
|
fee.setSettlementAmountNoTax(row.getSettlementAmountNoTax() == null ? null : nonNegative(row.getSettlementAmountNoTax(), "结算金额(不含税)"));
|
||||||
fee.setAdjustAmount(fee.getSettlementAmountTax().subtract(money(fee.getOriginalAmount())));
|
fee.setAdjustAmount(fee.getSettlementAmountTax().subtract(money(fee.getOriginalAmount())));
|
||||||
fee.setRemark(limit(row.getRemark(), 200));
|
|
||||||
detailFeeMapper.updateById(fee);
|
detailFeeMapper.updateById(fee);
|
||||||
if (beforeAmount.compareTo(fee.getSettlementAmountTax()) != 0) {
|
if (beforeAmount.compareTo(fee.getSettlementAmountTax()) != 0) {
|
||||||
changes.add("【" + firstNotEmpty(fee.getCargoName(), fee.getLineNo())
|
changes.add("【" + firstNotEmpty(fee.getCargoName(), fee.getLineNo())
|
||||||
@@ -1129,17 +1177,31 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
|||||||
}
|
}
|
||||||
List<FormalSettlementDetailFee> rows = detailFees(detail.getId());
|
List<FormalSettlementDetailFee> rows = detailFees(detail.getId());
|
||||||
detail.setTransportQuantity(rows.stream().map(FormalSettlementDetailFee::getTransportQuantity).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
|
detail.setTransportQuantity(rows.stream().map(FormalSettlementDetailFee::getTransportQuantity).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
|
||||||
|
detail.setMileage(rows.stream().map(FormalSettlementDetailFee::getMileage).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
|
||||||
|
// 运输单价无法按行简单求和,与前端暂存逻辑一致:取首行费用单价。
|
||||||
|
detail.setUnitPrice(rows.stream().map(FormalSettlementDetailFee::getUnitPrice).filter(Objects::nonNull).findFirst().orElse(null));
|
||||||
detail.setFreightAmount(rows.stream().map(FormalSettlementDetailFee::getFreightAmount).map(this::money).reduce(BigDecimal.ZERO, BigDecimal::add));
|
detail.setFreightAmount(rows.stream().map(FormalSettlementDetailFee::getFreightAmount).map(this::money).reduce(BigDecimal.ZERO, BigDecimal::add));
|
||||||
detail.setOriginalAmount(rows.stream().map(FormalSettlementDetailFee::getOriginalAmount).map(this::money).reduce(BigDecimal.ZERO, BigDecimal::add));
|
detail.setOriginalAmount(rows.stream().map(FormalSettlementDetailFee::getOriginalAmount).map(this::money).reduce(BigDecimal.ZERO, BigDecimal::add));
|
||||||
detail.setSettlementAmountTax(rows.stream().map(FormalSettlementDetailFee::getSettlementAmountTax).map(this::money).reduce(BigDecimal.ZERO, BigDecimal::add));
|
detail.setSettlementAmountTax(rows.stream().map(FormalSettlementDetailFee::getSettlementAmountTax).map(this::money).reduce(BigDecimal.ZERO, BigDecimal::add));
|
||||||
detail.setSettlementAmountNoTax(rows.stream().map(FormalSettlementDetailFee::getSettlementAmountNoTax).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
|
boolean hasNoTax = rows.stream().anyMatch(fee -> fee.getSettlementAmountNoTax() != null);
|
||||||
|
detail.setSettlementAmountNoTax(hasNoTax
|
||||||
|
? rows.stream().map(FormalSettlementDetailFee::getSettlementAmountNoTax).filter(Objects::nonNull).map(this::money).reduce(BigDecimal.ZERO, BigDecimal::add)
|
||||||
|
: null);
|
||||||
detail.setAdjustAmount(detail.getSettlementAmountTax().subtract(detail.getOriginalAmount()));
|
detail.setAdjustAmount(detail.getSettlementAmountTax().subtract(detail.getOriginalAmount()));
|
||||||
detail.setRemark(reason);
|
Map<String, BigDecimal> feeItems = new LinkedHashMap<>();
|
||||||
|
rows.forEach(fee -> parseFeeItems(fee.getFeeItemsJson()).forEach((name, amount) ->
|
||||||
|
feeItems.merge(name, money(amount), BigDecimal::add)));
|
||||||
|
detail.setFeeItemsJson(JsonUtil.toJson(feeItems));
|
||||||
|
detail.setRemark(detailRemark);
|
||||||
detailMapper.updateById(detail);
|
detailMapper.updateById(detail);
|
||||||
|
appendTextChange(changes, beforeData, afterData, "备注", beforeDetailRemark, detailRemark);
|
||||||
|
if (changes.isEmpty()) {
|
||||||
|
throw new ServiceException("未修改任何结算明细费用");
|
||||||
|
}
|
||||||
rebuildSummaryFees(settlement.getId());
|
rebuildSummaryFees(settlement.getId());
|
||||||
refreshSettlementAmount(settlement);
|
refreshSettlementAmount(settlement);
|
||||||
saveChange(settlement.getId(), "结算明细项", detail.getLineNo(), "调整",
|
saveChange(settlement.getId(), "结算明细项", detail.getLineNo(), "调整",
|
||||||
changes.isEmpty() ? "调整结算明细费用" : String.join(";", changes), reason);
|
String.join(";", changes), detailRemark, beforeData, afterData);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void rebuildSummaryFees(Long settlementId) {
|
private void rebuildSummaryFees(Long settlementId) {
|
||||||
@@ -1314,10 +1376,18 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
|||||||
// throw new ServiceException("费用类型与费用项不匹配或费用项已停用");
|
// throw new ServiceException("费用类型与费用项不匹配或费用项已停用");
|
||||||
// }
|
// }
|
||||||
FormalSettlementSummaryFee row = requestRow.getId() == null ? null : existingMap.get(requestRow.getId());
|
FormalSettlementSummaryFee row = requestRow.getId() == null ? null : existingMap.get(requestRow.getId());
|
||||||
if (row == null && requestRow.getId() == null) row = new FormalSettlementSummaryFee();
|
if (row == null && requestRow.getId() == null) {
|
||||||
|
row = new FormalSettlementSummaryFee();
|
||||||
|
}
|
||||||
if (row == null || row.getId() != null && !Integer.valueOf(1).equals(row.getManualFlag())) {
|
if (row == null || row.getId() != null && !Integer.valueOf(1).equals(row.getManualFlag())) {
|
||||||
throw new ServiceException("存在无效的手工费用行");
|
throw new ServiceException("存在无效的手工费用行");
|
||||||
}
|
}
|
||||||
|
boolean creating = row.getId() == null;
|
||||||
|
String beforeFeeType = creating ? null : row.getFeeType();
|
||||||
|
String beforeFeeItem = creating ? null : row.getFeeItem();
|
||||||
|
BigDecimal beforeAdjustAmount = creating ? null : money(row.getAdjustAmount());
|
||||||
|
BigDecimal beforeSettlementAmount = creating ? null : money(row.getSettlementAmount());
|
||||||
|
String beforeRemark = creating ? null : row.getRemark();
|
||||||
row.setFormalSettlementId(settlementId);
|
row.setFormalSettlementId(settlementId);
|
||||||
row.setFeeType(feeType);
|
row.setFeeType(feeType);
|
||||||
row.setFeeItem(feeItem);
|
row.setFeeItem(feeItem);
|
||||||
@@ -1326,13 +1396,15 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
|||||||
row.setSettlementAmount(row.getAdjustAmount());
|
row.setSettlementAmount(row.getAdjustAmount());
|
||||||
row.setRemark(limit(requestRow.getRemark(), 50));
|
row.setRemark(limit(requestRow.getRemark(), 50));
|
||||||
row.setManualFlag(1);
|
row.setManualFlag(1);
|
||||||
if (row.getId() == null) {
|
if (creating) {
|
||||||
row.setLineNo(nextLineNo++);
|
row.setLineNo(nextLineNo++);
|
||||||
summaryFeeMapper.insert(row);
|
summaryFeeMapper.insert(row);
|
||||||
} else {
|
} else {
|
||||||
summaryFeeMapper.updateById(row);
|
summaryFeeMapper.updateById(row);
|
||||||
}
|
}
|
||||||
retainedManualIds.add(row.getId());
|
retainedManualIds.add(row.getId());
|
||||||
|
saveManualSummaryFeeChange(settlementId, creating, beforeFeeType, beforeFeeItem,
|
||||||
|
beforeAdjustAmount, beforeSettlementAmount, beforeRemark, row);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
FormalSettlementSummaryFee row = existingMap.get(requestRow.getId());
|
FormalSettlementSummaryFee row = existingMap.get(requestRow.getId());
|
||||||
@@ -1346,13 +1418,43 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
|||||||
if (row == null || Integer.valueOf(1).equals(row.getManualFlag())) {
|
if (row == null || Integer.valueOf(1).equals(row.getManualFlag())) {
|
||||||
throw new ServiceException("存在无效的结算合计行");
|
throw new ServiceException("存在无效的结算合计行");
|
||||||
}
|
}
|
||||||
|
BigDecimal beforeAdjustAmount = money(row.getAdjustAmount());
|
||||||
|
BigDecimal beforeSettlementAmount = money(row.getSettlementAmount());
|
||||||
|
String beforeRemark = row.getRemark();
|
||||||
row.setAdjustAmount(money(requestRow.getAdjustAmount()));
|
row.setAdjustAmount(money(requestRow.getAdjustAmount()));
|
||||||
row.setSettlementAmount(money(row.getOriginalAmount()).add(row.getAdjustAmount()));
|
row.setSettlementAmount(money(row.getOriginalAmount()).add(row.getAdjustAmount()));
|
||||||
row.setRemark(limit(requestRow.getRemark(), 50));
|
row.setRemark(limit(requestRow.getRemark(), 50));
|
||||||
summaryFeeMapper.updateById(row);
|
summaryFeeMapper.updateById(row);
|
||||||
|
List<String> changes = new java.util.ArrayList<>();
|
||||||
|
Map<String, Object> beforeData = new LinkedHashMap<>();
|
||||||
|
Map<String, Object> afterData = new LinkedHashMap<>();
|
||||||
|
appendChange(changes, beforeData, afterData, "调整金额", beforeAdjustAmount, row.getAdjustAmount());
|
||||||
|
appendChange(changes, beforeData, afterData, "结算金额", beforeSettlementAmount, row.getSettlementAmount());
|
||||||
|
appendTextChange(changes, beforeData, afterData, "备注", beforeRemark, row.getRemark());
|
||||||
|
if (!changes.isEmpty()) {
|
||||||
|
saveChange(settlementId, "合计费用项", row.getLineNo(), "调整", String.join(";", changes), "",
|
||||||
|
beforeData, afterData);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (FormalSettlementSummaryFee manualRow : existingManualRows) {
|
for (FormalSettlementSummaryFee manualRow : existingManualRows) {
|
||||||
if (!retainedManualIds.contains(manualRow.getId())) summaryFeeMapper.deleteById(manualRow.getId());
|
if (!retainedManualIds.contains(manualRow.getId())) {
|
||||||
|
summaryFeeMapper.deleteById(manualRow.getId());
|
||||||
|
Map<String, Object> beforeData = new LinkedHashMap<>();
|
||||||
|
Map<String, Object> afterData = new LinkedHashMap<>();
|
||||||
|
beforeData.put("费用类型", manualRow.getFeeType());
|
||||||
|
beforeData.put("费用项", manualRow.getFeeItem());
|
||||||
|
beforeData.put("调整金额", money(manualRow.getAdjustAmount()));
|
||||||
|
beforeData.put("结算金额", money(manualRow.getSettlementAmount()));
|
||||||
|
beforeData.put("备注", manualRow.getRemark());
|
||||||
|
afterData.put("费用类型", "");
|
||||||
|
afterData.put("费用项", "");
|
||||||
|
afterData.put("调整金额", BigDecimal.ZERO.setScale(2));
|
||||||
|
afterData.put("结算金额", BigDecimal.ZERO.setScale(2));
|
||||||
|
afterData.put("备注", "");
|
||||||
|
saveChange(settlementId, "合计费用项", manualRow.getLineNo(), "删除",
|
||||||
|
"删除合计费用项【" + manualRow.getFeeItem() + "】金额【" + money(manualRow.getSettlementAmount()) + "】",
|
||||||
|
"", beforeData, afterData);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
renumberSummaryFees(settlementId);
|
renumberSummaryFees(settlementId);
|
||||||
}
|
}
|
||||||
@@ -1995,14 +2097,77 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
|||||||
saveChange(settlement.getId(), "结算单基本信息", null, "调整", node, reason);
|
saveChange(settlement.getId(), "结算单基本信息", null, "调整", node, reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void saveManualSummaryFeeChange(Long settlementId, boolean creating, String beforeFeeType,
|
||||||
|
String beforeFeeItem, BigDecimal beforeAdjustAmount, BigDecimal beforeSettlementAmount, String beforeRemark,
|
||||||
|
FormalSettlementSummaryFee row) {
|
||||||
|
List<String> changes = new java.util.ArrayList<>();
|
||||||
|
Map<String, Object> beforeData = new LinkedHashMap<>();
|
||||||
|
Map<String, Object> afterData = new LinkedHashMap<>();
|
||||||
|
if (creating) {
|
||||||
|
changes.add("新增合计费用项【" + row.getFeeItem() + "】金额【" + money(row.getSettlementAmount()) + "】");
|
||||||
|
beforeData.put("费用类型", "");
|
||||||
|
beforeData.put("费用项", "");
|
||||||
|
beforeData.put("调整金额", BigDecimal.ZERO.setScale(2));
|
||||||
|
beforeData.put("结算金额", BigDecimal.ZERO.setScale(2));
|
||||||
|
beforeData.put("备注", "");
|
||||||
|
afterData.put("费用类型", row.getFeeType());
|
||||||
|
afterData.put("费用项", row.getFeeItem());
|
||||||
|
afterData.put("调整金额", money(row.getAdjustAmount()));
|
||||||
|
afterData.put("结算金额", money(row.getSettlementAmount()));
|
||||||
|
afterData.put("备注", row.getRemark());
|
||||||
|
saveChange(settlementId, "合计费用项", row.getLineNo(), "新增", String.join(";", changes), "",
|
||||||
|
beforeData, afterData);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
appendTextChange(changes, beforeData, afterData, "费用类型", beforeFeeType, row.getFeeType());
|
||||||
|
appendTextChange(changes, beforeData, afterData, "费用项", beforeFeeItem, row.getFeeItem());
|
||||||
|
appendChange(changes, beforeData, afterData, "调整金额", beforeAdjustAmount, row.getAdjustAmount());
|
||||||
|
appendChange(changes, beforeData, afterData, "结算金额", beforeSettlementAmount, row.getSettlementAmount());
|
||||||
|
appendTextChange(changes, beforeData, afterData, "备注", beforeRemark, row.getRemark());
|
||||||
|
if (changes.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
saveChange(settlementId, "合计费用项", row.getLineNo(), "调整", String.join(";", changes), "",
|
||||||
|
beforeData, afterData);
|
||||||
|
}
|
||||||
|
|
||||||
|
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, oldValue);
|
||||||
|
afterData.put(fieldName, newValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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, oldValue);
|
||||||
|
afterData.put(fieldName, newValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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) {
|
||||||
FormalSettlementChangeRecord record = new FormalSettlementChangeRecord();
|
FormalSettlementChangeRecord record = new FormalSettlementChangeRecord();
|
||||||
record.setFormalSettlementId(settlementId);
|
record.setFormalSettlementId(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.setChangeReason(reason);
|
record.setChangeReason(reason);
|
||||||
record.setOperatorName(Func.isEmpty(AuthUtil.getUserName()) ? "system" : AuthUtil.getUserName());
|
record.setOperatorName(Func.isEmpty(AuthUtil.getUserName()) ? "system" : AuthUtil.getUserName());
|
||||||
record.setChangeTime(LocalDateTime.now());
|
record.setChangeTime(LocalDateTime.now());
|
||||||
|
|||||||
+125
-34
@@ -118,6 +118,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@@ -324,6 +325,7 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
|
|||||||
amount.setCumulativeAppliedAmount(cumulativeAppliedAmount.add(writeOffAmount));
|
amount.setCumulativeAppliedAmount(cumulativeAppliedAmount.add(writeOffAmount));
|
||||||
amount.setPayableAmount(settlementAmount.subtract(cumulativeAppliedAmount).subtract(writeOffAmount)
|
amount.setPayableAmount(settlementAmount.subtract(cumulativeAppliedAmount).subtract(writeOffAmount)
|
||||||
.max(BigDecimal.ZERO));
|
.max(BigDecimal.ZERO));
|
||||||
|
amount.setPaymentSequence(resolvePaymentSequence(preSettlementReference, referenceId, excludeId));
|
||||||
return amount;
|
return amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1945,7 +1947,7 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
|
|||||||
}
|
}
|
||||||
|
|
||||||
private List<PreSettlement> resolvePreSettlements(List<Long> ids) {
|
private List<PreSettlement> resolvePreSettlements(List<Long> ids) {
|
||||||
if (ids.size() <= 1) {
|
if (ids.isEmpty()) {
|
||||||
return List.of();
|
return List.of();
|
||||||
}
|
}
|
||||||
List<PreSettlement> settlements = ids.stream().map(preSettlementMapper::selectById).toList();
|
List<PreSettlement> settlements = ids.stream().map(preSettlementMapper::selectById).toList();
|
||||||
@@ -1953,9 +1955,11 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
|
|||||||
|| !TransportBusiConstant.APPROVED.equals(item.getApprovalStatus()))) {
|
|| !TransportBusiConstant.APPROVED.equals(item.getApprovalStatus()))) {
|
||||||
throw new ServiceException("只能选择审批通过、未作废的预结算单");
|
throw new ServiceException("只能选择审批通过、未作废的预结算单");
|
||||||
}
|
}
|
||||||
Long contractId = settlements.get(0).getContractId();
|
if (settlements.size() > 1) {
|
||||||
if (contractId == null || settlements.stream().anyMatch(item -> !Objects.equals(contractId, item.getContractId()))) {
|
Long contractId = settlements.get(0).getContractId();
|
||||||
throw new ServiceException("多选预结算单必须属于同一合同");
|
if (contractId == null || settlements.stream().anyMatch(item -> !Objects.equals(contractId, item.getContractId()))) {
|
||||||
|
throw new ServiceException("多选预结算单必须属于同一合同");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return settlements;
|
return settlements;
|
||||||
}
|
}
|
||||||
@@ -1982,24 +1986,30 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void savePreSettlementRelations(PaymentApplication entity, List<PreSettlement> settlements) {
|
private void savePreSettlementRelations(PaymentApplication entity, List<PreSettlement> settlements) {
|
||||||
if (settlements.size() > 1) {
|
settlementRelationMapper.delete(Wrappers.<PaymentApplicationSettlement>lambdaQuery()
|
||||||
settlementRelationMapper.delete(Wrappers.<PaymentApplicationSettlement>lambdaQuery()
|
.eq(PaymentApplicationSettlement::getPaymentApplicationId, entity.getId())
|
||||||
.eq(PaymentApplicationSettlement::getPaymentApplicationId, entity.getId()));
|
.isNotNull(PaymentApplicationSettlement::getPreSettlementId));
|
||||||
} else {
|
List<PreSettlement> targetSettlements = settlements;
|
||||||
settlementRelationMapper.delete(Wrappers.<PaymentApplicationSettlement>lambdaQuery()
|
if (targetSettlements.isEmpty() && entity.getPreSettlementId() != null) {
|
||||||
.eq(PaymentApplicationSettlement::getPaymentApplicationId, entity.getId())
|
PreSettlement single = preSettlementMapper.selectById(entity.getPreSettlementId());
|
||||||
.isNotNull(PaymentApplicationSettlement::getPreSettlementId));
|
if (single != null && !Objects.equals(single.getIsDeleted(), 1)) {
|
||||||
|
targetSettlements = List.of(single);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (targetSettlements.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
BigDecimal totalBase = settlements.stream()
|
// 单选/多选均落关联行,生成即占用可付款额度(删除草稿或审核不通过后释放)
|
||||||
|
BigDecimal totalBase = targetSettlements.stream()
|
||||||
.map(item -> payableOfPreSettlement(item.getId(), item.getSettlementAmount(), entity.getId()))
|
.map(item -> payableOfPreSettlement(item.getId(), item.getSettlementAmount(), entity.getId()))
|
||||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
BigDecimal remainingApplied = money(entity.getAppliedAmount());
|
BigDecimal remainingApplied = money(entity.getAppliedAmount());
|
||||||
for (int index = 0; index < settlements.size(); index++) {
|
for (int index = 0; index < targetSettlements.size(); index++) {
|
||||||
PreSettlement settlement = settlements.get(index);
|
PreSettlement settlement = targetSettlements.get(index);
|
||||||
BigDecimal base = payableOfPreSettlement(settlement.getId(), settlement.getSettlementAmount(), entity.getId());
|
BigDecimal base = payableOfPreSettlement(settlement.getId(), settlement.getSettlementAmount(), entity.getId());
|
||||||
BigDecimal applied = index == settlements.size() - 1 || totalBase.compareTo(BigDecimal.ZERO) == 0
|
BigDecimal applied = index == targetSettlements.size() - 1 || totalBase.compareTo(BigDecimal.ZERO) == 0
|
||||||
? remainingApplied : money(entity.getAppliedAmount()).multiply(base).divide(totalBase, 2, RoundingMode.DOWN);
|
? remainingApplied
|
||||||
|
: money(entity.getAppliedAmount()).multiply(base).divide(totalBase, 2, RoundingMode.DOWN);
|
||||||
PaymentApplicationSettlement relation = new PaymentApplicationSettlement();
|
PaymentApplicationSettlement relation = new PaymentApplicationSettlement();
|
||||||
relation.setPaymentApplicationId(entity.getId());
|
relation.setPaymentApplicationId(entity.getId());
|
||||||
relation.setPreSettlementId(settlement.getId());
|
relation.setPreSettlementId(settlement.getId());
|
||||||
@@ -2049,16 +2059,22 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
|
|||||||
}
|
}
|
||||||
|
|
||||||
private BigDecimal sumApplied(LambdaQueryWrapper<PaymentApplication> wrapper) {
|
private BigDecimal sumApplied(LambdaQueryWrapper<PaymentApplication> wrapper) {
|
||||||
return list(wrapper.ne(PaymentApplication::getApprovalStatus, TransportBusiConstant.VOIDED)).stream()
|
return list(wrapper).stream()
|
||||||
.filter(item -> !releasedBillPayment(item))
|
.filter(item -> !releasedOccupiedPayment(item))
|
||||||
.map(PaymentApplication::getAppliedAmount).map(this::money).reduce(BigDecimal.ZERO, BigDecimal::add);
|
.map(PaymentApplication::getAppliedAmount).map(this::money).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 汇票付款被驳回后不再占用结算单可付款金额,删除草稿由逻辑删除自然释放。 */
|
/**
|
||||||
private boolean releasedBillPayment(PaymentApplication payment) {
|
* 已释放占用的付款申请:作废、审核不通过(驳回)不再占用可付款金额;
|
||||||
return payment != null
|
* 删除草稿由逻辑删除自然释放。生成草稿/审批中/审批通过均占用。
|
||||||
&& isBillPayment(payment.getPaymentMethod())
|
*/
|
||||||
&& TransportBusiConstant.RETURNED.equals(payment.getApprovalStatus());
|
private boolean releasedOccupiedPayment(PaymentApplication payment) {
|
||||||
|
if (payment == null || Objects.equals(payment.getIsDeleted(), 1)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
String status = payment.getApprovalStatus();
|
||||||
|
return TransportBusiConstant.VOIDED.equals(status)
|
||||||
|
|| TransportBusiConstant.RETURNED.equals(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BigDecimal cumulativeAppliedAmount(String paymentType, Long referenceId, Long excludeId) {
|
private BigDecimal cumulativeAppliedAmount(String paymentType, Long referenceId, Long excludeId) {
|
||||||
@@ -2071,14 +2087,88 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
|
|||||||
return BigDecimal.ZERO;
|
return BigDecimal.ZERO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结算单当前付款次序:历史有效付款申请次数 + 1(作废、当前单据自身不计)。
|
||||||
|
*
|
||||||
|
* @param preSettlementReference 是否预结算关联
|
||||||
|
* @param referenceId 结算单主键
|
||||||
|
* @param excludeId 排除的付款申请主键(编辑中)
|
||||||
|
* @return 第几次付款,至少为 1
|
||||||
|
*/
|
||||||
|
private int resolvePaymentSequence(boolean preSettlementReference, Long referenceId, Long excludeId) {
|
||||||
|
Set<Long> paymentIds = new LinkedHashSet<>();
|
||||||
|
if (preSettlementReference) {
|
||||||
|
List<PaymentApplicationSettlement> relations = settlementRelationMapper.selectList(
|
||||||
|
Wrappers.<PaymentApplicationSettlement>lambdaQuery()
|
||||||
|
.eq(PaymentApplicationSettlement::getPreSettlementId, referenceId)
|
||||||
|
.eq(PaymentApplicationSettlement::getIsDeleted, 0));
|
||||||
|
for (PaymentApplicationSettlement relation : relations) {
|
||||||
|
if (relation.getPaymentApplicationId() != null) {
|
||||||
|
paymentIds.add(relation.getPaymentApplicationId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
list(Wrappers.<PaymentApplication>lambdaQuery()
|
||||||
|
.eq(PaymentApplication::getPreSettlementId, referenceId)
|
||||||
|
.ne(PaymentApplication::getApprovalStatus, TransportBusiConstant.VOIDED))
|
||||||
|
.forEach(payment -> paymentIds.add(payment.getId()));
|
||||||
|
} else {
|
||||||
|
List<PaymentApplicationSettlement> relations = settlementRelationMapper.selectList(
|
||||||
|
Wrappers.<PaymentApplicationSettlement>lambdaQuery()
|
||||||
|
.eq(PaymentApplicationSettlement::getFormalSettlementId, referenceId)
|
||||||
|
.eq(PaymentApplicationSettlement::getIsDeleted, 0));
|
||||||
|
for (PaymentApplicationSettlement relation : relations) {
|
||||||
|
if (relation.getPaymentApplicationId() != null) {
|
||||||
|
paymentIds.add(relation.getPaymentApplicationId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
list(Wrappers.<PaymentApplication>lambdaQuery()
|
||||||
|
.eq(PaymentApplication::getSettlementId, referenceId)
|
||||||
|
.ne(PaymentApplication::getApprovalStatus, TransportBusiConstant.VOIDED))
|
||||||
|
.forEach(payment -> paymentIds.add(payment.getId()));
|
||||||
|
}
|
||||||
|
if (paymentIds.isEmpty()) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
long priorCount = listByIds(paymentIds.stream().toList()).stream()
|
||||||
|
.filter(payment -> !releasedOccupiedPayment(payment))
|
||||||
|
.filter(payment -> !Objects.equals(payment.getId(), excludeId))
|
||||||
|
.count();
|
||||||
|
return (int) priorCount + 1;
|
||||||
|
}
|
||||||
|
|
||||||
private BigDecimal cumulativeFormalSettlementApplied(Long settlementId, Long excludeId) {
|
private BigDecimal cumulativeFormalSettlementApplied(Long settlementId, Long excludeId) {
|
||||||
return sumApplied(Wrappers.<PaymentApplication>lambdaQuery()
|
// 多选正式结算时按关联行累计占用;单选兼容主表 settlementId
|
||||||
|
List<PaymentApplicationSettlement> relations = settlementRelationMapper.selectList(
|
||||||
|
Wrappers.<PaymentApplicationSettlement>lambdaQuery()
|
||||||
|
.eq(PaymentApplicationSettlement::getFormalSettlementId, settlementId)
|
||||||
|
.eq(PaymentApplicationSettlement::getIsDeleted, 0));
|
||||||
|
Set<Long> coveredPaymentIds = new HashSet<>();
|
||||||
|
BigDecimal relationAmount = BigDecimal.ZERO;
|
||||||
|
if (!relations.isEmpty()) {
|
||||||
|
Map<Long, PaymentApplication> payments = listByIds(relations.stream()
|
||||||
|
.map(PaymentApplicationSettlement::getPaymentApplicationId).filter(Objects::nonNull).distinct().toList())
|
||||||
|
.stream().collect(Collectors.toMap(PaymentApplication::getId, item -> item, (left, right) -> left));
|
||||||
|
for (PaymentApplicationSettlement relation : relations) {
|
||||||
|
PaymentApplication payment = payments.get(relation.getPaymentApplicationId());
|
||||||
|
if (releasedOccupiedPayment(payment) || Objects.equals(payment.getId(), excludeId)) {
|
||||||
|
if (payment != null) {
|
||||||
|
coveredPaymentIds.add(payment.getId());
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
coveredPaymentIds.add(payment.getId());
|
||||||
|
relationAmount = relationAmount.add(money(relation.getAppliedAmount()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BigDecimal legacyAmount = sumApplied(Wrappers.<PaymentApplication>lambdaQuery()
|
||||||
.eq(PaymentApplication::getSettlementId, settlementId)
|
.eq(PaymentApplication::getSettlementId, settlementId)
|
||||||
.ne(excludeId != null, PaymentApplication::getId, excludeId));
|
.ne(excludeId != null, PaymentApplication::getId, excludeId)
|
||||||
|
.notIn(!coveredPaymentIds.isEmpty(), PaymentApplication::getId, coveredPaymentIds));
|
||||||
|
return relationAmount.add(legacyAmount);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BigDecimal cumulativePreSettlementApplied(Long preSettlementId, Long excludeId) {
|
private BigDecimal cumulativePreSettlementApplied(Long preSettlementId, Long excludeId) {
|
||||||
// 进度预付、尾款付款关联同一预结算单时累计占用可付款额度;多选时按关联行的申请金额累计,避免把整单金额算到第一张预结算上
|
// 进度预付、尾款付款关联同一预结算单时累计占用可付款额度;按关联行申请金额累计,兼容历史仅写主表的单据
|
||||||
List<PaymentApplicationSettlement> relations = settlementRelationMapper.selectList(
|
List<PaymentApplicationSettlement> relations = settlementRelationMapper.selectList(
|
||||||
Wrappers.<PaymentApplicationSettlement>lambdaQuery()
|
Wrappers.<PaymentApplicationSettlement>lambdaQuery()
|
||||||
.eq(PaymentApplicationSettlement::getPreSettlementId, preSettlementId)
|
.eq(PaymentApplicationSettlement::getPreSettlementId, preSettlementId)
|
||||||
@@ -2091,23 +2181,21 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
|
|||||||
.stream().collect(Collectors.toMap(PaymentApplication::getId, item -> item, (left, right) -> left));
|
.stream().collect(Collectors.toMap(PaymentApplication::getId, item -> item, (left, right) -> left));
|
||||||
for (PaymentApplicationSettlement relation : relations) {
|
for (PaymentApplicationSettlement relation : relations) {
|
||||||
PaymentApplication payment = payments.get(relation.getPaymentApplicationId());
|
PaymentApplication payment = payments.get(relation.getPaymentApplicationId());
|
||||||
if (payment == null || Objects.equals(payment.getIsDeleted(), 1)) {
|
if (releasedOccupiedPayment(payment) || Objects.equals(payment.getId(), excludeId)) {
|
||||||
|
if (payment != null) {
|
||||||
|
coveredPaymentIds.add(payment.getId());
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
coveredPaymentIds.add(payment.getId());
|
coveredPaymentIds.add(payment.getId());
|
||||||
if (Objects.equals(payment.getId(), excludeId) || TransportBusiConstant.VOIDED.equals(payment.getApprovalStatus())
|
|
||||||
|| releasedBillPayment(payment)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
relationAmount = relationAmount.add(money(relation.getAppliedAmount()));
|
relationAmount = relationAmount.add(money(relation.getAppliedAmount()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BigDecimal legacyAmount = list(Wrappers.<PaymentApplication>lambdaQuery()
|
BigDecimal legacyAmount = list(Wrappers.<PaymentApplication>lambdaQuery()
|
||||||
.eq(PaymentApplication::getPreSettlementId, preSettlementId)
|
.eq(PaymentApplication::getPreSettlementId, preSettlementId)
|
||||||
.ne(excludeId != null, PaymentApplication::getId, excludeId)
|
.ne(excludeId != null, PaymentApplication::getId, excludeId)
|
||||||
.notIn(!coveredPaymentIds.isEmpty(), PaymentApplication::getId, coveredPaymentIds)
|
.notIn(!coveredPaymentIds.isEmpty(), PaymentApplication::getId, coveredPaymentIds)).stream()
|
||||||
.ne(PaymentApplication::getApprovalStatus, TransportBusiConstant.VOIDED)).stream()
|
.filter(item -> !releasedOccupiedPayment(item))
|
||||||
.filter(item -> !releasedBillPayment(item))
|
|
||||||
.map(PaymentApplication::getAppliedAmount).map(this::money).reduce(BigDecimal.ZERO, BigDecimal::add);
|
.map(PaymentApplication::getAppliedAmount).map(this::money).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
return relationAmount.add(legacyAmount);
|
return relationAmount.add(legacyAmount);
|
||||||
}
|
}
|
||||||
@@ -2150,6 +2238,9 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
|
|||||||
|
|
||||||
private void validateBill(BillLedger ledger, Long deptId, BigDecimal amount, boolean checkMaturity, Long paymentApplicationId) {
|
private void validateBill(BillLedger ledger, Long deptId, BigDecimal amount, boolean checkMaturity, Long paymentApplicationId) {
|
||||||
if (ledger == null || Objects.equals(ledger.getIsDeleted(), 1)) throw new ServiceException("所选汇票台账不存在");
|
if (ledger == null || Objects.equals(ledger.getIsDeleted(), 1)) throw new ServiceException("所选汇票台账不存在");
|
||||||
|
if (!"received".equals(ledger.getBillType())) {
|
||||||
|
throw new ServiceException("汇票付款仅可选择收票类型的汇票");
|
||||||
|
}
|
||||||
if (checkMaturity && (ledger.getMaturityDate() == null || ledger.getMaturityDate().isBefore(LocalDate.now()))) {
|
if (checkMaturity && (ledger.getMaturityDate() == null || ledger.getMaturityDate().isBefore(LocalDate.now()))) {
|
||||||
throw new ServiceException("所选汇票已到期");
|
throw new ServiceException("所选汇票已到期");
|
||||||
}
|
}
|
||||||
|
|||||||
+183
-22
@@ -307,7 +307,9 @@ public class PreSettlementServiceImpl extends BaseServiceImpl<PreSettlementMappe
|
|||||||
IPage<ReceivablePayableDetail> sourcePage = sourceDetailMapper.selectPage(
|
IPage<ReceivablePayableDetail> sourcePage = sourceDetailMapper.selectPage(
|
||||||
new Page<>(page.getCurrent(), page.getSize()), wrapper);
|
new Page<>(page.getCurrent(), page.getSize()), wrapper);
|
||||||
Page<Map<String, Object>> result = new Page<>(sourcePage.getCurrent(), sourcePage.getSize(), sourcePage.getTotal());
|
Page<Map<String, Object>> result = new Page<>(sourcePage.getCurrent(), sourcePage.getSize(), sourcePage.getTotal());
|
||||||
result.setRecords(sourcePage.getRecords().stream().map(this::candidateMap).toList());
|
List<Map<String, Object>> records = sourcePage.getRecords().stream().map(this::candidateMap).toList();
|
||||||
|
fillCandidateBillingTypes(records);
|
||||||
|
result.setRecords(records);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -616,7 +618,9 @@ public class PreSettlementServiceImpl extends BaseServiceImpl<PreSettlementMappe
|
|||||||
if (Func.isEmpty(request.getRows())) {
|
if (Func.isEmpty(request.getRows())) {
|
||||||
throw new ServiceException("请填写需要调整的费用行");
|
throw new ServiceException("请填写需要调整的费用行");
|
||||||
}
|
}
|
||||||
String changeReason = limitRemark(request.getChangeReason(), 200);
|
// 弹窗底部备注非必填,写入结算明细备注
|
||||||
|
String detailRemark = limitRemark(request.getChangeReason(), 200);
|
||||||
|
String beforeDetailRemark = detail.getRemark();
|
||||||
Map<Long, PreSettlementDetailFee> existingMap = detailFees(detail.getId()).stream()
|
Map<Long, PreSettlementDetailFee> existingMap = detailFees(detail.getId()).stream()
|
||||||
.collect(Collectors.toMap(PreSettlementDetailFee::getId, Function.identity()));
|
.collect(Collectors.toMap(PreSettlementDetailFee::getId, Function.identity()));
|
||||||
if (request.getRows().size() != existingMap.size()) {
|
if (request.getRows().size() != existingMap.size()) {
|
||||||
@@ -636,7 +640,6 @@ public class PreSettlementServiceImpl extends BaseServiceImpl<PreSettlementMappe
|
|||||||
BigDecimal beforeFreight = fee.getFreightAmount();
|
BigDecimal beforeFreight = fee.getFreightAmount();
|
||||||
BigDecimal beforeAmount = money(fee.getSettlementAmountTax());
|
BigDecimal beforeAmount = money(fee.getSettlementAmountTax());
|
||||||
BigDecimal beforeNoTaxAmount = fee.getSettlementAmountNoTax();
|
BigDecimal beforeNoTaxAmount = fee.getSettlementAmountNoTax();
|
||||||
String beforeRemark = fee.getRemark();
|
|
||||||
Map<String, BigDecimal> beforeFeeItems = parseFeeItems(fee.getFeeItemsJson());
|
Map<String, BigDecimal> beforeFeeItems = parseFeeItems(fee.getFeeItemsJson());
|
||||||
fee.setTransportQuantity(nonNegative(requestRow.getTransportQuantity(), "运输总量"));
|
fee.setTransportQuantity(nonNegative(requestRow.getTransportQuantity(), "运输总量"));
|
||||||
fee.setMileage(nonNegative(requestRow.getMileage(), "里程"));
|
fee.setMileage(nonNegative(requestRow.getMileage(), "里程"));
|
||||||
@@ -649,7 +652,6 @@ public class PreSettlementServiceImpl extends BaseServiceImpl<PreSettlementMappe
|
|||||||
fee.setSettlementAmountNoTax(requestRow.getSettlementAmountNoTax() == null ? null
|
fee.setSettlementAmountNoTax(requestRow.getSettlementAmountNoTax() == null ? null
|
||||||
: money(requestRow.getSettlementAmountNoTax()));
|
: money(requestRow.getSettlementAmountNoTax()));
|
||||||
fee.setAdjustAmount(afterAmount.subtract(money(fee.getOriginalAmount())));
|
fee.setAdjustAmount(afterAmount.subtract(money(fee.getOriginalAmount())));
|
||||||
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, beforeData, afterData, prefix + "运输总量", beforeQuantity, fee.getTransportQuantity());
|
appendChange(changes, beforeData, afterData, prefix + "运输总量", beforeQuantity, fee.getTransportQuantity());
|
||||||
@@ -664,16 +666,19 @@ public class PreSettlementServiceImpl extends BaseServiceImpl<PreSettlementMappe
|
|||||||
appendChange(changes, beforeData, afterData, prefix + "结算金额(含税)", beforeAmount, afterAmount);
|
appendChange(changes, beforeData, afterData, prefix + "结算金额(含税)", beforeAmount, afterAmount);
|
||||||
appendChange(changes, beforeData, afterData, prefix + "结算金额(不含税)", beforeNoTaxAmount,
|
appendChange(changes, beforeData, afterData, prefix + "结算金额(不含税)", beforeNoTaxAmount,
|
||||||
fee.getSettlementAmountNoTax());
|
fee.getSettlementAmountNoTax());
|
||||||
appendTextChange(changes, beforeData, afterData, prefix + "备注", beforeRemark, fee.getRemark());
|
|
||||||
}
|
}
|
||||||
|
appendTextChange(changes, beforeData, afterData, "备注", beforeDetailRemark, detailRemark);
|
||||||
if (changes.isEmpty()) {
|
if (changes.isEmpty()) {
|
||||||
throw new ServiceException("未修改任何结算明细费用");
|
throw new ServiceException("未修改任何结算明细费用");
|
||||||
}
|
}
|
||||||
refreshDetail(detail);
|
refreshDetail(detail);
|
||||||
|
// refreshDetail 会按费用行回填备注,需在其后覆盖为弹窗底部备注
|
||||||
|
detail.setRemark(detailRemark);
|
||||||
|
detailMapper.updateById(detail);
|
||||||
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, beforeData, afterData);
|
String.join(";", changes), detailRemark, beforeData, afterData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -752,6 +757,7 @@ public class PreSettlementServiceImpl extends BaseServiceImpl<PreSettlementMappe
|
|||||||
result.put("quantityUnit", source.getQuantityUnit());
|
result.put("quantityUnit", source.getQuantityUnit());
|
||||||
result.put("mileage", source.getMileage());
|
result.put("mileage", source.getMileage());
|
||||||
result.put("batchNo", source.getBatchNo());
|
result.put("batchNo", source.getBatchNo());
|
||||||
|
result.put("billingType", "");
|
||||||
result.put("unitPrice", source.getUnitPrice());
|
result.put("unitPrice", source.getUnitPrice());
|
||||||
result.put("freightAmount", money(source.getFreightAmount()));
|
result.put("freightAmount", money(source.getFreightAmount()));
|
||||||
result.put("feeItemsJson", source.getFeeItemsJson());
|
result.put("feeItemsJson", source.getFeeItemsJson());
|
||||||
@@ -765,6 +771,35 @@ public class PreSettlementServiceImpl extends BaseServiceImpl<PreSettlementMappe
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 候选明细补充计费方式(货物费用计费类型去重汇总) */
|
||||||
|
private void fillCandidateBillingTypes(List<Map<String, Object>> records) {
|
||||||
|
if (records == null || records.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
List<Long> detailIds = records.stream()
|
||||||
|
.map(item -> Func.toLong(item.get("id")))
|
||||||
|
.filter(id -> id != null && id > 0)
|
||||||
|
.distinct()
|
||||||
|
.toList();
|
||||||
|
if (detailIds.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Map<Long, String> billingTypeMap = sourceFeeMapper.selectList(
|
||||||
|
Wrappers.<ReceivablePayableCargoFee>lambdaQuery()
|
||||||
|
.in(ReceivablePayableCargoFee::getDetailId, detailIds)
|
||||||
|
.orderByAsc(ReceivablePayableCargoFee::getLineNo))
|
||||||
|
.stream()
|
||||||
|
.filter(fee -> Func.isNotEmpty(fee.getBillingType()))
|
||||||
|
.collect(Collectors.groupingBy(ReceivablePayableCargoFee::getDetailId,
|
||||||
|
Collectors.mapping(ReceivablePayableCargoFee::getBillingType,
|
||||||
|
Collectors.collectingAndThen(Collectors.toCollection(LinkedHashSet::new),
|
||||||
|
values -> String.join("、", values)))));
|
||||||
|
for (Map<String, Object> record : records) {
|
||||||
|
Long detailId = Func.toLong(record.get("id"));
|
||||||
|
record.put("billingType", billingTypeMap.getOrDefault(detailId, ""));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void synchronizeDetails(PreSettlement settlement, List<Long> requestedIds, boolean allowSourceMismatch) {
|
private void synchronizeDetails(PreSettlement settlement, List<Long> requestedIds, boolean allowSourceMismatch) {
|
||||||
List<Long> distinctIds = requestedIds.stream().filter(Objects::nonNull).distinct().toList();
|
List<Long> distinctIds = requestedIds.stream().filter(Objects::nonNull).distinct().toList();
|
||||||
List<PreSettlementDetail> existingDetails = listDetails(settlement.getId());
|
List<PreSettlementDetail> existingDetails = listDetails(settlement.getId());
|
||||||
@@ -1001,13 +1036,30 @@ public class PreSettlementServiceImpl extends BaseServiceImpl<PreSettlementMappe
|
|||||||
summaryFeeMapper.delete(Wrappers.<PreSettlementSummaryFee>lambdaQuery()
|
summaryFeeMapper.delete(Wrappers.<PreSettlementSummaryFee>lambdaQuery()
|
||||||
.eq(PreSettlementSummaryFee::getPreSettlementId, settlementId)
|
.eq(PreSettlementSummaryFee::getPreSettlementId, settlementId)
|
||||||
.eq(PreSettlementSummaryFee::getManualFlag, 0));
|
.eq(PreSettlementSummaryFee::getManualFlag, 0));
|
||||||
int lineNo = 1;
|
// 尽量沿用已有系统归集行的序号,避免重建后与手工费用交错顺序被打乱。
|
||||||
for (Map.Entry<String, BigDecimal> entry : aggregates.entrySet()) {
|
List<Map.Entry<String, BigDecimal>> orderedAggregates = new ArrayList<>(aggregates.entrySet());
|
||||||
|
orderedAggregates.sort((left, right) -> {
|
||||||
|
PreSettlementSummaryFee leftOld = existingGenerated.get(left.getKey());
|
||||||
|
PreSettlementSummaryFee rightOld = existingGenerated.get(right.getKey());
|
||||||
|
Integer leftLineNo = leftOld == null ? null : leftOld.getLineNo();
|
||||||
|
Integer rightLineNo = rightOld == null ? null : rightOld.getLineNo();
|
||||||
|
if (leftLineNo == null && rightLineNo == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (leftLineNo == null) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (rightLineNo == null) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return Integer.compare(leftLineNo, rightLineNo);
|
||||||
|
});
|
||||||
|
for (Map.Entry<String, BigDecimal> entry : orderedAggregates) {
|
||||||
String[] keyParts = entry.getKey().split("\\|", 2);
|
String[] keyParts = entry.getKey().split("\\|", 2);
|
||||||
PreSettlementSummaryFee old = existingGenerated.get(entry.getKey());
|
PreSettlementSummaryFee old = existingGenerated.get(entry.getKey());
|
||||||
PreSettlementSummaryFee row = new PreSettlementSummaryFee();
|
PreSettlementSummaryFee row = new PreSettlementSummaryFee();
|
||||||
row.setPreSettlementId(settlementId);
|
row.setPreSettlementId(settlementId);
|
||||||
row.setLineNo(lineNo++);
|
row.setLineNo(old == null || old.getLineNo() == null ? Integer.MAX_VALUE : old.getLineNo());
|
||||||
row.setFeeType(keyParts[0]);
|
row.setFeeType(keyParts[0]);
|
||||||
row.setFeeItem(keyParts.length > 1 ? keyParts[1] : "");
|
row.setFeeItem(keyParts.length > 1 ? keyParts[1] : "");
|
||||||
// 原金额是明细首次生成时的快照,多次调整后不得被当前结算金额覆盖。
|
// 原金额是明细首次生成时的快照,多次调整后不得被当前结算金额覆盖。
|
||||||
@@ -1023,7 +1075,14 @@ public class PreSettlementServiceImpl extends BaseServiceImpl<PreSettlementMappe
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void applySummaryRequest(Long settlementId, List<PreSettlementSaveRequest.SummaryFee> requestRows) {
|
private void applySummaryRequest(Long settlementId, List<PreSettlementSaveRequest.SummaryFee> requestRows) {
|
||||||
if (requestRows == null) return;
|
if (requestRows == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 空列表表示沿用 rebuildSummaryFees 结果(如更换合同后),不得再按空请求删光合计行。
|
||||||
|
if (requestRows.isEmpty()) {
|
||||||
|
renumberSummaryFees(settlementId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
Map<String, Set<String>> allowedManualFees = new LinkedHashMap<>();
|
Map<String, Set<String>> allowedManualFees = new LinkedHashMap<>();
|
||||||
if (requestRows.stream().anyMatch(row -> Integer.valueOf(1).equals(row.getManualFlag()))) {
|
if (requestRows.stream().anyMatch(row -> Integer.valueOf(1).equals(row.getManualFlag()))) {
|
||||||
for (Map<String, Object> option : feeOptions()) {
|
for (Map<String, Object> option : feeOptions()) {
|
||||||
@@ -1043,6 +1102,7 @@ public class PreSettlementServiceImpl extends BaseServiceImpl<PreSettlementMappe
|
|||||||
List<PreSettlementSummaryFee> availableGeneratedRows = new ArrayList<>(existingGeneratedRows);
|
List<PreSettlementSummaryFee> availableGeneratedRows = new ArrayList<>(existingGeneratedRows);
|
||||||
Set<Long> retainedManualIds = new LinkedHashSet<>();
|
Set<Long> retainedManualIds = new LinkedHashSet<>();
|
||||||
Set<Long> retainedGeneratedIds = new LinkedHashSet<>();
|
Set<Long> retainedGeneratedIds = new LinkedHashSet<>();
|
||||||
|
int lineNo = 1;
|
||||||
for (PreSettlementSaveRequest.SummaryFee requestRow : requestRows) {
|
for (PreSettlementSaveRequest.SummaryFee requestRow : requestRows) {
|
||||||
if (Integer.valueOf(1).equals(requestRow.getManualFlag())) {
|
if (Integer.valueOf(1).equals(requestRow.getManualFlag())) {
|
||||||
String feeType = requiredText(requestRow.getFeeType(), "费用类型");
|
String feeType = requiredText(requestRow.getFeeType(), "费用类型");
|
||||||
@@ -1059,11 +1119,20 @@ public class PreSettlementServiceImpl extends BaseServiceImpl<PreSettlementMappe
|
|||||||
&& Objects.equals(item.getFeeItem(), requestRow.getFeeItem()))
|
&& Objects.equals(item.getFeeItem(), requestRow.getFeeItem()))
|
||||||
.findFirst().orElse(null);
|
.findFirst().orElse(null);
|
||||||
}
|
}
|
||||||
if (row == null && requestRow.getId() == null) row = new PreSettlementSummaryFee();
|
if (row == null && requestRow.getId() == null) {
|
||||||
|
row = new PreSettlementSummaryFee();
|
||||||
|
}
|
||||||
if (row == null || (row.getId() != null && !Integer.valueOf(1).equals(row.getManualFlag()))) {
|
if (row == null || (row.getId() != null && !Integer.valueOf(1).equals(row.getManualFlag()))) {
|
||||||
throw new ServiceException("存在无效的手工费用行");
|
throw new ServiceException("存在无效的手工费用行");
|
||||||
}
|
}
|
||||||
|
boolean creating = row.getId() == null;
|
||||||
|
String beforeFeeType = creating ? null : row.getFeeType();
|
||||||
|
String beforeFeeItem = creating ? null : row.getFeeItem();
|
||||||
|
BigDecimal beforeAdjustAmount = creating ? null : money(row.getAdjustAmount());
|
||||||
|
BigDecimal beforeSettlementAmount = creating ? null : money(row.getSettlementAmount());
|
||||||
|
String beforeRemark = creating ? null : row.getRemark();
|
||||||
row.setPreSettlementId(settlementId);
|
row.setPreSettlementId(settlementId);
|
||||||
|
row.setLineNo(lineNo++);
|
||||||
row.setFeeType(feeType);
|
row.setFeeType(feeType);
|
||||||
row.setFeeItem(feeItem);
|
row.setFeeItem(feeItem);
|
||||||
row.setOriginalAmount(BigDecimal.ZERO.setScale(2));
|
row.setOriginalAmount(BigDecimal.ZERO.setScale(2));
|
||||||
@@ -1071,10 +1140,14 @@ public class PreSettlementServiceImpl extends BaseServiceImpl<PreSettlementMappe
|
|||||||
row.setSettlementAmount(row.getAdjustAmount());
|
row.setSettlementAmount(row.getAdjustAmount());
|
||||||
row.setRemark(limitRemark(requestRow.getRemark(), 50));
|
row.setRemark(limitRemark(requestRow.getRemark(), 50));
|
||||||
row.setManualFlag(1);
|
row.setManualFlag(1);
|
||||||
if (row.getId() == null) summaryFeeMapper.insert(row); else summaryFeeMapper.updateById(row);
|
if (creating) {
|
||||||
|
summaryFeeMapper.insert(row);
|
||||||
|
} else {
|
||||||
|
summaryFeeMapper.updateById(row);
|
||||||
|
}
|
||||||
retainedManualIds.add(row.getId());
|
retainedManualIds.add(row.getId());
|
||||||
saveChange(settlementId, "合计费用项", null, requestRow.getId() == null ? "新增" : "调整",
|
saveManualSummaryFeeChange(settlementId, creating, beforeFeeType, beforeFeeItem,
|
||||||
row.getFeeItem() + "金额" + row.getSettlementAmount(), "");
|
beforeAdjustAmount, beforeSettlementAmount, beforeRemark, row);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
String feeItem = requiredText(requestRow.getFeeItem(), "费用项");
|
String feeItem = requiredText(requestRow.getFeeItem(), "费用项");
|
||||||
@@ -1094,6 +1167,7 @@ public class PreSettlementServiceImpl extends BaseServiceImpl<PreSettlementMappe
|
|||||||
row.setPreSettlementId(settlementId);
|
row.setPreSettlementId(settlementId);
|
||||||
row.setManualFlag(0);
|
row.setManualFlag(0);
|
||||||
}
|
}
|
||||||
|
row.setLineNo(lineNo++);
|
||||||
row.setFeeType(feeType);
|
row.setFeeType(feeType);
|
||||||
row.setFeeItem(feeItem);
|
row.setFeeItem(feeItem);
|
||||||
// 生成费用行的三个金额必须来源于结算明细快照,不能接受前端回传值覆盖原金额。
|
// 生成费用行的三个金额必须来源于结算明细快照,不能接受前端回传值覆盖原金额。
|
||||||
@@ -1106,15 +1180,37 @@ public class PreSettlementServiceImpl extends BaseServiceImpl<PreSettlementMappe
|
|||||||
if (row.getId() == null) summaryFeeMapper.insert(row); else summaryFeeMapper.updateById(row);
|
if (row.getId() == null) summaryFeeMapper.insert(row); else summaryFeeMapper.updateById(row);
|
||||||
retainedGeneratedIds.add(row.getId());
|
retainedGeneratedIds.add(row.getId());
|
||||||
if (before.compareTo(row.getAdjustAmount()) != 0) {
|
if (before.compareTo(row.getAdjustAmount()) != 0) {
|
||||||
saveChange(settlementId, "合计费用项", null, "调整",
|
Map<String, Object> beforeData = new LinkedHashMap<>();
|
||||||
"【调整金额】从【" + before + "】调整为【" + row.getAdjustAmount() + "】", "");
|
Map<String, Object> afterData = new LinkedHashMap<>();
|
||||||
|
beforeData.put("费用项", row.getFeeItem());
|
||||||
|
beforeData.put("调整金额", before);
|
||||||
|
beforeData.put("结算金额", money(row.getOriginalAmount().add(before)));
|
||||||
|
afterData.put("费用项", row.getFeeItem());
|
||||||
|
afterData.put("调整金额", row.getAdjustAmount());
|
||||||
|
afterData.put("结算金额", money(row.getSettlementAmount()));
|
||||||
|
saveChange(settlementId, "合计费用项", row.getLineNo(), "调整",
|
||||||
|
"【" + row.getFeeItem() + "-调整金额】从【" + before + "】调整为【" + row.getAdjustAmount() + "】",
|
||||||
|
"", beforeData, afterData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (PreSettlementSummaryFee manualRow : manualRows) {
|
for (PreSettlementSummaryFee manualRow : manualRows) {
|
||||||
if (!retainedManualIds.contains(manualRow.getId())) {
|
if (!retainedManualIds.contains(manualRow.getId())) {
|
||||||
summaryFeeMapper.deleteById(manualRow.getId());
|
summaryFeeMapper.deleteById(manualRow.getId());
|
||||||
saveChange(settlementId, "合计费用项", null, "删除",
|
Map<String, Object> beforeData = new LinkedHashMap<>();
|
||||||
"删除" + manualRow.getFeeItem() + "费用" + manualRow.getSettlementAmount(), "");
|
Map<String, Object> afterData = new LinkedHashMap<>();
|
||||||
|
beforeData.put("费用类型", manualRow.getFeeType());
|
||||||
|
beforeData.put("费用项", manualRow.getFeeItem());
|
||||||
|
beforeData.put("调整金额", money(manualRow.getAdjustAmount()));
|
||||||
|
beforeData.put("结算金额", money(manualRow.getSettlementAmount()));
|
||||||
|
beforeData.put("备注", manualRow.getRemark());
|
||||||
|
afterData.put("费用类型", "");
|
||||||
|
afterData.put("费用项", "");
|
||||||
|
afterData.put("调整金额", BigDecimal.ZERO.setScale(2));
|
||||||
|
afterData.put("结算金额", BigDecimal.ZERO.setScale(2));
|
||||||
|
afterData.put("备注", "");
|
||||||
|
saveChange(settlementId, "合计费用项", manualRow.getLineNo(), "删除",
|
||||||
|
"删除合计费用项【" + manualRow.getFeeItem() + "】金额【" + money(manualRow.getSettlementAmount()) + "】",
|
||||||
|
"", beforeData, afterData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (PreSettlementSummaryFee generatedRow : existingGeneratedRows) {
|
for (PreSettlementSummaryFee generatedRow : existingGeneratedRows) {
|
||||||
@@ -1122,32 +1218,63 @@ public class PreSettlementServiceImpl extends BaseServiceImpl<PreSettlementMappe
|
|||||||
summaryFeeMapper.deleteById(generatedRow.getId());
|
summaryFeeMapper.deleteById(generatedRow.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
renumberSummaryFees(settlementId);
|
// lineNo 已按前端提交顺序写入,不再按旧序号重排,避免手工费用与系统归集费用顺序被打乱。
|
||||||
}
|
}
|
||||||
|
|
||||||
private void refreshDetail(PreSettlementDetail detail) {
|
private void refreshDetail(PreSettlementDetail detail) {
|
||||||
List<PreSettlementDetailFee> fees = detailFees(detail.getId());
|
List<PreSettlementDetailFee> fees = detailFees(detail.getId());
|
||||||
|
BigDecimal transportQuantity = fees.stream().map(PreSettlementDetailFee::getTransportQuantity)
|
||||||
|
.filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
|
BigDecimal mileage = fees.stream().map(PreSettlementDetailFee::getMileage)
|
||||||
|
.filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
BigDecimal freightAmount = fees.stream().map(PreSettlementDetailFee::getFreightAmount)
|
BigDecimal freightAmount = fees.stream().map(PreSettlementDetailFee::getFreightAmount)
|
||||||
.map(this::money).reduce(BigDecimal.ZERO, BigDecimal::add);
|
.map(this::money).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
BigDecimal originalAmount = fees.stream().map(PreSettlementDetailFee::getOriginalAmount)
|
BigDecimal originalAmount = fees.stream().map(PreSettlementDetailFee::getOriginalAmount)
|
||||||
.map(this::money).reduce(BigDecimal.ZERO, BigDecimal::add);
|
.map(this::money).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
BigDecimal settlementAmountTax = fees.stream().map(PreSettlementDetailFee::getSettlementAmountTax)
|
BigDecimal settlementAmountTax = fees.stream().map(PreSettlementDetailFee::getSettlementAmountTax)
|
||||||
.map(this::money).reduce(BigDecimal.ZERO, BigDecimal::add);
|
.map(this::money).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
|
BigDecimal settlementAmountNoTax = fees.stream().map(PreSettlementDetailFee::getSettlementAmountNoTax)
|
||||||
|
.filter(Objects::nonNull).map(this::money).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
Map<String, BigDecimal> feeItems = new LinkedHashMap<>();
|
Map<String, BigDecimal> feeItems = new LinkedHashMap<>();
|
||||||
fees.forEach(fee -> parseFeeItems(fee.getFeeItemsJson()).forEach((name, amount) ->
|
fees.forEach(fee -> parseFeeItems(fee.getFeeItemsJson()).forEach((name, amount) ->
|
||||||
feeItems.merge(name, money(amount), BigDecimal::add)));
|
feeItems.merge(name, money(amount), BigDecimal::add)));
|
||||||
|
// 运输单价无法按行简单求和,与前端暂存逻辑一致:取首行费用单价。
|
||||||
|
BigDecimal unitPrice = fees.stream().map(PreSettlementDetailFee::getUnitPrice)
|
||||||
|
.filter(Objects::nonNull).findFirst().orElse(null);
|
||||||
|
String remark = fees.stream().map(PreSettlementDetailFee::getRemark)
|
||||||
|
.filter(Func::isNotEmpty).findFirst().orElse(detail.getRemark());
|
||||||
|
detail.setTransportQuantity(money(transportQuantity));
|
||||||
|
detail.setMileage(mileage);
|
||||||
|
detail.setUnitPrice(unitPrice);
|
||||||
detail.setFreightAmount(money(freightAmount));
|
detail.setFreightAmount(money(freightAmount));
|
||||||
detail.setOriginalAmount(money(originalAmount));
|
detail.setOriginalAmount(money(originalAmount));
|
||||||
detail.setAdjustAmount(money(settlementAmountTax.subtract(originalAmount)));
|
detail.setAdjustAmount(money(settlementAmountTax.subtract(originalAmount)));
|
||||||
detail.setSettlementAmountTax(money(settlementAmountTax));
|
detail.setSettlementAmountTax(money(settlementAmountTax));
|
||||||
|
detail.setSettlementAmountNoTax(fees.stream().anyMatch(fee -> fee.getSettlementAmountNoTax() != null)
|
||||||
|
? money(settlementAmountNoTax) : null);
|
||||||
detail.setFeeItemsJson(JsonUtil.toJson(feeItems));
|
detail.setFeeItemsJson(JsonUtil.toJson(feeItems));
|
||||||
|
detail.setRemark(limitRemark(remark, 200));
|
||||||
detailMapper.updateById(detail);
|
detailMapper.updateById(detail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结算金额以结算合计为准(含手工新增费用),与详情页合计及付款申请取数口径一致。
|
||||||
|
* 合计行为空时回退为明细含税金额合计。
|
||||||
|
*/
|
||||||
private void refreshSettlementAmount(PreSettlement settlement) {
|
private void refreshSettlementAmount(PreSettlement settlement) {
|
||||||
BigDecimal settlementAmount = listDetails(settlement.getId()).stream()
|
List<PreSettlementSummaryFee> summaryFees = listSummaryFees(settlement.getId());
|
||||||
.map(PreSettlementDetail::getSettlementAmountTax).map(this::money)
|
BigDecimal settlementAmount;
|
||||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
if (!summaryFees.isEmpty()) {
|
||||||
|
settlementAmount = summaryFees.stream()
|
||||||
|
.map(PreSettlementSummaryFee::getSettlementAmount)
|
||||||
|
.map(this::money)
|
||||||
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
|
} else {
|
||||||
|
settlementAmount = listDetails(settlement.getId()).stream()
|
||||||
|
.map(PreSettlementDetail::getSettlementAmountTax)
|
||||||
|
.map(this::money)
|
||||||
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
|
}
|
||||||
settlement.setSettlementAmount(money(settlementAmount));
|
settlement.setSettlementAmount(money(settlementAmount));
|
||||||
BigDecimal rate = normalizeRate(settlement.getExchangeRate(), settlement.getCurrency());
|
BigDecimal rate = normalizeRate(settlement.getExchangeRate(), settlement.getCurrency());
|
||||||
settlement.setExchangeRate(rate);
|
settlement.setExchangeRate(rate);
|
||||||
@@ -1405,6 +1532,40 @@ public class PreSettlementServiceImpl extends BaseServiceImpl<PreSettlementMappe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void saveManualSummaryFeeChange(Long settlementId, boolean creating, String beforeFeeType,
|
||||||
|
String beforeFeeItem, BigDecimal beforeAdjustAmount, BigDecimal beforeSettlementAmount, String beforeRemark,
|
||||||
|
PreSettlementSummaryFee row) {
|
||||||
|
List<String> changes = new ArrayList<>();
|
||||||
|
Map<String, Object> beforeData = new LinkedHashMap<>();
|
||||||
|
Map<String, Object> afterData = new LinkedHashMap<>();
|
||||||
|
if (creating) {
|
||||||
|
changes.add("新增合计费用项【" + row.getFeeItem() + "】金额【" + money(row.getSettlementAmount()) + "】");
|
||||||
|
beforeData.put("费用类型", "");
|
||||||
|
beforeData.put("费用项", "");
|
||||||
|
beforeData.put("调整金额", BigDecimal.ZERO.setScale(2));
|
||||||
|
beforeData.put("结算金额", BigDecimal.ZERO.setScale(2));
|
||||||
|
beforeData.put("备注", "");
|
||||||
|
afterData.put("费用类型", row.getFeeType());
|
||||||
|
afterData.put("费用项", row.getFeeItem());
|
||||||
|
afterData.put("调整金额", money(row.getAdjustAmount()));
|
||||||
|
afterData.put("结算金额", money(row.getSettlementAmount()));
|
||||||
|
afterData.put("备注", row.getRemark());
|
||||||
|
saveChange(settlementId, "合计费用项", row.getLineNo(), "新增", String.join(";", changes), "",
|
||||||
|
beforeData, afterData);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
appendTextChange(changes, beforeData, afterData, "费用类型", beforeFeeType, row.getFeeType());
|
||||||
|
appendTextChange(changes, beforeData, afterData, "费用项", beforeFeeItem, row.getFeeItem());
|
||||||
|
appendChange(changes, beforeData, afterData, "调整金额", beforeAdjustAmount, row.getAdjustAmount());
|
||||||
|
appendChange(changes, beforeData, afterData, "结算金额", beforeSettlementAmount, row.getSettlementAmount());
|
||||||
|
appendTextChange(changes, beforeData, afterData, "备注", beforeRemark, row.getRemark());
|
||||||
|
if (changes.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
saveChange(settlementId, "合计费用项", row.getLineNo(), "调整", String.join(";", changes), "",
|
||||||
|
beforeData, afterData);
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
saveChange(settlementId, changeType, lineNo, operationType, content, reason, null, null);
|
||||||
|
|||||||
+10
-2
@@ -385,9 +385,17 @@ public class WaybillImportBatchServiceImpl extends BaseServiceImpl<WaybillImport
|
|||||||
public BusinessRemoveResultVO removeBatches(String ids) {
|
public BusinessRemoveResultVO removeBatches(String ids) {
|
||||||
List<Long> idList = Func.toLongList(ids);
|
List<Long> idList = Func.toLongList(ids);
|
||||||
if (Func.isEmpty(idList)) throw new ServiceException("请选择需要删除的运单批次");
|
if (Func.isEmpty(idList)) throw new ServiceException("请选择需要删除的运单批次");
|
||||||
|
List<WaybillImportBatch> batches = listByIds(idList).stream()
|
||||||
|
.filter(batch -> !Objects.equals(batch.getIsDeleted(), 1))
|
||||||
|
.toList();
|
||||||
|
// 与前端一致:仅草稿可删;选中含已完成/进行中时整批拒绝
|
||||||
|
boolean hasNonDraft = batches.stream()
|
||||||
|
.anyMatch(batch -> !STATUS_DRAFT.equals(batch.getImportStatus()));
|
||||||
|
if (hasNonDraft) {
|
||||||
|
throw new ServiceException("已完成运单不可删除");
|
||||||
|
}
|
||||||
BusinessRemoveResultVO result = new BusinessRemoveResultVO();
|
BusinessRemoveResultVO result = new BusinessRemoveResultVO();
|
||||||
for (WaybillImportBatch batch : listByIds(idList)) {
|
for (WaybillImportBatch batch : batches) {
|
||||||
if (Objects.equals(batch.getIsDeleted(), 1)) continue;
|
|
||||||
List<Waybill> waybills = waybillService.list(Wrappers.<Waybill>lambdaQuery()
|
List<Waybill> waybills = waybillService.list(Wrappers.<Waybill>lambdaQuery()
|
||||||
.eq(Waybill::getImportBatchId, batch.getId()).eq(Waybill::getIsDeleted, 0));
|
.eq(Waybill::getImportBatchId, batch.getId()).eq(Waybill::getIsDeleted, 0));
|
||||||
if (Func.isNotEmpty(waybills)) {
|
if (Func.isNotEmpty(waybills)) {
|
||||||
|
|||||||
@@ -44,7 +44,9 @@ CREATE TABLE IF NOT EXISTS `blade_formal_settlement_change_record` (
|
|||||||
`update_user` bigint(20) DEFAULT NULL, `update_time` datetime DEFAULT NULL, `status` int(11) DEFAULT '1', `is_deleted` int(11) DEFAULT '0',
|
`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 '变更类型',
|
`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 '操作类型',
|
`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 '变更原因',
|
`change_content` text NOT NULL COMMENT '变更内容',
|
||||||
|
`before_data` longtext COMMENT '变更前数据JSON', `after_data` longtext COMMENT '变更后数据JSON',
|
||||||
|
`change_reason` varchar(200) DEFAULT NULL COMMENT '变更原因',
|
||||||
`operator_name` varchar(100) DEFAULT NULL COMMENT '操作人', `change_time` datetime NOT 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`),
|
PRIMARY KEY (`id`), KEY `idx_formal_settlement_change_bill` (`formal_settlement_id`),
|
||||||
KEY `idx_formal_settlement_change_time` (`change_time`)
|
KEY `idx_formal_settlement_change_time` (`change_time`)
|
||||||
@@ -123,17 +125,29 @@ CREATE TABLE IF NOT EXISTS `blade_formal_settlement_payment` (
|
|||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='正式结算付款申请';
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='正式结算付款申请';
|
||||||
|
|
||||||
INSERT INTO `blade_menu` (`id`,`parent_id`,`code`,`name`,`alias`,`path`,`source`,`sort`,`category`,`action`,`is_open`,`component`,`remark`,`is_deleted`) VALUES
|
INSERT INTO `blade_menu` (`id`,`parent_id`,`code`,`name`,`alias`,`path`,`source`,`sort`,`category`,`action`,`is_open`,`component`,`remark`,`is_deleted`) VALUES
|
||||||
(2090000000000001040,2090000000000001000,'formal_settlement','正式结算单','formal_settlement','/settlement/formal-settlement','iconfont icon-caidanguanli',4,1,0,1,NULL,'',0),
|
(2090000000000001040,2090000000000001000,'payment_settlement','付款结算单','payment_settlement','/settlement/payment-settlement','iconfont icon-caidanguanli',4,1,0,1,NULL,'',0),
|
||||||
(2090000000000001041,2090000000000001040,'formal_settlement_view','查看','formal_settlement_view','','',1,2,0,1,NULL,'',0),
|
(2090000000000001041,2090000000000001040,'payment_settlement_view','查看','payment_settlement_view','','',1,2,0,1,NULL,'',0),
|
||||||
(2090000000000001042,2090000000000001040,'formal_settlement_add','新增','formal_settlement_add','','',2,2,0,1,NULL,'',0),
|
(2090000000000001042,2090000000000001040,'payment_settlement_add','新增','payment_settlement_add','','',2,2,0,1,NULL,'',0),
|
||||||
(2090000000000001043,2090000000000001040,'formal_settlement_edit','编辑','formal_settlement_edit','','',3,2,0,1,NULL,'',0),
|
(2090000000000001043,2090000000000001040,'payment_settlement_edit','编辑','payment_settlement_edit','','',3,2,0,1,NULL,'',0),
|
||||||
(2090000000000001044,2090000000000001040,'formal_settlement_delete','删除','formal_settlement_delete','','',4,2,0,1,NULL,'',0),
|
(2090000000000001044,2090000000000001040,'payment_settlement_delete','删除','payment_settlement_delete','','',4,2,0,1,NULL,'',0),
|
||||||
(2090000000000001045,2090000000000001040,'formal_settlement_submit','提交审批','formal_settlement_submit','','',5,2,0,1,NULL,'',0),
|
(2090000000000001045,2090000000000001040,'payment_settlement_submit','提交审批','payment_settlement_submit','','',5,2,0,1,NULL,'',0),
|
||||||
(2090000000000001046,2090000000000001040,'formal_settlement_approve','审批','formal_settlement_approve','','',6,2,0,1,NULL,'',0),
|
(2090000000000001046,2090000000000001040,'payment_settlement_approve','审批','payment_settlement_approve','','',6,2,0,1,NULL,'',0),
|
||||||
(2090000000000001047,2090000000000001040,'formal_settlement_sync','同步金蝶','formal_settlement_sync','','',7,2,0,1,NULL,'',0),
|
(2090000000000001047,2090000000000001040,'payment_settlement_sync','同步金蝶','payment_settlement_sync','','',7,2,0,1,NULL,'',0),
|
||||||
(2090000000000001048,2090000000000001040,'formal_settlement_print','打印','formal_settlement_print','','',8,2,0,1,NULL,'',0),
|
(2090000000000001048,2090000000000001040,'payment_settlement_print','打印','payment_settlement_print','','',8,2,0,1,NULL,'',0),
|
||||||
(2090000000000001049,2090000000000001040,'formal_settlement_export','导出','formal_settlement_export','','',9,2,0,1,NULL,'',0),
|
(2090000000000001049,2090000000000001040,'payment_settlement_export','导出','payment_settlement_export','','',9,2,0,1,NULL,'',0),
|
||||||
(2090000000000001050,2090000000000001040,'formal_settlement_void','作废','formal_settlement_void','','',10,2,0,1,NULL,'',0),
|
(2090000000000001050,2090000000000001040,'payment_settlement_void','作废','payment_settlement_void','','',10,2,0,1,NULL,'',0),
|
||||||
(2090000000000001051,2090000000000001040,'formal_settlement_adjust','明细调整','formal_settlement_adjust','','',11,2,0,1,NULL,'',0),
|
(2090000000000001051,2090000000000001040,'payment_settlement_adjust','明细调整','payment_settlement_adjust','','',11,2,0,1,NULL,'',0),
|
||||||
(2090000000000001052,2090000000000001040,'formal_settlement_payment','付款申请','formal_settlement_payment','','',12,2,0,1,NULL,'',0)
|
(2090000000000001052,2090000000000001040,'payment_settlement_payment','付款申请','payment_settlement_payment','','',12,2,0,1,NULL,'',0),
|
||||||
|
(2090000000000002100,2090000000000001000,'receipt_settlement','收款结算单','receipt_settlement','/settlement/receipt-settlement','iconfont icon-caidanguanli',5,1,0,1,NULL,'',0),
|
||||||
|
(2090000000000002101,2090000000000002100,'receipt_settlement_view','查看','receipt_settlement_view','','',1,2,0,1,NULL,'',0),
|
||||||
|
(2090000000000002102,2090000000000002100,'receipt_settlement_add','新增','receipt_settlement_add','','',2,2,0,1,NULL,'',0),
|
||||||
|
(2090000000000002103,2090000000000002100,'receipt_settlement_edit','编辑','receipt_settlement_edit','','',3,2,0,1,NULL,'',0),
|
||||||
|
(2090000000000002104,2090000000000002100,'receipt_settlement_delete','删除','receipt_settlement_delete','','',4,2,0,1,NULL,'',0),
|
||||||
|
(2090000000000002105,2090000000000002100,'receipt_settlement_submit','提交审批','receipt_settlement_submit','','',5,2,0,1,NULL,'',0),
|
||||||
|
(2090000000000002106,2090000000000002100,'receipt_settlement_approve','审批','receipt_settlement_approve','','',6,2,0,1,NULL,'',0),
|
||||||
|
(2090000000000002107,2090000000000002100,'receipt_settlement_sync','同步金蝶','receipt_settlement_sync','','',7,2,0,1,NULL,'',0),
|
||||||
|
(2090000000000002108,2090000000000002100,'receipt_settlement_print','打印','receipt_settlement_print','','',8,2,0,1,NULL,'',0),
|
||||||
|
(2090000000000002109,2090000000000002100,'receipt_settlement_export','导出','receipt_settlement_export','','',9,2,0,1,NULL,'',0),
|
||||||
|
(2090000000000002110,2090000000000002100,'receipt_settlement_void','作废','receipt_settlement_void','','',10,2,0,1,NULL,'',0),
|
||||||
|
(2090000000000002111,2090000000000002100,'receipt_settlement_adjust','明细调整','receipt_settlement_adjust','','',11,2,0,1,NULL,'',0)
|
||||||
ON DUPLICATE KEY UPDATE `name`=VALUES(`name`),`path`=VALUES(`path`),`is_deleted`=0;
|
ON DUPLICATE KEY UPDATE `name`=VALUES(`name`),`path`=VALUES(`path`),`is_deleted`=0;
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ CREATE TABLE IF NOT EXISTS `blade_formal_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',
|
||||||
`change_reason` varchar(200) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '变更原因',
|
`change_reason` varchar(200) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '变更原因',
|
||||||
`operator_name` varchar(100) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '操作人',
|
`operator_name` varchar(100) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '操作人',
|
||||||
`change_time` datetime NOT NULL COMMENT '变更时间',
|
`change_time` datetime NOT NULL COMMENT '变更时间',
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
-- 正式结算变更记录补充前后值明细,与预结算变更记录口径一致。
|
||||||
|
SET @before_data_exists := (
|
||||||
|
SELECT COUNT(1) FROM information_schema.COLUMNS
|
||||||
|
WHERE TABLE_SCHEMA = DATABASE()
|
||||||
|
AND TABLE_NAME = 'blade_formal_settlement_change_record'
|
||||||
|
AND COLUMN_NAME = 'before_data'
|
||||||
|
);
|
||||||
|
SET @before_data_sql := IF(
|
||||||
|
@before_data_exists = 0,
|
||||||
|
'ALTER TABLE `blade_formal_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(1) FROM information_schema.COLUMNS
|
||||||
|
WHERE TABLE_SCHEMA = DATABASE()
|
||||||
|
AND TABLE_NAME = 'blade_formal_settlement_change_record'
|
||||||
|
AND COLUMN_NAME = 'after_data'
|
||||||
|
);
|
||||||
|
SET @after_data_sql := IF(
|
||||||
|
@after_data_exists = 0,
|
||||||
|
'ALTER TABLE `blade_formal_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;
|
||||||
@@ -200,7 +200,7 @@ CREATE TABLE IF NOT EXISTS `blade_pre_settlement_change_record` (
|
|||||||
INSERT INTO `blade_menu`
|
INSERT INTO `blade_menu`
|
||||||
(`id`, `parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `component`, `remark`, `is_deleted`)
|
(`id`, `parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `component`, `remark`, `is_deleted`)
|
||||||
VALUES
|
VALUES
|
||||||
(2090000000000001020, 2090000000000001000, 'pre_settlement', '预结算', 'pre_settlement', '/settlement/pre-settlement', 'iconfont icon-caidanguanli', 3, 1, 0, 1, NULL, '', 0),
|
(2090000000000001020, 2090000000000001000, 'pre_settlement', '预付结算单', 'pre_settlement', '/settlement/pre-settlement', 'iconfont icon-caidanguanli', 3, 1, 0, 1, NULL, '', 0),
|
||||||
(2090000000000001021, 2090000000000001020, 'pre_settlement_view', '查看', 'pre_settlement_view', '', '', 1, 2, 0, 1, NULL, '', 0),
|
(2090000000000001021, 2090000000000001020, 'pre_settlement_view', '查看', 'pre_settlement_view', '', '', 1, 2, 0, 1, NULL, '', 0),
|
||||||
(2090000000000001022, 2090000000000001020, 'pre_settlement_add', '新增', 'pre_settlement_add', '', '', 2, 2, 0, 1, NULL, '', 0),
|
(2090000000000001022, 2090000000000001020, 'pre_settlement_add', '新增', 'pre_settlement_add', '', '', 2, 2, 0, 1, NULL, '', 0),
|
||||||
(2090000000000001023, 2090000000000001020, 'pre_settlement_edit', '编辑', 'pre_settlement_edit', '', '', 3, 2, 0, 1, NULL, '', 0),
|
(2090000000000001023, 2090000000000001020, 'pre_settlement_edit', '编辑', 'pre_settlement_edit', '', '', 3, 2, 0, 1, NULL, '', 0),
|
||||||
|
|||||||
@@ -0,0 +1,163 @@
|
|||||||
|
-- 结算菜单调整:
|
||||||
|
-- 1)预结算 → 预付结算单
|
||||||
|
-- 2)正式结算单拆分为:付款结算单(应付)、收款结算单(应收)
|
||||||
|
-- 执行后需重新登录;已授权「正式结算单/付款结算单」的角色会同步授权「收款结算单」。
|
||||||
|
|
||||||
|
-- ① 预结算改名
|
||||||
|
UPDATE `blade_menu`
|
||||||
|
SET `name` = '预付结算单'
|
||||||
|
WHERE `code` = 'pre_settlement'
|
||||||
|
AND `is_deleted` = 0;
|
||||||
|
|
||||||
|
-- ② 原正式结算单菜单改为「付款结算单」(保留原菜单 id,角色授权不丢)
|
||||||
|
UPDATE `blade_menu`
|
||||||
|
SET `code` = 'payment_settlement',
|
||||||
|
`name` = '付款结算单',
|
||||||
|
`alias` = 'payment_settlement',
|
||||||
|
`path` = '/settlement/payment-settlement',
|
||||||
|
`is_deleted` = 0
|
||||||
|
WHERE `code` IN ('formal_settlement', 'payment_settlement')
|
||||||
|
AND `category` = 1
|
||||||
|
AND `is_deleted` = 0;
|
||||||
|
|
||||||
|
-- 付款结算单按钮权限码:formal_settlement_* → payment_settlement_*
|
||||||
|
UPDATE `blade_menu` child
|
||||||
|
INNER JOIN `blade_menu` parent
|
||||||
|
ON parent.`id` = child.`parent_id`
|
||||||
|
AND parent.`code` = 'payment_settlement'
|
||||||
|
AND parent.`is_deleted` = 0
|
||||||
|
SET child.`code` = REPLACE(child.`code`, 'formal_settlement_', 'payment_settlement_'),
|
||||||
|
child.`alias` = REPLACE(IFNULL(child.`alias`, child.`code`), 'formal_settlement_', 'payment_settlement_'),
|
||||||
|
child.`is_deleted` = 0
|
||||||
|
WHERE child.`category` = 2
|
||||||
|
AND child.`code` LIKE 'formal_settlement_%';
|
||||||
|
|
||||||
|
-- ③ 新增「收款结算单」菜单
|
||||||
|
INSERT INTO `blade_menu`
|
||||||
|
(`id`,`parent_id`,`code`,`name`,`alias`,`path`,`source`,`sort`,`category`,`action`,`is_open`,`component`,`remark`,`is_deleted`)
|
||||||
|
SELECT
|
||||||
|
2090000000000002100,
|
||||||
|
parent.`parent_id`,
|
||||||
|
'receipt_settlement',
|
||||||
|
'收款结算单',
|
||||||
|
'receipt_settlement',
|
||||||
|
'/settlement/receipt-settlement',
|
||||||
|
IFNULL(parent.`source`, 'iconfont icon-caidanguanli'),
|
||||||
|
IFNULL(parent.`sort`, 4) + 1,
|
||||||
|
1, 0, 1, NULL, '', 0
|
||||||
|
FROM `blade_menu` parent
|
||||||
|
WHERE parent.`code` = 'payment_settlement'
|
||||||
|
AND parent.`is_deleted` = 0
|
||||||
|
AND NOT EXISTS (
|
||||||
|
SELECT 1 FROM `blade_menu` x WHERE x.`code` = 'receipt_settlement' AND x.`is_deleted` = 0
|
||||||
|
)
|
||||||
|
LIMIT 1;
|
||||||
|
|
||||||
|
INSERT INTO `blade_menu`
|
||||||
|
(`id`,`parent_id`,`code`,`name`,`alias`,`path`,`source`,`sort`,`category`,`action`,`is_open`,`component`,`remark`,`is_deleted`)
|
||||||
|
SELECT 2090000000000002101, p.id, 'receipt_settlement_view', '查看', 'receipt_settlement_view', '', '', 1, 2, 0, 1, NULL, '', 0
|
||||||
|
FROM `blade_menu` p WHERE p.code = 'receipt_settlement' AND p.is_deleted = 0
|
||||||
|
AND NOT EXISTS (SELECT 1 FROM `blade_menu` x WHERE x.code = 'receipt_settlement_view' AND x.is_deleted = 0)
|
||||||
|
LIMIT 1;
|
||||||
|
INSERT INTO `blade_menu`
|
||||||
|
(`id`,`parent_id`,`code`,`name`,`alias`,`path`,`source`,`sort`,`category`,`action`,`is_open`,`component`,`remark`,`is_deleted`)
|
||||||
|
SELECT 2090000000000002102, p.id, 'receipt_settlement_add', '新增', 'receipt_settlement_add', '', '', 2, 2, 0, 1, NULL, '', 0
|
||||||
|
FROM `blade_menu` p WHERE p.code = 'receipt_settlement' AND p.is_deleted = 0
|
||||||
|
AND NOT EXISTS (SELECT 1 FROM `blade_menu` x WHERE x.code = 'receipt_settlement_add' AND x.is_deleted = 0)
|
||||||
|
LIMIT 1;
|
||||||
|
INSERT INTO `blade_menu`
|
||||||
|
(`id`,`parent_id`,`code`,`name`,`alias`,`path`,`source`,`sort`,`category`,`action`,`is_open`,`component`,`remark`,`is_deleted`)
|
||||||
|
SELECT 2090000000000002103, p.id, 'receipt_settlement_edit', '编辑', 'receipt_settlement_edit', '', '', 3, 2, 0, 1, NULL, '', 0
|
||||||
|
FROM `blade_menu` p WHERE p.code = 'receipt_settlement' AND p.is_deleted = 0
|
||||||
|
AND NOT EXISTS (SELECT 1 FROM `blade_menu` x WHERE x.code = 'receipt_settlement_edit' AND x.is_deleted = 0)
|
||||||
|
LIMIT 1;
|
||||||
|
INSERT INTO `blade_menu`
|
||||||
|
(`id`,`parent_id`,`code`,`name`,`alias`,`path`,`source`,`sort`,`category`,`action`,`is_open`,`component`,`remark`,`is_deleted`)
|
||||||
|
SELECT 2090000000000002104, p.id, 'receipt_settlement_delete', '删除', 'receipt_settlement_delete', '', '', 4, 2, 0, 1, NULL, '', 0
|
||||||
|
FROM `blade_menu` p WHERE p.code = 'receipt_settlement' AND p.is_deleted = 0
|
||||||
|
AND NOT EXISTS (SELECT 1 FROM `blade_menu` x WHERE x.code = 'receipt_settlement_delete' AND x.is_deleted = 0)
|
||||||
|
LIMIT 1;
|
||||||
|
INSERT INTO `blade_menu`
|
||||||
|
(`id`,`parent_id`,`code`,`name`,`alias`,`path`,`source`,`sort`,`category`,`action`,`is_open`,`component`,`remark`,`is_deleted`)
|
||||||
|
SELECT 2090000000000002105, p.id, 'receipt_settlement_submit', '提交审批', 'receipt_settlement_submit', '', '', 5, 2, 0, 1, NULL, '', 0
|
||||||
|
FROM `blade_menu` p WHERE p.code = 'receipt_settlement' AND p.is_deleted = 0
|
||||||
|
AND NOT EXISTS (SELECT 1 FROM `blade_menu` x WHERE x.code = 'receipt_settlement_submit' AND x.is_deleted = 0)
|
||||||
|
LIMIT 1;
|
||||||
|
INSERT INTO `blade_menu`
|
||||||
|
(`id`,`parent_id`,`code`,`name`,`alias`,`path`,`source`,`sort`,`category`,`action`,`is_open`,`component`,`remark`,`is_deleted`)
|
||||||
|
SELECT 2090000000000002106, p.id, 'receipt_settlement_approve', '审批', 'receipt_settlement_approve', '', '', 6, 2, 0, 1, NULL, '', 0
|
||||||
|
FROM `blade_menu` p WHERE p.code = 'receipt_settlement' AND p.is_deleted = 0
|
||||||
|
AND NOT EXISTS (SELECT 1 FROM `blade_menu` x WHERE x.code = 'receipt_settlement_approve' AND x.is_deleted = 0)
|
||||||
|
LIMIT 1;
|
||||||
|
INSERT INTO `blade_menu`
|
||||||
|
(`id`,`parent_id`,`code`,`name`,`alias`,`path`,`source`,`sort`,`category`,`action`,`is_open`,`component`,`remark`,`is_deleted`)
|
||||||
|
SELECT 2090000000000002107, p.id, 'receipt_settlement_sync', '同步金蝶', 'receipt_settlement_sync', '', '', 7, 2, 0, 1, NULL, '', 0
|
||||||
|
FROM `blade_menu` p WHERE p.code = 'receipt_settlement' AND p.is_deleted = 0
|
||||||
|
AND NOT EXISTS (SELECT 1 FROM `blade_menu` x WHERE x.code = 'receipt_settlement_sync' AND x.is_deleted = 0)
|
||||||
|
LIMIT 1;
|
||||||
|
INSERT INTO `blade_menu`
|
||||||
|
(`id`,`parent_id`,`code`,`name`,`alias`,`path`,`source`,`sort`,`category`,`action`,`is_open`,`component`,`remark`,`is_deleted`)
|
||||||
|
SELECT 2090000000000002108, p.id, 'receipt_settlement_print', '打印', 'receipt_settlement_print', '', '', 8, 2, 0, 1, NULL, '', 0
|
||||||
|
FROM `blade_menu` p WHERE p.code = 'receipt_settlement' AND p.is_deleted = 0
|
||||||
|
AND NOT EXISTS (SELECT 1 FROM `blade_menu` x WHERE x.code = 'receipt_settlement_print' AND x.is_deleted = 0)
|
||||||
|
LIMIT 1;
|
||||||
|
INSERT INTO `blade_menu`
|
||||||
|
(`id`,`parent_id`,`code`,`name`,`alias`,`path`,`source`,`sort`,`category`,`action`,`is_open`,`component`,`remark`,`is_deleted`)
|
||||||
|
SELECT 2090000000000002109, p.id, 'receipt_settlement_export', '导出', 'receipt_settlement_export', '', '', 9, 2, 0, 1, NULL, '', 0
|
||||||
|
FROM `blade_menu` p WHERE p.code = 'receipt_settlement' AND p.is_deleted = 0
|
||||||
|
AND NOT EXISTS (SELECT 1 FROM `blade_menu` x WHERE x.code = 'receipt_settlement_export' AND x.is_deleted = 0)
|
||||||
|
LIMIT 1;
|
||||||
|
INSERT INTO `blade_menu`
|
||||||
|
(`id`,`parent_id`,`code`,`name`,`alias`,`path`,`source`,`sort`,`category`,`action`,`is_open`,`component`,`remark`,`is_deleted`)
|
||||||
|
SELECT 2090000000000002110, p.id, 'receipt_settlement_void', '作废', 'receipt_settlement_void', '', '', 10, 2, 0, 1, NULL, '', 0
|
||||||
|
FROM `blade_menu` p WHERE p.code = 'receipt_settlement' AND p.is_deleted = 0
|
||||||
|
AND NOT EXISTS (SELECT 1 FROM `blade_menu` x WHERE x.code = 'receipt_settlement_void' AND x.is_deleted = 0)
|
||||||
|
LIMIT 1;
|
||||||
|
INSERT INTO `blade_menu`
|
||||||
|
(`id`,`parent_id`,`code`,`name`,`alias`,`path`,`source`,`sort`,`category`,`action`,`is_open`,`component`,`remark`,`is_deleted`)
|
||||||
|
SELECT 2090000000000002111, p.id, 'receipt_settlement_adjust', '明细调整', 'receipt_settlement_adjust', '', '', 11, 2, 0, 1, NULL, '', 0
|
||||||
|
FROM `blade_menu` p WHERE p.code = 'receipt_settlement' AND p.is_deleted = 0
|
||||||
|
AND NOT EXISTS (SELECT 1 FROM `blade_menu` x WHERE x.code = 'receipt_settlement_adjust' AND x.is_deleted = 0)
|
||||||
|
LIMIT 1;
|
||||||
|
|
||||||
|
-- ④ 角色授权:持有付款结算单的角色同步收款结算单(含按钮)
|
||||||
|
INSERT INTO `blade_role_menu` (`id`, `menu_id`, `role_id`)
|
||||||
|
SELECT
|
||||||
|
2091200000000000000 + CAST(rm.`role_id` AS UNSIGNED) % 100000,
|
||||||
|
receipt.`id`,
|
||||||
|
rm.`role_id`
|
||||||
|
FROM `blade_role_menu` rm
|
||||||
|
JOIN `blade_menu` payment ON payment.`id` = rm.`menu_id`
|
||||||
|
AND payment.`code` = 'payment_settlement'
|
||||||
|
AND payment.`is_deleted` = 0
|
||||||
|
JOIN `blade_menu` receipt ON receipt.`code` = 'receipt_settlement'
|
||||||
|
AND receipt.`is_deleted` = 0
|
||||||
|
WHERE NOT EXISTS (
|
||||||
|
SELECT 1 FROM `blade_role_menu` x
|
||||||
|
WHERE x.`menu_id` = receipt.`id` AND x.`role_id` = rm.`role_id`
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO `blade_role_menu` (`id`, `menu_id`, `role_id`)
|
||||||
|
SELECT
|
||||||
|
2091300000000000000
|
||||||
|
+ (CAST(rm.`role_id` AS UNSIGNED) % 100000) * 20
|
||||||
|
+ (CAST(receipt_btn.`id` AS UNSIGNED) % 20),
|
||||||
|
receipt_btn.`id`,
|
||||||
|
rm.`role_id`
|
||||||
|
FROM `blade_role_menu` rm
|
||||||
|
JOIN `blade_menu` payment_btn ON payment_btn.`id` = rm.`menu_id`
|
||||||
|
AND payment_btn.`code` LIKE 'payment_settlement_%'
|
||||||
|
AND payment_btn.`is_deleted` = 0
|
||||||
|
JOIN `blade_menu` receipt_btn
|
||||||
|
ON receipt_btn.`code` = REPLACE(payment_btn.`code`, 'payment_settlement_', 'receipt_settlement_')
|
||||||
|
AND receipt_btn.`is_deleted` = 0
|
||||||
|
WHERE NOT EXISTS (
|
||||||
|
SELECT 1 FROM `blade_role_menu` x
|
||||||
|
WHERE x.`menu_id` = receipt_btn.`id` AND x.`role_id` = rm.`role_id`
|
||||||
|
);
|
||||||
|
|
||||||
|
-- ⑤ 残留旧正式结算菜单隐藏
|
||||||
|
UPDATE `blade_menu`
|
||||||
|
SET `is_deleted` = 1
|
||||||
|
WHERE `code` = 'formal_settlement'
|
||||||
|
AND `category` = 1;
|
||||||
Reference in New Issue
Block a user