调整业务模块

This commit is contained in:
2026-09-04 05:22:59 +08:00
parent 809b4eb63a
commit c725aaf203
5 changed files with 143 additions and 23 deletions
@@ -25,6 +25,7 @@ public class WaybillImportBatchRequest {
private Long carrierId;
private List<Long> carrierIds;
private String carrierName;
private Long carrierContractId;
private String status;
private String importStatus;
private String importType;
@@ -261,7 +261,7 @@ public class MasterOrderServiceImpl extends BaseServiceImpl<MasterOrderMapper, M
BigDecimal freightTotal = dispatches.stream().map(item -> decimal(item, "quantity").multiply(decimal(item, "unitPrice"))).reduce(BigDecimal.ZERO, BigDecimal::add);
plan.setFreightJson(Func.isNotEmpty(freightJson) ? freightJson : buildFreightJson(null, freightTotal, first));
plan.setDataSource("多联总单调度"); plan.setBusinessStatus("waiting_dispatch");
plan.setRemark(string(first, "remark"));
plan.setRemark(string(first, "routeRemark", string(first, "remark")));
transportPlanService.submit(plan);
}
@@ -103,6 +103,7 @@ public class ReceivablePayableDetailServiceImpl
private static final String SOURCE_MASTER_ORDER = "总单系统生成";
private static final String SOURCE_LOADING_ORDER = "配载单系统生成";
private static final String SOURCE_MANUAL_GENERATION = "手动生成";
private static final String TRANSPORT_TYPE_SELF = "自运";
private static final String FEE_SOURCE_AUTO = "自动生成";
private static final String FEE_SOURCE_MANUAL = "手动录入";
private static final Set<String> FEE_SOURCE_MANUAL_LEGACY = Set.of("手工录入", "手动添加");
@@ -604,11 +605,15 @@ public class ReceivablePayableDetailServiceImpl
Long currentUserId = AuthUtil.getUserId();
Date generateTime = new Date();
ContractManage contract = contractManageService.getById(request.getContractId());
String targetSettlementType = settlementType(request.getSettlementType());
for (Waybill waybill : waybills) {
if (existsByWaybill(waybill.getId(), settlementType(request.getSettlementType()))) {
if ("payable".equals(targetSettlementType) && isSelfTransport(waybill)) {
continue;
}
ReceivablePayableDetail detail = buildDetail(waybill, contract, request.getBillingPlanId(), settlementType(request.getSettlementType()));
if (existsByWaybill(waybill.getId(), targetSettlementType)) {
continue;
}
ReceivablePayableDetail detail = buildDetail(waybill, contract, request.getBillingPlanId(), targetSettlementType);
detail.setSourceType(SOURCE_MANUAL_GENERATION);
save(detail);
calculatedFees(waybill, contract, request.getBillingPlanId()).forEach(fee -> {
@@ -645,11 +650,14 @@ public class ReceivablePayableDetailServiceImpl
Long currentUserId = AuthUtil.getUserId();
Date generateTime = new Date();
generateAutomaticWaybillDetails(waybills, true, waybill -> null, currentUserId, generateTime);
List<Waybill> payableWaybills = waybills.stream()
.filter(waybill -> !isSelfTransport(waybill)).toList();
if (payableWaybills.isEmpty()) return;
generateAutomaticDetail(carrierContract, "payable",
() -> existsByLoading(loadingNo, "payable"), waybills,
() -> existsByLoading(loadingNo, "payable"), payableWaybills,
(fees, unitPrice) -> {
normalizeWaybillFeeLines(fees);
return buildLoadingDetail(loadingNo, carrierContract, waybills, fees, unitPrice);
return buildLoadingDetail(loadingNo, carrierContract, payableWaybills, fees, unitPrice);
},
false, currentUserId, generateTime);
}
@@ -672,10 +680,12 @@ public class ReceivablePayableDetailServiceImpl
generateAutomaticWaybillDetail(waybill, receivableContract, "receivable",
currentUserId, generateTime);
}
if (!isSelfTransport(waybill)) {
ContractManage payableContract = payableContractResolver == null
? null : payableContractResolver.apply(waybill);
generateAutomaticWaybillDetail(waybill, payableContract, "payable",
currentUserId, generateTime);
}
} catch (Exception exception) {
log.error("自动生成运单费用明细失败,waybillId:{}, waybillNo:{}, receivableContractId:{}, failureReason:{}",
waybill.getId(), waybill.getWaybillNo(), waybill.getContractId(), exception.getMessage(), exception);
@@ -767,10 +777,13 @@ public class ReceivablePayableDetailServiceImpl
private void generateClosedMasterOrderPayables(MasterOrder masterOrder, Long currentUserId,
Date generateTime) {
if (isSelfTransport(masterOrder.getTransportOrganizationType())) return;
List<Waybill> waybills = waybillService.list(Wrappers.<Waybill>lambdaQuery()
.eq(Waybill::getIsDeleted, 0)
.eq(Waybill::getMasterNo, masterOrder.getMasterNo())
.isNotNull(Waybill::getCarrierContractId));
waybills = waybills.stream()
.filter(waybill -> !isSelfTransport(waybill)).toList();
if (waybills.isEmpty()) return;
Map<Long, ContractManage> carrierContracts = contractManageService.listByIds(waybills.stream()
.map(Waybill::getCarrierContractId).distinct().toList()).stream()
@@ -800,13 +813,21 @@ public class ReceivablePayableDetailServiceImpl
return Objects.equals(expectedCategory, contract.getContractCategory()) && isSystemGeneration(contract);
}
private boolean isSelfTransport(String transportType) {
return TRANSPORT_TYPE_SELF.equals(transportType == null ? null : transportType.trim());
}
private boolean isSelfTransport(Waybill waybill) {
return isSelfTransport(waybill.getTransportType()) || isSelfTransport(waybill.getCarrierType());
}
private List<ReceivablePayableCargoFee> calculateAutomaticFees(List<Waybill> waybills,
ContractManage contract) {
List<ReceivablePayableCargoFee> matchedFees = new ArrayList<>();
for (Waybill waybill : waybills) {
String planId = matchedPlanId(waybill, contract);
if (Func.isEmpty(planId)) continue;
// 自动生成统一使用合同默认计费方案,且禁止回退读取运单自身其他费用。
// 自动生成使用选定合同计费方案,且禁止回退读取运单自身其他费用。
matchedFees.addAll(calculatedFees(waybill, contract, planId, true));
}
return matchedFees;
@@ -1088,6 +1109,10 @@ public class ReceivablePayableDetailServiceImpl
.eq(Waybill::getProjectId, contract.getProjectId())
.eq(Waybill::getCarrierName, contract.getPartyB());
}
wrapper.and(item -> item.isNull(Waybill::getTransportType)
.or().ne(Waybill::getTransportType, TRANSPORT_TYPE_SELF));
wrapper.and(item -> item.isNull(Waybill::getCarrierType)
.or().ne(Waybill::getCarrierType, TRANSPORT_TYPE_SELF));
}
wrapper.notInSql(Waybill::getId,
"select waybill_id from blade_receivable_payable_detail"
@@ -1494,13 +1519,19 @@ public class ReceivablePayableDetailServiceImpl
}
private Map<String, Object> resolveDefaultBillingPlan(List<Map<String, Object>> plans, String transportType) {
return plans.stream().filter(this::isDefaultPlan)
if (plans.isEmpty()) return null;
if (plans.size() == 1) return plans.get(0);
Optional<Map<String, Object>> matchedDefaultPlan = plans.stream().filter(this::isDefaultPlan)
.filter(plan -> !isBlank(plan.get("transportMode")))
.filter(plan -> matchesCondition(plan.get("transportMode"), transportType))
.findFirst()
.orElseGet(() -> plans.stream().filter(this::isDefaultPlan)
.findFirst();
if (matchedDefaultPlan.isPresent()) return matchedDefaultPlan.get();
Optional<Map<String, Object>> defaultPlanWithoutTransportMode = plans.stream()
.filter(this::isDefaultPlan)
.filter(plan -> isBlank(plan.get("transportMode")))
.findFirst().orElse(null));
.findFirst();
if (defaultPlanWithoutTransportMode.isPresent()) return defaultPlanWithoutTransportMode.get();
return plans.stream().noneMatch(this::isDefaultPlan) ? plans.get(plans.size() - 1) : null;
}
private BigDecimal calculateRule(Map<String, Object> rule, Waybill waybill) {
@@ -86,7 +86,7 @@ public class WaybillImportBatchServiceImpl extends BaseServiceImpl<WaybillImport
for (int index = 0; index < request.getRows().size(); index++) {
try {
Waybill waybill = buildWaybill(request.getRows().get(index), batch);
Waybill waybill = buildWaybill(request.getRows().get(index), batch, request.getCarrierContractId());
waybillService.submit(waybill);
} catch (Exception exception) {
throw new ServiceException("" + (index + 1) + "行导入失败:" + exception.getMessage());
@@ -155,9 +155,44 @@ public class WaybillImportBatchServiceImpl extends BaseServiceImpl<WaybillImport
return batch;
}
private Waybill buildWaybill(Map<String, Object> row, WaybillImportBatch batch) {
Waybill waybill = BeanUtil.copyProperties(row, Waybill.class);
if (waybill == null) throw new ServiceException("运单数据不正确");
private Waybill buildWaybill(Map<String, Object> row, WaybillImportBatch batch, Long carrierContractId) {
if (row == null) throw new ServiceException("运单数据不正确");
Waybill waybill = new Waybill();
waybill.setOriginalNo(stringValue(row, "originalNo"));
waybill.setVehicleNo(stringValue(row, "vehicleNo"));
waybill.setDriverId(longValue(row, "driverId", "司机ID"));
waybill.setDriverName(stringValue(row, "driverName"));
waybill.setDriverPhone(stringValue(row, "driverPhone"));
waybill.setTransportType(stringValue(row, "transportType", "运输类型", "*运输类型", "运输方式", "*运输方式"));
waybill.setCargoName(stringValue(row, "cargoName"));
waybill.setCargoType(stringValue(row, "cargoType"));
waybill.setSpecification(stringValue(row, "specification"));
waybill.setModel(stringValue(row, "model"));
waybill.setQuantity(decimalValue(row, "quantity", "重量"));
waybill.setQuantityUnit(stringValue(row, "quantityUnit"));
waybill.setDepartureAddressId(longValue(row, "departureAddressId", "发货地址ID"));
waybill.setDepartureName(stringValue(row, "departureName"));
waybill.setDepartureAddress(stringValue(row, "departureAddress"));
waybill.setDepartureContact(stringValue(row, "departureContact"));
waybill.setDeparturePhone(stringValue(row, "departurePhone"));
waybill.setArrivalAddressId(longValue(row, "arrivalAddressId", "收货地址ID"));
waybill.setArrivalName(stringValue(row, "arrivalName"));
waybill.setArrivalAddress(stringValue(row, "arrivalAddress"));
waybill.setArrivalContact(stringValue(row, "arrivalContact"));
waybill.setArrivalPhone(stringValue(row, "arrivalPhone"));
waybill.setCaptainName(stringValue(row, "captainName"));
waybill.setCabinNo(stringValue(row, "cabinNo"));
waybill.setContainerNo(stringValue(row, "containerNo"));
waybill.setTrailerVehicleNo(stringValue(row, "trailerVehicleNo"));
waybill.setEscortName(stringValue(row, "escortName"));
waybill.setEscortPhone(stringValue(row, "escortPhone"));
waybill.setMileage(normalizeImportMileage(decimalValue(
row, "mileage", "里程", "里程", "里程(km)", "里程(公里)"
)));
waybill.setUnitPrice(decimalValue(row, "unitPrice", "单价"));
waybill.setPriceUnit(stringValue(row, "priceUnit"));
waybill.setOtherFeeTotal(decimalValue(row, "otherFeeTotal", "其他费用合计", "其他费用合计"));
waybill.setRemark(stringValue(row, "remark"));
waybill.setProjectId(batch.getProjectId());
waybill.setProjectName(batch.getProjectName());
waybill.setCustomerName(batch.getCustomerName());
@@ -166,6 +201,7 @@ public class WaybillImportBatchServiceImpl extends BaseServiceImpl<WaybillImport
waybill.setCarrierType(batch.getCarrierType());
waybill.setCarrierId(firstCarrierId(batch.getCarrierIds()));
waybill.setCarrierName(batch.getCarrierName());
waybill.setCarrierContractId(carrierContractId);
waybill.setPlanId(batch.getPlanId());
waybill.setPlanName(batch.getPlanName());
waybill.setImportBatchId(batch.getId());
@@ -180,6 +216,44 @@ public class WaybillImportBatchServiceImpl extends BaseServiceImpl<WaybillImport
return waybill;
}
private String stringValue(Map<String, Object> row, String field, String... aliases) {
Object value = row.get(field);
if (value != null && !String.valueOf(value).trim().isEmpty()) {
return String.valueOf(value).trim();
}
for (String alias : aliases) {
Object aliasValue = row.get(alias);
if (aliasValue != null && !String.valueOf(aliasValue).trim().isEmpty()) {
return String.valueOf(aliasValue).trim();
}
}
return null;
}
private Long longValue(Map<String, Object> row, String field, String fieldName) {
String value = stringValue(row, field);
if (Func.isEmpty(value)) return null;
try {
return Long.valueOf(value);
} catch (NumberFormatException exception) {
throw new ServiceException(fieldName + "格式不正确");
}
}
private BigDecimal decimalValue(Map<String, Object> row, String field, String fieldName, String... aliases) {
String value = stringValue(row, field, aliases);
if (Func.isEmpty(value)) return null;
try {
return new BigDecimal(value);
} catch (NumberFormatException exception) {
throw new ServiceException(fieldName + "格式不正确");
}
}
private BigDecimal normalizeImportMileage(BigDecimal mileage) {
return mileage != null && mileage.compareTo(BigDecimal.ONE.negate()) == 0 ? null : mileage;
}
private LocalDate parseDate(Object value, String fieldName) {
if (value == null || String.valueOf(value).isBlank()) throw new ServiceException(fieldName + "不能为空");
String text = String.valueOf(value).trim();
@@ -35,6 +35,7 @@ import org.springblade.system.pojo.entity.Dept;
import org.springblade.transport.excel.WaybillExcel;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import org.springblade.transport.mapper.WaybillMapper;
import org.springblade.transport.pojo.entity.LoadingManage;
import org.springblade.transport.pojo.entity.ContractManage;
@@ -504,7 +505,21 @@ public class WaybillServiceImpl extends BaseServiceImpl<WaybillMapper, Waybill>
queryWrapper.like(Waybill::getCustomerName, waybill.getCustomerName());
}
if (Func.isNotEmpty(waybill.getTransportType())) {
queryWrapper.eq(Waybill::getTransportType, waybill.getTransportType());
List<String> transportTypes = Arrays.stream(waybill.getTransportType().split("[,]"))
.map(String::trim)
.filter(Func::isNotEmpty)
.distinct()
.toList();
if (transportTypes.size() == 1) {
queryWrapper.eq(Waybill::getTransportType, transportTypes.get(0));
} else if (!transportTypes.isEmpty()) {
queryWrapper.and(wrapper -> {
wrapper.eq(Waybill::getTransportType, transportTypes.get(0));
for (int i = 1; i < transportTypes.size(); i++) {
wrapper.or().eq(Waybill::getTransportType, transportTypes.get(i));
}
});
}
}
if (Func.isNotEmpty(waybill.getCargoName())) {
queryWrapper.like(Waybill::getCargoName, waybill.getCargoName());
@@ -667,7 +682,6 @@ public class WaybillServiceImpl extends BaseServiceImpl<WaybillMapper, Waybill>
TransportBusinessSupport.validateRequired(waybill.getCarrierName(), "承运商不能为空");
} else {
TransportBusinessSupport.validateRequired(waybill.getDriverName(), "司机不能为空");
TransportBusinessSupport.validateRequired(waybill.getDriverPhone(), "司机手机号不能为空");
}
}
TransportBusinessSupport.validateRequired(waybill.getCarrierJson(), "承运信息不能为空");
@@ -744,7 +758,7 @@ public class WaybillServiceImpl extends BaseServiceImpl<WaybillMapper, Waybill>
}
private void validateCarrierContract(Waybill waybill) {
if (!"承运商".equals(waybill.getCarrierType())) {
if ("自运".equals(waybill.getCarrierType())) {
waybill.setCarrierContractId(null);
return;
}