fix(lastleg): repair first appointment execution scope on validated release baseline
This commit is contained in:
+2
-1
@@ -39,7 +39,8 @@ public class FbaAppointmentExecutionAdapter implements FbaAppointmentExecutionPo
|
||||
var members=members(input);if(members.isEmpty()) throw bad("请选择需要重新预约的客户");
|
||||
var before=read(batches(members));var selected=selected(before,members);
|
||||
var tripNos=tripNos(selected);var numbers=dispatchNos(selected);
|
||||
amendments.lockExistingAppointmentDispatches(new Actor(operator,ActorMode.PLATFORM,null),numbers);
|
||||
// 尚未排车的客户仍需核对完整执行版本,但没有原排车资源需要加锁。
|
||||
if(!numbers.isEmpty()) amendments.lockExistingAppointmentDispatches(new Actor(operator,ActorMode.PLATFORM,null),numbers);
|
||||
for(var number:numbers) {
|
||||
dispatches.completion(number,true);
|
||||
dispatches.lockForPlanning(number);
|
||||
|
||||
+27
@@ -52,6 +52,33 @@ class FbaAppointmentExecutionAdapterTest {
|
||||
assertThrows(org.springframework.web.server.ResponseStatusException.class,()->adapter.lockAndInspect(List.of(),"empty","operator"));
|
||||
verifyNoInteractions(mapper,amendments,dispatches);
|
||||
}
|
||||
/** 有真实客户货物但尚未排车时,可按当前完整版本登记预约,不调用原排车锁。 */
|
||||
@Test void unassignedCustomerCanRebookWithoutLockingAnEmptyDispatchScope() {
|
||||
when(mapper.transportRows(List.of(batch),List.of())).thenReturn(List.of());
|
||||
var current=adapter.inspect(List.of(b));
|
||||
var locked=adapter.lockAndInspect(List.of(b),current.version(),"operator");
|
||||
assertEquals(current.version(),locked.version());
|
||||
assertFalse(locked.members().get(0).completed());assertTrue(locked.members().get(0).canRebook());
|
||||
verifyNoInteractions(amendments,dispatches);
|
||||
}
|
||||
/** 无排车不免除乐观锁,过期的完整执行版本仍须拒绝。 */
|
||||
@Test void unassignedCustomerStillRequiresTheCurrentCompleteExecutionVersion() {
|
||||
when(mapper.transportRows(List.of(batch),List.of())).thenReturn(List.of());
|
||||
var error=assertThrows(org.springframework.web.server.ResponseStatusException.class,
|
||||
()->adapter.lockAndInspect(List.of(b),"stale-version","operator"));
|
||||
assertEquals(409,error.getStatusCode().value());
|
||||
verifyNoInteractions(amendments,dispatches);
|
||||
}
|
||||
/** 首读无排车、复核时已关联排车,必须拒绝并要求刷新,不能沿空范围放行。 */
|
||||
@Test void dispatchAssociatedDuringTheEmptyScopeRecheckInvalidatesTheVersion() {
|
||||
when(mapper.transportRows(List.of(batch),List.of())).thenReturn(List.of(),List.of(),List.of(row("B","BEFORE_LOADING","PLANNED")));
|
||||
var prior=adapter.inspect(List.of(b));
|
||||
var error=assertThrows(org.springframework.web.server.ResponseStatusException.class,
|
||||
()->adapter.lockAndInspect(List.of(b),prior.version(),"operator"));
|
||||
assertEquals(409,error.getStatusCode().value());
|
||||
verifyNoInteractions(amendments);
|
||||
verify(dispatches,never()).completion(anyString(),eq(true));verify(dispatches,never()).lockForPlanning(anyString());
|
||||
}
|
||||
/** 同车总发运量不能替代本客户的真实签收数量。 */
|
||||
@Test void onePhysicalDispatchUsesCustomerEvidenceInsteadOfTheWholeCarShipmentTotal() {
|
||||
var rows=List.of(new AppointmentWorkDispatchMapper.TransportRow(1,"D-ONE","A","ACTIVE","DELIVERING",2L,200,200,LocalDateTime.of(2026,10,1,12,0),11,101,100,"RECEIVED",batch,"ORDER:1","FBA:ONT8",100,"T-ONE",2L,"IN_TRANSIT",201L,"OUTBOUNDED","COMPLETED"),
|
||||
|
||||
Reference in New Issue
Block a user