1、调整合同
2、调整项目 3、调整付款管理
This commit is contained in:
+1
-1
@@ -134,7 +134,7 @@ public class CurrencyServiceImpl extends BaseServiceImpl<CurrencyMapper, Currenc
|
||||
successCount++;
|
||||
} catch (Exception exception) {
|
||||
String message = exception instanceof ServiceException ? exception.getMessage() : "导入失败";
|
||||
excel.setErrorMessage("第" + (index + 2) + "行:" + message);
|
||||
excel.setErrorMessage(message);
|
||||
errorList.add(excel);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -159,7 +159,7 @@ public class RegionServiceImpl extends ServiceImpl<RegionMapper, Region> impleme
|
||||
this.save(region);
|
||||
}
|
||||
} catch (Exception exception) {
|
||||
excel.setErrorMessage("第" + (index + 2) + "行:" + exception.getMessage());
|
||||
excel.setErrorMessage(exception.getMessage());
|
||||
errorList.add(excel);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -162,7 +162,7 @@ public class CommonCargoServiceImpl extends BaseServiceImpl<CommonCargoMapper, C
|
||||
} catch (Exception exception) {
|
||||
CommonCargoImportFailureExcel failureExcel = new CommonCargoImportFailureExcel();
|
||||
BeanUtil.copyProperties(excel, failureExcel);
|
||||
failureExcel.setErrorMessage("第" + (index + 2) + "行:" + exception.getMessage());
|
||||
failureExcel.setErrorMessage(exception.getMessage());
|
||||
failureList.add(failureExcel);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -138,7 +138,7 @@ public class CommonRouteServiceImpl extends BaseServiceImpl<CommonRouteMapper, C
|
||||
BeanUtil.copyProperties(excel, commonRoute);
|
||||
submit(commonRoute);
|
||||
} catch (Exception exception) {
|
||||
excel.setErrorMessage("第" + (index + 2) + "行:" + exception.getMessage());
|
||||
excel.setErrorMessage(exception.getMessage());
|
||||
failureList.add(excel);
|
||||
}
|
||||
}
|
||||
|
||||
+26
@@ -46,6 +46,7 @@ import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
@@ -231,6 +232,7 @@ public class ContractManageServiceImpl extends BaseServiceImpl<ContractManageMap
|
||||
source.setStartDate(request.getStartDate()); source.setEndDate(request.getEndDate()); source.setContractFormat(request.getContractFormat());
|
||||
source.setSettlementMode(request.getSettlementMode()); source.setLegalSealFlag(request.getLegalSealFlag()); source.setCopyCount(request.getCopyCount());
|
||||
source.setPaymentDays(request.getPaymentDays()); source.setRemark(request.getRemark()); source.setBillingEnabled(request.getBillingEnabled()); source.setFeeGenerationMode(request.getFeeGenerationMode());
|
||||
normalizeOptionalIntegerFields(source);
|
||||
source.setBillingPlanJson(request.getBillingPlanJson()); source.setSettlementRuleJson(request.getSettlementRuleJson()); source.setPreSettlementConfigJson(request.getPreSettlementConfigJson()); source.setFormalSettlementConfigJson(request.getFormalSettlementConfigJson()); source.setPaymentRatioJson(request.getPaymentRatioJson());
|
||||
source.setContractFileJson(request.getContractFileJson()); source.setAttachmentsJson(request.getAttachmentsJson());
|
||||
updateById(source);
|
||||
@@ -491,6 +493,7 @@ public class ContractManageServiceImpl extends BaseServiceImpl<ContractManageMap
|
||||
throw new ServiceException("同一运输方式仅支持配置一个默认计费方案");
|
||||
}
|
||||
}
|
||||
validateBillingMatchConditions(plan);
|
||||
}
|
||||
} catch (ServiceException exception) {
|
||||
throw exception;
|
||||
@@ -499,6 +502,29 @@ public class ContractManageServiceImpl extends BaseServiceImpl<ContractManageMap
|
||||
}
|
||||
}
|
||||
|
||||
private void validateBillingMatchConditions(Map<?, ?> plan) {
|
||||
if (!(plan.get("rules") instanceof List<?> rules)) return;
|
||||
for (Object ruleValue : rules) {
|
||||
if (!(ruleValue instanceof Map<?, ?> rule)
|
||||
|| !(rule.get("matchCondition") instanceof Map<?, ?> condition)) continue;
|
||||
boolean cargoNameConfigured = hasConfiguredValue(condition.get("cargoNames"))
|
||||
|| hasConfiguredValue(condition.get("cargoName"));
|
||||
boolean cargoTypeConfigured = hasConfiguredValue(condition.get("cargoType"))
|
||||
|| hasConfiguredValue(condition.get("cargoTypeCode"))
|
||||
|| hasConfiguredValue(condition.get("cargoTypePath"));
|
||||
if (cargoNameConfigured && !cargoTypeConfigured) {
|
||||
throw new ServiceException("设置货物名称匹配条件前请先选择货物类型");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasConfiguredValue(Object value) {
|
||||
if (value instanceof Collection<?> values) {
|
||||
return values.stream().anyMatch(this::hasConfiguredValue);
|
||||
}
|
||||
return value != null && !String.valueOf(value).trim().isEmpty();
|
||||
}
|
||||
|
||||
private boolean isDefaultBillingPlan(Map<?, ?> plan) {
|
||||
Object value = plan.get("defaultPlan");
|
||||
return Boolean.TRUE.equals(value) || "true".equalsIgnoreCase(String.valueOf(value)) || "1".equals(String.valueOf(value));
|
||||
|
||||
+3
-3
@@ -142,7 +142,7 @@ public class InvoiceApplicationServiceImpl extends BaseServiceImpl<InvoiceApplic
|
||||
@Override
|
||||
public List<Map<String, Object>> settlementCandidates(String keyword) {
|
||||
List<FormalSettlement> settlements = formalSettlementMapper.selectList(Wrappers.<FormalSettlement>lambdaQuery()
|
||||
.eq(FormalSettlement::getSettlementType, "receivable")
|
||||
.eq(FormalSettlement::getSettlementType, "payable")
|
||||
.eq(FormalSettlement::getApprovalStatus, APPROVED)
|
||||
.eq(FormalSettlement::getStatus, 1)
|
||||
.and(Func.isNotEmpty(keyword), wrapper -> wrapper.like(FormalSettlement::getFormalSettlementNo, keyword)
|
||||
@@ -418,8 +418,8 @@ public class InvoiceApplicationServiceImpl extends BaseServiceImpl<InvoiceApplic
|
||||
FormalSettlement settlement = formalSettlementMapper.selectById(id);
|
||||
if (settlement == null || Objects.equals(settlement.getIsDeleted(), 1)) throw new ServiceException("正式结算单不存在");
|
||||
if (!Objects.equals(settlement.getStatus(), 1) || !APPROVED.equals(settlement.getApprovalStatus())
|
||||
|| !"receivable".equals(settlement.getSettlementType())) {
|
||||
throw new ServiceException("只能选择审批通过、未作废的应收正式结算单");
|
||||
|| !"payable".equals(settlement.getSettlementType())) {
|
||||
throw new ServiceException("只能选择审批通过、未作废的应付正式结算单");
|
||||
}
|
||||
return settlement;
|
||||
}
|
||||
|
||||
+24
-7
@@ -886,7 +886,6 @@ public class PreSettlementServiceImpl extends BaseServiceImpl<PreSettlementMappe
|
||||
|
||||
private void applySummaryRequest(Long settlementId, List<PreSettlementSaveRequest.SummaryFee> requestRows) {
|
||||
if (requestRows == null) return;
|
||||
Map<String, String> generatedFeeTypeMap = contractFeeTypeMap(loadExisting(settlementId).getContractId());
|
||||
Map<String, Set<String>> allowedManualFees = new LinkedHashMap<>();
|
||||
if (requestRows.stream().anyMatch(row -> Integer.valueOf(1).equals(row.getManualFlag()))) {
|
||||
for (Map<String, Object> option : feeOptions()) {
|
||||
@@ -901,7 +900,11 @@ public class PreSettlementServiceImpl extends BaseServiceImpl<PreSettlementMappe
|
||||
.collect(Collectors.toMap(PreSettlementSummaryFee::getId, Function.identity()));
|
||||
List<PreSettlementSummaryFee> manualRows = existingMap.values().stream()
|
||||
.filter(row -> Integer.valueOf(1).equals(row.getManualFlag())).toList();
|
||||
List<PreSettlementSummaryFee> existingGeneratedRows = existingMap.values().stream()
|
||||
.filter(row -> !Integer.valueOf(1).equals(row.getManualFlag())).toList();
|
||||
List<PreSettlementSummaryFee> availableGeneratedRows = new ArrayList<>(existingGeneratedRows);
|
||||
Set<Long> retainedManualIds = new LinkedHashSet<>();
|
||||
Set<Long> retainedGeneratedIds = new LinkedHashSet<>();
|
||||
for (PreSettlementSaveRequest.SummaryFee requestRow : requestRows) {
|
||||
if (Integer.valueOf(1).equals(requestRow.getManualFlag())) {
|
||||
String feeType = requiredText(requestRow.getFeeType(), "费用类型");
|
||||
@@ -939,18 +942,26 @@ public class PreSettlementServiceImpl extends BaseServiceImpl<PreSettlementMappe
|
||||
continue;
|
||||
}
|
||||
String feeItem = requiredText(requestRow.getFeeItem(), "费用项");
|
||||
String feeType = generatedFeeTypeMap.getOrDefault(feeItem, "");
|
||||
String feeType = requestRow.getFeeType() == null ? "" : requestRow.getFeeType().trim();
|
||||
PreSettlementSummaryFee row = existingMap.get(requestRow.getId());
|
||||
if (row != null && (Integer.valueOf(1).equals(row.getManualFlag())
|
||||
|| retainedGeneratedIds.contains(row.getId()))) row = null;
|
||||
if (row == null) {
|
||||
row = existingMap.values().stream()
|
||||
.filter(item -> !Integer.valueOf(1).equals(item.getManualFlag()))
|
||||
row = availableGeneratedRows.stream()
|
||||
.filter(item -> Objects.equals(item.getFeeType(), feeType)
|
||||
&& Objects.equals(item.getFeeItem(), feeItem))
|
||||
.findFirst().orElse(null);
|
||||
}
|
||||
if (row == null || Integer.valueOf(1).equals(row.getManualFlag())) {
|
||||
throw new ServiceException("存在无效的结算合计行");
|
||||
if (row != null) availableGeneratedRows.remove(row);
|
||||
if (row == null) {
|
||||
row = new PreSettlementSummaryFee();
|
||||
row.setPreSettlementId(settlementId);
|
||||
row.setManualFlag(0);
|
||||
}
|
||||
row.setFeeType(feeType);
|
||||
row.setFeeItem(feeItem);
|
||||
row.setOriginalAmount(requestRow.getOriginalAmount() == null
|
||||
? money(row.getOriginalAmount()) : money(requestRow.getOriginalAmount()));
|
||||
BigDecimal before = money(row.getAdjustAmount());
|
||||
row.setAdjustAmount(money(requestRow.getAdjustAmount()));
|
||||
row.setSettlementAmount(money(row.getOriginalAmount()).add(row.getAdjustAmount()));
|
||||
@@ -958,7 +969,8 @@ public class PreSettlementServiceImpl extends BaseServiceImpl<PreSettlementMappe
|
||||
throw new ServiceException("结算金额不能小于0");
|
||||
}
|
||||
row.setRemark(limitRemark(requestRow.getRemark(), 50));
|
||||
summaryFeeMapper.updateById(row);
|
||||
if (row.getId() == null) summaryFeeMapper.insert(row); else summaryFeeMapper.updateById(row);
|
||||
retainedGeneratedIds.add(row.getId());
|
||||
if (before.compareTo(row.getAdjustAmount()) != 0) {
|
||||
saveChange(settlementId, "合计费用项", null, "调整",
|
||||
"【调整金额】从【" + before + "】调整为【" + row.getAdjustAmount() + "】", "");
|
||||
@@ -971,6 +983,11 @@ public class PreSettlementServiceImpl extends BaseServiceImpl<PreSettlementMappe
|
||||
"删除" + manualRow.getFeeItem() + "费用" + manualRow.getSettlementAmount(), "");
|
||||
}
|
||||
}
|
||||
for (PreSettlementSummaryFee generatedRow : existingGeneratedRows) {
|
||||
if (!retainedGeneratedIds.contains(generatedRow.getId())) {
|
||||
summaryFeeMapper.deleteById(generatedRow.getId());
|
||||
}
|
||||
}
|
||||
renumberSummaryFees(settlementId);
|
||||
}
|
||||
|
||||
|
||||
+94
-7
@@ -804,7 +804,7 @@ public class ReceivablePayableDetailServiceImpl
|
||||
return matchesLocation(condition, "origin", waybill.getDepartureAddressId(), waybill.getDepartureName(), waybill.getDepartureAddress())
|
||||
&& matchesLocation(condition, "destination", waybill.getArrivalAddressId(), waybill.getArrivalName(), waybill.getArrivalAddress())
|
||||
&& matchesCondition(condition.get("transportMode"), waybill.getTransportType())
|
||||
&& matchesCargoType(condition, waybill);
|
||||
&& matchesCargo(condition, waybill);
|
||||
}
|
||||
|
||||
private boolean hasConfiguredMatchCondition(Map<?, ?> condition) {
|
||||
@@ -814,7 +814,10 @@ public class ReceivablePayableDetailServiceImpl
|
||||
|| !isBlank(condition.get("destinationCode"))
|
||||
|| !isBlank(condition.get("transportMode"))
|
||||
|| !isBlank(condition.get("cargoType"))
|
||||
|| !isBlank(condition.get("cargoTypeCode"));
|
||||
|| !isBlank(condition.get("cargoTypeCode"))
|
||||
|| !isBlank(condition.get("cargoTypePath"))
|
||||
|| !isBlank(condition.get("cargoNames"))
|
||||
|| !isBlank(condition.get("cargoName"));
|
||||
}
|
||||
|
||||
private boolean matchesLocation(Map<?, ?> condition, String location, Long addressId, String addressName,
|
||||
@@ -831,14 +834,98 @@ public class ReceivablePayableDetailServiceImpl
|
||||
|| matchesCondition(expectedName, detailAddress);
|
||||
}
|
||||
|
||||
private boolean matchesCargoType(Map<?, ?> condition, Waybill waybill) {
|
||||
Object expectedName = condition.get("cargoType");
|
||||
Object expectedCode = condition.get("cargoTypeCode");
|
||||
if (!isBlank(expectedName)) return matchesCondition(expectedName, waybill.getCargoType());
|
||||
if (!isBlank(expectedCode)) return matchesCondition(expectedCode, waybill.getCargoType());
|
||||
private boolean matchesCargo(Map<?, ?> condition, Waybill waybill) {
|
||||
Object expectedTypeName = condition.get("cargoType");
|
||||
Object expectedTypeCode = condition.get("cargoTypeCode");
|
||||
Object expectedTypePath = condition.get("cargoTypePath");
|
||||
Object expectedCargoNames = !isBlank(condition.get("cargoNames"))
|
||||
? condition.get("cargoNames") : condition.get("cargoName");
|
||||
boolean cargoTypeConfigured = !isBlank(expectedTypeName)
|
||||
|| !isBlank(expectedTypeCode) || !isBlank(expectedTypePath);
|
||||
if (!cargoTypeConfigured && isBlank(expectedCargoNames)) return true;
|
||||
List<Map<String, Object>> goods = parseCargoTypeGoods(waybill.getGoodsJson());
|
||||
if (goods.isEmpty()) {
|
||||
return (!cargoTypeConfigured || matchesCondition(expectedTypeName, waybill.getCargoType()))
|
||||
&& (isBlank(expectedCargoNames)
|
||||
|| matchesCargoName(expectedCargoNames, waybill.getCargoName()));
|
||||
}
|
||||
return goods.stream().anyMatch(item ->
|
||||
(!cargoTypeConfigured || matchesCargoType(expectedTypeName, expectedTypeCode,
|
||||
expectedTypePath, item, waybill.getCargoType()))
|
||||
&& (isBlank(expectedCargoNames) || matchesCargoName(expectedCargoNames,
|
||||
stringValue(item, "cargoName", waybill.getCargoName()))));
|
||||
}
|
||||
|
||||
private List<Map<String, Object>> parseCargoTypeGoods(String goodsJson) {
|
||||
List<Map<String, Object>> goods = parseList(goodsJson);
|
||||
if (!goods.isEmpty()) return goods;
|
||||
if (Func.isEmpty(goodsJson)) return List.of();
|
||||
try {
|
||||
Object parsed = JsonUtil.parse(goodsJson, Object.class);
|
||||
if (parsed instanceof Map<?, ?> source) return List.of(stringMap(source));
|
||||
} catch (Exception ignored) {
|
||||
// 兼容历史货物 JSON 异常数据,后续回退使用运单货物类型名称匹配。
|
||||
}
|
||||
return List.of();
|
||||
}
|
||||
|
||||
private boolean matchesCargoName(Object expectedNames, String actualName) {
|
||||
String actual = String.valueOf(actualName == null ? "" : actualName).trim();
|
||||
if (actual.isEmpty()) return false;
|
||||
if (expectedNames instanceof Collection<?> values) {
|
||||
return values.stream().anyMatch(value -> matchesCargoName(value, actual));
|
||||
}
|
||||
return Objects.equals(String.valueOf(expectedNames).trim(), actual);
|
||||
}
|
||||
|
||||
private boolean matchesCargoType(Object expectedName, Object expectedCode, Object expectedPath,
|
||||
Map<String, Object> goods, String fallbackName) {
|
||||
Object actualPath = goods.get("cargoTypePath");
|
||||
if (matchesCargoTypePath(expectedPath, actualPath)) return true;
|
||||
String actualCode = firstNotBlank(
|
||||
goods.get("cargoTypeCode"),
|
||||
goods.get("secondCargoTypeCode"),
|
||||
goods.get("firstCargoTypeCode"));
|
||||
if (!isBlank(expectedCode) && Func.isNotEmpty(actualCode)) {
|
||||
String expectedCodeText = String.valueOf(expectedCode).trim();
|
||||
if (expectedCodeText.equals(actualCode)) return true;
|
||||
if (isFirstLevelCargoType(expectedPath, expectedCodeText)
|
||||
&& actualCode.startsWith(expectedCodeText)) return true;
|
||||
}
|
||||
if (isBlank(expectedName)) return false;
|
||||
return matchesCondition(expectedName, stringValue(goods, "cargoType", fallbackName))
|
||||
|| matchesCondition(expectedName, stringValue(goods, "secondCargoTypeName", ""))
|
||||
|| matchesCondition(expectedName, stringValue(goods, "firstCargoTypeName", ""));
|
||||
}
|
||||
|
||||
private boolean matchesCargoTypePath(Object expectedPath, Object actualPath) {
|
||||
if (!(expectedPath instanceof Collection<?> expectedValues)
|
||||
|| !(actualPath instanceof Collection<?> actualValues)
|
||||
|| expectedValues.isEmpty() || actualValues.size() < expectedValues.size()) {
|
||||
return false;
|
||||
}
|
||||
List<String> expected = expectedValues.stream().map(String::valueOf).toList();
|
||||
List<String> actual = actualValues.stream().map(String::valueOf).toList();
|
||||
for (int index = 0; index < expected.size(); index++) {
|
||||
if (!Objects.equals(expected.get(index), actual.get(index))) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isFirstLevelCargoType(Object expectedPath, String expectedCode) {
|
||||
if (expectedPath instanceof Collection<?> values && !values.isEmpty()) {
|
||||
return values.size() == 1;
|
||||
}
|
||||
return expectedCode.matches("\\d{2}");
|
||||
}
|
||||
|
||||
private String firstNotBlank(Object... values) {
|
||||
for (Object value : values) {
|
||||
if (!isBlank(value)) return String.valueOf(value).trim();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private String resolveRegionCode(Long addressId) {
|
||||
if (addressId == null) return "";
|
||||
try {
|
||||
|
||||
+1
-1
@@ -184,7 +184,7 @@ public class ShippingTemplateServiceImpl extends BaseServiceImpl<ShippingTemplat
|
||||
if (StringUtil.isNotBlank(item.getQuantity()) && !item.getQuantity().trim().matches("^\\d+(\\.\\d{1,3})?$")) throw new ServiceException("数量只能输入非负数字,最多保留3位小数");
|
||||
if (StringUtil.isNotBlank(item.getRemark()) && item.getRemark().trim().length() > 200) throw new ServiceException("备注不能超过200个字符");
|
||||
} catch (Exception e) {
|
||||
item.setErrorMessage("第" + (index + 2) + "行:" + e.getMessage());
|
||||
item.setErrorMessage(e.getMessage());
|
||||
failures.add(item);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -190,7 +190,7 @@ public class TransportPlanServiceImpl extends BaseServiceImpl<TransportPlanMappe
|
||||
transportPlan.setBusinessStatus("waiting_dispatch");
|
||||
submit(transportPlan);
|
||||
} catch (Exception exception) {
|
||||
excel.setErrorMessage("第" + (index + 2) + "行:" + exception.getMessage());
|
||||
excel.setErrorMessage(exception.getMessage());
|
||||
errorList.add(excel);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -200,7 +200,7 @@ public class TransportReconciliationServiceImpl
|
||||
external.setRawDataJson(JsonUtil.toJson(row)); externalMapper.insert(external);
|
||||
} catch (Exception exception) {
|
||||
VehicleReconciliationFailureExcel failure = new VehicleReconciliationFailureExcel();
|
||||
BeanUtil.copyProperties(row, failure); failure.setErrorMessage("第" + (index + 2) + "行:" + exception.getMessage());
|
||||
BeanUtil.copyProperties(row, failure); failure.setErrorMessage(exception.getMessage());
|
||||
failures.add(failure);
|
||||
}
|
||||
}
|
||||
@@ -229,7 +229,7 @@ public class TransportReconciliationServiceImpl
|
||||
external.setRawDataJson(JsonUtil.toJson(row)); externalMapper.insert(external);
|
||||
} catch (Exception exception) {
|
||||
CargoReconciliationFailureExcel failure = new CargoReconciliationFailureExcel();
|
||||
BeanUtil.copyProperties(row, failure); failure.setErrorMessage("第" + (index + 2) + "行:" + exception.getMessage());
|
||||
BeanUtil.copyProperties(row, failure); failure.setErrorMessage(exception.getMessage());
|
||||
failures.add(failure);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -197,7 +197,7 @@ public class WaybillServiceImpl extends BaseServiceImpl<WaybillMapper, Waybill>
|
||||
waybill.setCarrierJson(buildImportCarrierJson(waybill));
|
||||
submit(waybill);
|
||||
} catch (Exception exception) {
|
||||
excel.setErrorMessage("第" + (index + 2) + "行:" + exception.getMessage());
|
||||
excel.setErrorMessage(exception.getMessage());
|
||||
errorList.add(excel);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user