调整结算管理
This commit is contained in:
+2
-2
@@ -81,8 +81,8 @@ public class FormalSettlementController extends BladeController {
|
||||
@GetMapping("/next-no")
|
||||
@ApiOperationSupport(order = 5)
|
||||
@Operation(summary = "获取最新正式结算单号")
|
||||
public R<String> nextNo() {
|
||||
return R.data(formalSettlementService.nextNo());
|
||||
public R<String> nextNo(@RequestParam String settlementType) {
|
||||
return R.data(formalSettlementService.nextNo(settlementType));
|
||||
}
|
||||
|
||||
@GetMapping("/fee-options")
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ import org.springblade.transport.pojo.dto.FormalSettlementPaymentRequest;
|
||||
public interface IFormalSettlementService extends BaseService<FormalSettlement> {
|
||||
IPage<FormalSettlementVO> selectPage(IPage<FormalSettlement> page, FormalSettlementVO query);
|
||||
IPage<PreSettlementVO> candidatePreSettlements(IPage<PreSettlement> page, PreSettlementVO query);
|
||||
String nextNo();
|
||||
String nextNo(String settlementType);
|
||||
FormalSettlementVO detail(Long id);
|
||||
Long saveDraft(FormalSettlementSaveRequest request);
|
||||
void removeDraft(Long id);
|
||||
|
||||
+13
-4
@@ -144,8 +144,13 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized String nextNo() {
|
||||
String prefix = "JS" + LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE);
|
||||
public synchronized String nextNo(String settlementType) {
|
||||
String code = switch (settlementType) {
|
||||
case "receivable" -> "SJS";
|
||||
case "payable" -> "FJS";
|
||||
default -> throw new ServiceException("结算类型不正确");
|
||||
};
|
||||
String prefix = code + LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE);
|
||||
List<String> numbers = list(Wrappers.<FormalSettlement>lambdaQuery()
|
||||
.select(FormalSettlement::getFormalSettlementNo)
|
||||
.likeRight(FormalSettlement::getFormalSettlementNo, prefix))
|
||||
@@ -160,7 +165,7 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
||||
.likeRight(FormalSettlement::getFormalSettlementNo, prefix))) + 1;
|
||||
}
|
||||
}
|
||||
return prefix + String.format("%04d", sequence);
|
||||
return prefix + String.format("%05d", sequence);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -207,7 +212,7 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
||||
throw new ServiceException("合同未审核完成,不可转正式结算单");
|
||||
}
|
||||
if (settlement.getId() == null) {
|
||||
settlement.setFormalSettlementNo(nextNo());
|
||||
settlement.setFormalSettlementNo(nextNo(settlementType));
|
||||
settlement.setApprovalStatus(DRAFT);
|
||||
settlement.setCurrentNode("草稿");
|
||||
settlement.setSourceType(sources.isEmpty() ? "应收应付" : directDetails.isEmpty() ? "预结算合并" : "混合来源");
|
||||
@@ -225,6 +230,9 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
||||
.map(this::money).reduce(BigDecimal.ZERO, BigDecimal::add));
|
||||
settlement.setPaidAmount(sources.stream().map(PreSettlement::getAdvancePaidAmount)
|
||||
.map(this::money).reduce(BigDecimal.ZERO, BigDecimal::add));
|
||||
settlement.setRemainingPayableAmount(money(settlement.getSettlementAmount())
|
||||
.subtract(money(settlement.getPaidAmount())).max(BigDecimal.ZERO));
|
||||
if (settlement.getInvoiceAmount() == null) settlement.setInvoiceAmount(BigDecimal.ZERO.setScale(2));
|
||||
settlement.setLocalSettlementAmount(settlement.getSettlementAmount().multiply(settlement.getExchangeRate()));
|
||||
settlement.setAttachmentsJson(request.getAttachmentsJson());
|
||||
settlement.setRemark(limit(request.getRemark(), 200));
|
||||
@@ -511,6 +519,7 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
||||
settlement.setSettlementAmount(amount);
|
||||
settlement.setLocalSettlementAmount(amount.multiply(
|
||||
settlement.getExchangeRate() == null ? BigDecimal.ONE : settlement.getExchangeRate()));
|
||||
settlement.setRemainingPayableAmount(amount.subtract(money(settlement.getPaidAmount())).max(BigDecimal.ZERO));
|
||||
updateById(settlement);
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -522,6 +522,7 @@ public class InvoiceApplicationServiceImpl extends BaseServiceImpl<InvoiceApplic
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
String status = allocated.compareTo(BigDecimal.ZERO) <= 0 ? "unreceived"
|
||||
: allocated.compareTo(money(settlement.getSettlementAmount())) >= 0 ? "completed" : "partial";
|
||||
settlement.setInvoiceAmount(allocated);
|
||||
settlement.setInvoiceStatus(status);
|
||||
formalSettlementMapper.updateById(settlement);
|
||||
}
|
||||
|
||||
+26
@@ -57,9 +57,11 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -208,6 +210,7 @@ public class InvoiceReceiptServiceImpl extends BaseServiceImpl<InvoiceReceiptMap
|
||||
validateRequest(request);
|
||||
boolean creating = request.getId() == null;
|
||||
InvoiceReceipt entity = creating ? new InvoiceReceipt() : editable(request.getId());
|
||||
List<Long> oldSettlementIds = entity.getId() == null ? List.of() : relationSettlementIds(entity.getId());
|
||||
KingdeeInvoicePool invoice = lockedInvoice(request.getKingdeeInvoicePoolId());
|
||||
assertInvoiceUnused(invoice, entity.getId());
|
||||
|
||||
@@ -260,6 +263,9 @@ public class InvoiceReceiptServiceImpl extends BaseServiceImpl<InvoiceReceiptMap
|
||||
settlementRelationMapper.delete(Wrappers.<InvoiceReceiptSettlement>lambdaQuery()
|
||||
.eq(InvoiceReceiptSettlement::getInvoiceReceiptId, entity.getId()));
|
||||
saveRelations(entity.getId(), requestedRows, settlementMap);
|
||||
Set<Long> refreshIds = new LinkedHashSet<>(oldSettlementIds);
|
||||
refreshIds.addAll(settlementMap.keySet());
|
||||
refreshIds.forEach(this::refreshSettlementInvoiceStatus);
|
||||
record(entity.getId(), creating ? "create" : "save", creating ? "创建草稿" : "保存草稿",
|
||||
entity.getApprovalStatus(), entity.getApprovalStatus(), null, entity.getKingdeeBillNo());
|
||||
return entity.getId();
|
||||
@@ -272,11 +278,13 @@ public class InvoiceReceiptServiceImpl extends BaseServiceImpl<InvoiceReceiptMap
|
||||
if (!DRAFT.equals(entity.getApprovalStatus())) {
|
||||
throw new ServiceException("仅草稿状态的收票登记允许删除");
|
||||
}
|
||||
List<Long> settlementIds = relationSettlementIds(id);
|
||||
settlementRelationMapper.delete(Wrappers.<InvoiceReceiptSettlement>lambdaQuery()
|
||||
.eq(InvoiceReceiptSettlement::getInvoiceReceiptId, id));
|
||||
recordMapper.delete(Wrappers.<InvoiceReceiptRecord>lambdaQuery()
|
||||
.eq(InvoiceReceiptRecord::getInvoiceReceiptId, id));
|
||||
removeById(entity);
|
||||
settlementIds.forEach(this::refreshSettlementInvoiceStatus);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -466,6 +474,23 @@ public class InvoiceReceiptServiceImpl extends BaseServiceImpl<InvoiceReceiptMap
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
}
|
||||
|
||||
private List<Long> relationSettlementIds(Long receiptId) {
|
||||
return settlementRelationMapper.selectList(Wrappers.<InvoiceReceiptSettlement>lambdaQuery()
|
||||
.eq(InvoiceReceiptSettlement::getInvoiceReceiptId, receiptId)).stream()
|
||||
.map(InvoiceReceiptSettlement::getFormalSettlementId).distinct().toList();
|
||||
}
|
||||
|
||||
private void refreshSettlementInvoiceStatus(Long settlementId) {
|
||||
FormalSettlement settlement = formalSettlementMapper.selectById(settlementId);
|
||||
if (settlement == null) return;
|
||||
BigDecimal invoiceAmount = receivedAmount(settlementId, null);
|
||||
String invoiceStatus = invoiceAmount.compareTo(BigDecimal.ZERO) <= 0 ? "unreceived"
|
||||
: invoiceAmount.compareTo(money(settlement.getSettlementAmount())) >= 0 ? "completed" : "partial";
|
||||
settlement.setInvoiceAmount(invoiceAmount);
|
||||
settlement.setInvoiceStatus(invoiceStatus);
|
||||
formalSettlementMapper.updateById(settlement);
|
||||
}
|
||||
|
||||
private List<InvoiceReceiptSettlement> activeRelations(Long settlementId, Long excludeReceiptId) {
|
||||
List<InvoiceReceiptSettlement> relations = settlementRelationMapper.selectList(
|
||||
Wrappers.<InvoiceReceiptSettlement>lambdaQuery()
|
||||
@@ -568,6 +593,7 @@ public class InvoiceReceiptServiceImpl extends BaseServiceImpl<InvoiceReceiptMap
|
||||
entity.setCurrentNode(actionName);
|
||||
entity.setCurrentProcessor(AuthUtil.getUserName());
|
||||
updateById(entity);
|
||||
relationSettlementIds(entity.getId()).forEach(this::refreshSettlementInvoiceStatus);
|
||||
record(entity.getId(), actionType, actionName, fromStatus, toStatus, reason, entity.getKingdeeBillNo());
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -180,6 +180,8 @@ public class ReceiptClaimRecordServiceImpl extends BaseServiceImpl<ReceiptClaimM
|
||||
BigDecimal paidAfter = money(settlement.getPaidAmount())
|
||||
.subtract(money(relation.getAllocatedReceiptAmount())).max(BigDecimal.ZERO);
|
||||
settlement.setPaidAmount(paidAfter);
|
||||
settlement.setRemainingPayableAmount(money(settlement.getSettlementAmount())
|
||||
.subtract(paidAfter).max(BigDecimal.ZERO));
|
||||
settlement.setPaymentStatus(amountStatus(paidAfter, settlement.getSettlementAmount()));
|
||||
formalSettlementMapper.updateById(settlement);
|
||||
relation.setStatus(0);
|
||||
|
||||
+2
@@ -216,6 +216,8 @@ public class ReceiptFlowServiceImpl extends BaseServiceImpl<KingdeeReceiptFlowMa
|
||||
claimSettlementMapper.insert(relation);
|
||||
|
||||
settlement.setPaidAmount(claimedAfter);
|
||||
settlement.setRemainingPayableAmount(money(settlement.getSettlementAmount())
|
||||
.subtract(claimedAfter).max(BigDecimal.ZERO));
|
||||
settlement.setPaymentStatus(amountStatus(claimedAfter, settlement.getSettlementAmount()));
|
||||
formalSettlementMapper.updateById(settlement);
|
||||
}
|
||||
|
||||
+117
-44
@@ -102,6 +102,8 @@ public class ReceivablePayableDetailServiceImpl
|
||||
|
||||
private static final String SOURCE_MASTER_ORDER = "总单系统生成";
|
||||
private static final String SOURCE_LOADING_ORDER = "配载单系统生成";
|
||||
private static final String FEE_SOURCE_AUTO = "自动生成";
|
||||
private static final String FEE_SOURCE_MANUAL = "手工录入";
|
||||
|
||||
private final ReceivablePayableCargoFeeMapper cargoFeeMapper;
|
||||
private final ReceivablePayableChangeRecordMapper changeRecordMapper;
|
||||
@@ -161,6 +163,12 @@ public class ReceivablePayableDetailServiceImpl
|
||||
}
|
||||
});
|
||||
}
|
||||
rows.forEach(row -> {
|
||||
if (Func.isEmpty(row.getDataSource())) {
|
||||
row.setDataSource("手工调整".equals(row.getBillingFactor())
|
||||
? FEE_SOURCE_MANUAL : FEE_SOURCE_AUTO);
|
||||
}
|
||||
});
|
||||
ReceivablePayableFeeDetailVO result = buildFeeDetail(rows);
|
||||
LinkedHashSet<String> feeItemNames = new LinkedHashSet<>(contractFeeItemNames(detail.getContractId()));
|
||||
feeItemNames.addAll(result.getFeeItemNames());
|
||||
@@ -274,37 +282,34 @@ public class ReceivablePayableDetailServiceImpl
|
||||
throw new ServiceException("变更原因不能超过300个字");
|
||||
}
|
||||
if (Boolean.TRUE.equals(adjusted.getManualFee())) {
|
||||
if (Func.isEmpty(adjusted.getFeeItemName())) {
|
||||
throw new ServiceException("请填写手工费用项目");
|
||||
if (existing == null && !"receivable".equals(detail.getSettlementType())) {
|
||||
throw new ServiceException("仅应收明细允许新增手工费用");
|
||||
}
|
||||
if (!List.of("charge", "deduct").contains(adjusted.getFeeType())) {
|
||||
throw new ServiceException("手工费用类型不正确");
|
||||
if (existing != null && !isManualFee(existing)) {
|
||||
throw new ServiceException("自动生成费用行不能变更为手工录入");
|
||||
}
|
||||
validateNonNegative(adjusted.getAmount(), "手工费用金额");
|
||||
BigDecimal signedAmount = money(adjusted.getAmount())
|
||||
.multiply("deduct".equals(adjusted.getFeeType()) ? BigDecimal.valueOf(-1) : BigDecimal.ONE);
|
||||
Map<String, BigDecimal> manualItems = new LinkedHashMap<>();
|
||||
manualItems.put(adjusted.getFeeItemName().trim(), signedAmount);
|
||||
validateAdjustRow(adjusted, true);
|
||||
Map<String, BigDecimal> manualItems = validatedFeeItems(adjusted.getFeeItems(), allowedFeeItems);
|
||||
BigDecimal freightAmount = money(adjusted.getFreightAmount());
|
||||
BigDecimal afterAmount = adjustedAfterAmount(freightAmount, manualItems);
|
||||
boolean newManualRow = existing == null;
|
||||
if (newManualRow) {
|
||||
existing = new ReceivablePayableCargoFee();
|
||||
existing.setDetailId(detail.getId());
|
||||
existing.setWaybillId(detail.getWaybillId());
|
||||
existing.setLineNo("ADJ-" + System.currentTimeMillis());
|
||||
existing.setOriginalAmount(BigDecimal.ZERO);
|
||||
}
|
||||
String oldName = existing.getCargoName();
|
||||
String oldCargoName = existing.getCargoName();
|
||||
BigDecimal oldAmount = money(existing.getAfterAmount());
|
||||
// cargoName 表示运单货物名称,手工收费项名称仅保存到费用项目 JSON。
|
||||
existing.setCargoName(detail.getCargoName());
|
||||
existing.setBillingFactor("手工调整");
|
||||
existing.setBillingType("deduct".equals(adjusted.getFeeType()) ? "手工扣费" : "手工收费");
|
||||
existing.setTransportQuantity(detail.getTransportQuantity());
|
||||
existing.setQuantityUnit(detail.getQuantityUnit());
|
||||
existing.setMileage(detail.getMileage());
|
||||
existing.setFreightAmount(BigDecimal.ZERO);
|
||||
applyEditableFields(existing, adjusted, true);
|
||||
existing.setDataSource(FEE_SOURCE_MANUAL);
|
||||
existing.setBillingFactor("-");
|
||||
existing.setBillingType("-");
|
||||
existing.setFreightAmount(freightAmount);
|
||||
existing.setFeeItemsJson(JsonUtil.toJson(manualItems));
|
||||
existing.setAdjustAmount(signedAmount.subtract(money(existing.getOriginalAmount())));
|
||||
existing.setAfterAmount(signedAmount);
|
||||
existing.setAdjustAmount(afterAmount.subtract(money(existing.getOriginalAmount())));
|
||||
existing.setAfterAmount(afterAmount);
|
||||
existing.setRemark(adjusted.getRemark());
|
||||
existing.setChangeReason(adjusted.getChangeReason());
|
||||
if (newManualRow) {
|
||||
@@ -313,39 +318,30 @@ public class ReceivablePayableDetailServiceImpl
|
||||
} else {
|
||||
cargoFeeMapper.updateById(existing);
|
||||
}
|
||||
changes.add("【手工费用】从[" + oldName + " " + formatValue(oldAmount) + "]调整为["
|
||||
+ existing.getBillingType() + " " + existing.getCargoName() + " " + formatValue(signedAmount) + "]");
|
||||
changes.add("【手工费用】从[" + Objects.toString(oldCargoName, "") + " "
|
||||
+ formatValue(oldAmount) + "]调整为[" + Objects.toString(existing.getCargoName(), "")
|
||||
+ " " + formatValue(afterAmount) + "]");
|
||||
continue;
|
||||
}
|
||||
if (existing == null) {
|
||||
throw new ServiceException("存在无效的费用调整行");
|
||||
}
|
||||
validateNonNegative(adjusted.getTransportQuantity(), "运输量");
|
||||
validateNonNegative(adjusted.getMileage(), "里程");
|
||||
validateNonNegative(adjusted.getFreightAmount(), "运输费");
|
||||
Map<String, BigDecimal> feeItems = new LinkedHashMap<>();
|
||||
if (adjusted.getFeeItems() != null) {
|
||||
adjusted.getFeeItems().forEach((name, amount) -> {
|
||||
if (!allowedFeeItems.contains(name)) {
|
||||
throw new ServiceException("费用项目不存在:" + name);
|
||||
}
|
||||
validateNonNegative(amount, name);
|
||||
feeItems.put(name, money(amount));
|
||||
});
|
||||
if (isManualFee(existing)) {
|
||||
throw new ServiceException("手工录入费用行不能变更为自动生成");
|
||||
}
|
||||
validateAdjustRow(adjusted, false);
|
||||
Map<String, BigDecimal> feeItems = validatedFeeItems(adjusted.getFeeItems(), allowedFeeItems);
|
||||
BigDecimal transportQuantity = money(adjusted.getTransportQuantity());
|
||||
BigDecimal mileage = money(adjusted.getMileage());
|
||||
BigDecimal freightAmount = money(adjusted.getFreightAmount());
|
||||
Map<String, BigDecimal> effectiveFeeItems = feeItems;
|
||||
boolean ruleInputChanged = money(existing.getTransportQuantity()).compareTo(transportQuantity) != 0
|
||||
|| money(existing.getMileage()).compareTo(mileage) != 0;
|
||||
if (ruleInputChanged) {
|
||||
AdjustedFeeCalculation calculation = calculateAdjustedFee(detail, existing, transportQuantity,
|
||||
mileage, freightAmount, effectiveFeeItems);
|
||||
freightAmount = calculation.freightAmount();
|
||||
effectiveFeeItems = calculation.feeItems();
|
||||
}
|
||||
appendChange(changes, "规格", existing.getSpecification(), adjusted.getSpecification());
|
||||
appendChange(changes, "型号", existing.getModel(), adjusted.getModel());
|
||||
appendChange(changes, "计费要素", existing.getBillingFactor(), adjusted.getBillingFactor());
|
||||
appendChange(changes, "计费类型", existing.getBillingType(), adjusted.getBillingType());
|
||||
appendChange(changes, "计费数量", existing.getTransportQuantity(), transportQuantity);
|
||||
appendChange(changes, "运费计算单位", existing.getPriceUnit(), adjusted.getPriceUnit());
|
||||
appendChange(changes, "运输单价", existing.getUnitPrice(), adjusted.getUnitPrice());
|
||||
appendChange(changes, "里程", existing.getMileage(), mileage);
|
||||
appendChange(changes, "运输费", existing.getFreightAmount(), freightAmount);
|
||||
if (!Objects.equals(existing.getRemark(), adjusted.getRemark())) {
|
||||
@@ -361,6 +357,10 @@ public class ReceivablePayableDetailServiceImpl
|
||||
appendChange(changes, name, decimal(oldFeeItems.get(name)), money(effectiveFeeItems.get(name)));
|
||||
}
|
||||
BigDecimal afterAmount = adjustedAfterAmount(freightAmount, effectiveFeeItems);
|
||||
applyEditableFields(existing, adjusted, false);
|
||||
if (Func.isEmpty(existing.getDataSource())) {
|
||||
existing.setDataSource(FEE_SOURCE_AUTO);
|
||||
}
|
||||
existing.setTransportQuantity(transportQuantity);
|
||||
existing.setMileage(mileage);
|
||||
existing.setFreightAmount(freightAmount);
|
||||
@@ -889,6 +889,9 @@ public class ReceivablePayableDetailServiceImpl
|
||||
.like(Func.isNotEmpty(query.getBatchNo()), ReceivablePayableDetail::getBatchNo, query.getBatchNo())
|
||||
.like(Func.isNotEmpty(query.getVehicleNo()), ReceivablePayableDetail::getVehicleNo, query.getVehicleNo())
|
||||
.eq(Func.isNotEmpty(query.getSettlementStatus()), ReceivablePayableDetail::getSettlementStatus, query.getSettlementStatus());
|
||||
if (Func.isNotEmpty(query.getIds())) {
|
||||
wrapper.in(ReceivablePayableDetail::getId, Func.toLongList(query.getIds()));
|
||||
}
|
||||
wrapper.eq(Func.isNotEmpty(query.getSettlementType()), ReceivablePayableDetail::getSettlementType, query.getSettlementType());
|
||||
return wrapper.orderByDesc(ReceivablePayableDetail::getCreateTime);
|
||||
}
|
||||
@@ -1146,6 +1149,7 @@ public class ReceivablePayableDetailServiceImpl
|
||||
cargoFee.setDetailId(detailId);
|
||||
cargoFee.setWaybillId(waybill.getId());
|
||||
cargoFee.setLineNo("0001");
|
||||
cargoFee.setDataSource(FEE_SOURCE_AUTO);
|
||||
cargoFee.setCargoName(waybill.getCargoName());
|
||||
cargoFee.setCargoType(waybill.getCargoType());
|
||||
cargoFee.setSpecification(waybill.getSpecification());
|
||||
@@ -1225,6 +1229,7 @@ public class ReceivablePayableDetailServiceImpl
|
||||
Map<String, String> feeGoods, Map<String, Object> rule) {
|
||||
ReceivablePayableCargoFee fee = new ReceivablePayableCargoFee();
|
||||
fee.setWaybillId(waybill.getId());
|
||||
fee.setDataSource(FEE_SOURCE_AUTO);
|
||||
fee.setCargoName(feeGoods.getOrDefault("cargoName", feeWaybill.getCargoName()));
|
||||
fee.setCargoType(feeGoods.getOrDefault("cargoType", feeWaybill.getCargoType()));
|
||||
fee.setSpecification(feeGoods.getOrDefault("specification", feeWaybill.getSpecification()));
|
||||
@@ -1519,6 +1524,9 @@ public class ReceivablePayableDetailServiceImpl
|
||||
Set<String> feeItemNames = new LinkedHashSet<>();
|
||||
List<ReceivablePayableCargoFeeVO> records = rows.stream().map(row -> {
|
||||
ReceivablePayableCargoFeeVO vo = Objects.requireNonNull(BeanUtil.copyProperties(row, ReceivablePayableCargoFeeVO.class));
|
||||
if (Func.isEmpty(vo.getDataSource())) {
|
||||
vo.setDataSource(isManualFee(row) ? FEE_SOURCE_MANUAL : FEE_SOURCE_AUTO);
|
||||
}
|
||||
Map<String, Object> feeItems = parseMap(row.getFeeItemsJson());
|
||||
feeItemNames.addAll(feeItems.keySet());
|
||||
vo.setFeeItems(feeItems);
|
||||
@@ -1552,6 +1560,63 @@ public class ReceivablePayableDetailServiceImpl
|
||||
return new ArrayList<>(names);
|
||||
}
|
||||
|
||||
private boolean isManualFee(ReceivablePayableCargoFee fee) {
|
||||
return FEE_SOURCE_MANUAL.equals(fee.getDataSource()) || "手工调整".equals(fee.getBillingFactor());
|
||||
}
|
||||
|
||||
private void validateAdjustRow(ReceivablePayableAdjustFeeRequest.AdjustRow row, boolean manualFee) {
|
||||
if (manualFee) {
|
||||
validateLength(row.getCargoName(), 100, "货物名称");
|
||||
validateLength(row.getCargoType(), 100, "货物类型");
|
||||
}
|
||||
validateLength(row.getSpecification(), 255, "规格");
|
||||
validateLength(row.getModel(), 255, "型号");
|
||||
validateLength(row.getBillingFactor(), 100, "计费要素");
|
||||
validateLength(row.getBillingType(), 100, "计费类型");
|
||||
validateLength(row.getPriceUnit(), 50, "运费计算单位");
|
||||
validateNonNegative(row.getTransportQuantity(), "运输量");
|
||||
validateNonNegative(row.getUnitPrice(), "运输单价");
|
||||
validateNonNegative(row.getMileage(), "里程");
|
||||
validateNonNegative(row.getFreightAmount(), "运输费");
|
||||
}
|
||||
|
||||
private void validateLength(String value, int maxLength, String field) {
|
||||
if (value != null && value.length() > maxLength) {
|
||||
throw new ServiceException(field + "不能超过" + maxLength + "个字");
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, BigDecimal> validatedFeeItems(Map<String, BigDecimal> feeItems,
|
||||
Set<String> allowedFeeItems) {
|
||||
Map<String, BigDecimal> result = new LinkedHashMap<>();
|
||||
if (feeItems == null) return result;
|
||||
feeItems.forEach((name, amount) -> {
|
||||
if (!allowedFeeItems.contains(name)) {
|
||||
throw new ServiceException("费用项目不存在:" + name);
|
||||
}
|
||||
validateNonNegative(amount, name);
|
||||
result.put(name, money(amount));
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
private void applyEditableFields(ReceivablePayableCargoFee fee,
|
||||
ReceivablePayableAdjustFeeRequest.AdjustRow adjusted,
|
||||
boolean manualFee) {
|
||||
if (manualFee) {
|
||||
fee.setCargoName(adjusted.getCargoName());
|
||||
fee.setCargoType(adjusted.getCargoType());
|
||||
}
|
||||
fee.setSpecification(adjusted.getSpecification());
|
||||
fee.setModel(adjusted.getModel());
|
||||
fee.setBillingFactor(adjusted.getBillingFactor());
|
||||
fee.setBillingType(adjusted.getBillingType());
|
||||
fee.setTransportQuantity(money(adjusted.getTransportQuantity()));
|
||||
fee.setPriceUnit(adjusted.getPriceUnit());
|
||||
fee.setUnitPrice(money(adjusted.getUnitPrice()));
|
||||
fee.setMileage(money(adjusted.getMileage()));
|
||||
}
|
||||
|
||||
private void validateNonNegative(BigDecimal value, String field) {
|
||||
if (value != null && value.compareTo(BigDecimal.ZERO) < 0) {
|
||||
throw new ServiceException(field + "不能小于0");
|
||||
@@ -1572,7 +1637,7 @@ public class ReceivablePayableDetailServiceImpl
|
||||
ReceivablePayableCargoFee fee, BigDecimal transportQuantity,
|
||||
BigDecimal mileage, BigDecimal freightAmount,
|
||||
Map<String, BigDecimal> feeItems) {
|
||||
if ("手工调整".equals(fee.getBillingFactor())) {
|
||||
if (isManualFee(fee)) {
|
||||
throw new ServiceException("手工费用不支持按合同计费规则试算");
|
||||
}
|
||||
ContractManage contract = contractManageService.getById(detail.getContractId());
|
||||
@@ -1691,6 +1756,13 @@ public class ReceivablePayableDetailServiceImpl
|
||||
}
|
||||
}
|
||||
|
||||
private void appendChange(List<String> changes, String field, String before, String after) {
|
||||
if (!Objects.equals(before, after)) {
|
||||
changes.add("【" + field + "】从[" + Objects.toString(before, "") + "]调整为["
|
||||
+ Objects.toString(after, "") + "]");
|
||||
}
|
||||
}
|
||||
|
||||
private String formatValue(BigDecimal value) {
|
||||
return money(value).stripTrailingZeros().toPlainString();
|
||||
}
|
||||
@@ -1883,7 +1955,8 @@ public class ReceivablePayableDetailServiceImpl
|
||||
private void applyManualAdjustment(ReceivablePayableDetail detail, BigDecimal amount, String feeItem, String reason) {
|
||||
ReceivablePayableCargoFee fee = new ReceivablePayableCargoFee();
|
||||
fee.setDetailId(detail.getId()); fee.setWaybillId(detail.getWaybillId()); fee.setLineNo("ADJ-" + System.currentTimeMillis());
|
||||
fee.setCargoName(Func.isEmpty(feeItem) ? "手工调差" : feeItem); fee.setBillingFactor("手工调整"); fee.setBillingType("手工调差");
|
||||
fee.setDataSource(FEE_SOURCE_MANUAL); fee.setCargoName(Func.isEmpty(feeItem) ? "手工调差" : feeItem);
|
||||
fee.setBillingFactor("-"); fee.setBillingType("-");
|
||||
fee.setOriginalAmount(BigDecimal.ZERO); fee.setAdjustAmount(money(amount)); fee.setAfterAmount(money(amount)); fee.setFeeItemsJson(JsonUtil.toJson(Map.of(fee.getCargoName(), money(amount)))); fee.setRemark(reason);
|
||||
cargoFeeMapper.insert(fee);
|
||||
detail.setOtherFeeAmount(money(detail.getOtherFeeAmount()).add(money(amount)));
|
||||
|
||||
+1
@@ -136,6 +136,7 @@ public class SettlementAdjustmentServiceImpl extends BaseServiceImpl<SettlementA
|
||||
adjustment.setContractNo(formal.getContractNo()); adjustment.setContractName(formal.getContractName());
|
||||
adjustment.setKingdeeSyncStatus(formal.getKingdeeSyncStatus());
|
||||
adjustment.setOriginalSettlementAmount(money(formal.getSettlementAmount())); adjustment.setRemark(limit(request.getRemark(), 200));
|
||||
adjustment.setAttachmentsJson(request.getAttachmentsJson());
|
||||
BigDecimal total = BigDecimal.ZERO;
|
||||
if (request.getDetails() != null) for (SettlementAdjustmentSaveRequest.Detail row : request.getDetails()) {
|
||||
FormalSettlementDetailFee fee = validateFee(formal.getId(), row.getFormalSettlementDetailId(), row.getFormalSettlementDetailFeeId());
|
||||
|
||||
+5
@@ -14,6 +14,7 @@ import org.springblade.system.cache.UserCache;
|
||||
import org.springblade.transport.pojo.entity.FormalSettlement;
|
||||
import org.springblade.transport.pojo.vo.FormalSettlementVO;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@@ -30,6 +31,10 @@ public class FormalSettlementWrapper extends BaseEntityWrapper<FormalSettlement,
|
||||
@Override
|
||||
public FormalSettlementVO entityVO(FormalSettlement entity) {
|
||||
FormalSettlementVO vo = Objects.requireNonNull(BeanUtil.copyProperties(entity, FormalSettlementVO.class));
|
||||
BigDecimal settlementAmount = entity.getSettlementAmount() == null ? BigDecimal.ZERO : entity.getSettlementAmount();
|
||||
BigDecimal paidAmount = entity.getPaidAmount() == null ? BigDecimal.ZERO : entity.getPaidAmount();
|
||||
vo.setRemainingPayableAmount(settlementAmount.subtract(paidAmount).max(BigDecimal.ZERO));
|
||||
vo.setInvoiceAmount(entity.getInvoiceAmount() == null ? BigDecimal.ZERO : entity.getInvoiceAmount());
|
||||
vo.setCreateUserName(UserCache.getUserRealName(entity.getCreateUser()));
|
||||
vo.setSettlementTypeName("receivable".equals(entity.getSettlementType()) ? "应收" : "应付");
|
||||
vo.setApprovalStatusName(switch (entity.getApprovalStatus() == null ? "" : entity.getApprovalStatus()) {
|
||||
|
||||
Reference in New Issue
Block a user