Merge remote-tracking branch 'origin/test' into test
This commit is contained in:
+14
@@ -115,6 +115,20 @@ class InventoryTurnoverContextTest {
|
||||
&&p.days().subList(0,12).stream().allMatch(d->d.coverage()==0)
|
||||
&&p.days().subList(15,30).stream().allMatch(d->d.coverage()==1)));
|
||||
}
|
||||
@Test void volumeChartUsesDirectoryNamesAndKeepsEstimateEvidence() {
|
||||
var directory=mock(SelfopOwnerDirectory.class);
|
||||
when(directory.names(any(),any())).thenReturn(Map.of("C","货主甲"));
|
||||
when(mapper.report(any())).thenReturn(List.of(
|
||||
Map.of("section","TOTAL","payload","{\"total\":0}"),
|
||||
Map.of("section","OVERVIEW","payload","{\"sku_count\":0}"),
|
||||
Map.of("section","OWNER_VOLUME","payload","{\"customer_code\":\"C\",\"physical_volume\":12.345678,\"physical_estimated_quantity\":9}"),
|
||||
Map.of("section","OWNER_VOLUME_META","payload","{\"unknown_count\":2}")));
|
||||
var charts=new InventoryTurnoverQueryService(contexts,mapper,json,directory).query(request(null)).charts();
|
||||
assertEquals(2,charts.unknownVolumeOwnerCount());assertEquals(1,charts.ownerVolumeTop().size());
|
||||
var owner=charts.ownerVolumeTop().get(0);assertEquals("货主甲",owner.customerName());
|
||||
assertEquals(new java.math.BigDecimal("12.345678"),owner.inventoryVolumeM3().value());
|
||||
assertTrue(owner.inventoryVolumeM3().reasonCodes().contains("DECLARED_DIMENSIONS_ESTIMATE"));
|
||||
}
|
||||
@Test void firstPageSharesAggregationAndPaginationDoesNotRepeatOverviewQueries() {
|
||||
var service=new InventoryTurnoverQueryService(contexts,mapper,json,org.mockito.Mockito.mock(SelfopOwnerDirectory.class));
|
||||
when(mapper.report(any())).thenReturn(List.of(Map.of("section","TOTAL","payload","{\"total\":0}"),
|
||||
|
||||
+57
@@ -33,6 +33,63 @@ class InventoryTurnoverSqlTest {
|
||||
private void product(String owner,String sku,String declared,String measured) throws Exception {
|
||||
execute("INSERT INTO ll_selfop_product VALUES(901,'demo','"+owner+"','"+sku+"',"+declared+","+measured+")");
|
||||
}
|
||||
@Test void ownerVolumeChartRanksFullTotalsExcludesUnknownsAndIgnoresListFilters() throws Exception {
|
||||
master();
|
||||
for(int i=0;i<12;i++) {
|
||||
String owner=String.format("C%02d",i);seed(owner,"SAME",0);
|
||||
product(owner,"SAME",(i<2?"1":Integer.toString(i))+",1,1,'m'","NULL,NULL,NULL,NULL");
|
||||
}
|
||||
seed("MISSING","SAME",0);seed("UNKNOWN","SAME",0);
|
||||
product("UNKNOWN","SAME","100,1,1,'m'","NULL,NULL,NULL,NULL");
|
||||
execute("UPDATE ll_selfop_inventory_snapshot SET quality_status='INVALID' WHERE customer_code='UNKNOWN'");
|
||||
for(int days:List.of(7,30)) {
|
||||
var q=new InventoryTurnoverRequest("demo","W",END,days,"SKU",null,"not-present","FROZEN",null,null,"PHYSICAL_DESC",2,1,true,"fixed");
|
||||
var report=query("report",input(q,30,0,true));
|
||||
var ranking=new ArrayList<com.fasterxml.jackson.databind.JsonNode>();
|
||||
for(var part:report)if("OWNER_VOLUME".equals(part.get("section")))ranking.add(payload(part));
|
||||
assertEquals(10,ranking.size());
|
||||
assertEquals("C11",ranking.get(0).path("customer_code").asText());
|
||||
assertEquals("C02",ranking.get(9).path("customer_code").asText());
|
||||
decimal("6710",ranking.get(0).path("physical_volume").decimalValue());
|
||||
decimal("610",ranking.get(0).path("physical_estimated_quantity").decimalValue());
|
||||
assertEquals(2,payload(report.stream().filter(r->"OWNER_VOLUME_META".equals(r.get("section"))).findFirst().orElseThrow()).path("unknown_count").asInt());
|
||||
assertTrue(report.stream().noneMatch(r->"ROW".equals(r.get("section"))));
|
||||
}
|
||||
execute("UPDATE ll_selfop_product SET declared_length=1");
|
||||
var tied=query("report",input(request("OWNER","ALL","PHYSICAL_DESC",null,null,1,1),30,0,true));
|
||||
var ranking=new ArrayList<com.fasterxml.jackson.databind.JsonNode>();
|
||||
for(var part:tied)if("OWNER_VOLUME".equals(part.get("section")))ranking.add(payload(part));
|
||||
assertEquals("C00",ranking.get(0).path("customer_code").asText());
|
||||
assertEquals("C09",ranking.get(9).path("customer_code").asText());
|
||||
execute("UPDATE ll_selfop_inventory_snapshot SET quality_status='INVALID'");
|
||||
var unknown=query("report",input(request("SKU","ALL","PHYSICAL_DESC",null,null,1,1),30,0,true));
|
||||
assertTrue(unknown.stream().noneMatch(r->"OWNER_VOLUME".equals(r.get("section"))));
|
||||
}
|
||||
@Test void volumeSortsUseSelectedWindowFormalValuesBeforePagingWithStableTiesAndUnknownLast() throws Exception {
|
||||
master();
|
||||
for(String owner:List.of("A","B","C","D"))seed(owner,"SAME",0);
|
||||
for(String owner:List.of("A","B","D"))product(owner,"SAME",("B".equals(owner)?"2":"1")+",1,1,'m'","NULL,NULL,NULL,NULL");
|
||||
execute("UPDATE ll_selfop_sku_daily_sales SET outbound_quantity=CASE WHEN customer_code='A' THEN CASE WHEN business_date>=DATE '"+END.minusDays(2)+"' THEN 100 ELSE 0 END WHEN customer_code='B' THEN CASE WHEN business_date>=DATE '"+END.minusDays(2)+"' THEN 1 ELSE 100 END ELSE 10 END");
|
||||
for(String group:List.of("SKU","OWNER"))for(String metric:List.of("INVENTORY_VOLUME","OUTBOUND_VOLUME","UNIT_VOLUME")) {
|
||||
if(group.equals("OWNER")&&metric.equals("UNIT_VOLUME"))continue;
|
||||
for(int days:List.of(3,30))for(String direction:List.of("ASC","DESC")) {
|
||||
var expected=metric.equals("OUTBOUND_VOLUME")&&days==3
|
||||
? direction.equals("ASC")?List.of("B","D","A","C"):List.of("A","D","B","C")
|
||||
: direction.equals("ASC")?List.of("A","D","B","C"):List.of("B","A","D","C");
|
||||
var actual=new ArrayList<Object>();
|
||||
for(int page=1;page<=2;page++) {
|
||||
var q=new InventoryTurnoverRequest("demo","W",END,days,group,null,null,"ALL",null,null,metric+"_"+direction,page,2,true,"fixed");
|
||||
q.validate(END.plusDays(1));
|
||||
actual.addAll(reportRows(input(q,30,0,true)).stream().map(r->r.get("customer_code")).toList());
|
||||
}
|
||||
assertEquals(expected,actual,group+" "+metric+" "+days+" "+direction);
|
||||
}
|
||||
}
|
||||
var incomplete=reportRows(input(request("SKU","ALL","OUTBOUND_VOLUME_DESC",null,null,1,20),7,0,true));
|
||||
assertEquals(List.of("A","B","C","D"),incomplete.stream().map(r->r.get("customer_code")).toList());
|
||||
assertTrue(incomplete.stream().allMatch(r->r.get("w30_outbound_volume")==null));
|
||||
for(String direction:List.of("ASC","DESC"))assertThrows(RuntimeException.class,()->request("OWNER","ALL","UNIT_VOLUME_"+direction,null,null,1,20).validate(END.plusDays(1)));
|
||||
}
|
||||
@Test void emptyUncoveredOutboundVolumeIsUnknownAndCompleteEmptyVolumesAreZero() throws Exception {
|
||||
var q=request("SKU","ALL","PHYSICAL_DESC",null,null,1,20);
|
||||
var unknown=query("overview",input(q,0,0,true)).get(0);
|
||||
|
||||
Reference in New Issue
Block a user