perf(selfop): seek latest outbound date for inventory page

This commit is contained in:
2026-10-13 10:11:06 +08:00
parent 2d7b6e4381
commit d08ed2f2ca
3 changed files with 60 additions and 4 deletions
@@ -103,6 +103,16 @@ class AnalyticsReadMapperTest {
if("HOT".equals(kind))assertFalse(stats.contains("ll_selfop_inventory_snapshot"));
}
}
@Test void stockFirstHistoryLookupRetainsCorrelatedScopeAndReverseIndexOrder(){
var c=config();var p=request("INVENTORY");var o=new AnalyticsInventoryOptions(null,"ALL","AVAILABLE_DESC",null,null,null,null,null);
String sql=bound(c,"inventoryPage",Map.of("p",p,"o",o)).getSql();
assertFalse(sql.contains("last_sales AS"));assertFalse(sql.contains("JOIN last_sales"));
assertTrue(sql.contains("d.customer_code=k.customer_code AND d.sku_code=k.sku_code"));
assertTrue(sql.contains("d.sales_run_id=? AND d.source_account=? AND d.warehouse_code=?"));
assertTrue(sql.contains("d.outbound_quantity>0 AND d.quantity_unit='PCS' ORDER BY d.customer_code DESC,d.sku_code DESC,d.business_date DESC LIMIT 1"));
assertTrue(sql.indexOf("stock_paged AS")<sql.indexOf("ORDER BY d.customer_code DESC"));
immutableOnly(sql);
}
@Test void inventoryHistoryOnlyEnrichesQualifiedPageAndNeverCountsOrOwnerTotals(){
var c=config();var p=request("INVENTORY");var o=new AnalyticsInventoryOptions(null,"COVERAGE_GT_THRESHOLD","PHYSICAL_DESC",90,null,null,null,null);
String page=bound(c,"inventoryPage",Map.of("p",p,"o",o)).getSql();
@@ -389,6 +389,45 @@ public class AnalyticsSqlSemanticTest {
for(String sort:List.of("PHYSICAL_DESC","COVERAGE_DAYS_DESC","OUTBOUND_30D_ASC"))
assertFalse(AnalyticsInventorySql.inventoryPage(Map.of("p",p,"o",new AnalyticsInventoryOptions(null,"ALL",sort,null,null,null,null,null))).contains("stock_paged"));
}
@Test void stockFirstLastOutboundSkipsInvalidLatestRowsAndKeepsAllScopeBoundaries() throws Exception {
for(String sku:List.of("HISTORY","NONE","ANCHOR")){
profile(22,"C",sku,"INVENTORY_OBSERVATION",utc(D.minusDays(90),0),"PCS");stock("C",sku,0,"10");
}
profile(22,"B","HISTORY","INVENTORY_OBSERVATION",utc(D.minusDays(90),0),"PCS");stock("B","HISTORY",0,"10");
historyRow(11,"demo","W","C","HISTORY",D.minusDays(40),"4","PCS");
historyRow(11,"demo","W","C","HISTORY",D.minusDays(2),"100","BOX");
historyRow(11,"demo","W","C","HISTORY",D.minusDays(1),"0","PCS");
historyRow(11,"demo","W","C","HISTORY",D.plusDays(1),"100","PCS");
historyRow(99,"demo","W","C","HISTORY",D,"100","PCS");
historyRow(11,"other-account","W","C","HISTORY",D,"100","PCS");
historyRow(11,"demo","OTHER","C","HISTORY",D,"100","PCS");
historyRow(11,"demo","W","B","HISTORY",D.minusDays(3),"9","PCS");
historyRow(11,"demo","W","C","OTHER-SKU",D,"100","PCS");
historyRow(11,"demo","W","C","NONE",D.minusDays(3),null,"PCS");
historyRow(11,"demo","W","C","NONE",D.minusDays(2),"8",null);
historyRow(11,"demo","W","C","NONE",D.minusDays(1),"-1","PCS");
historyRow(11,"demo","W","C","NONE",D,"0","PCS");
historyRow(11,"demo","W","C","ANCHOR",D,"1","PCS");
var p=request("INVENTORY",D.minusDays(30),D,null,null,utc(D,8),0,20);
var options=new AnalyticsInventoryOptions(null,"ALL","AVAILABLE_DESC",null,null,null,null,null);
var rows=inventoryRows(p,options);assertEquals(4,rows.size());
for(var row:rows){
LocalDate expected=row.skuCode().equals("ANCHOR")?D:row.skuCode().equals("NONE")?null:row.customerCode().equals("B")?D.minusDays(3):D.minusDays(40);
assertEquals(expected,row.lastOutbound(),row.customerCode()+"/"+row.skuCode());
}
// The pre-existing grouped path remains an independent semantic baseline.
var legacy=inventoryRows(p,new AnalyticsInventoryOptions(null,"ALL","PHYSICAL_DESC",null,null,null,null,null));
assertEquals(legacy,rows);
var selected=inventoryRows(request("INVENTORY",D.minusDays(30),D,"C","HISTORY",utc(D,8),0,20),options);
assertEquals(1,selected.size());assertEquals(D.minusDays(40),selected.get(0).lastOutbound());
}
private void historyRow(long version,String account,String warehouse,String owner,String sku,LocalDate day,String quantity,String unit)throws Exception {
try(var statement=schema.prepareStatement("INSERT INTO ll_selfop_sku_daily_sales VALUES(?,?,?,?,?,?,?,?,?,?)")){
statement.setLong(1,nextId++);statement.setLong(2,version);statement.setString(3,account);statement.setString(4,warehouse);
statement.setString(5,owner);statement.setString(6,sku);statement.setObject(7,day);
statement.setBigDecimal(8,quantity==null?null:new BigDecimal(quantity));statement.setLong(9,1L);statement.setString(10,unit);statement.executeUpdate();
}
}
@Test void stockFirstDoesNotTurnUnavailableSalesOrExpiredInventoryIntoKnownValues() throws Exception {
profile(22,"C","SKU","INVENTORY_OBSERVATION",utc(D.minusDays(60),0),"PCS");stock("C","SKU",0,"10");daily(11,"W","C","SKU",D.minusDays(1),"3");
var options=new AnalyticsInventoryOptions(null,null,null,90,null,null,null,null);