fix(firstleg): allow fee revision until final fulfillment lock
This commit is contained in:
+16
@@ -93,6 +93,22 @@ public class PlatformInboundMeasurementController {
|
||||
return ApiResponse.success(service.saveDraft(tenantId, inboundId, user.userId(), request));
|
||||
}
|
||||
|
||||
@BusinessAudit(event = "INBOUND_MEASUREMENT_CALCULATION_STRATEGY_UPDATE", resourceType = "INBOUND",
|
||||
resourceId = "#inboundId", description = "更新入库测量箱规计算规则")
|
||||
@Operation(summary = "更新箱规计算规则",
|
||||
description = "独立更新当前测量批次全部明细的箱规计算规则并重算体积;不改变测量提交或审核状态。"
|
||||
+ "仅当客户已确认费用且该票已装柜完成时冻结。")
|
||||
@PutMapping("/measurement/calculation-strategy")
|
||||
@PreAuthorize("hasAuthority('platform:firstleg:inbound:measure:edit')")
|
||||
public ApiResponse<InboundMeasurementResponses.CalculationStrategyUpdated> updateCalculationStrategy(
|
||||
@AuthenticationPrincipal AuthenticatedUser user,
|
||||
@RequestParam long tenantId,
|
||||
@PathVariable long inboundId,
|
||||
@Valid @RequestBody InboundMeasurementRequests.UpdateCalculationStrategyRequest request) {
|
||||
requirePlatformTenant(user, tenantId);
|
||||
return ApiResponse.success(service.updateCalculationStrategy(tenantId, inboundId, request));
|
||||
}
|
||||
|
||||
@BusinessAudit(event = "INBOUND_MEASUREMENT_SUBMIT", resourceType = "INBOUND",
|
||||
resourceId = "#inboundId", description = "确认测量并提交审核")
|
||||
@Operation(summary = "确认测量并提交审核",
|
||||
|
||||
@@ -87,6 +87,14 @@ public final class InboundMeasurementRequests {
|
||||
) {
|
||||
}
|
||||
|
||||
public record UpdateCalculationStrategyRequest(
|
||||
@NotNull @Positive Long measurementId,
|
||||
@NotNull @PositiveOrZero Integer version,
|
||||
@NotBlank @jakarta.validation.constraints.Pattern(regexp = "ACTUAL|ADD|MULTIPLY") String coefficientMode,
|
||||
@Positive Long chargeRuleId
|
||||
) {
|
||||
}
|
||||
|
||||
public record ConfirmedPackageCountRequest(
|
||||
@NotNull @PositiveOrZero Integer measurementVersion,
|
||||
@NotNull @Positive @Max(1000000) Integer confirmedPackageCount
|
||||
|
||||
@@ -183,6 +183,11 @@ public final class InboundMeasurementResponses {
|
||||
public record DraftSaved(Long measurementId, Integer version, String status) {
|
||||
}
|
||||
|
||||
public record CalculationStrategyUpdated(
|
||||
Long measurementId, Integer version, String status, String coefficientMode, Long chargeRuleId
|
||||
) {
|
||||
}
|
||||
|
||||
public record MeasurementSubmitted(Long measurementId, Integer version, String processStatus,
|
||||
String measureReviewStatus,
|
||||
@Schema(description = "测量完成后的推荐托盘类型,仅为建议,不代表已分配托盘",
|
||||
|
||||
@@ -15,7 +15,6 @@ import com.baiyue.firstleg.loading.mapper.LoadingInboundMapper.CompletionTarget;
|
||||
import com.baiyue.firstleg.loading.bridge.service.LoadingModelBridgeService;
|
||||
import com.baiyue.firstleg.loading.repository.LoadingRepository;
|
||||
import com.baiyue.firstleg.repository.LoadingPickRepository;
|
||||
import com.baiyue.firstleg.service.FbaPricingService;
|
||||
import com.baiyue.firstleg.service.InboundHoldGuard;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
@@ -42,7 +41,6 @@ public class LoadingDeliveryService {
|
||||
@Resource private LoadingCompletionGateService completionGate;
|
||||
@Resource private InboundStatusHistoryMapper histories;
|
||||
@Resource private CabinetLoadingEvidenceService cabinetEvidenceService;
|
||||
@Resource private FbaPricingService pricingService;
|
||||
@Resource private ObjectMapper objectMapper;
|
||||
@Resource private InboundHoldGuard inboundHoldGuard;
|
||||
|
||||
@@ -69,7 +67,6 @@ public class LoadingDeliveryService {
|
||||
}
|
||||
if ("LOADED".equals(inbound.processStatus()) || "DELIVERED".equals(inbound.processStatus())) {
|
||||
requireLoadingPlanGate(tenantId, inboundId, acceptedPdaCompletion);
|
||||
pricingService.autoConfirmAfterLoading(tenantId, inboundId);
|
||||
return complete(tenantId, inboundId, operatorId, COMPLETE_LOADING, key,
|
||||
new LoadingActionResponse(inbound.processStatus()));
|
||||
}
|
||||
@@ -80,7 +77,6 @@ public class LoadingDeliveryService {
|
||||
requireCabinetEvidence(tenantId, inboundId);
|
||||
if (repository.completeLoading(tenantId, inboundId, operatorId, request.expectedVersion()) != 1) throw concurrent();
|
||||
addHistory(tenantId, inboundId, "LOADING", "LOADED", COMPLETE_LOADING, request.remark(), operatorId, operatorName);
|
||||
pricingService.autoConfirmAfterLoading(tenantId, inboundId);
|
||||
return complete(tenantId, inboundId, operatorId, COMPLETE_LOADING, key,
|
||||
new LoadingActionResponse("LOADED"));
|
||||
}
|
||||
@@ -124,7 +120,6 @@ public class LoadingDeliveryService {
|
||||
CompletionTarget target,
|
||||
boolean acceptedPdaCompletion) {
|
||||
if ("LOADED".equals(target.loadedChildStatus())) {
|
||||
pricingService.autoConfirmAfterLoading(tenantId, target.completionInboundId());
|
||||
return complete(tenantId, inboundId, operatorId, COMPLETE_LOADING, key,
|
||||
new LoadingActionResponse("LOADED"));
|
||||
}
|
||||
@@ -140,7 +135,6 @@ public class LoadingDeliveryService {
|
||||
repository.aggregateRootLoaded(tenantId, target.rootInboundId(), operatorId);
|
||||
addHistory(tenantId, target.completionInboundId(), "LOADING", "LOADED", COMPLETE_LOADING,
|
||||
request.remark(), operatorId, operatorName);
|
||||
pricingService.autoConfirmAfterLoading(tenantId, target.completionInboundId());
|
||||
return complete(tenantId, inboundId, operatorId, COMPLETE_LOADING, key,
|
||||
new LoadingActionResponse("LOADED"));
|
||||
}
|
||||
|
||||
@@ -285,12 +285,12 @@ public class FbaPricingRepository {
|
||||
.set(InboundFeeEntity::getUpdatedAt, LocalDateTime.now()));
|
||||
}
|
||||
|
||||
public int markInboundAdjusted(long tenantId, long inboundId, String feeStatus,
|
||||
public int markInboundAdjusted(long tenantId, long inboundId, String processStatus, String feeStatus,
|
||||
String chargeUnit, java.math.BigDecimal chargeableQuantity) {
|
||||
LambdaUpdateWrapper<InboundPricingEntity> update = new LambdaUpdateWrapper<InboundPricingEntity>()
|
||||
.eq(InboundPricingEntity::getTenantId, tenantId)
|
||||
.eq(InboundPricingEntity::getId, inboundId)
|
||||
.eq(InboundPricingEntity::getProcessStatus, "WAIT_SPLIT")
|
||||
.eq(InboundPricingEntity::getProcessStatus, processStatus)
|
||||
.set(InboundPricingEntity::getFeeStatus, feeStatus);
|
||||
if ("KG".equals(chargeUnit)) {
|
||||
update.set(InboundPricingEntity::getChargeableWeightKg, chargeableQuantity);
|
||||
@@ -308,7 +308,8 @@ public class FbaPricingRepository {
|
||||
.eq(InboundPricingEntity::getProcessStatus, processStatus)
|
||||
.in(InboundPricingEntity::getFeeStatus, List.of("UNPRICED", "CALCULATED", "SENT"))
|
||||
.set(InboundPricingEntity::getFeeStatus, "CALCULATED");
|
||||
if (!List.of("WAIT_PALLET", "WAIT_PALLETIZE", "WAIT_SPLIT", "LOADING").contains(processStatus)) {
|
||||
if (!List.of("WAIT_PALLET", "WAIT_PALLETIZE", "WAIT_SPLIT", "LOADING", "LOADED", "DELIVERED")
|
||||
.contains(processStatus)) {
|
||||
update.set(InboundPricingEntity::getProcessStatus, "FEE_CONFIRMING");
|
||||
}
|
||||
if ("KG".equals(chargeMode)) update.set(InboundPricingEntity::getChargeableWeightKg, chargeable);
|
||||
|
||||
+8
@@ -71,6 +71,14 @@ public class InboundMeasurementRepository {
|
||||
.eq(InboundMeasurementEntity::getId, measurementId));
|
||||
}
|
||||
|
||||
public InboundMeasurementEntity lockMeasurement(long tenantId, long inboundId, long measurementId) {
|
||||
return measurements.selectOne(new LambdaQueryWrapper<InboundMeasurementEntity>()
|
||||
.eq(InboundMeasurementEntity::getTenantId, tenantId)
|
||||
.eq(InboundMeasurementEntity::getInboundId, inboundId)
|
||||
.eq(InboundMeasurementEntity::getId, measurementId)
|
||||
.last("FOR UPDATE"));
|
||||
}
|
||||
|
||||
public InboundMeasurementEntity findLatestMeasurement(long tenantId, long inboundId) {
|
||||
return measurements.selectOne(new LambdaQueryWrapper<InboundMeasurementEntity>()
|
||||
.eq(InboundMeasurementEntity::getTenantId, tenantId)
|
||||
|
||||
@@ -44,7 +44,6 @@ public class FbaPricingService {
|
||||
private static final BigDecimal ADJUST_TOLERANCE_PERCENT = new BigDecimal("10.00");
|
||||
private static final BigDecimal ONE_HUNDRED = new BigDecimal("100");
|
||||
private static final long AUTOMATIC_CONFIRM_OPERATOR_ID = 0L;
|
||||
private static final String AUTOMATIC_CONFIRM_OPERATOR_NAME = "装柜完成自动确认";
|
||||
private static final String CONTAINER_RECALCULATE_OPERATION = "CONTAINER_FEE_RECALCULATE";
|
||||
@Resource
|
||||
private FbaPricingRepository repository;
|
||||
@@ -99,8 +98,8 @@ public class FbaPricingService {
|
||||
if (published == null || !"SENT".equals(published.getFeeStatus())) {
|
||||
throw conflict("费用状态已变化,请刷新后重试");
|
||||
}
|
||||
if (published.getCustomerConfirmedAt() != null) {
|
||||
throw conflict("客户已确认该费用,不允许再修改或重新发送");
|
||||
if (feeRevisionLocked(inbound, published)) {
|
||||
throw conflict("客户已确认且该票已装柜完成,不允许再修改或重新发送费用");
|
||||
}
|
||||
}
|
||||
var measurement = measurementRepository.findLatestMeasurement(tenantId, inboundId);
|
||||
@@ -390,8 +389,8 @@ public class FbaPricingService {
|
||||
public FeeSnapshotResponse confirm(long tenantId, long operatorId, long inboundId,
|
||||
String idempotencyKey) {
|
||||
InboundPricingEntity inbound = requireApprovedInbound(tenantId, inboundId);
|
||||
if (!feeEditableBeforeLoading(inbound.getProcessStatus())) {
|
||||
throw conflict("订单已进入装柜流程,不能再修改或发送费用");
|
||||
if (!feeRevisionStatusSupported(inbound.getProcessStatus())) {
|
||||
throw conflict("当前入库单状态不允许确认费用");
|
||||
}
|
||||
InboundFeeEntity current = repository.findLatestFee(tenantId, inboundId);
|
||||
if (current == null) throw conflict("入库单尚无可确认的费用试算");
|
||||
@@ -412,8 +411,8 @@ public class FbaPricingService {
|
||||
public FeeSnapshotResponse send(long tenantId, long operatorId, long inboundId,
|
||||
String idempotencyKey) {
|
||||
InboundPricingEntity inbound = requireApprovedInbound(tenantId, inboundId);
|
||||
if (!feeEditableBeforeLoading(inbound.getProcessStatus())) {
|
||||
throw conflict("订单已进入装柜流程,不能再修改或发送费用");
|
||||
if (!feeRevisionStatusSupported(inbound.getProcessStatus())) {
|
||||
throw conflict("当前入库单状态不允许发送费用");
|
||||
}
|
||||
InboundFeeEntity current = repository.findLatestFee(tenantId, inboundId);
|
||||
if (current == null) throw conflict("入库单尚无费用快照");
|
||||
@@ -445,21 +444,6 @@ public class FbaPricingService {
|
||||
return response(tenantId, fee.getId(), null);
|
||||
}
|
||||
|
||||
/** 客户未操作时,装柜完成以系统身份确认最新一版已发送费用。 */
|
||||
@Transactional
|
||||
public void autoConfirmAfterLoading(long tenantId, long inboundId) {
|
||||
InboundFeeEntity current = repository.findLatestFeeForUpdate(tenantId, inboundId);
|
||||
if (current == null || !"SENT".equals(current.getFeeStatus())
|
||||
|| current.getCustomerConfirmedAt() != null) {
|
||||
return;
|
||||
}
|
||||
LocalDateTime now = LocalDateTime.now(clock);
|
||||
if (repository.confirmFeeByCustomer(tenantId, current.getId(), current.getFeeVersion(),
|
||||
AUTOMATIC_CONFIRM_OPERATOR_ID, AUTOMATIC_CONFIRM_OPERATOR_NAME, now) != 1) {
|
||||
throw conflict("装柜完成自动确认费用失败,请重试");
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public FeeSnapshotResponse confirmByCustomer(long tenantId, long operatorId, String operatorName,
|
||||
long inboundId, int expectedFeeVersion,
|
||||
@@ -498,15 +482,15 @@ public class FbaPricingService {
|
||||
AdjustFeeRequest request, String idempotencyKey) {
|
||||
InboundPricingEntity inbound = repository.findInbound(tenantId, inboundId);
|
||||
if (inbound == null) throw new BizException(ResultCode.NOT_FOUND, "入库单不存在");
|
||||
if (!isCompletedInbound(inbound.getProcessStatus())) {
|
||||
throw conflict("只能在待分柜阶段修改初算或已发布费用");
|
||||
if (!feeRevisionStatusSupported(inbound.getProcessStatus())) {
|
||||
throw conflict("当前入库单状态不允许修改初算或已发布费用");
|
||||
}
|
||||
InboundFeeEntity current = repository.findLatestFee(tenantId, inboundId);
|
||||
if (current == null || !List.of("CALCULATED", "CONFIRMED", "SENT").contains(current.getFeeStatus())) {
|
||||
throw conflict("入库单没有可修改的初算或已发布费用");
|
||||
}
|
||||
if (current.getCustomerConfirmedAt() != null) {
|
||||
throw conflict("客户已确认该费用,不允许再修改");
|
||||
if (feeRevisionLocked(inbound, current)) {
|
||||
throw conflict("客户已确认且该票已装柜完成,不允许再修改费用");
|
||||
}
|
||||
if (!request.expectedFeeVersion().equals(current.getFeeVersion())) {
|
||||
throw conflict("费用版本已变化,请刷新后重试");
|
||||
@@ -554,6 +538,9 @@ public class FbaPricingService {
|
||||
adjusted.setConfirmedAt(published ? now : null);
|
||||
adjusted.setSentBy(published ? operatorId : null);
|
||||
adjusted.setSentAt(published ? now : null);
|
||||
adjusted.setCustomerConfirmedBy(null);
|
||||
adjusted.setCustomerConfirmedByName(null);
|
||||
adjusted.setCustomerConfirmedAt(null);
|
||||
adjusted.setCreatedAt(now);
|
||||
adjusted.setUpdatedAt(now);
|
||||
if (repository.supersedeCurrent(tenantId, current.getId(), current.getFeeStatus()) != 1) {
|
||||
@@ -576,7 +563,7 @@ public class FbaPricingService {
|
||||
extra.setRemark(request.reason().trim());
|
||||
repository.insertItem(extra);
|
||||
}
|
||||
if (repository.markInboundAdjusted(tenantId, inboundId, adjusted.getFeeStatus(),
|
||||
if (repository.markInboundAdjusted(tenantId, inboundId, inbound.getProcessStatus(), adjusted.getFeeStatus(),
|
||||
adjusted.getChargeUnit(), quantity) != 1) {
|
||||
throw conflict("入库单状态已变化,费用调整未保存");
|
||||
}
|
||||
@@ -594,7 +581,7 @@ public class FbaPricingService {
|
||||
|
||||
private InboundPricingEntity requireEligibleInbound(long tenantId, long inboundId) {
|
||||
InboundPricingEntity inbound = requireApprovedInbound(tenantId, inboundId);
|
||||
if (!feeEditableBeforeLoading(inbound.getProcessStatus())
|
||||
if (!feeRevisionStatusSupported(inbound.getProcessStatus())
|
||||
|| !List.of("UNPRICED", "CALCULATED", "SENT").contains(inbound.getFeeStatus())) {
|
||||
throw conflict("当前入库单状态不允许费用试算");
|
||||
}
|
||||
@@ -613,20 +600,23 @@ public class FbaPricingService {
|
||||
return inbound;
|
||||
}
|
||||
|
||||
private static boolean isCompletedInbound(String processStatus) {
|
||||
return "WAIT_SPLIT".equals(processStatus);
|
||||
}
|
||||
|
||||
private static boolean preserveProcessStatusDuringPricing(String processStatus) {
|
||||
return List.of("WAIT_PALLET", "WAIT_PALLETIZE", "WAIT_SPLIT", "LOADING").contains(processStatus);
|
||||
return List.of("WAIT_PALLET", "WAIT_PALLETIZE", "WAIT_SPLIT", "LOADING", "LOADED", "DELIVERED")
|
||||
.contains(processStatus);
|
||||
}
|
||||
|
||||
private static boolean feeEditableBeforeLoading(String processStatus) {
|
||||
private static boolean feeRevisionStatusSupported(String processStatus) {
|
||||
return List.of("WAIT_MEASURE", "MEASURING", "MEASURE_PENDING", "MEASURE_REJECTED",
|
||||
"WAIT_PRICING", "FEE_CONFIRMING", "WAIT_PALLET", "WAIT_PALLETIZE", "WAIT_SPLIT", "LOADING")
|
||||
"WAIT_PRICING", "FEE_CONFIRMING", "WAIT_PALLET", "WAIT_PALLETIZE", "WAIT_SPLIT", "LOADING",
|
||||
"LOADED", "DELIVERED")
|
||||
.contains(processStatus);
|
||||
}
|
||||
|
||||
private static boolean feeRevisionLocked(InboundPricingEntity inbound, InboundFeeEntity fee) {
|
||||
return fee != null && fee.getCustomerConfirmedAt() != null
|
||||
&& List.of("LOADED", "DELIVERED").contains(inbound.getProcessStatus());
|
||||
}
|
||||
|
||||
private static PricingDestinationType destinationType(InboundPricingEntity inbound) {
|
||||
try {
|
||||
return PricingDestinationType.valueOf(inbound.getDestinationType());
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.baiyue.firstleg.entity.InboundWeightRevisionEntity;
|
||||
import com.baiyue.firstleg.entity.MeasureReviewRecordEntity;
|
||||
import com.baiyue.firstleg.repository.InboundMeasurementRepository;
|
||||
import com.baiyue.firstleg.repository.InboundPalletAllocationRepository;
|
||||
import com.baiyue.firstleg.repository.FbaPricingRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -61,6 +62,8 @@ public class InboundMeasurementService {
|
||||
@Resource
|
||||
private MeasurementBatchService batchService;
|
||||
@Resource
|
||||
private FbaPricingRepository pricingRepository;
|
||||
@Resource
|
||||
private FbaMasterDataService fbaMasterDataService;
|
||||
@Resource
|
||||
private OrderCargoClient orderCargoClient;
|
||||
@@ -162,6 +165,40 @@ public class InboundMeasurementService {
|
||||
return new InboundMeasurementResponses.DraftSaved(saved.getId(), saved.getVersion(), saved.getStatus());
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public InboundMeasurementResponses.CalculationStrategyUpdated updateCalculationStrategy(
|
||||
long tenantId, long inboundId,
|
||||
InboundMeasurementRequests.UpdateCalculationStrategyRequest request) {
|
||||
InboundOrderEntity inbound = repository.lockInbound(tenantId, inboundId);
|
||||
if (inbound == null) throw new BizException(ResultCode.NOT_FOUND, "入库单不存在");
|
||||
var currentFee = pricingRepository.findLatestFeeForUpdate(tenantId, inboundId);
|
||||
boolean customerConfirmed = currentFee != null && currentFee.getCustomerConfirmedAt() != null;
|
||||
boolean loadingCompleted = Set.of("LOADED", "DELIVERED").contains(inbound.getProcessStatus());
|
||||
if (customerConfirmed && loadingCompleted) {
|
||||
throw new BizException(ResultCode.CONFLICT,
|
||||
"客户已确认且该票已装柜完成,不能修改箱规计算规则");
|
||||
}
|
||||
if ("MULTIPLY".equals(request.coefficientMode()) && request.chargeRuleId() == null) {
|
||||
throw new BizException(ResultCode.VALIDATION_FAILED, "箱规系数模式必须选择计费规则");
|
||||
}
|
||||
InboundMeasurementEntity measurement = repository.lockMeasurement(
|
||||
tenantId, inboundId, request.measurementId());
|
||||
if (measurement == null) throw new BizException(ResultCode.NOT_FOUND, "测量批次不存在");
|
||||
requireVersion(request.version(), measurement.getVersion());
|
||||
List<InboundMeasurementItemEntity> items = repository.listItems(tenantId, measurement.getId());
|
||||
batchService.recalculateStrategy(tenantId, measurement, items,
|
||||
request.coefficientMode(), request.chargeRuleId());
|
||||
measurement.setUpdatedAt(LocalDateTime.now());
|
||||
if (!repository.updateMeasurement(measurement)) throw concurrentModification();
|
||||
inbound.setActualVolumeCbm(measurement.getTotalVolumeCbm());
|
||||
inbound.setVolumeWeightKg(measurement.getVolumeWeightKg());
|
||||
if (!repository.updateInbound(inbound)) throw concurrentModification();
|
||||
Long appliedRuleId = "MULTIPLY".equals(request.coefficientMode()) ? request.chargeRuleId() : null;
|
||||
return new InboundMeasurementResponses.CalculationStrategyUpdated(
|
||||
measurement.getId(), measurement.getVersion(), measurement.getStatus(),
|
||||
request.coefficientMode(), appliedRuleId);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public InboundMeasurementResponses.MeasurementSubmitted submit(
|
||||
long tenantId, long inboundId, long operatorId,
|
||||
|
||||
@@ -93,6 +93,49 @@ public class MeasurementBatchService {
|
||||
return measurement;
|
||||
}
|
||||
|
||||
void recalculateStrategy(long tenantId, InboundMeasurementEntity measurement,
|
||||
List<InboundMeasurementItemEntity> existingItems,
|
||||
String coefficientMode, Long chargeRuleId) {
|
||||
if (existingItems.isEmpty()) {
|
||||
throw new BizException(ResultCode.CONFLICT, "当前测量批次没有可重算的明细");
|
||||
}
|
||||
MeasurementBatchCommand command = new MeasurementBatchCommand(
|
||||
tenantId, measurement.getInboundId(), measurement.getId(), measurement.getVersion(),
|
||||
measurement.getSourceType(), measurement.getSourceCode(), measurement.getExternalEventNo(),
|
||||
measurement.getDeviceCode(), measurement.getWarehouseCode(), measurement.getMeasuredAt(),
|
||||
measurement.getRawPayloadJson(), measurement.getOriginalDocumentNo(),
|
||||
measurement.getOriginalGrossWeightKg(), measurement.getOriginalVolumeCbm(),
|
||||
measurement.getActualGoodsName(), measurement.getCreatedBy(),
|
||||
existingItems.stream().map(item -> new MeasurementBatchCommand.Item(
|
||||
item.getInboundDetailId(), item.getItemNo(), item.getBoxSpecification(), item.getPackageCount(),
|
||||
item.getLengthCm(), item.getWidthCm(), item.getHeightCm(), null, item.getSourceImageFileId(),
|
||||
item.getOverLimitWarning(), item.getManualOuterLengthCm(), item.getManualOuterWidthCm(),
|
||||
item.getManualOuterHeightCm(), chargeRuleId, coefficientMode, item.getRemark())).toList());
|
||||
List<InboundMeasurementItemEntity> recalculated = calculateItems(
|
||||
command, dimensionWeighting.load(tenantId));
|
||||
for (int index = 0; index < existingItems.size(); index++) {
|
||||
InboundMeasurementItemEntity target = existingItems.get(index);
|
||||
InboundMeasurementItemEntity source = recalculated.get(index);
|
||||
target.setGirthCm(source.getGirthCm());
|
||||
target.setUnitVolumeCbm(source.getUnitVolumeCbm());
|
||||
target.setVolumeRawCbm(source.getVolumeRawCbm());
|
||||
target.setVolumeCbm(source.getVolumeCbm());
|
||||
target.setTotalVolumeCbm(source.getTotalVolumeCbm());
|
||||
target.setVolumeWeightKg(source.getVolumeWeightKg());
|
||||
target.setChargeRuleId(source.getChargeRuleId());
|
||||
target.setCoefficientMode(source.getCoefficientMode());
|
||||
target.setCalculationRuleVersion(source.getCalculationRuleVersion());
|
||||
target.setOuterLengthCm(source.getOuterLengthCm());
|
||||
target.setOuterWidthCm(source.getOuterWidthCm());
|
||||
target.setOuterHeightCm(source.getOuterHeightCm());
|
||||
target.setUpdatedAt(LocalDateTime.now());
|
||||
if (!repository.updateItem(target)) {
|
||||
throw concurrentModification();
|
||||
}
|
||||
}
|
||||
applyTotals(measurement, existingItems);
|
||||
}
|
||||
|
||||
/**
|
||||
* 人工补录会整批替换可编辑测量项,但不能抹掉同一项已冻结的扫码身份与设备取证。
|
||||
* 只按入库货物明细和明细号精确匹配,避免把一个箱码猜测性地复制给其他测量项。
|
||||
|
||||
Reference in New Issue
Block a user