feat(orders): expose customer-owned loaded transport facts
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
package com.baiyue.firstleg.dto;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/** Customer-safe, read-only transport facts for one actually loaded inbound/container fragment. */
|
||||
public record CustomerTransportFragment(String inboundCode, String cabinetNo, String containerNo,
|
||||
List<Node> nodes) {
|
||||
public record Node(String standardNode, Integer nodeSequence, String providerCode,
|
||||
LocalDateTime estimatedAt, LocalDateTime actualAt,
|
||||
String locationCode, String locationName) {}
|
||||
|
||||
public record Row(Long inboundId, Long containerBookingId, String inboundCode, String cabinetNo,
|
||||
String containerNo, String standardNode, Integer nodeSequence, String providerCode,
|
||||
LocalDateTime estimatedAt, LocalDateTime actualAt,
|
||||
String locationCode, String locationName) {}
|
||||
}
|
||||
@@ -6,7 +6,8 @@ import java.util.List;
|
||||
/** Detail payload for the product-level order detail. */
|
||||
public record UnifiedInboundDetail(
|
||||
UnifiedInboundSummary summary,
|
||||
List<TimelineEvent> timeline
|
||||
List<TimelineEvent> timeline,
|
||||
List<CustomerTransportFragment> transportFragments
|
||||
) {
|
||||
public record TimelineEvent(String source, String eventType, String fromStatus, String toStatus,
|
||||
String action, String remark, Long operatorId, String operatorName,
|
||||
|
||||
@@ -10,6 +10,29 @@ import java.util.List;
|
||||
/** 统一订单按当前有效装柜明细批量读取柜次船期。 */
|
||||
@Mapper
|
||||
public interface UnifiedInboundTransportMapper {
|
||||
@Select("""
|
||||
SELECT owned.inbound_id, owned.container_booking_id, owned.inbound_code,
|
||||
b.cabinet_no, b.container_no, n.standard_node, n.node_sequence, n.provider_code,
|
||||
n.estimated_at, n.actual_at, n.location_code, n.location_name
|
||||
FROM (
|
||||
SELECT DISTINCT o.id AS inbound_id, p.container_booking_id, o.inbound_code
|
||||
FROM fl_inbound_order o
|
||||
JOIN fl_loading_plan_item i ON i.inbound_id=o.id AND i.account_id=o.tenant_id
|
||||
JOIN fl_loading_plan p ON p.id=i.loading_plan_id AND p.plan_status='COMPLETED'
|
||||
JOIN fl_loading_pick_task t ON t.loading_plan_id=p.id AND t.task_status='COMPLETED'
|
||||
JOIN fl_loading_pick_item picked ON picked.pick_task_id=t.id
|
||||
AND picked.loading_plan_item_id=i.id
|
||||
WHERE o.tenant_id=#{tenantId} AND o.order_id=#{orderId} AND o.deleted=0
|
||||
AND i.deleted=0 AND picked.item_status IN ('PICKED','PARTIAL')
|
||||
AND picked.picked_package_count>0
|
||||
) owned
|
||||
JOIN fl_container_booking b ON b.id=owned.container_booking_id
|
||||
LEFT JOIN fl_carrier_schedule_node_fact n ON n.container_booking_id=owned.container_booking_id
|
||||
ORDER BY owned.inbound_id, owned.container_booking_id, n.node_sequence, n.id
|
||||
""")
|
||||
List<com.baiyue.firstleg.dto.CustomerTransportFragment.Row> findCustomerTransportNodes(
|
||||
@Param("tenantId") long tenantId, @Param("orderId") long orderId);
|
||||
|
||||
@Select("""
|
||||
<script>
|
||||
SELECT DISTINCT i.inbound_id, i.account_id, p.container_booking_id,
|
||||
|
||||
+18
@@ -86,6 +86,24 @@ public class UnifiedInboundReadRepository {
|
||||
return findTransports(Map.of(inboundId, tenantId)).get(inboundId);
|
||||
}
|
||||
|
||||
public List<com.baiyue.firstleg.dto.CustomerTransportFragment> findCustomerTransportFragments(
|
||||
long tenantId, long orderId) {
|
||||
var grouped = new java.util.LinkedHashMap<String,
|
||||
List<com.baiyue.firstleg.dto.CustomerTransportFragment.Row>>();
|
||||
transports.findCustomerTransportNodes(tenantId, orderId).forEach(row ->
|
||||
grouped.computeIfAbsent(row.inboundId() + ":" + row.containerBookingId(),
|
||||
ignored -> new java.util.ArrayList<>()).add(row));
|
||||
return grouped.values().stream().map(rows -> {
|
||||
var first = rows.get(0);
|
||||
var nodes = rows.stream().filter(row -> row.standardNode() != null)
|
||||
.map(row -> new com.baiyue.firstleg.dto.CustomerTransportFragment.Node(
|
||||
row.standardNode(), row.nodeSequence(), row.providerCode(), row.estimatedAt(),
|
||||
row.actualAt(), row.locationCode(), row.locationName())).toList();
|
||||
return new com.baiyue.firstleg.dto.CustomerTransportFragment(first.inboundCode(),
|
||||
first.cabinetNo(), first.containerNo(), nodes);
|
||||
}).toList();
|
||||
}
|
||||
|
||||
public Map<Long, CurrentContainerTransport> findTransports(Map<Long, Long> tenantByInbound) {
|
||||
if (tenantByInbound.isEmpty()) return Map.of();
|
||||
Map<Long, List<CurrentContainerTransport>> grouped = transports
|
||||
|
||||
@@ -83,8 +83,11 @@ public class UnifiedInboundQueryService {
|
||||
? operations.findTransport(tenantId, inbound.getId()) : null;
|
||||
boolean customerFeeConfirmationRequired = pricing.customerFeeConfirmationRequiredMap(
|
||||
tenantId, Map.of(inbound.getId(), inbound.getTenantId())).getOrDefault(inbound.getId(), false);
|
||||
boolean hasTransportScope = includePhaseThree || inbounds.findByOrderIds(tenantId, List.of(orderId))
|
||||
.stream().anyMatch(item -> requiresPhaseThreeSummary(mainStatus(item.getProcessStatus())));
|
||||
return new UnifiedInboundDetail(summary(inbound, detail, preload, pick, evidence, deliveryAt,
|
||||
transport, null, null, customerFeeConfirmationRequired), timeline);
|
||||
transport, null, null, customerFeeConfirmationRequired), timeline,
|
||||
hasTransportScope ? operations.findCustomerTransportFragments(tenantId, orderId) : List.of());
|
||||
}
|
||||
|
||||
private List<UnifiedInboundSummary> summaries(List<InboundOrderEntity> records) {
|
||||
|
||||
Reference in New Issue
Block a user