暂存提交

This commit is contained in:
2026-08-19 16:24:02 +08:00
parent f5c4bf130a
commit 6acb6178da
354 changed files with 25000 additions and 198 deletions
@@ -0,0 +1,9 @@
package com.baiyue.lastleg.delivery;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@MapperScan("com.baiyue.lastleg.delivery.mapper")
public class DeliveryMapperConfiguration {
}
@@ -0,0 +1,74 @@
package com.baiyue.lastleg.delivery.controller;
import com.baiyue.common.core.api.ApiResponse;
import com.baiyue.common.core.api.PageResult;
import com.baiyue.common.security.AuthenticatedUser;
import com.baiyue.lastleg.delivery.dto.DeliveryRequests;
import com.baiyue.lastleg.delivery.dto.DeliveryResponses;
import com.baiyue.lastleg.delivery.service.DeliveryTransferService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ResponseStatusException;
@RestController
@RequestMapping("/api/platform/v1/last-leg")
@Tag(name = "Outbound and delivery")
public class DeliveryTransferController {
@Resource private DeliveryTransferService service;
@PostMapping("/dispatches/{dispatchNo}/transfer-delivery")
@Operation(summary = "Create one pending outbound order and one pending delivery order")
public ApiResponse<DeliveryResponses.TransferResult> transfer(
@AuthenticationPrincipal AuthenticatedUser user, @PathVariable String dispatchNo,
@RequestParam(required = false) String customerId,
@Valid @RequestBody DeliveryRequests.Transfer request) {
return ApiResponse.success(service.transfer(scope(user, customerId), dispatchNo, operator(user), request));
}
@GetMapping("/outbound-orders")
public ApiResponse<PageResult<DeliveryResponses.OutboundRow>> outboundPage(
@AuthenticationPrincipal AuthenticatedUser user, @RequestParam(required = false) String customerId,
@Valid DeliveryRequests.Query query) {
return ApiResponse.success(service.outboundPage(scope(user, customerId), query));
}
@GetMapping("/outbound-orders/{outboundNo}")
public ApiResponse<DeliveryResponses.OutboundDetail> outboundDetail(
@AuthenticationPrincipal AuthenticatedUser user, @RequestParam(required = false) String customerId,
@PathVariable String outboundNo, @Valid DeliveryRequests.PalletQuery query) {
return ApiResponse.success(service.outboundDetail(scope(user, customerId), outboundNo, query));
}
@GetMapping("/delivery-orders")
public ApiResponse<PageResult<DeliveryResponses.DeliveryRow>> deliveryPage(
@AuthenticationPrincipal AuthenticatedUser user, @RequestParam(required = false) String customerId,
@Valid DeliveryRequests.Query query) {
return ApiResponse.success(service.deliveryPage(scope(user, customerId), query));
}
@GetMapping("/delivery-orders/{deliveryNo}")
public ApiResponse<DeliveryResponses.OutboundDetail> deliveryDetail(
@AuthenticationPrincipal AuthenticatedUser user, @RequestParam(required = false) String customerId,
@PathVariable String deliveryNo, @Valid DeliveryRequests.PalletQuery query) {
return ApiResponse.success(service.deliveryDetail(scope(user, customerId), deliveryNo, query));
}
private String scope(AuthenticatedUser user, String requestedCustomer) {
if (user == null || user.tenantId() == null) throw new ResponseStatusException(HttpStatus.UNAUTHORIZED);
if ("PLATFORM".equals(user.appCode()) && user.tenantId() == 0L) {
if (requestedCustomer == null || requestedCustomer.isBlank() || "0".equals(requestedCustomer)) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Platform request must specify target tenant");
}
return requestedCustomer.trim();
}
return String.valueOf(user.tenantId());
}
private String operator(AuthenticatedUser user) {
return user.userId() == null ? user.username() : String.valueOf(user.userId());
}
}
@@ -0,0 +1,23 @@
package com.baiyue.lastleg.delivery.dto;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
public final class DeliveryRequests {
private DeliveryRequests() {}
public record Transfer(@NotBlank @Size(max = 255) String idempotencyKey,
@Size(max = 1000) String remark) {}
public record Query(@Min(1) long page, @Min(1) @Max(200) long size,
String documentNo, String warehouseId, String status) {
public Query { if (page == 0) page = 1; if (size == 0) size = 20; }
}
public record PalletQuery(@Min(1) long page, @Min(1) @Max(200) long size,
String destinationWarehouseCode) {
public PalletQuery { if (page == 0) page = 1; if (size == 0) size = 20; }
}
}
@@ -0,0 +1,27 @@
package com.baiyue.lastleg.delivery.dto;
import com.baiyue.common.core.api.PageResult;
import java.time.LocalDateTime;
public final class DeliveryResponses {
private DeliveryResponses() {}
public record TransferResult(String dispatchNo, String outboundNo, String outboundStatus,
String deliveryNo, String deliveryStatus, int palletCount,
int packageCount, boolean replayed) {}
public record OutboundRow(Long id, String outboundNo, String dispatchNo, String overseasWarehouseId,
String status, int palletCount, int packageCount, LocalDateTime createdAt) {}
public record DeliveryRow(Long id, String deliveryNo, String outboundNo, String dispatchNo,
String overseasWarehouseId, String status, int palletCount,
int packageCount, LocalDateTime createdAt) {}
public record PalletRow(Long id, Long warehousePalletId, String palletNo, String inboundCode,
String orderRefs, String destinationWarehouseId,
String destinationWarehouseCode, String destinationWarehouseName,
int packageCount) {}
public record OutboundDetail(OutboundRow outbound, DeliveryRow delivery,
PageResult<PalletRow> pallets) {}
}
@@ -0,0 +1,30 @@
package com.baiyue.lastleg.delivery.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.time.LocalDateTime;
/** Delivery document linked one-to-one to its outbound document and dispatch. */
@Data
@TableName("ll_delivery_order")
public class DeliveryOrder {
@TableId(type = IdType.ASSIGN_ID)
private Long id;
private String customerId;
private String deliveryNo;
private Long outboundOrderId;
private String outboundNo;
private Long dispatchOrderId;
private String dispatchNo;
private String overseasWarehouseId;
private String status;
private Integer packageCount;
private Integer palletCount;
private String idempotencyKey;
private String createdBy;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
}
@@ -0,0 +1,28 @@
package com.baiyue.lastleg.delivery.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.time.LocalDateTime;
/** Outbound document created when a dispatch is transferred to delivery. */
@Data
@TableName("ll_outbound_order")
public class OutboundOrder {
@TableId(type = IdType.ASSIGN_ID)
private Long id;
private String customerId;
private String outboundNo;
private Long dispatchOrderId;
private String dispatchNo;
private String overseasWarehouseId;
private String status;
private Integer packageCount;
private Integer palletCount;
private String idempotencyKey;
private String createdBy;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
}
@@ -0,0 +1,27 @@
package com.baiyue.lastleg.delivery.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.time.LocalDateTime;
/** Pallet-level immutable snapshot belonging to one outbound document. */
@Data
@TableName("ll_outbound_pallet_item")
public class OutboundPalletItem {
@TableId(type = IdType.ASSIGN_ID)
private Long id;
private String customerId;
private Long outboundOrderId;
private Long warehousePalletId;
private String palletNo;
private String destinationWarehouseId;
private String destinationWarehouseCode;
private String destinationWarehouseName;
private Integer packageCount;
private String orderRefs;
private String inboundCode;
private LocalDateTime createdAt;
}
@@ -0,0 +1,17 @@
package com.baiyue.lastleg.delivery.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baiyue.lastleg.delivery.entity.DeliveryOrder;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
@Mapper
public interface DeliveryOrderMapper extends BaseMapper<DeliveryOrder> {
@Select("SELECT * FROM ll_delivery_order WHERE customer_id=#{customerId} AND delivery_no=#{deliveryNo} LIMIT 1")
DeliveryOrder findByNo(@Param("customerId") String customerId, @Param("deliveryNo") String deliveryNo);
@Select("SELECT * FROM ll_delivery_order WHERE customer_id=#{customerId} AND idempotency_key=#{key} LIMIT 1")
DeliveryOrder findByIdempotency(@Param("customerId") String customerId, @Param("key") String key);
@Select("SELECT * FROM ll_delivery_order WHERE customer_id=#{customerId} AND outbound_order_id=#{outboundOrderId} LIMIT 1 FOR UPDATE")
DeliveryOrder lockByOutbound(@Param("customerId") String customerId, @Param("outboundOrderId") Long outboundOrderId);
}
@@ -0,0 +1,17 @@
package com.baiyue.lastleg.delivery.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baiyue.lastleg.delivery.entity.OutboundOrder;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
@Mapper
public interface OutboundOrderMapper extends BaseMapper<OutboundOrder> {
@Select("SELECT * FROM ll_outbound_order WHERE customer_id=#{customerId} AND outbound_no=#{outboundNo} LIMIT 1")
OutboundOrder findByNo(@Param("customerId") String customerId, @Param("outboundNo") String outboundNo);
@Select("SELECT * FROM ll_outbound_order WHERE customer_id=#{customerId} AND idempotency_key=#{key} LIMIT 1")
OutboundOrder findByIdempotency(@Param("customerId") String customerId, @Param("key") String key);
@Select("SELECT * FROM ll_outbound_order WHERE customer_id=#{customerId} AND dispatch_order_id=#{dispatchOrderId} LIMIT 1 FOR UPDATE")
OutboundOrder lockByDispatch(@Param("customerId") String customerId, @Param("dispatchOrderId") Long dispatchOrderId);
}
@@ -0,0 +1,14 @@
package com.baiyue.lastleg.delivery.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baiyue.lastleg.delivery.entity.OutboundPalletItem;
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 OutboundPalletItemMapper extends BaseMapper<OutboundPalletItem> {
@Select("SELECT * FROM ll_outbound_pallet_item WHERE customer_id=#{customerId} AND outbound_order_id=#{outboundOrderId} ORDER BY id")
List<OutboundPalletItem> findByOutbound(@Param("customerId") String customerId, @Param("outboundOrderId") Long outboundOrderId);
}
@@ -0,0 +1,213 @@
package com.baiyue.lastleg.delivery.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baiyue.common.core.api.PageResult;
import com.baiyue.lastleg.delivery.dto.DeliveryRequests;
import com.baiyue.lastleg.delivery.dto.DeliveryResponses;
import com.baiyue.lastleg.delivery.entity.DeliveryOrder;
import com.baiyue.lastleg.delivery.entity.OutboundOrder;
import com.baiyue.lastleg.delivery.entity.OutboundPalletItem;
import com.baiyue.lastleg.delivery.mapper.DeliveryOrderMapper;
import com.baiyue.lastleg.delivery.mapper.OutboundOrderMapper;
import com.baiyue.lastleg.delivery.mapper.OutboundPalletItemMapper;
import com.baiyue.lastleg.dispatch.entity.DispatchItem;
import com.baiyue.lastleg.dispatch.entity.DispatchOrder;
import com.baiyue.lastleg.dispatch.mapper.DispatchItemMapper;
import com.baiyue.lastleg.dispatch.mapper.DispatchOrderMapper;
import com.baiyue.lastleg.entity.LastlegOrder;
import com.baiyue.lastleg.entity.LastlegOrderStatusHistory;
import com.baiyue.lastleg.inboundplan.entity.InboundPlanLine;
import com.baiyue.lastleg.inboundplan.entity.InboundPlanPalletAllocation;
import com.baiyue.lastleg.inboundplan.mapper.InboundPlanLineMapper;
import com.baiyue.lastleg.inboundplan.mapper.InboundPlanPalletAllocationMapper;
import com.baiyue.lastleg.mapper.LastlegOrderMapper;
import com.baiyue.lastleg.mapper.LastlegOrderStatusHistoryMapper;
import jakarta.annotation.Resource;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ResponseStatusException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
@Service
public class DeliveryTransferService {
@Resource private DispatchOrderMapper dispatchOrders;
@Resource private DispatchItemMapper dispatchItems;
@Resource private OutboundOrderMapper outboundOrders;
@Resource private OutboundPalletItemMapper outboundPallets;
@Resource private DeliveryOrderMapper deliveryOrders;
@Resource private InboundPlanPalletAllocationMapper planAllocations;
@Resource private InboundPlanLineMapper planLines;
@Resource private LastlegOrderMapper tailOrders;
@Resource private LastlegOrderStatusHistoryMapper histories;
@Transactional
public DeliveryResponses.TransferResult transfer(String customerId, String dispatchNo, String operatorId,
DeliveryRequests.Transfer request) {
DispatchOrder found = dispatchOrders.findByDispatchNo(customerId, dispatchNo);
if (found == null) throw notFound("Dispatch order not found");
DispatchOrder dispatch = dispatchOrders.lockById(customerId, found.getId());
OutboundOrder replay = outboundOrders.findByIdempotency(customerId, request.idempotencyKey().trim());
if (replay != null) {
if (!dispatch.getId().equals(replay.getDispatchOrderId())) throw conflict("Idempotency key belongs to another dispatch");
return result(replay, requireDelivery(customerId, replay.getId()), true);
}
OutboundOrder existing = outboundOrders.lockByDispatch(customerId, dispatch.getId());
if (existing != null) return result(existing, requireDelivery(customerId, existing.getId()), true);
if (Set.of("CANCELLED", "DEPARTED", "PARTIAL_DEPARTED", "COMPLETED").contains(dispatch.getStatus())) {
throw conflict("Dispatch cannot be transferred to delivery in its current status");
}
List<DispatchItem> items = dispatchItems.findByDispatchOrder(customerId, dispatch.getId());
if (items.isEmpty()) throw conflict("Dispatch has no pallets");
if (items.stream().anyMatch(item -> item.getWarehousePalletId() == null)) {
throw conflict("All dispatch pallets must be received before transfer to delivery");
}
if (!StringUtils.hasText(dispatch.getOverseasWarehouseId())) throw conflict("Dispatch warehouse is required");
LocalDateTime now = LocalDateTime.now();
OutboundOrder outbound = new OutboundOrder();
outbound.setId(IdWorker.getId()); outbound.setCustomerId(customerId);
outbound.setOutboundNo("OUT" + now.format(DateTimeFormatter.BASIC_ISO_DATE) + outbound.getId());
outbound.setDispatchOrderId(dispatch.getId()); outbound.setDispatchNo(dispatch.getDispatchNo());
outbound.setOverseasWarehouseId(dispatch.getOverseasWarehouseId()); outbound.setStatus("WAIT_OUTBOUND");
outbound.setPackageCount(items.stream().map(DispatchItem::getPackageCount).filter(Objects::nonNull).mapToInt(Integer::intValue).sum());
outbound.setPalletCount(items.size()); outbound.setIdempotencyKey(request.idempotencyKey().trim());
outbound.setCreatedBy(operatorId); outbound.setCreatedAt(now); outbound.setUpdatedAt(now);
try {
outboundOrders.insert(outbound);
} catch (DuplicateKeyException e) {
// The unique keys are the final concurrent guard. A client retry must observe
// the document created by the winning transaction rather than receive a false failure.
OutboundOrder concurrent = outboundOrders.findByIdempotency(customerId, request.idempotencyKey().trim());
if (concurrent != null && dispatch.getId().equals(concurrent.getDispatchOrderId())) {
return result(concurrent, requireDelivery(customerId, concurrent.getId()), true);
}
concurrent = outboundOrders.lockByDispatch(customerId, dispatch.getId());
if (concurrent != null) {
return result(concurrent, requireDelivery(customerId, concurrent.getId()), true);
}
throw conflict("Dispatch was concurrently transferred to delivery");
}
for (DispatchItem source : items) {
OutboundPalletItem item = new OutboundPalletItem();
item.setId(IdWorker.getId()); item.setCustomerId(customerId); item.setOutboundOrderId(outbound.getId());
item.setWarehousePalletId(source.getWarehousePalletId()); item.setPalletNo(source.getPalletNo());
item.setDestinationWarehouseId(source.getDestinationWarehouseId());
item.setDestinationWarehouseCode(source.getDestinationWarehouseCode());
item.setDestinationWarehouseName(source.getDestinationWarehouseName());
item.setPackageCount(Objects.requireNonNullElse(source.getPackageCount(), 0));
item.setOrderRefs(source.getOrderRefs()); item.setInboundCode(source.getInboundCode()); item.setCreatedAt(now);
outboundPallets.insert(item);
}
DeliveryOrder delivery = new DeliveryOrder();
delivery.setId(IdWorker.getId()); delivery.setCustomerId(customerId);
delivery.setDeliveryNo("DEL" + now.format(DateTimeFormatter.BASIC_ISO_DATE) + delivery.getId());
delivery.setOutboundOrderId(outbound.getId()); delivery.setOutboundNo(outbound.getOutboundNo());
delivery.setDispatchOrderId(dispatch.getId()); delivery.setDispatchNo(dispatch.getDispatchNo());
delivery.setOverseasWarehouseId(dispatch.getOverseasWarehouseId()); delivery.setStatus("WAIT_DELIVERY");
delivery.setPackageCount(outbound.getPackageCount()); delivery.setPalletCount(outbound.getPalletCount());
delivery.setIdempotencyKey(request.idempotencyKey().trim()); delivery.setCreatedBy(operatorId);
delivery.setCreatedAt(now); delivery.setUpdatedAt(now); deliveryOrders.insert(delivery);
bindTailOrders(customerId, items, outbound.getOutboundNo(), delivery.getDeliveryNo(), request.remark(), now);
return result(outbound, delivery, false);
}
public PageResult<DeliveryResponses.OutboundRow> outboundPage(String customerId, DeliveryRequests.Query query) {
Page<OutboundOrder> page = outboundOrders.selectPage(new Page<>(query.page(), query.size()),
new LambdaQueryWrapper<OutboundOrder>().eq(OutboundOrder::getCustomerId, customerId)
.like(StringUtils.hasText(query.documentNo()), OutboundOrder::getOutboundNo, query.documentNo())
.eq(StringUtils.hasText(query.warehouseId()), OutboundOrder::getOverseasWarehouseId, query.warehouseId())
.eq(StringUtils.hasText(query.status()), OutboundOrder::getStatus, query.status())
.orderByDesc(OutboundOrder::getCreatedAt));
return page(page, page.getRecords().stream().map(this::outboundRow).toList());
}
public DeliveryResponses.OutboundDetail outboundDetail(String customerId, String outboundNo,
DeliveryRequests.PalletQuery query) {
OutboundOrder outbound = outboundOrders.findByNo(customerId, outboundNo);
if (outbound == null) throw notFound("Outbound order not found");
DeliveryOrder delivery = requireDelivery(customerId, outbound.getId());
Page<OutboundPalletItem> page = outboundPallets.selectPage(new Page<>(query.page(), query.size()),
new LambdaQueryWrapper<OutboundPalletItem>().eq(OutboundPalletItem::getCustomerId, customerId)
.eq(OutboundPalletItem::getOutboundOrderId, outbound.getId())
.eq(StringUtils.hasText(query.destinationWarehouseCode()),
OutboundPalletItem::getDestinationWarehouseCode, query.destinationWarehouseCode())
.orderByAsc(OutboundPalletItem::getId));
return new DeliveryResponses.OutboundDetail(outboundRow(outbound), deliveryRow(delivery),
page(page, page.getRecords().stream().map(this::palletRow).toList()));
}
public PageResult<DeliveryResponses.DeliveryRow> deliveryPage(String customerId, DeliveryRequests.Query query) {
Page<DeliveryOrder> page = deliveryOrders.selectPage(new Page<>(query.page(), query.size()),
new LambdaQueryWrapper<DeliveryOrder>().eq(DeliveryOrder::getCustomerId, customerId)
.like(StringUtils.hasText(query.documentNo()), DeliveryOrder::getDeliveryNo, query.documentNo())
.eq(StringUtils.hasText(query.warehouseId()), DeliveryOrder::getOverseasWarehouseId, query.warehouseId())
.eq(StringUtils.hasText(query.status()), DeliveryOrder::getStatus, query.status())
.orderByDesc(DeliveryOrder::getCreatedAt));
return page(page, page.getRecords().stream().map(this::deliveryRow).toList());
}
public DeliveryResponses.OutboundDetail deliveryDetail(String customerId, String deliveryNo,
DeliveryRequests.PalletQuery query) {
DeliveryOrder delivery = deliveryOrders.findByNo(customerId, deliveryNo);
if (delivery == null) throw notFound("Delivery order not found");
OutboundOrder outbound = outboundOrders.selectById(delivery.getOutboundOrderId());
if (outbound == null || !customerId.equals(outbound.getCustomerId())) throw notFound("Outbound order not found");
return outboundDetail(customerId, outbound.getOutboundNo(), query);
}
private void bindTailOrders(String customerId, List<DispatchItem> items, String outboundNo, String deliveryNo,
String remark, LocalDateTime now) {
Set<Long> orderIds = new LinkedHashSet<>();
items.stream().map(DispatchItem::getOrderId).filter(Objects::nonNull).forEach(orderIds::add);
List<Long> palletIds = items.stream().map(DispatchItem::getPlanPalletId).filter(Objects::nonNull).distinct().toList();
if (!palletIds.isEmpty()) {
List<InboundPlanPalletAllocation> allocations = planAllocations.selectList(
new LambdaQueryWrapper<InboundPlanPalletAllocation>().in(InboundPlanPalletAllocation::getPalletId, palletIds));
List<Long> lineIds = allocations.stream().map(InboundPlanPalletAllocation::getLineId)
.filter(Objects::nonNull).distinct().toList();
if (!lineIds.isEmpty()) {
planLines.selectBatchIds(lineIds).stream().map(InboundPlanLine::getOrderId)
.filter(Objects::nonNull).forEach(orderIds::add);
}
}
if (orderIds.isEmpty()) return;
for (LastlegOrder order : tailOrders.selectList(new LambdaQueryWrapper<LastlegOrder>()
.eq(LastlegOrder::getCustomerId, customerId).in(LastlegOrder::getId, orderIds))) {
String from = order.getCurrentStatus(); order.setOutboundOrderNo(outboundNo);
order.setDeliveryOrderNo(deliveryNo); order.setCurrentStatus("WAIT_OUTBOUND"); order.setUpdatedAt(now);
order.setSubOrderStatus("OUTBOUND:WAIT_OUTBOUND;DELIVERY:WAIT_DELIVERY");
tailOrders.updateById(order);
LastlegOrderStatusHistory history = new LastlegOrderStatusHistory(); history.setOrderId(order.getId());
history.setFromStatus(from); history.setToStatus("WAIT_OUTBOUND");
history.setEventId("TRANSFER_DELIVERY:" + deliveryNo);
history.setRemark(StringUtils.hasText(remark) ? remark.trim() : "Transferred to outbound and delivery documents");
history.setCreatedAt(now); histories.insert(history);
}
}
private DeliveryOrder requireDelivery(String customerId, Long outboundId) {
DeliveryOrder value = deliveryOrders.lockByOutbound(customerId, outboundId);
if (value == null) throw new IllegalStateException("Delivery document is missing for outbound order");
return value;
}
private DeliveryResponses.TransferResult result(OutboundOrder o, DeliveryOrder d, boolean replayed) {
return new DeliveryResponses.TransferResult(o.getDispatchNo(), o.getOutboundNo(), o.getStatus(),
d.getDeliveryNo(), d.getStatus(), o.getPalletCount(), o.getPackageCount(), replayed);
}
private DeliveryResponses.OutboundRow outboundRow(OutboundOrder o) { return new DeliveryResponses.OutboundRow(o.getId(), o.getOutboundNo(), o.getDispatchNo(), o.getOverseasWarehouseId(), o.getStatus(), o.getPalletCount(), o.getPackageCount(), o.getCreatedAt()); }
private DeliveryResponses.DeliveryRow deliveryRow(DeliveryOrder d) { return new DeliveryResponses.DeliveryRow(d.getId(), d.getDeliveryNo(), d.getOutboundNo(), d.getDispatchNo(), d.getOverseasWarehouseId(), d.getStatus(), d.getPalletCount(), d.getPackageCount(), d.getCreatedAt()); }
private DeliveryResponses.PalletRow palletRow(OutboundPalletItem p) { return new DeliveryResponses.PalletRow(p.getId(), p.getWarehousePalletId(), p.getPalletNo(), p.getInboundCode(), p.getOrderRefs(), p.getDestinationWarehouseId(), p.getDestinationWarehouseCode(), p.getDestinationWarehouseName(), p.getPackageCount()); }
private static <T> PageResult<T> page(Page<?> page, List<T> records) { return new PageResult<>(records, page.getCurrent(), page.getSize(), page.getTotal(), page.getPages()); }
private static ResponseStatusException conflict(String message) { return new ResponseStatusException(HttpStatus.CONFLICT, message); }
private static ResponseStatusException notFound(String message) { return new ResponseStatusException(HttpStatus.NOT_FOUND, message); }
}