fix: count split picking facts in trip operations
This commit is contained in:
+10
-4
@@ -81,13 +81,19 @@ public class TripOperationsService {
|
||||
if(!pallets.add(pallet.warehousePalletId())) throw new IllegalStateException("发车实物托盘重复");
|
||||
spaces+=pallet.palletSpaces();
|
||||
}
|
||||
long own=0,external=0; var destinations=new TreeMap<String,String>(); var seen=new HashSet<String>();
|
||||
long own=0,external=0; var destinations=new TreeMap<String,String>();
|
||||
var cargoIdentity=new HashMap<String,List<String>>();
|
||||
var shippedByPallet=new HashMap<String,Long>();
|
||||
for(var cargo:load.cargo()) {
|
||||
if (!pallets.contains(cargo.warehousePalletId()) || !seen.add(cargo.dispatchNo()+":"+cargo.dispatchItemId()))
|
||||
throw new IllegalStateException("发车装载货物未核平或重复");
|
||||
shippedByPallet.merge(cargo.dispatchNo()+":"+cargo.customerId()+":"+cargo.warehousePalletId(),(long)cargo.packages(),Long::sum);
|
||||
if (!pallets.contains(cargo.warehousePalletId()) || cargo.packages()<=0
|
||||
|| cargo.dispatchNo()==null || cargo.dispatchItemId()==null || cargo.customerId()==null)
|
||||
throw new IllegalStateException("发车装载货物未核平");
|
||||
if(cargo.destinationKey()==null || cargo.destinationLabel()==null)throw new IllegalStateException("发车货物缺少目的地依据");
|
||||
// 装车快照按真实拣货来源逐段记录,同一排车明细可含多次拣货;逐段累加但归属不能漂移。
|
||||
var identity=List.of(cargo.customerId(),cargo.warehousePalletId(),cargo.destinationKey(),cargo.destinationLabel());
|
||||
var previous=cargoIdentity.putIfAbsent(cargo.dispatchNo()+":"+cargo.dispatchItemId(),identity);
|
||||
if(previous!=null && !previous.equals(identity))throw new IllegalStateException("发车装载明细归属不一致");
|
||||
shippedByPallet.merge(cargo.dispatchNo()+":"+cargo.customerId()+":"+cargo.warehousePalletId(),(long)cargo.packages(),Long::sum);
|
||||
destinations.put(cargo.destinationKey(),cargo.destinationLabel());
|
||||
}
|
||||
for(var entry:externalByPallet.entrySet()) if(entry.getValue()>shippedByPallet.getOrDefault(entry.getKey(),0L))throw new IllegalStateException("外接实收超过实际发车货量");
|
||||
|
||||
+27
@@ -34,6 +34,33 @@ class TripOperationsServiceTest {
|
||||
assertThatThrownBy(()->service.project(new TripOperationsRepository.Departure("TR-A","IN_TRANSIT",null,null,null))).hasMessageContaining("不可变历史");
|
||||
assertThatThrownBy(()->service.project(new TripOperationsRepository.Departure("TR-A","IN_TRANSIT",null,DEPARTURE.replace("\"receivedPackages\":4","\"receivedPackages\":20").replace("\"packages\":4","\"packages\":20"),null))).hasMessageContaining("超过实际发车");
|
||||
}
|
||||
/** 同一排车明细的分次拣货必须逐段计数,实托只计一次且客户和目的地仍严格核对。 */
|
||||
@Test void splitPicksOfOneDispatchItemSumWithoutDuplicatingPhysicalPallets() throws Exception {
|
||||
var mapper=new ObjectMapper().registerModule(new JavaTimeModule());
|
||||
var snapshot=mapper.readTree(DEPARTURE);
|
||||
var cargo=(com.fasterxml.jackson.databind.node.ArrayNode)snapshot.path("confirmedLoad").path("cargo");
|
||||
var first=(com.fasterxml.jackson.databind.node.ObjectNode)cargo.get(0);
|
||||
first.put("packages",2);
|
||||
var second=first.deepCopy().put("packages",8);
|
||||
cargo.add(second);
|
||||
var service=new TripOperationsService(mock(TripOperationsRepository.class),mapper,mock(FleetTripCostService.class));
|
||||
var row=service.project(new TripOperationsRepository.Departure("TR-A","IN_TRANSIT",null,mapper.writeValueAsString(snapshot),null));
|
||||
assertThat(row.ownPackages()).isEqualTo(11);
|
||||
assertThat(row.externalPackages()).isEqualTo(4);
|
||||
assertThat(row.physicalPallets()).isEqualTo(1);
|
||||
assertThat(row.palletSpaces()).isEqualTo(2);
|
||||
for(String field:List.of("customerId","destinationKey","destinationLabel","warehousePalletId")) {
|
||||
var invalid=snapshot.deepCopy();
|
||||
((com.fasterxml.jackson.databind.node.ObjectNode)invalid.path("confirmedLoad").path("cargo").get(2)).put(field,"OTHER");
|
||||
String value=mapper.writeValueAsString(invalid);
|
||||
assertThatThrownBy(()->service.project(new TripOperationsRepository.Departure("TR-A","IN_TRANSIT",null,value,null)))
|
||||
.isInstanceOf(IllegalStateException.class).hasMessageContaining("发车装载");
|
||||
}
|
||||
second.put("packages",0);
|
||||
String zero=mapper.writeValueAsString(snapshot);
|
||||
assertThatThrownBy(()->service.project(new TripOperationsRepository.Departure("TR-A","IN_TRANSIT",null,zero,null)))
|
||||
.hasMessageContaining("未核平");
|
||||
}
|
||||
@Test void summaryUsesAllFilteredDeparturesNotCurrentPageAndSeparatesCurrencies() {
|
||||
var repo=mock(TripOperationsRepository.class);var service=new TripOperationsService(repo,new ObjectMapper().registerModule(new JavaTimeModule()),mock(FleetTripCostService.class));
|
||||
var query=new TripOperationsModels.Query(1,1,Instant.parse("2026-10-01T00:00:00Z"),Instant.parse("2026-10-03T00:00:00Z"),null,null,"EXTERNAL",null);
|
||||
|
||||
Reference in New Issue
Block a user