优化
This commit is contained in:
@@ -202,7 +202,7 @@ public class FbaPricingRepository {
|
||||
LambdaUpdateWrapper<InboundPricingEntity> update = new LambdaUpdateWrapper<InboundPricingEntity>()
|
||||
.eq(InboundPricingEntity::getTenantId, inbound.getTenantId())
|
||||
.eq(InboundPricingEntity::getId, inbound.getId())
|
||||
.in(InboundPricingEntity::getFeeStatus, List.of("UNPRICED", "CALCULATED"))
|
||||
.in(InboundPricingEntity::getFeeStatus, List.of("UNPRICED", "CALCULATED", "VOIDED"))
|
||||
.set(InboundPricingEntity::getChannelCode, channelCode)
|
||||
.set(InboundPricingEntity::getChannelName, channelName)
|
||||
.set(InboundPricingEntity::getFeeStatus, "UNPRICED")
|
||||
|
||||
+2
-1
@@ -129,7 +129,8 @@ public class OrderChannelChangePricingService {
|
||||
|| feeItems.findPublishedFreight(inbound.getTenantId(), inbound.getId()) != null) {
|
||||
throw conflict("费用已确认或已发布,渠道不可变更;请先按费用作废流程处理");
|
||||
}
|
||||
if (!"UNPRICED".equals(inbound.getFeeStatus()) && !"CALCULATED".equals(inbound.getFeeStatus())) {
|
||||
if (!"UNPRICED".equals(inbound.getFeeStatus()) && !"CALCULATED".equals(inbound.getFeeStatus())
|
||||
&& !"VOIDED".equals(inbound.getFeeStatus())) {
|
||||
throw conflict("当前费用状态不可逆,渠道不可变更");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ paths:
|
||||
仅供 Order 在渠道变更成功后调用。tenantId + orderId + orderVersion 构成幂等边界;
|
||||
旧版本重放不会覆盖新版本。只将 CALCULATED 费用及草稿运费标记为 SUPERSEDED,
|
||||
入库单恢复 UNPRICED 并可重新计价;实际净重、实际体积和测量审核事实保持不变。
|
||||
已确认、已发送或已发布费用一律拒绝,不能由本命令覆盖。
|
||||
已确认、已发送或已发布费用一律拒绝,不能由本命令覆盖;费用正式作废为 VOIDED 后可重新计价。
|
||||
security:
|
||||
- internalServiceToken: []
|
||||
requestBody:
|
||||
@@ -1066,7 +1066,7 @@ components:
|
||||
orderVersion: {type: integer, format: int64}
|
||||
channelCode: {type: string}
|
||||
priceBookVersionId: {type: integer, format: int64, nullable: true}
|
||||
feeStatus: {type: string, enum: [UNPRICED, CALCULATED]}
|
||||
feeStatus: {type: string, enum: [UNPRICED, CALCULATED, VOIDED]}
|
||||
calculatedFeeWillBeInvalidated: {type: boolean}
|
||||
invalidatedFeeId: {type: integer, format: int64, nullable: true}
|
||||
UnifiedMainStatus:
|
||||
|
||||
@@ -218,6 +218,8 @@ paths:
|
||||
/internal/firstleg/v1/pricing/order-channel-changes/validate,两个服务均失败关闭。
|
||||
国内收货仓或中转仓如需变化必须重新下单。成功后通过 ORDER_DECLARATION_UPDATED_V1 Outbox
|
||||
同步 Firstleg;消费者按 eventId 幂等、version 顺序刷新申报快照,不覆盖实测、箱码或已确认费用。
|
||||
本次 changes 含渠道字段时,同版本 Outbox 还必须调用
|
||||
/internal/firstleg/v1/pricing/order-channel-changes/apply,使未确认价格预估显式失效;普通申报更新不得调用。
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/UnifiedOrderId'
|
||||
- $ref: '#/components/parameters/UnifiedTenantId'
|
||||
|
||||
+6
-1
@@ -51,7 +51,8 @@ class OrderDeclarationUpdateContractTest {
|
||||
assertThat(map(row.get("actualVolumeCbm")).get("description").toString()).contains("仅 Firstleg 实测");
|
||||
assertThat(source).contains("ORDER_DECLARATION_UPDATED_V1", "platform:order:declaration:edit", "A0409",
|
||||
"/internal/firstleg/v1/inbounds/order-channel-changes/validate",
|
||||
"/internal/firstleg/v1/pricing/order-channel-changes/validate");
|
||||
"/internal/firstleg/v1/pricing/order-channel-changes/validate",
|
||||
"/internal/firstleg/v1/pricing/order-channel-changes/apply");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -60,10 +61,14 @@ class OrderDeclarationUpdateContractTest {
|
||||
String.class, FirstlegInboundClient.OrderChannelChangeValidationRequest.class);
|
||||
var pricing = FirstlegPricingClient.class.getDeclaredMethod("validateOrderChannelChange",
|
||||
String.class, FirstlegPricingClient.OrderChannelChangeRequest.class);
|
||||
var applyPricing = FirstlegPricingClient.class.getDeclaredMethod("applyOrderChannelChange",
|
||||
String.class, FirstlegPricingClient.OrderChannelChangeRequest.class);
|
||||
assertThat(fulfillment.getAnnotation(PostMapping.class).value())
|
||||
.containsExactly("/order-channel-changes/validate");
|
||||
assertThat(pricing.getAnnotation(PostMapping.class).value())
|
||||
.containsExactly("/order-channel-changes/validate");
|
||||
assertThat(applyPricing.getAnnotation(PostMapping.class).value())
|
||||
.containsExactly("/order-channel-changes/apply");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
@@ -171,6 +171,25 @@ class OrderInboundOutboxPublisherTest {
|
||||
verify(fixture.repository).markOutboxPublished(eq(11L), eq(41L), any(LocalDateTime.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void channelPricingApplyFailureKeepsOutboxPendingAndDoesNotAdvanceFulfillmentSnapshot() {
|
||||
String payload = "{\"schemaVersion\":1,\"eventId\":\"evt-3\",\"tenantId\":11,"
|
||||
+ "\"orderId\":21,\"orderNo\":\"ORD-21\",\"inboundCode\":\"RK-21\","
|
||||
+ "\"version\":4,\"operatorId\":7,\"channelCode\":\"SEA\","
|
||||
+ "\"channelName\":\"海运\",\"channelChanged\":true,\"cargoes\":[],"
|
||||
+ "\"changes\":[{\"field\":\"channelName\",\"beforeValue\":\"旧渠道\",\"afterValue\":\"海运\"}]}";
|
||||
Fixture fixture = fixture(event("ORDER_DECLARATION_UPDATED_V1", 11L, 21L, payload));
|
||||
when(fixture.pricingClient.applyOrderChannelChange(eq("internal-token"), any())).thenReturn(
|
||||
ApiResponse.failure(com.baiyue.common.core.api.ResultCode.CONFLICT,
|
||||
"费用已确认或已发布,渠道不可变更", null, null));
|
||||
|
||||
fixture.publisher.publishApprovedOrders();
|
||||
|
||||
verify(fixture.repository).markOutboxRetry(eq(11L), eq(41L), any(LocalDateTime.class));
|
||||
verify(fixture.client, never()).updateDeclaration(any(), any());
|
||||
verify(fixture.repository, never()).markOutboxPublished(anyLong(), anyLong(), any());
|
||||
}
|
||||
|
||||
private Fixture fixture(OutboxEventEntity event) {
|
||||
return fixture(event, "BUY_DECLARATION");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user