fix: expose the selected container schedule for editing
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
package com.baiyue.firstleg.entity;
|
package com.baiyue.firstleg.entity;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import com.baomidou.mybatisplus.annotation.FieldFill;
|
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
@@ -75,6 +76,9 @@ public class ContainerBookingEntity {
|
|||||||
@TableField(exist = false) private Long planId;
|
@TableField(exist = false) private Long planId;
|
||||||
@TableField(exist = false) private String planNo;
|
@TableField(exist = false) private String planNo;
|
||||||
@TableField(exist = false) private String planStatus;
|
@TableField(exist = false) private String planStatus;
|
||||||
|
/** Identity of the port schedule selected for the current transport read model. */
|
||||||
|
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
||||||
|
@TableField(exist = false) private Long currentPortScheduleId;
|
||||||
/** Actual completion timestamp projected from the associated loading plan. */
|
/** Actual completion timestamp projected from the associated loading plan. */
|
||||||
@JsonIgnore @TableField(exist = false) private LocalDateTime completedLoadingAt;
|
@JsonIgnore @TableField(exist = false) private LocalDateTime completedLoadingAt;
|
||||||
@TableField(exist = false) private Boolean exceptionActive;
|
@TableField(exist = false) private Boolean exceptionActive;
|
||||||
|
|||||||
@@ -71,9 +71,12 @@ public class ContainerRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void resolveCurrentPortSchedule(ContainerBookingEntity value) {
|
private void resolveCurrentPortSchedule(ContainerBookingEntity value) {
|
||||||
if (value == null || value.getCustomerId() == null || value.getOceanBookingId() == null) return;
|
if (value == null) return;
|
||||||
|
value.setCurrentPortScheduleId(null);
|
||||||
|
if (value.getCustomerId() == null || value.getOceanBookingId() == null) return;
|
||||||
PortScheduleEntity schedule = schedules.latestForDispatch(value.getCustomerId(), value.getOceanBookingId(), value.getId());
|
PortScheduleEntity schedule = schedules.latestForDispatch(value.getCustomerId(), value.getOceanBookingId(), value.getId());
|
||||||
if (schedule == null) return;
|
if (schedule == null) return;
|
||||||
|
value.setCurrentPortScheduleId(schedule.getId());
|
||||||
value.setVesselName(schedule.getVesselName());
|
value.setVesselName(schedule.getVesselName());
|
||||||
value.setVoyageNo(schedule.getVoyageNo());
|
value.setVoyageNo(schedule.getVoyageNo());
|
||||||
value.setEstimatedSailingAt(schedule.getEtdAt());
|
value.setEstimatedSailingAt(schedule.getEtdAt());
|
||||||
|
|||||||
@@ -2260,6 +2260,7 @@ components:
|
|||||||
required: [id, bookingNo, cabinetNo, sourceType, recordStatus, warehouseId, warehouseName, channelGroupCode, containerType, capacityCbm, maxWeightKg, planStatus, exceptionActive, destinationClearanceDocumentStatus, customsDeclarationDocumentStatus, deliveryOrderDocumentStatus, version]
|
required: [id, bookingNo, cabinetNo, sourceType, recordStatus, warehouseId, warehouseName, channelGroupCode, containerType, capacityCbm, maxWeightKg, planStatus, exceptionActive, destinationClearanceDocumentStatus, customsDeclarationDocumentStatus, deliveryOrderDocumentStatus, version]
|
||||||
properties:
|
properties:
|
||||||
id: {type: string, pattern: '^[1-9][0-9]*$'}
|
id: {type: string, pattern: '^[1-9][0-9]*$'}
|
||||||
|
currentPortScheduleId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true, readOnly: true, description: 当前运输读模型由 latestForDispatch 选中的船期记录 ID;无匹配时为空,仅用于定位关联船期,不作为业务编号展示}
|
||||||
planId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true, description: 关联智能装柜计划ID;未创建计划时为空}
|
planId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true, description: 关联智能装柜计划ID;未创建计划时为空}
|
||||||
planNo: {type: string, nullable: true, pattern: '^LP-[0-9]{6}-[0-9]{4}$', example: LP-260818-0001, description: 预装与确认装柜清单共用的稳定编号;未创建计划时为空}
|
planNo: {type: string, nullable: true, pattern: '^LP-[0-9]{6}-[0-9]{4}$', example: LP-260818-0001, description: 预装与确认装柜清单共用的稳定编号;未创建计划时为空}
|
||||||
bookingNo: {type: string, pattern: '^CB-[0-9]{6}-[0-9]{4}$', example: CB-260818-0001, description: 平台内部货柜登记号}
|
bookingNo: {type: string, pattern: '^CB-[0-9]{6}-[0-9]{4}$', example: CB-260818-0001, description: 平台内部货柜登记号}
|
||||||
|
|||||||
+38
@@ -4,6 +4,8 @@ import com.baiyue.firstleg.entity.ContainerBookingEntity;
|
|||||||
import com.baiyue.firstleg.mapper.ContainerBookingMapper;
|
import com.baiyue.firstleg.mapper.ContainerBookingMapper;
|
||||||
import com.baiyue.firstleg.portschedule.entity.PortScheduleEntity;
|
import com.baiyue.firstleg.portschedule.entity.PortScheduleEntity;
|
||||||
import com.baiyue.firstleg.portschedule.mapper.PortScheduleMapper;
|
import com.baiyue.firstleg.portschedule.mapper.PortScheduleMapper;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.mockito.InjectMocks;
|
import org.mockito.InjectMocks;
|
||||||
@@ -32,6 +34,7 @@ class ContainerRepositoryLoadingTimeTest {
|
|||||||
ContainerBookingEntity result = repository.find(7L);
|
ContainerBookingEntity result = repository.find(7L);
|
||||||
|
|
||||||
assertThat(result.getLoadingAt()).isEqualTo(completedAt);
|
assertThat(result.getLoadingAt()).isEqualTo(completedAt);
|
||||||
|
assertThat(result.getCurrentPortScheduleId()).isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -58,6 +61,7 @@ class ContainerRepositoryLoadingTimeTest {
|
|||||||
booking.setVesselName("OLD-VESSEL");
|
booking.setVesselName("OLD-VESSEL");
|
||||||
booking.setVoyageNo("OLD-V01");
|
booking.setVoyageNo("OLD-V01");
|
||||||
PortScheduleEntity schedule = new PortScheduleEntity();
|
PortScheduleEntity schedule = new PortScheduleEntity();
|
||||||
|
schedule.setId(11L);
|
||||||
schedule.setVesselName("NEW-VESSEL");
|
schedule.setVesselName("NEW-VESSEL");
|
||||||
schedule.setVoyageNo("NEW-V01");
|
schedule.setVoyageNo("NEW-V01");
|
||||||
schedule.setEtdAt(LocalDateTime.of(2026, 10, 7, 8, 0));
|
schedule.setEtdAt(LocalDateTime.of(2026, 10, 7, 8, 0));
|
||||||
@@ -68,9 +72,43 @@ class ContainerRepositoryLoadingTimeTest {
|
|||||||
ContainerBookingEntity result = repository.find(8L);
|
ContainerBookingEntity result = repository.find(8L);
|
||||||
|
|
||||||
assertThat(result.getContainerNo()).isEqualTo("TSTU0000001");
|
assertThat(result.getContainerNo()).isEqualTo("TSTU0000001");
|
||||||
|
assertThat(result.getCurrentPortScheduleId()).isEqualTo(11L);
|
||||||
assertThat(result.getVesselName()).isEqualTo("NEW-VESSEL");
|
assertThat(result.getVesselName()).isEqualTo("NEW-VESSEL");
|
||||||
assertThat(result.getVoyageNo()).isEqualTo("NEW-V01");
|
assertThat(result.getVoyageNo()).isEqualTo("NEW-V01");
|
||||||
assertThat(result.getEstimatedSailingAt()).isEqualTo(schedule.getEtdAt());
|
assertThat(result.getEstimatedSailingAt()).isEqualTo(schedule.getEtdAt());
|
||||||
assertThat(result.getEstimatedPortArrivalAt()).isEqualTo(schedule.getEtaAt());
|
assertThat(result.getEstimatedPortArrivalAt()).isEqualTo(schedule.getEtaAt());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void leavesCurrentPortScheduleNullWhenNoScheduleMatches() {
|
||||||
|
ContainerBookingEntity booking = new ContainerBookingEntity();
|
||||||
|
booking.setId(8L);
|
||||||
|
booking.setCustomerId(9L);
|
||||||
|
booking.setOceanBookingId(10L);
|
||||||
|
booking.setCurrentPortScheduleId(11L);
|
||||||
|
booking.setVesselName("BOOKING-VESSEL");
|
||||||
|
booking.setVoyageNo("BOOKING-V01");
|
||||||
|
when(mapper.selectBooking(8L)).thenReturn(booking);
|
||||||
|
when(schedules.latestForDispatch(9L, 10L, 8L)).thenReturn(null);
|
||||||
|
|
||||||
|
ContainerBookingEntity result = repository.find(8L);
|
||||||
|
|
||||||
|
assertThat(result.getCurrentPortScheduleId()).isNull();
|
||||||
|
assertThat(result.getVesselName()).isEqualTo("BOOKING-VESSEL");
|
||||||
|
assertThat(result.getVoyageNo()).isEqualTo("BOOKING-V01");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void currentPortScheduleIsNonPersistentAndSerializedReadOnly() throws Exception {
|
||||||
|
var field = ContainerBookingEntity.class.getDeclaredField("currentPortScheduleId");
|
||||||
|
assertThat(field.getAnnotation(TableField.class).exist()).isFalse();
|
||||||
|
ObjectMapper json = new ObjectMapper();
|
||||||
|
ContainerBookingEntity booking = new ContainerBookingEntity();
|
||||||
|
booking.setCurrentPortScheduleId(11L);
|
||||||
|
|
||||||
|
assertThat(json.readTree(json.writeValueAsString(booking)).get("currentPortScheduleId").asLong())
|
||||||
|
.isEqualTo(11L);
|
||||||
|
assertThat(json.readValue("{\"currentPortScheduleId\":11}", ContainerBookingEntity.class)
|
||||||
|
.getCurrentPortScheduleId()).isNull();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user