fix(booking): TEST restore required arrival candidate

This commit is contained in:
2026-10-22 18:48:21 +08:00
parent c5ac966ce9
commit 310d86da85
3 changed files with 9 additions and 16 deletions
@@ -262,13 +262,13 @@ public class OceanBookingService {
} }
} }
private static void validateRange(LocalDateTime from, LocalDateTime to) { if (from != null && to != null && to.isBefore(from)) throw badRequest("预计到港时间不能早于预计开船时间"); } private static void validateRange(LocalDateTime from, LocalDateTime to) { if (from != null && to != null && to.isBefore(from)) throw badRequest("预计到港时间不能早于预计开船时间"); }
/** 放舱核对必要运输资料;预计到港为可选计划,不阻断放舱。 */ /** 放舱要求预计到港,供关联柜次的到港日历及默认到仓日期使用。 */
private static void validateRelease(OceanBookingEntity booking, List<OceanBookingPartyEntity> parties, private static void validateRelease(OceanBookingEntity booking, List<OceanBookingPartyEntity> parties,
List<OceanBookingContainerRequirementEntity> requirements) { List<OceanBookingContainerRequirementEntity> requirements) {
if (!StringUtils.hasText(booking.getChannelCode()) || booking.getWarehouseId() == null if (!StringUtils.hasText(booking.getChannelCode()) || booking.getWarehouseId() == null
|| !StringUtils.hasText(booking.getBillOfLadingNo()) || !StringUtils.hasText(booking.getVesselName()) || !StringUtils.hasText(booking.getBillOfLadingNo()) || !StringUtils.hasText(booking.getVesselName())
|| !StringUtils.hasText(booking.getVoyageNo()) || booking.getEstimatedSailingAt() == null || !StringUtils.hasText(booking.getVoyageNo()) || booking.getEstimatedSailingAt() == null
|| booking.getShippingCompanyId() == null || booking.getEstimatedArrivalAt() == null || booking.getShippingCompanyId() == null
|| (!StringUtils.hasText(booking.getDeparturePortName()) && !StringUtils.hasText(booking.getDeparturePortCode())) || (!StringUtils.hasText(booking.getDeparturePortName()) && !StringUtils.hasText(booking.getDeparturePortCode()))
|| (!StringUtils.hasText(booking.getDestinationPortName()) && !StringUtils.hasText(booking.getDestinationPortCode())) || (!StringUtils.hasText(booking.getDestinationPortName()) && !StringUtils.hasText(booking.getDestinationPortCode()))
|| !StringUtils.hasText(booking.getPlaceOfDelivery()) || !StringUtils.hasText(booking.getPlaceOfDelivery())
@@ -200,7 +200,7 @@ components:
destinationPortName: {type: string, nullable: true} destinationPortName: {type: string, nullable: true}
placeOfDelivery: {type: string, nullable: true} placeOfDelivery: {type: string, nullable: true}
estimatedSailingAt: {type: string, format: date-time, nullable: true} estimatedSailingAt: {type: string, format: date-time, nullable: true}
estimatedArrivalAt: {type: string, format: date-time, nullable: true, description: 可选预计到港时间;放舱不要求填写,填写时不得早于预计开船时间} estimatedArrivalAt: {type: string, format: date-time, nullable: true, description: 草稿可留空,放舱前必填;不得早于预计开船时间,关联柜次后作为到港日历及默认到仓日期来源}
remark: {type: string, nullable: true} remark: {type: string, nullable: true}
freightTerm: {type: string, maxLength: 64, nullable: true, description: 运费条款;新建页面默认FREIGHT PREPAID} freightTerm: {type: string, maxLength: 64, nullable: true, description: 运费条款;新建页面默认FREIGHT PREPAID}
serviceTerm: {type: string, maxLength: 64, nullable: true, description: 运输条款;新建页面默认CY-CY} serviceTerm: {type: string, maxLength: 64, nullable: true, description: 运输条款;新建页面默认CY-CY}
@@ -231,24 +231,17 @@ class OceanBookingServiceTest {
verify(repository, times(1)).transition(1L, "DRAFT", "RELEASED", 3, 9L, "admin"); verify(repository, times(1)).transition(1L, "DRAFT", "RELEASED", 3, 9L, "admin");
} }
/** 不录预计到港仍可放舱,其余资料及附件门禁保持有效。 */ /** 缺预计到港不能放舱,避免关联柜次后丢失日历及默认到仓日期来源。 */
@Test @Test
void releasesWithoutEstimatedArrival() { void rejectsReleaseWithoutEstimatedArrival() {
stubMasterData();
OceanBookingEntity draft = completeBooking("DRAFT", 3); OceanBookingEntity draft = completeBooking("DRAFT", 3);
OceanBookingEntity released = completeBooking("RELEASED", 4);
draft.setEstimatedArrivalAt(null); draft.setEstimatedArrivalAt(null);
released.setEstimatedArrivalAt(null); when(repository.find(1L)).thenReturn(draft);
when(repository.find(1L)).thenReturn(draft, released);
when(repository.parties(1L)).thenReturn(parties()); when(repository.parties(1L)).thenReturn(parties());
when(repository.requirements(1L)).thenReturn(List.of(requirement())); when(repository.requirements(1L)).thenReturn(List.of(requirement()));
when(repository.transition(1L, "DRAFT", "RELEASED", 3, 9L, "admin")).thenReturn(1); assertThatThrownBy(() -> service.release(1L, 9L, "admin", "release-no-arrival", new ReleaseRequest(3, "确认放舱")))
.isInstanceOf(BizException.class).hasMessageContaining("尚未填写完整");
Detail result = service.release(1L, 9L, "admin", "release-no-arrival", new ReleaseRequest(3, "确认放舱")); verify(repository, never()).transition(anyLong(), anyString(), anyString(), anyInt(), anyLong(), anyString());
assertThat(result.oceanBooking().getStatus()).isEqualTo("RELEASED");
assertThat(result.oceanBooking().getEstimatedArrivalAt()).isNull();
verify(documents).requireActiveValidDocument(draft);
} }
@Test @Test