fix: isolate legacy from shadow admission errors

This commit is contained in:
zgw
2026-09-03 17:49:55 +08:00
parent 81888f5150
commit c8fa9f767f
4 changed files with 58 additions and 3 deletions

View File

@@ -419,7 +419,7 @@ public class ToWmsServiceImpl implements IToWmsService {
InboundShadowCompletion shadowCompletion = InboundShadowCompletion.rejected(); InboundShadowCompletion shadowCompletion = InboundShadowCompletion.rejected();
try { try {
shadowCompletion = shadowObservationGateway.observeInbound(taskNo, inJob.getTrayCode()); shadowCompletion = shadowObservationGateway.observeInbound(taskNo, inJob.getTrayCode());
} catch (RuntimeException exception) { } catch (RuntimeException | Error exception) {
// Shadow admission is best-effort; Legacy continues unchanged. // Shadow admission is best-effort; Legacy continues unchanged.
} }
try { try {

View File

@@ -258,7 +258,7 @@ public class OutStockoutServiceImpl implements IOutStockoutService
private OutboundShadowCompletion observeProjectOutboundShadow(String stockoutDetailId) { private OutboundShadowCompletion observeProjectOutboundShadow(String stockoutDetailId) {
try { try {
return shadowObservationGateway.observeProjectOutbound(stockoutDetailId); return shadowObservationGateway.observeProjectOutbound(stockoutDetailId);
} catch (RuntimeException exception) { } catch (RuntimeException | Error exception) {
return OutboundShadowCompletion.rejected(); return OutboundShadowCompletion.rejected();
} }
} }
@@ -266,7 +266,7 @@ public class OutStockoutServiceImpl implements IOutStockoutService
private OutboundShadowCompletion observeExactStockOutboundShadow(String stockoutDetailId, String stockId) { private OutboundShadowCompletion observeExactStockOutboundShadow(String stockoutDetailId, String stockId) {
try { try {
return shadowObservationGateway.observeExactStockOutbound(stockoutDetailId, stockId); return shadowObservationGateway.observeExactStockOutbound(stockoutDetailId, stockId);
} catch (RuntimeException exception) { } catch (RuntimeException | Error exception) {
return OutboundShadowCompletion.rejected(); return OutboundShadowCompletion.rejected();
} }
} }

View File

@@ -93,6 +93,20 @@ class ToWmsServiceImplShadowTest {
verify(mydoJobMapper, times(1)).allotInJobSpace(any()); verify(mydoJobMapper, times(1)).allotInJobSpace(any());
} }
@Test
void shadowErrorCannotSkipOrReplaceLegacyAllocation() {
AssertionError shadowFailure = new AssertionError("shadow fatal failure");
prepareSuccessfulLegacyAllocation();
when(shadowObservationGateway.observeInbound("TASK-1", "TRAY-1"))
.thenThrow(shadowFailure);
AjaxResult result = service.requestEnterByTaskNo(request);
assertThat(result.get(AjaxResult.DATA_TAG)).isSameAs(legacyResult);
verify(shadowObservationGateway).observeInbound("TASK-1", "TRAY-1");
verify(mydoJobMapper, times(1)).allotInJobSpace(any());
}
@Test @Test
void legacyWarningCompletesShadowAndPreservesLegacyResponse() { void legacyWarningCompletesShadowAndPreservesLegacyResponse() {
when(shadowObservationGateway.observeInbound("TASK-1", "TRAY-1")) when(shadowObservationGateway.observeInbound("TASK-1", "TRAY-1"))

View File

@@ -97,6 +97,27 @@ class OutStockoutServiceImplShadowTest {
verify(outStockoutMapper, times(1)).autoAllot(any()); verify(outStockoutMapper, times(1)).autoAllot(any());
} }
@Test
void shadowErrorStillRunsAutoAllotAndPreservesLegacySuccess() {
AssertionError shadowFailure = new AssertionError("shadow fatal failure");
prepareAutoAllot();
when(shadowObservationGateway.observeProjectOutbound("DETAIL-1"))
.thenThrow(shadowFailure);
doAnswer(invocation -> {
@SuppressWarnings("unchecked")
HashMap<String, String> parameters = invocation.getArgument(0);
parameters.put("v_result", "10");
parameters.put("v_resultmsg", "ok");
return null;
}).when(outStockoutMapper).autoAllot(any());
AjaxResult result = service.autoAllot("OUT-1");
assertThat(result.isSuccess()).isTrue();
verify(shadowObservationGateway).observeProjectOutbound("DETAIL-1");
verify(outStockoutMapper, times(1)).autoAllot(any());
}
@Test @Test
void autoAllotLegacyExceptionClosesShadowActivityAndEscapesUnchanged() { void autoAllotLegacyExceptionClosesShadowActivityAndEscapesUnchanged() {
IllegalStateException legacyFailure = new IllegalStateException("legacy database failure"); IllegalStateException legacyFailure = new IllegalStateException("legacy database failure");
@@ -139,6 +160,26 @@ class OutStockoutServiceImplShadowTest {
verify(secondCompletion).complete("10"); verify(secondCompletion).complete("10");
} }
@Test
void shadowErrorStillRunsManualAllotOnce() {
AssertionError shadowFailure = new AssertionError("shadow fatal failure");
when(shadowObservationGateway.observeExactStockOutbound("DETAIL-1", "STOCK-1"))
.thenThrow(shadowFailure);
doAnswer(invocation -> {
@SuppressWarnings("unchecked")
HashMap<String, String> parameters = invocation.getArgument(0);
parameters.put("v_result", "10");
parameters.put("v_resultString", "ok");
return null;
}).when(outStockoutMapper).manualAllot(any());
AjaxResult result = service.manualAllot(new String[]{"STOCK-1"}, "DETAIL-1");
assertThat(result.isSuccess()).isTrue();
verify(shadowObservationGateway).observeExactStockOutbound("DETAIL-1", "STOCK-1");
verify(outStockoutMapper, times(1)).manualAllot(any());
}
@Test @Test
void manualAllotLegacyErrorClosesShadowActivityAndEscapesUnchanged() { void manualAllotLegacyErrorClosesShadowActivityAndEscapesUnchanged() {
AssertionError legacyFailure = new AssertionError("legacy fatal failure"); AssertionError legacyFailure = new AssertionError("legacy fatal failure");