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 shippedPackageCount, int remainingPackageCount, String partialCompletionReason,
|
||||
LocalDateTime createdAt,
|
||||
List<Item> items) {
|
||||
List<Item> items, List<BolLine> bolLines) {
|
||||
public record Item(Long id, Long planPalletId, Long warehousePalletId, String palletNo,
|
||||
String overseasWarehouseId, String overseasWarehouseName,
|
||||
String orderNo, String orderRefs, String inboundCode, String destinationWarehouseCode,
|
||||
String destinationWarehouseName, String fbaWarehouseCode, int packageCount,
|
||||
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.DispatchDraftContainer;
|
||||
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.DispatchOrderMapper;
|
||||
import com.baiyue.lastleg.dispatch.mapper.DispatchPalletLockMapper;
|
||||
@@ -49,6 +50,7 @@ public class DispatchService {
|
||||
|
||||
@Resource private DispatchOrderMapper orders;
|
||||
@Resource private DispatchItemMapper items;
|
||||
@Resource private DispatchBolMapper bolLines;
|
||||
@Resource private DispatchPalletLockMapper locks;
|
||||
@Resource private DispatchDraftMapper drafts;
|
||||
@Resource private DispatchDraftContainerMapper draftContainers;
|
||||
@@ -429,7 +431,8 @@ public class DispatchService {
|
||||
|
||||
public DispatchResponse detail(String customerId, String 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) {
|
||||
@@ -437,7 +440,8 @@ public class DispatchService {
|
||||
if (dispatch == null) {
|
||||
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
|
||||
@@ -499,6 +503,11 @@ public class DispatchService {
|
||||
}
|
||||
|
||||
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())
|
||||
.distinct().collect(Collectors.joining(","));
|
||||
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.getOrderNo(), item.getOrderRefs(), item.getInboundCode(),
|
||||
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) {
|
||||
|
||||
@@ -2251,6 +2251,10 @@ components:
|
||||
partialCompletionReason: { type: string, nullable: true }
|
||||
createdAt: { type: string, format: date-time }
|
||||
items: { type: array, items: { $ref: '#/components/schemas/DispatchItem' } }
|
||||
bolLines:
|
||||
type: array
|
||||
description: 仅详情接口返回的BOL打印聚合行;分页接口返回空数组,避免列表查询放大
|
||||
items: { $ref: '#/components/schemas/DispatchBolLine' }
|
||||
DispatchItem:
|
||||
type: object
|
||||
properties:
|
||||
@@ -2269,6 +2273,17 @@ components:
|
||||
packageCount: { type: integer }
|
||||
volumeCbm: { type: number }
|
||||
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] }
|
||||
RelabelMerchantPageResponse:
|
||||
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.DispatchPalletLock;
|
||||
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.DispatchDraftMapper;
|
||||
import com.baiyue.lastleg.dispatch.mapper.DispatchItemMapper;
|
||||
@@ -49,6 +50,7 @@ import static org.mockito.Mockito.when;
|
||||
class DispatchServiceTest {
|
||||
@Mock DispatchOrderMapper orders;
|
||||
@Mock DispatchItemMapper items;
|
||||
@Mock DispatchBolMapper bolLines;
|
||||
@Mock DispatchPalletLockMapper locks;
|
||||
@Mock DispatchCandidateMapper candidates;
|
||||
@Mock DispatchDraftMapper drafts;
|
||||
@@ -62,6 +64,7 @@ class DispatchServiceTest {
|
||||
service = new DispatchService();
|
||||
ReflectionTestUtils.setField(service, "orders", orders);
|
||||
ReflectionTestUtils.setField(service, "items", items);
|
||||
ReflectionTestUtils.setField(service, "bolLines", bolLines);
|
||||
ReflectionTestUtils.setField(service, "locks", locks);
|
||||
ReflectionTestUtils.setField(service, "candidates", candidates);
|
||||
ReflectionTestUtils.setField(service, "drafts", drafts);
|
||||
@@ -70,6 +73,7 @@ class DispatchServiceTest {
|
||||
ReflectionTestUtils.setField(service, "tailOrders", tailOrders);
|
||||
ReflectionTestUtils.setField(service, "orderNoGenerator", new com.baiyue.lastleg.service.LastlegOrderNoGenerator());
|
||||
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());
|
||||
}
|
||||
|
||||
@@ -322,6 +326,7 @@ class DispatchServiceTest {
|
||||
service.detail("200", "PC1");
|
||||
|
||||
verify(items).findByDispatchOrder("200", 1L);
|
||||
verify(bolLines).findByDispatchOrder("200", 1L);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -339,6 +344,7 @@ class DispatchServiceTest {
|
||||
assertEquals(2, result.total());
|
||||
verify(items).findByDispatchOrder("100", 1L);
|
||||
verify(items).findByDispatchOrder("200", 2L);
|
||||
verify(bolLines, never()).findByDispatchOrder(any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -347,9 +353,15 @@ class DispatchServiceTest {
|
||||
dispatch.setId(1L); dispatch.setCustomerId("200"); dispatch.setDispatchNo("PC1");
|
||||
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(bolLines).findByDispatchOrder("200", 1L);
|
||||
assertEquals(List.of(expected), result.bolLines());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user