feat: add self-operated analytics and enforce Lastleg module boundaries
This commit is contained in:
+3
-3
@@ -69,7 +69,7 @@ class FbaAppointmentPersistenceTest {
|
||||
new AppointmentSourceService.Source("ORDER:2","B",2L,"IN-B",null,null,"100","美国仓","FBA:ONT8","ONT8",secondPackages,"ORDER:1",true,List.of()));
|
||||
}
|
||||
private static SourceFbaAppointmentRequest request(String key) {
|
||||
return new SourceFbaAppointmentRequest(List.of(new AppointmentCoverageService.SourceRef("A","ORDER:1","FBA:ONT8"),new AppointmentCoverageService.SourceRef("B","ORDER:2","FBA:ONT8")),
|
||||
return new SourceFbaAppointmentRequest(List.of(new SourceFbaAppointmentRequest.SourceRef("A","ORDER:1","FBA:ONT8"),new SourceFbaAppointmentRequest.SourceRef("B","ORDER:2","FBA:ONT8")),
|
||||
"100","ONT8",new FbaAppointmentDetails(null,null,null,null,null,null,"PENDING",null,null,null),key);
|
||||
}
|
||||
@Test void failureAfterHeaderAndFirstItemRollsBackTheCommandAndEntireAggregate() {
|
||||
@@ -169,7 +169,7 @@ class FbaAppointmentPersistenceTest {
|
||||
var service=context.getBean(InboundFbaAppointmentService.class);var linker=context.getBean(AppointmentSourceLinker.class);
|
||||
var before=new AppointmentSourceService.Source("BOOKING:B-1","C",null,null,"B-1",null,"100","美国仓","FBA:ONT8","ONT8",null,"BOOKING:1",true,List.of());
|
||||
when(context.getBean(AppointmentSourceService.class).resolveBatch(anyList())).thenReturn(List.of(before));
|
||||
var request=new SourceFbaAppointmentRequest(List.of(new AppointmentCoverageService.SourceRef("C","BOOKING:B-1","FBA:ONT8")),"100","ONT8",request("unused").details(),"before-incoming");
|
||||
var request=new SourceFbaAppointmentRequest(List.of(new SourceFbaAppointmentRequest.SourceRef("C","BOOKING:B-1","FBA:ONT8")),"100","ONT8",request("unused").details(),"before-incoming");
|
||||
var saved=service.createFromSources("operator",request);
|
||||
assertNull(saved.items().get(0).orderId());
|
||||
assertThrows(org.springframework.transaction.IllegalTransactionStateException.class,()->linker.materialized("C","B-1",100L));
|
||||
@@ -221,7 +221,7 @@ class FbaAppointmentPersistenceTest {
|
||||
@Bean AppointmentCoverageMapper destinationFacts(){return mock(AppointmentCoverageMapper.class);}
|
||||
@Bean com.baiyue.lastleg.mapper.LastlegOrderMapper orders(){var mock=mock(com.baiyue.lastleg.mapper.LastlegOrderMapper.class);var row=new com.baiyue.lastleg.entity.LastlegOrder();row.setId(100L);row.setCustomerId("C");row.setInboundCode("WT-REAL");when(mock.selectById(100L)).thenReturn(row);return mock;}
|
||||
@Bean AppointmentExternalSourceGateway bookings(){var mock=mock(AppointmentExternalSourceGateway.class);when(mock.resolve(anyList())).thenReturn(List.of(new AppointmentExternalSourceGateway.Source("C","B-1","TR-1","RECEIVED","100","FBA:ONT8",100L,10,2L)));return mock;}
|
||||
@Bean AppointmentSourceLinker linker(com.baiyue.lastleg.mapper.LastlegOrderMapper orders,InboundFbaAppointmentItemMapper items,AppointmentExternalSourceGateway bookings){return new AppointmentSourceLinker(orders,items,bookings);}
|
||||
@Bean AppointmentSourceLinker linker(com.baiyue.lastleg.mapper.LastlegOrderMapper orders,InboundFbaAppointmentItemMapper items,AppointmentExternalSourceGateway bookings){return new InboundAppointmentSourceLinker(orders,items,bookings);}
|
||||
@Bean InboundFbaAppointmentService service(){return new InboundFbaAppointmentService();}
|
||||
}
|
||||
}
|
||||
|
||||
+13
-2
@@ -55,15 +55,26 @@ class InboundFbaAppointmentServiceTest {
|
||||
List<AppointmentCoverageService.SourceRef> refs(String... keys) {return Arrays.stream(keys).map(key->new AppointmentCoverageService.SourceRef(cargo.get(key).customerId(),key,cargo.get(key).destinationKey())).toList();}
|
||||
FbaAppointmentDetails pending(String remark) {return new FbaAppointmentDetails(LocalDate.of(2026,10,15),null,null,null,null,null,"PENDING",remark,null,null);}
|
||||
FbaAppointmentDetails confirmed() {return new FbaAppointmentDetails(LocalDate.of(2026,10,14),null,null,"EXT-ONT8-1",at,at.plusHours(1),"SUCCESS","已核实",null,null);}
|
||||
SourceFbaAppointmentRequest request(String key,FbaAppointmentDetails details,String... sources) {return new SourceFbaAppointmentRequest(refs(sources),"100","ONT8",details,key);}
|
||||
List<SourceFbaAppointmentRequest.SourceRef> requestRefs(String... keys) {return refs(keys).stream().map(r->new SourceFbaAppointmentRequest.SourceRef(r.customerId(),r.sourceKey(),r.destinationKey())).toList();}
|
||||
SourceFbaAppointmentRequest request(String key,FbaAppointmentDetails details,String... sources) {return new SourceFbaAppointmentRequest(requestRefs(sources),"100","ONT8",details,key);}
|
||||
FbaAppointmentResponse create(String key) {return service.createFromSources("operator",request(key,pending(null),"ORDER:1","ORDER:2"));}
|
||||
|
||||
@Test void sourceRequestKeepsWireShapeAndPassesAllSourceFieldsToResolution() throws Exception {
|
||||
var json=new ObjectMapper().findAndRegisterModules();
|
||||
var input=request("source-json",pending(null),"ORDER:1","ORDER:2");
|
||||
assertEquals(json.valueToTree(refs("ORDER:1","ORDER:2")),json.valueToTree(input).get("sources"));
|
||||
var decoded=json.readValue(json.writeValueAsString(input),SourceFbaAppointmentRequest.class);
|
||||
assertEquals(input,decoded);
|
||||
service.createFromSources("operator",decoded);
|
||||
verify(sources,times(2)).resolveBatch(refs("ORDER:1","ORDER:2"));
|
||||
}
|
||||
|
||||
@Test void refusesOriginOrDestinationChangedAfterSelection() {
|
||||
var intent=request("origin-changed",pending(null),"ORDER:1");
|
||||
add("ORDER:1","A",1L,"200","ONT8",10);
|
||||
assertEquals(409,assertThrows(ResponseStatusException.class,()->service.createFromSources("operator",intent)).getStatusCode().value());
|
||||
add("ORDER:1","A",1L,"100","LAX9",10);
|
||||
var changed=new SourceFbaAppointmentRequest(refs("ORDER:1"),"100","ONT8",pending(null),"destination-changed");
|
||||
var changed=new SourceFbaAppointmentRequest(requestRefs("ORDER:1"),"100","ONT8",pending(null),"destination-changed");
|
||||
assertEquals(409,assertThrows(ResponseStatusException.class,()->service.createFromSources("operator",changed)).getStatusCode().value());
|
||||
verify(headers,never()).insert(any(InboundFbaAppointment.class));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user