fix(customs): keep declaration pending while exceptions remain
This commit is contained in:
+5
-2
@@ -428,8 +428,11 @@ public class ContainerCustomsService {
|
||||
if (mapper.insertClearanceResult(resultId, batch.id(), batch.customsContainerId(), type, resultStatus,
|
||||
batch.customsEntryNo(), request.occurredAt(), trim(request.resolution()), request.evidenceFileId(),
|
||||
operatorId, operatorName, null) != 1) throw conflict("海关结果保存失败");
|
||||
if ("OPEN".equals(resultStatus)) mapper.markDeclarationResultPending(batch.id());
|
||||
else mapper.closeDeclarationBatch(batch.id());
|
||||
if ("OPEN".equals(resultStatus) || mapper.openClearanceResultCount(batch.id()) > 0) {
|
||||
mapper.markDeclarationResultPending(batch.id());
|
||||
} else {
|
||||
mapper.closeDeclarationBatch(batch.id());
|
||||
}
|
||||
ContainerRow container = mapper.lockContainerById(batch.customsContainerId());
|
||||
if (container != null) history(container, "RECORD_CUSTOMS_CLEARANCE_RESULT", container.status(), container.status(), type, operatorId, operatorName);
|
||||
completeCommand(operatorId, action, key, resultId);
|
||||
|
||||
+41
@@ -4,11 +4,14 @@ import com.baiyue.common.core.api.ResultCode;
|
||||
import com.baiyue.common.core.exception.BizException;
|
||||
import com.baiyue.firstleg.customs.container.dto.ContainerCustomsDtos.ActionRequest;
|
||||
import com.baiyue.firstleg.customs.container.dto.ContainerCustomsDtos.ScopeRequest;
|
||||
import com.baiyue.firstleg.customs.container.dto.ContainerCustomsDtos.ClearanceResultRequest;
|
||||
import com.baiyue.firstleg.customs.container.mapper.ContainerCustomsMapper;
|
||||
import com.baiyue.firstleg.customs.container.service.ContainerCustomsService;
|
||||
import com.baiyue.firstleg.customs.client.CustomsFileClient;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.*;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.CsvSource;
|
||||
import org.mockito.*;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
@@ -438,6 +441,44 @@ class ContainerCustomsServiceTest {
|
||||
verify(events,times(1)).publishEvent(new ContainerCustomsService.CustomsCompletedEvent(8L));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@CsvSource({
|
||||
"INSPECTION,true,1,true",
|
||||
"RELEASED,false,2,true",
|
||||
"OTHER,true,0,false",
|
||||
"RELEASED,false,0,false",
|
||||
"DETAINED,false,1,true"
|
||||
})
|
||||
void newlyResolvedResultDoesNotCloseBatchWithOtherOpenExceptions(
|
||||
String type, boolean resolved, int openResults, boolean remainsPending) {
|
||||
var at = java.time.LocalDateTime.of(2026,9,30,11,0);
|
||||
var batch = new ContainerCustomsMapper.DeclarationBatchRow(
|
||||
41L,2L,9L,"CD-LP9-01","RESULT_PENDING",3,"CUSTOMS-001","admin",at,
|
||||
"admin",at,"",4,at,at);
|
||||
String status = "RELEASED".equals(type) || resolved ? "RESOLVED" : "OPEN";
|
||||
when(mapper.claimCommand(anyLong(),eq(5L),anyString(),eq("result-key"),anyString())).thenReturn(1);
|
||||
when(mapper.lockDeclarationBatch(41L)).thenReturn(batch);
|
||||
when(mapper.insertClearanceResult(anyLong(),eq(41L),eq(2L),eq(type),eq(status),
|
||||
eq("CUSTOMS-001"),eq(at),eq("人工处理说明"),isNull(),eq(5L),eq("admin"),isNull())).thenReturn(1);
|
||||
when(mapper.openClearanceResultCount(41L)).thenReturn(openResults);
|
||||
when(mapper.completeCommand(eq(5L),anyString(),eq("result-key"),anyLong())).thenReturn(1);
|
||||
when(mapper.clearanceResult(anyLong())).thenAnswer(call -> new ContainerCustomsMapper.ClearanceResultRow(
|
||||
call.getArgument(0),41L,2L,type,status,"CUSTOMS-001",at,"人工处理说明",null,5L,"admin",at,null));
|
||||
|
||||
var result = service.addClearanceResult(41L,5L,"admin","result-key",
|
||||
new ClearanceResultRequest(4,type,at,"人工处理说明",null,resolved));
|
||||
|
||||
assertThat(result.resultStatus()).isEqualTo(status);
|
||||
if (remainsPending) {
|
||||
verify(mapper).markDeclarationResultPending(41L);
|
||||
verify(mapper,never()).closeDeclarationBatch(anyLong());
|
||||
} else {
|
||||
verify(mapper).closeDeclarationBatch(41L);
|
||||
verify(mapper,never()).markDeclarationResultPending(anyLong());
|
||||
}
|
||||
verifyNoInteractions(events,files);
|
||||
}
|
||||
|
||||
private static ContainerCustomsMapper.DocumentRow document(long id){return new ContainerCustomsMapper.DocumentRow(id,2L,7L,10L,"source.bin","a".repeat(64),"application/octet-stream",1L,"ACTIVE",5L,java.time.LocalDateTime.now(),1,java.time.LocalDateTime.now(),1);}
|
||||
private static ContainerCustomsMapper.BrokerSubmissionRow brokerSubmission(){return new ContainerCustomsMapper.BrokerSubmissionRow(41L,2L,9L,"BR-LP9-01","SENT",3,"admin",java.time.LocalDateTime.now(),1);}
|
||||
private static ContainerCustomsMapper.ContainerRow container(String status,int version){return new ContainerCustomsMapper.ContainerRow(2L,9L,8L,status,null,null,null,null,null,null,null,null,version);}
|
||||
|
||||
+2
-1
@@ -53,7 +53,7 @@ test('钱包闭环覆盖充值、授信、采购冻结结算和换标结算释
|
||||
test('托盘汇总和拆柜成本验证总数、分摊及跨区金额守恒', () => {
|
||||
for (const token of [
|
||||
'/api/platform/v1/pallets/summary',
|
||||
'/api/platform/v1/warehouse-admin/pallets/summary',
|
||||
'/api/platform/v1/overseas-warehouse-resources/pallets/summary',
|
||||
'/pallets/summary?page=1&size=20',
|
||||
'OVERSEAS_CONTAINER',
|
||||
'DESTUFF_PALLET',
|
||||
@@ -61,6 +61,7 @@ test('托盘汇总和拆柜成本验证总数、分摊及跨区金额守恒', ()
|
||||
'sourceFeeId',
|
||||
'pollRequests=',
|
||||
]) assert.ok(source.includes(token), token)
|
||||
assert.doesNotMatch(source, /\/warehouse-admin\/pallets\/summary/)
|
||||
assert.match(source, /Number\(d\.totalCount\) === Number\(d\.idleCount\) \+ Number\(d\.occupiedCount\)/)
|
||||
assert.match(source, /allocated === money\(fact\.expectedPalletCost\)/)
|
||||
assert.match(source, /delivered\.reduce[\s\S]*fact\.expectedPalletCost/)
|
||||
|
||||
@@ -304,7 +304,7 @@ async function verifyPalletSummaries(context, warehouseId) {
|
||||
success(domestic) && summaryValid(d, ['totalCount', 'idleCount', 'occupiedCount'])
|
||||
&& Number(d.totalCount) === Number(d.idleCount) + Number(d.occupiedCount),
|
||||
`total=${d?.totalCount}, idle=${d?.idleCount}, occupied=${d?.occupiedCount}`)
|
||||
const overseas = await context.request('GET', '/api/platform/v1/warehouse-admin/pallets/summary?page=1&size=20')
|
||||
const overseas = await context.request('GET', '/api/platform/v1/overseas-warehouse-resources/pallets/summary?page=1&size=20')
|
||||
const o = overseas?.body?.data
|
||||
assert(context, '海外托盘汇总含闲置、占用和报废数量', overseas,
|
||||
success(overseas) && summaryValid(o, ['totalCount', 'idleCount', 'occupiedCount', 'scrappedCount'])
|
||||
|
||||
Reference in New Issue
Block a user