1
This commit is contained in:
@@ -23,6 +23,8 @@ public final class InboundMeasurementResponses {
|
||||
Integer expectedPalletCount,
|
||||
String processStatus,
|
||||
String measureReviewStatus,
|
||||
@Schema(description = "当前最新费用版本是否已由客户确认;确认后测量数据不可再修改")
|
||||
boolean customerFeeConfirmed,
|
||||
@Schema(description = "测量完成后的推荐托盘类型,仅为建议,不代表已分配托盘",
|
||||
allowableValues = "STANDARD", example = "STANDARD")
|
||||
String recommendedPalletType,
|
||||
|
||||
@@ -109,7 +109,7 @@ public class InboundMeasurementService {
|
||||
MeasureReviewRecordEntity review = repository.findLatestReview(tenantId, inbound.getId());
|
||||
LatestDeclaration latestDeclaration = loadLatestDeclaration(inbound);
|
||||
return toDetail(inbound, measurement, items, weights, allocationSlots, allocationsByWeight,
|
||||
review, latestDeclaration);
|
||||
review, latestDeclaration, customerFeeConfirmed(tenantId, inbound.getId()));
|
||||
}
|
||||
|
||||
public PageResult<InboundMeasurementResponses.PalletSnapshot> weightPalletOptions(
|
||||
@@ -236,10 +236,9 @@ public class InboundMeasurementService {
|
||||
InboundOrderEntity inbound, String subject) {
|
||||
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) {
|
||||
if (customerConfirmed) {
|
||||
throw new BizException(ResultCode.CONFLICT,
|
||||
"客户已确认且该票已装柜完成,不能修改" + subject);
|
||||
"客户已确认费用,不能修改" + subject);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -569,12 +568,14 @@ public class InboundMeasurementService {
|
||||
List<com.baiyue.firstleg.entity.InboundPalletAllocationEntity> allocationSlots,
|
||||
Map<Long, com.baiyue.firstleg.entity.InboundPalletAllocationEntity> allocationsByWeight,
|
||||
MeasureReviewRecordEntity review,
|
||||
LatestDeclaration latestDeclaration) {
|
||||
LatestDeclaration latestDeclaration,
|
||||
boolean customerFeeConfirmed) {
|
||||
InboundMeasurementResponses.DeclarationSnapshot declaration = latestDeclaration.snapshot();
|
||||
return new InboundMeasurementResponses.Detail(
|
||||
inbound.getId(), inbound.getInboundCode(), customerDisplayName(inbound), inbound.getChannelCode(),
|
||||
inbound.getChannelName(), inbound.getFulfillmentType(), inbound.getPalletCount(),
|
||||
inbound.getProcessStatus(), inbound.getMeasureReviewStatus(),
|
||||
customerFeeConfirmed,
|
||||
RECOMMENDED_PALLET_TYPE,
|
||||
review == null ? null : review.getReviewReason(), review == null ? null : review.getReviewerId(),
|
||||
review == null ? null : review.getReviewerName(), measurement == null ? null : measurement.getId(),
|
||||
@@ -603,6 +604,11 @@ public class InboundMeasurementService {
|
||||
toPalletLocationGuide(allocationSlots));
|
||||
}
|
||||
|
||||
private boolean customerFeeConfirmed(long tenantId, long inboundId) {
|
||||
var latestFee = pricingRepository.findLatestFee(tenantId, inboundId);
|
||||
return latestFee != null && latestFee.getCustomerConfirmedAt() != null;
|
||||
}
|
||||
|
||||
private static InboundMeasurementResponses.PalletLocationGuide toPalletLocationGuide(
|
||||
List<com.baiyue.firstleg.entity.InboundPalletAllocationEntity> slots) {
|
||||
if (slots.isEmpty()) return null;
|
||||
|
||||
@@ -1018,8 +1018,7 @@ paths:
|
||||
summary: 更新箱规计算规则
|
||||
description: >-
|
||||
独立更新当前测量批次全部明细的箱规计算规则并重算体积,不覆盖整批测量数据,
|
||||
不改变测量提交或审核状态。客户未确认或该票尚未装柜完成时均可修改;
|
||||
仅当客户已确认费用且该票已装柜完成时冻结。
|
||||
不改变测量提交或审核状态。客户确认费用后立即冻结,不得再修改。
|
||||
parameters:
|
||||
- {name: tenantId, in: query, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
|
||||
- {name: inboundId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
|
||||
@@ -1036,8 +1035,7 @@ paths:
|
||||
summary: 更新仓库外箱长宽高
|
||||
description: >-
|
||||
独立更新当前测量批次指定明细的仓库外箱尺寸并重算体积,不覆盖整批测量数据,
|
||||
不改变测量提交或审核状态。客户未确认或该票尚未装柜完成时均可修改;
|
||||
仅当客户已确认费用且该票已装柜完成时冻结。
|
||||
不改变测量提交或审核状态。客户确认费用后立即冻结,不得再修改。
|
||||
parameters:
|
||||
- {name: tenantId, in: query, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
|
||||
- {name: inboundId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
|
||||
@@ -1905,7 +1903,7 @@ components:
|
||||
type: object
|
||||
description: >-
|
||||
入库测量权威详情。尺寸证据天然归属 items,称重证据天然归属 weightResults,响应不提供统一 images。
|
||||
required: [inboundId, inboundVersion, items, weightResults]
|
||||
required: [inboundId, inboundVersion, customerFeeConfirmed, items, weightResults]
|
||||
properties:
|
||||
inboundId: {type: string, pattern: '^[1-9][0-9]*$'}
|
||||
inboundCode: {type: string, nullable: true, description: 当前测量详情唯一入仓码,UI业务主展示字段}
|
||||
@@ -1914,6 +1912,7 @@ components:
|
||||
channelName: {type: string, nullable: true}
|
||||
processStatus: {type: string, nullable: true}
|
||||
measureReviewStatus: {type: string, nullable: true}
|
||||
customerFeeConfirmed: {type: boolean, description: 当前最新费用版本已由客户确认,确认后测量数据不可再修改}
|
||||
recommendedPalletType: {type: string, nullable: true}
|
||||
reviewReason: {type: string, nullable: true}
|
||||
reviewerId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true}
|
||||
|
||||
+20
-3
@@ -124,8 +124,8 @@ class InboundMeasurementServiceTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void locksCalculationStrategyOnlyAfterCustomerConfirmationAndLoadingCompletion() {
|
||||
InboundOrderEntity inbound = inbound("LOADED");
|
||||
void locksCalculationStrategyAsSoonAsCustomerConfirmsFee() {
|
||||
InboundOrderEntity inbound = inbound("WAIT_SPLIT");
|
||||
InboundFeeEntity fee = new InboundFeeEntity();
|
||||
fee.setCustomerConfirmedAt(LocalDateTime.now());
|
||||
when(repository.lockInbound(1L, 10L)).thenReturn(inbound);
|
||||
@@ -134,7 +134,7 @@ class InboundMeasurementServiceTest {
|
||||
assertThatThrownBy(() -> service.updateCalculationStrategy(1L, 10L,
|
||||
new InboundMeasurementRequests.UpdateCalculationStrategyRequest(30L, 5, "ACTUAL", null)))
|
||||
.isInstanceOf(BizException.class)
|
||||
.hasMessageContaining("客户已确认且该票已装柜完成");
|
||||
.hasMessageContaining("客户已确认费用");
|
||||
|
||||
verify(repository, never()).lockMeasurement(anyLong(), anyLong(), anyLong());
|
||||
}
|
||||
@@ -245,6 +245,23 @@ class InboundMeasurementServiceTest {
|
||||
verify(repository, never()).updateInbound(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void detailReportsCustomerFeeConfirmationForTheMeasurementLock() {
|
||||
InboundOrderEntity inbound = inbound("WAIT_SPLIT");
|
||||
InboundMeasurementEntity measurement = new InboundMeasurementEntity();
|
||||
measurement.setId(30L);
|
||||
InboundFeeEntity fee = new InboundFeeEntity();
|
||||
fee.setCustomerConfirmedAt(LocalDateTime.now());
|
||||
when(repository.findInbound(1L, 10L)).thenReturn(inbound);
|
||||
when(repository.findLatestMeasurement(1L, 10L)).thenReturn(measurement);
|
||||
when(repository.listWeights(1L, 10L)).thenReturn(List.of());
|
||||
when(pricingRepository.findLatestFee(1L, 10L)).thenReturn(fee);
|
||||
|
||||
InboundMeasurementResponses.Detail result = service.detail(1L, 10L);
|
||||
|
||||
assertThat(result.customerFeeConfirmed()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void detailReportsOrderContractNotReadyInsteadOfExposingDownstreamBadRequest() {
|
||||
InboundOrderEntity inbound = inbound("MEASURE_PENDING");
|
||||
|
||||
Reference in New Issue
Block a user