fix(selfop): support inventory and outbound volume sorting

This commit is contained in:
2026-10-14 18:11:02 +08:00
parent 8bc8518496
commit 7079455eb0
4 changed files with 32 additions and 3 deletions
@@ -33,6 +33,31 @@ 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 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);