test(firstleg): cover booking-level truck lifecycle

This commit is contained in:
2026-09-01 16:36:41 +08:00
parent 9098d8dfdf
commit 0ba3df2fce
4 changed files with 247 additions and 196 deletions
@@ -455,6 +455,78 @@ class TruckAppointmentServiceTest {
assertThat(history.getValue().getToStatus()).isEqualTo("RESCHEDULED");
}
@Test void createRejectsUnknownBookingWithoutWriting() {
SaveRequest request = validRequest();
when(oceanBookings.find(99L)).thenReturn(null);
assertThatThrownBy(() -> service.create(7L, "admin", request))
.isInstanceOf(BizException.class).hasMessageContaining("关联订舱不存在");
verify(repository, never()).insert(any());
verify(repository, never()).history(any());
}
@Test void createRejectsWarehouseMismatchWithoutWriting() {
SaveRequest request = validRequest();
when(request.warehouseId()).thenReturn(19L);
assertThatThrownBy(() -> service.create(7L, "admin", request))
.isInstanceOf(BizException.class).hasMessageContaining("warehouseId与订舱不一致");
verify(repository, never()).insert(any());
}
@Test void createRejectsInvalidTruckingSupplierWithoutWriting() {
SaveRequest request = validRequest();
when(suppliers.trucking(8L, null)).thenThrow(
new BizException(com.baiyue.common.core.api.ResultCode.CONFLICT, "拖车服务商未启用"));
assertThatThrownBy(() -> service.create(7L, "admin", request))
.isInstanceOf(BizException.class).hasMessageContaining("拖车服务商未启用");
verify(repository, never()).insert(any());
}
@Test void editRejectsTargetBookingOwnedByAnotherActiveAppointment() {
TruckAppointmentEntity current = entity(TruckAppointmentStatus.DRAFT, 3);
current.setOceanBookingId(99L);
TruckAppointmentEntity occupied = entity(TruckAppointmentStatus.PENDING_DISPATCH, 1);
occupied.setId(2L); occupied.setOceanBookingId(199L); occupied.setAppointmentNo("TA-260901-0099");
SaveRequest request = validRequest();
when(request.expectedVersion()).thenReturn(3);
when(request.oceanBookingId()).thenReturn(199L);
OceanBookingEntity target = releasedBooking(); target.setId(199L);
when(oceanBookings.find(199L)).thenReturn(target);
when(repository.find(1L)).thenReturn(current);
when(repository.firstActiveForUpdate(199L)).thenReturn(occupied);
assertThatThrownBy(() -> service.edit(1L, 7L, "admin", request))
.isInstanceOf(BizException.class).hasMessageContaining("TA-260901-0099");
verify(repository, never()).updateEdit(any(), anyInt());
}
@Test void detailJsonContainsNoContainerProtocolFields() throws Exception {
TruckAppointmentEntity appointment = entity(TruckAppointmentStatus.DRAFT, 0);
appointment.setOceanBookingId(99L); appointment.setContainerBookingId(88L);
appointment.setLoadingPlanId(77L); appointment.setCabinetNo("CAB-OLD"); appointment.setContainerNo("MSCU6639870");
when(repository.find(1L)).thenReturn(appointment);
String json = objectMapper.writeValueAsString(service.detail(1L));
assertThat(json).doesNotContain("containerBookingId", "loadingPlanId", "cabinetNo", "containerNo", "containers");
assertThat(json).contains("oceanBookingId");
}
@Test void deleteAttachmentKeepsAppointmentOwnershipGuard() {
when(repository.find(1L)).thenReturn(entity(TruckAppointmentStatus.DRAFT, 0));
when(repository.deleteAttachment(1L, 77L)).thenReturn(1);
service.deleteAttachment(1L, 77L);
verify(repository).deleteAttachment(1L, 77L);
}
private String requestHash(String action, long id, Object request) throws Exception {
String canonical = action + '|' + id + '|' + objectMapper.writeValueAsString(request);
return java.util.HexFormat.of().formatHex(java.security.MessageDigest.getInstance("SHA-256")