feat: expose dispatch BOL lines
This commit is contained in:
@@ -12,11 +12,16 @@ public record DispatchResponse(Long id, String dispatchNo, String vehiclePlate,
|
|||||||
int itemCount, int palletCount, int packageCount, int pickedPackageCount,
|
int itemCount, int palletCount, int packageCount, int pickedPackageCount,
|
||||||
int shippedPackageCount, int remainingPackageCount, String partialCompletionReason,
|
int shippedPackageCount, int remainingPackageCount, String partialCompletionReason,
|
||||||
LocalDateTime createdAt,
|
LocalDateTime createdAt,
|
||||||
List<Item> items) {
|
List<Item> items, List<BolLine> bolLines) {
|
||||||
public record Item(Long id, Long planPalletId, Long warehousePalletId, String palletNo,
|
public record Item(Long id, Long planPalletId, Long warehousePalletId, String palletNo,
|
||||||
String overseasWarehouseId, String overseasWarehouseName,
|
String overseasWarehouseId, String overseasWarehouseName,
|
||||||
String orderNo, String orderRefs, String inboundCode, String destinationWarehouseCode,
|
String orderNo, String orderRefs, String inboundCode, String destinationWarehouseCode,
|
||||||
String destinationWarehouseName, String fbaWarehouseCode, int packageCount,
|
String destinationWarehouseName, String fbaWarehouseCode, int packageCount,
|
||||||
BigDecimal volumeCbm, String sourceStage) {
|
BigDecimal volumeCbm, String sourceStage) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public record BolLine(String containerNo, String palletNo, String fbaWarehouseCode,
|
||||||
|
String destinationWarehouseName, String warehouseNo, String fbaShipmentId,
|
||||||
|
String poReferenceNo, int packageCount) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+35
@@ -0,0 +1,35 @@
|
|||||||
|
package com.baiyue.lastleg.dispatch.mapper;
|
||||||
|
|
||||||
|
import com.baiyue.lastleg.dispatch.dto.DispatchResponse;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import org.apache.ibatis.annotations.Select;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface DispatchBolMapper {
|
||||||
|
@Select("SELECT " +
|
||||||
|
"COALESCE(MAX(NULLIF(o.container_no,'')),MAX(NULLIF(ip.container_no,''))) AS containerNo," +
|
||||||
|
"MAX(NULLIF(di.pallet_no,'')) AS palletNo," +
|
||||||
|
"COALESCE(MAX(NULLIF(l.destination_warehouse_code,'')),MAX(NULLIF(di.fba_warehouse_code,''))," +
|
||||||
|
"MAX(NULLIF(di.destination_warehouse_code,''))) AS fbaWarehouseCode," +
|
||||||
|
"COALESCE(MAX(NULLIF(l.destination_warehouse_name,'')),MAX(NULLIF(di.destination_warehouse_name,''))) AS destinationWarehouseName," +
|
||||||
|
"COALESCE(MAX(NULLIF(l.inbound_code,'')),MAX(NULLIF(di.inbound_code,''))) AS warehouseNo," +
|
||||||
|
"GROUP_CONCAT(DISTINCT NULLIF(od.shipment_no,'') ORDER BY od.shipment_no SEPARATOR ', ') AS fbaShipmentId," +
|
||||||
|
"GROUP_CONCAT(DISTINCT NULLIF(od.fba_tracking_no,'') ORDER BY od.fba_tracking_no SEPARATOR ', ') AS poReferenceNo," +
|
||||||
|
"CASE WHEN MAX(l.id) IS NULL THEN COALESCE(MAX(di.package_count),0) " +
|
||||||
|
"WHEN COALESCE(MAX(a.picked_package_count),0)>0 THEN MAX(a.picked_package_count) " +
|
||||||
|
"ELSE COALESCE(MAX(a.planned_package_count),0) END AS packageCount " +
|
||||||
|
"FROM ll_dispatch_item di " +
|
||||||
|
"LEFT JOIN ll_inbound_plan_pallet p ON p.id=di.plan_pallet_id " +
|
||||||
|
"LEFT JOIN ll_inbound_plan ip ON ip.id=p.plan_id AND ip.customer_id=di.customer_id " +
|
||||||
|
"LEFT JOIN ll_inbound_plan_pallet_allocation a ON a.pallet_id=p.id " +
|
||||||
|
"LEFT JOIN ll_inbound_plan_line l ON l.id=a.line_id AND l.customer_id=di.customer_id " +
|
||||||
|
"LEFT JOIN ll_order o ON o.id=l.order_id AND o.customer_id=di.customer_id " +
|
||||||
|
"LEFT JOIN ll_order_detail od ON od.order_id=l.order_id AND od.customer_id=di.customer_id " +
|
||||||
|
"WHERE di.customer_id=#{customerId} AND di.dispatch_order_id=#{dispatchOrderId} " +
|
||||||
|
"GROUP BY di.id,l.id ORDER BY di.id,l.id")
|
||||||
|
List<DispatchResponse.BolLine> findByDispatchOrder(@Param("customerId") String customerId,
|
||||||
|
@Param("dispatchOrderId") Long dispatchOrderId);
|
||||||
|
}
|
||||||
+13
-3
@@ -12,6 +12,7 @@ import com.baiyue.lastleg.dispatch.entity.DispatchPalletLock;
|
|||||||
import com.baiyue.lastleg.dispatch.entity.DispatchDraft;
|
import com.baiyue.lastleg.dispatch.entity.DispatchDraft;
|
||||||
import com.baiyue.lastleg.dispatch.entity.DispatchDraftContainer;
|
import com.baiyue.lastleg.dispatch.entity.DispatchDraftContainer;
|
||||||
import com.baiyue.lastleg.dispatch.mapper.DispatchCandidateMapper;
|
import com.baiyue.lastleg.dispatch.mapper.DispatchCandidateMapper;
|
||||||
|
import com.baiyue.lastleg.dispatch.mapper.DispatchBolMapper;
|
||||||
import com.baiyue.lastleg.dispatch.mapper.DispatchItemMapper;
|
import com.baiyue.lastleg.dispatch.mapper.DispatchItemMapper;
|
||||||
import com.baiyue.lastleg.dispatch.mapper.DispatchOrderMapper;
|
import com.baiyue.lastleg.dispatch.mapper.DispatchOrderMapper;
|
||||||
import com.baiyue.lastleg.dispatch.mapper.DispatchPalletLockMapper;
|
import com.baiyue.lastleg.dispatch.mapper.DispatchPalletLockMapper;
|
||||||
@@ -49,6 +50,7 @@ public class DispatchService {
|
|||||||
|
|
||||||
@Resource private DispatchOrderMapper orders;
|
@Resource private DispatchOrderMapper orders;
|
||||||
@Resource private DispatchItemMapper items;
|
@Resource private DispatchItemMapper items;
|
||||||
|
@Resource private DispatchBolMapper bolLines;
|
||||||
@Resource private DispatchPalletLockMapper locks;
|
@Resource private DispatchPalletLockMapper locks;
|
||||||
@Resource private DispatchDraftMapper drafts;
|
@Resource private DispatchDraftMapper drafts;
|
||||||
@Resource private DispatchDraftContainerMapper draftContainers;
|
@Resource private DispatchDraftContainerMapper draftContainers;
|
||||||
@@ -429,7 +431,8 @@ public class DispatchService {
|
|||||||
|
|
||||||
public DispatchResponse detail(String customerId, String dispatchNo) {
|
public DispatchResponse detail(String customerId, String dispatchNo) {
|
||||||
DispatchOrder dispatch = find(customerId, dispatchNo);
|
DispatchOrder dispatch = find(customerId, dispatchNo);
|
||||||
return response(dispatch, items.findByDispatchOrder(dispatch.getCustomerId(), dispatch.getId()));
|
return response(dispatch, items.findByDispatchOrder(dispatch.getCustomerId(), dispatch.getId()),
|
||||||
|
bolLines.findByDispatchOrder(dispatch.getCustomerId(), dispatch.getId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public DispatchResponse platformDetail(String dispatchNo) {
|
public DispatchResponse platformDetail(String dispatchNo) {
|
||||||
@@ -437,7 +440,8 @@ public class DispatchService {
|
|||||||
if (dispatch == null) {
|
if (dispatch == null) {
|
||||||
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Dispatch order not found");
|
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Dispatch order not found");
|
||||||
}
|
}
|
||||||
return response(dispatch, items.findByDispatchOrder(dispatch.getCustomerId(), dispatch.getId()));
|
return response(dispatch, items.findByDispatchOrder(dispatch.getCustomerId(), dispatch.getId()),
|
||||||
|
bolLines.findByDispatchOrder(dispatch.getCustomerId(), dispatch.getId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@@ -499,6 +503,11 @@ public class DispatchService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private DispatchResponse response(DispatchOrder order, List<DispatchItem> itemList) {
|
private DispatchResponse response(DispatchOrder order, List<DispatchItem> itemList) {
|
||||||
|
return response(order, itemList, List.of());
|
||||||
|
}
|
||||||
|
|
||||||
|
private DispatchResponse response(DispatchOrder order, List<DispatchItem> itemList,
|
||||||
|
List<DispatchResponse.BolLine> bolLineList) {
|
||||||
String orderNos = itemList.stream().flatMap(item -> splitOrderRefs(item.getOrderRefs(), item.getOrderNo()).stream())
|
String orderNos = itemList.stream().flatMap(item -> splitOrderRefs(item.getOrderRefs(), item.getOrderNo()).stream())
|
||||||
.distinct().collect(Collectors.joining(","));
|
.distinct().collect(Collectors.joining(","));
|
||||||
return new DispatchResponse(order.getId(), order.getDispatchNo(), order.getVehiclePlate(), order.getDriverName(),
|
return new DispatchResponse(order.getId(), order.getDispatchNo(), order.getVehiclePlate(), order.getDriverName(),
|
||||||
@@ -515,7 +524,8 @@ public class DispatchService {
|
|||||||
item.getWarehousePalletId(), item.getPalletNo(), item.getOverseasWarehouseId(), item.getOverseasWarehouseName(),
|
item.getWarehousePalletId(), item.getPalletNo(), item.getOverseasWarehouseId(), item.getOverseasWarehouseName(),
|
||||||
item.getOrderNo(), item.getOrderRefs(), item.getInboundCode(),
|
item.getOrderNo(), item.getOrderRefs(), item.getInboundCode(),
|
||||||
item.getDestinationWarehouseCode(), item.getDestinationWarehouseName(), item.getFbaWarehouseCode(),
|
item.getDestinationWarehouseCode(), item.getDestinationWarehouseName(), item.getFbaWarehouseCode(),
|
||||||
Objects.requireNonNullElse(item.getPackageCount(), 0), item.getVolumeCbm(), item.getSourceStage())).toList());
|
Objects.requireNonNullElse(item.getPackageCount(), 0), item.getVolumeCbm(), item.getSourceStage())).toList(),
|
||||||
|
bolLineList == null ? List.of() : bolLineList);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String route(List<DispatchPalletCandidate> selected) {
|
private static String route(List<DispatchPalletCandidate> selected) {
|
||||||
|
|||||||
@@ -2251,6 +2251,10 @@ components:
|
|||||||
partialCompletionReason: { type: string, nullable: true }
|
partialCompletionReason: { type: string, nullable: true }
|
||||||
createdAt: { type: string, format: date-time }
|
createdAt: { type: string, format: date-time }
|
||||||
items: { type: array, items: { $ref: '#/components/schemas/DispatchItem' } }
|
items: { type: array, items: { $ref: '#/components/schemas/DispatchItem' } }
|
||||||
|
bolLines:
|
||||||
|
type: array
|
||||||
|
description: 仅详情接口返回的BOL打印聚合行;分页接口返回空数组,避免列表查询放大
|
||||||
|
items: { $ref: '#/components/schemas/DispatchBolLine' }
|
||||||
DispatchItem:
|
DispatchItem:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
@@ -2269,6 +2273,17 @@ components:
|
|||||||
packageCount: { type: integer }
|
packageCount: { type: integer }
|
||||||
volumeCbm: { type: number }
|
volumeCbm: { type: number }
|
||||||
sourceStage: { type: string, enum: [PLAN, RECEIVED] }
|
sourceStage: { type: string, enum: [PLAN, RECEIVED] }
|
||||||
|
DispatchBolLine:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
containerNo: { type: string, nullable: true }
|
||||||
|
palletNo: { type: string, nullable: true }
|
||||||
|
fbaWarehouseCode: { type: string, nullable: true }
|
||||||
|
destinationWarehouseName: { type: string, nullable: true }
|
||||||
|
warehouseNo: { type: string, nullable: true, description: 来源入仓码/仓库单号 }
|
||||||
|
fbaShipmentId: { type: string, nullable: true, description: 来源冻结货件编号;多值以逗号分隔 }
|
||||||
|
poReferenceNo: { type: string, nullable: true, description: 来源冻结FBA跟踪/参考号;多值以逗号分隔 }
|
||||||
|
packageCount: { type: integer, minimum: 0 }
|
||||||
RelabelStatus: { type: string, enum: [PENDING_PROCESSING, PROCESSING, CUSTOMER_CONFIRM_PENDING, READY_FOR_OUTBOUND, COMPLETED, REJECTED, CANCELLED] }
|
RelabelStatus: { type: string, enum: [PENDING_PROCESSING, PROCESSING, CUSTOMER_CONFIRM_PENDING, READY_FOR_OUTBOUND, COMPLETED, REJECTED, CANCELLED] }
|
||||||
RelabelMerchantPageResponse:
|
RelabelMerchantPageResponse:
|
||||||
allOf:
|
allOf:
|
||||||
|
|||||||
+13
-1
@@ -10,6 +10,7 @@ import com.baiyue.lastleg.dispatch.entity.DispatchItem;
|
|||||||
import com.baiyue.lastleg.dispatch.entity.DispatchOrder;
|
import com.baiyue.lastleg.dispatch.entity.DispatchOrder;
|
||||||
import com.baiyue.lastleg.dispatch.entity.DispatchPalletLock;
|
import com.baiyue.lastleg.dispatch.entity.DispatchPalletLock;
|
||||||
import com.baiyue.lastleg.dispatch.mapper.DispatchCandidateMapper;
|
import com.baiyue.lastleg.dispatch.mapper.DispatchCandidateMapper;
|
||||||
|
import com.baiyue.lastleg.dispatch.mapper.DispatchBolMapper;
|
||||||
import com.baiyue.lastleg.dispatch.mapper.DispatchDraftContainerMapper;
|
import com.baiyue.lastleg.dispatch.mapper.DispatchDraftContainerMapper;
|
||||||
import com.baiyue.lastleg.dispatch.mapper.DispatchDraftMapper;
|
import com.baiyue.lastleg.dispatch.mapper.DispatchDraftMapper;
|
||||||
import com.baiyue.lastleg.dispatch.mapper.DispatchItemMapper;
|
import com.baiyue.lastleg.dispatch.mapper.DispatchItemMapper;
|
||||||
@@ -49,6 +50,7 @@ import static org.mockito.Mockito.when;
|
|||||||
class DispatchServiceTest {
|
class DispatchServiceTest {
|
||||||
@Mock DispatchOrderMapper orders;
|
@Mock DispatchOrderMapper orders;
|
||||||
@Mock DispatchItemMapper items;
|
@Mock DispatchItemMapper items;
|
||||||
|
@Mock DispatchBolMapper bolLines;
|
||||||
@Mock DispatchPalletLockMapper locks;
|
@Mock DispatchPalletLockMapper locks;
|
||||||
@Mock DispatchCandidateMapper candidates;
|
@Mock DispatchCandidateMapper candidates;
|
||||||
@Mock DispatchDraftMapper drafts;
|
@Mock DispatchDraftMapper drafts;
|
||||||
@@ -62,6 +64,7 @@ class DispatchServiceTest {
|
|||||||
service = new DispatchService();
|
service = new DispatchService();
|
||||||
ReflectionTestUtils.setField(service, "orders", orders);
|
ReflectionTestUtils.setField(service, "orders", orders);
|
||||||
ReflectionTestUtils.setField(service, "items", items);
|
ReflectionTestUtils.setField(service, "items", items);
|
||||||
|
ReflectionTestUtils.setField(service, "bolLines", bolLines);
|
||||||
ReflectionTestUtils.setField(service, "locks", locks);
|
ReflectionTestUtils.setField(service, "locks", locks);
|
||||||
ReflectionTestUtils.setField(service, "candidates", candidates);
|
ReflectionTestUtils.setField(service, "candidates", candidates);
|
||||||
ReflectionTestUtils.setField(service, "drafts", drafts);
|
ReflectionTestUtils.setField(service, "drafts", drafts);
|
||||||
@@ -70,6 +73,7 @@ class DispatchServiceTest {
|
|||||||
ReflectionTestUtils.setField(service, "tailOrders", tailOrders);
|
ReflectionTestUtils.setField(service, "tailOrders", tailOrders);
|
||||||
ReflectionTestUtils.setField(service, "orderNoGenerator", new com.baiyue.lastleg.service.LastlegOrderNoGenerator());
|
ReflectionTestUtils.setField(service, "orderNoGenerator", new com.baiyue.lastleg.service.LastlegOrderNoGenerator());
|
||||||
lenient().when(items.findByDispatchOrder(any(), any())).thenReturn(List.of());
|
lenient().when(items.findByDispatchOrder(any(), any())).thenReturn(List.of());
|
||||||
|
lenient().when(bolLines.findByDispatchOrder(any(), any())).thenReturn(List.of());
|
||||||
lenient().when(tailOrders.selectList(any())).thenReturn(List.of());
|
lenient().when(tailOrders.selectList(any())).thenReturn(List.of());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -322,6 +326,7 @@ class DispatchServiceTest {
|
|||||||
service.detail("200", "PC1");
|
service.detail("200", "PC1");
|
||||||
|
|
||||||
verify(items).findByDispatchOrder("200", 1L);
|
verify(items).findByDispatchOrder("200", 1L);
|
||||||
|
verify(bolLines).findByDispatchOrder("200", 1L);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -339,6 +344,7 @@ class DispatchServiceTest {
|
|||||||
assertEquals(2, result.total());
|
assertEquals(2, result.total());
|
||||||
verify(items).findByDispatchOrder("100", 1L);
|
verify(items).findByDispatchOrder("100", 1L);
|
||||||
verify(items).findByDispatchOrder("200", 2L);
|
verify(items).findByDispatchOrder("200", 2L);
|
||||||
|
verify(bolLines, never()).findByDispatchOrder(any(), any());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -347,9 +353,15 @@ class DispatchServiceTest {
|
|||||||
dispatch.setId(1L); dispatch.setCustomerId("200"); dispatch.setDispatchNo("PC1");
|
dispatch.setId(1L); dispatch.setCustomerId("200"); dispatch.setDispatchNo("PC1");
|
||||||
when(orders.findGlobalByDispatchNo("PC1")).thenReturn(dispatch);
|
when(orders.findGlobalByDispatchNo("PC1")).thenReturn(dispatch);
|
||||||
|
|
||||||
service.platformDetail("PC1");
|
var expected = new DispatchResponse.BolLine("D2144", "D2144-112-1", "LBE1", "Amazon LBE1",
|
||||||
|
"NPHK2607030206", "FBA19HFHQCHB", "7UH3F1DW", 138);
|
||||||
|
when(bolLines.findByDispatchOrder("200", 1L)).thenReturn(List.of(expected));
|
||||||
|
|
||||||
|
var result = service.platformDetail("PC1");
|
||||||
|
|
||||||
verify(items).findByDispatchOrder("200", 1L);
|
verify(items).findByDispatchOrder("200", 1L);
|
||||||
|
verify(bolLines).findByDispatchOrder("200", 1L);
|
||||||
|
assertEquals(List.of(expected), result.bolLines());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user