暂扣 标记合托功能
This commit is contained in:
+48
-7
@@ -3,15 +3,59 @@ package com.baiyue.lastleg.service;
|
||||
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Locale;
|
||||
|
||||
@Component
|
||||
public class LastlegOrderNoGenerator {
|
||||
public String next() {
|
||||
return "LMO" + IdWorker.getIdStr();
|
||||
long id = IdWorker.getId();
|
||||
return next("LMO", null, id);
|
||||
}
|
||||
|
||||
public String next(String businessType, String warehouse, long uniqueId) {
|
||||
String type = normalizeType(businessType);
|
||||
return type + "-" + warehouseCode(warehouse) + "-"
|
||||
+ LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE) + "-"
|
||||
+ String.format(Locale.ROOT, "%06d", Math.floorMod(uniqueId, 1_000_000));
|
||||
}
|
||||
|
||||
private String normalizeType(String value) {
|
||||
String code = value == null ? "LMO" : value.trim().toUpperCase(Locale.ROOT);
|
||||
return switch (code) {
|
||||
case "FIRST_LEG" -> "FL";
|
||||
case "ONE_CLICK_DROPSHIP" -> "OD";
|
||||
case "RELABEL_APPLICATION", "RELABEL" -> "RL";
|
||||
case "WAREHOUSE_TRANSFER", "TRANSFER" -> "WT";
|
||||
case "LOCAL_LOOSEBOARD", "LOOSEBOARD" -> "LB";
|
||||
case "DISPATCH", "PICKUP_CAR" -> "DS";
|
||||
case "OUTBOUND" -> "OB";
|
||||
case "DELIVERY" -> "DL";
|
||||
case "TRUCK" -> "TR";
|
||||
case "EXCEPTION" -> "EX";
|
||||
case "DISCARD" -> "CD";
|
||||
case "PROCUREMENT" -> "PR";
|
||||
case "INBOUND_PLAN" -> "IP";
|
||||
default -> {
|
||||
String normalized = code.replaceAll("[^A-Z0-9]", "");
|
||||
yield normalized.isEmpty() ? "LMO" : normalized.substring(0, Math.min(4, normalized.length()));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public String warehouseCode(String value) {
|
||||
String code = value == null ? "" : value.trim().toUpperCase(Locale.ROOT);
|
||||
if (code.isEmpty()) return "WH";
|
||||
if (code.matches(".*(LAX|ONT|NYC|JFK|LGB|EWR|SFO|SEA|DFW|ORD|ATL|MIA|PHX|LAS|YYZ|YVR|AMS|LHR|FRA|CDG|HKG|NRT|SYD).*")) {
|
||||
var match = java.util.regex.Pattern.compile("(LAX|ONT|NYC|JFK|LGB|EWR|SFO|SEA|DFW|ORD|ATL|MIA|PHX|LAS|YYZ|YVR|AMS|LHR|FRA|CDG|HKG|NRT|SYD)").matcher(code);
|
||||
if (match.find()) return match.group(1);
|
||||
}
|
||||
if (code.matches("[A-Z0-9]{2,8}")) return code;
|
||||
return "WH";
|
||||
}
|
||||
|
||||
/** The physical container number is the tail-leg business order grouping boundary. */
|
||||
@@ -20,14 +64,11 @@ public class LastlegOrderNoGenerator {
|
||||
throw new IllegalArgumentException("containerNo is required");
|
||||
}
|
||||
String normalized = containerNo.trim();
|
||||
if (normalized.matches("[0-9]{1,29}")) {
|
||||
return "LMO" + normalized;
|
||||
}
|
||||
try {
|
||||
byte[] digest = MessageDigest.getInstance("SHA-256")
|
||||
.digest(normalized.getBytes(StandardCharsets.UTF_8));
|
||||
String digits = new BigInteger(1, digest).toString();
|
||||
return "LMO" + digits.substring(0, Math.min(29, digits.length()));
|
||||
long suffix = java.nio.ByteBuffer.wrap(digest, 0, 8).getLong();
|
||||
return next("FIRST_LEG", null, suffix);
|
||||
} catch (NoSuchAlgorithmException exception) {
|
||||
throw new IllegalStateException("SHA-256 is unavailable", exception);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import com.baiyue.lastleg.entity.LastlegOrderFee;
|
||||
import com.baiyue.lastleg.entity.LastlegOrderOperationLog;
|
||||
import com.baiyue.lastleg.inboundplan.entity.InboundPlanCarton;
|
||||
import com.baiyue.lastleg.inboundplan.mapper.InboundPlanCartonMapper;
|
||||
import com.baiyue.lastleg.inventory.command.service.InventoryCommandService;
|
||||
import com.baiyue.lastleg.mapper.LastlegOrderDetailMapper;
|
||||
import com.baiyue.lastleg.mapper.LastlegOrderMapper;
|
||||
import com.baiyue.lastleg.mapper.LastlegOrderStatusHistoryMapper;
|
||||
@@ -38,6 +39,8 @@ public class LastlegOrderService {
|
||||
public static final String PENDING_ASSIGNMENT = "PENDING_ASSIGNMENT";
|
||||
public static final String DESTINATION_ASSIGNED = "DESTINATION_ASSIGNED";
|
||||
public static final String INBOUND_PLANNED = "INBOUND_PLANNED";
|
||||
public static final String PALLET_MERGE_REQUIRED = "REQUIRED";
|
||||
public static final String PALLET_MERGED = "MERGED";
|
||||
|
||||
@Resource private LastlegOrderMapper orderMapper;
|
||||
@Resource private LastlegOrderDetailMapper detailMapper;
|
||||
@@ -45,6 +48,7 @@ public class LastlegOrderService {
|
||||
@Resource private LastlegOrderFeeMapper feeMapper;
|
||||
@Resource private LastlegOrderOperationLogMapper operationLogMapper;
|
||||
@Resource private InboundPlanCartonMapper cartonMapper;
|
||||
@Resource private InventoryCommandService inventory;
|
||||
|
||||
public PageResult<LastlegOrderSummary> page(String customerId, LastlegOrderRequests.Query query) {
|
||||
Page<LastlegOrder> page = orderMapper.selectPage(
|
||||
@@ -110,6 +114,70 @@ public class LastlegOrderService {
|
||||
return fee;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void setDetained(String customerId, long orderId, LastlegOrderRequests.SetDetained request,
|
||||
String operatorName) {
|
||||
LastlegOrder current = findOwned(customerId, orderId);
|
||||
LastlegOrder order = orderMapper.lockById(current.getCustomerId(), orderId);
|
||||
if (order == null) throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Tail-leg order not found");
|
||||
boolean detained = request.detained();
|
||||
if (Boolean.TRUE.equals(order.getDetained()) == detained) {
|
||||
throw new ResponseStatusException(HttpStatus.CONFLICT, detained ? "Order is already held" : "Order is not held");
|
||||
}
|
||||
if (detained && "INBOUND_COMPLETED".equals(order.getCurrentStatus())) {
|
||||
throw new ResponseStatusException(HttpStatus.CONFLICT, "Completed inbound orders cannot be newly held");
|
||||
}
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
order.setDetained(detained);
|
||||
order.setUpdatedAt(now);
|
||||
orderMapper.updateById(order);
|
||||
if (!detained && "INBOUND_COMPLETED".equals(order.getCurrentStatus())) {
|
||||
inventory.releaseInboundOrderHold(order.getCustomerId(), operatorName, orderId, order.getOrderNo(), request.remark().trim());
|
||||
}
|
||||
LastlegOrderOperationLog operation = new LastlegOrderOperationLog();
|
||||
operation.setId(IdWorker.getId());
|
||||
operation.setCustomerId(order.getCustomerId());
|
||||
operation.setOrderId(orderId);
|
||||
operation.setOperationNode(detained ? "暂扣" : "解除暂扣");
|
||||
operation.setOperatorName(operatorName);
|
||||
operation.setResult(request.remark().trim());
|
||||
operation.setCreatedAt(now);
|
||||
operationLogMapper.insert(operation);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void setPalletMergeRequired(String customerId, long orderId,
|
||||
LastlegOrderRequests.SetPalletMergeRequired request,
|
||||
String operatorName) {
|
||||
LastlegOrder current = findOwned(customerId, orderId);
|
||||
LastlegOrder order = orderMapper.lockById(current.getCustomerId(), orderId);
|
||||
if (order == null) throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Tail-leg order not found");
|
||||
if ("INBOUND_COMPLETED".equals(order.getCurrentStatus())) {
|
||||
throw new ResponseStatusException(HttpStatus.CONFLICT,
|
||||
"Completed inbound orders cannot change the pallet merge mark");
|
||||
}
|
||||
if (PALLET_MERGED.equals(order.getPalletMergeFlag())) {
|
||||
throw new ResponseStatusException(HttpStatus.CONFLICT,
|
||||
"A completed pallet merge cannot be unmarked");
|
||||
}
|
||||
String target = request.palletMergeRequired() ? PALLET_MERGE_REQUIRED : null;
|
||||
if (Objects.equals(target, order.getPalletMergeFlag())) return;
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
if (orderMapper.updatePalletMergeFlag(order.getCustomerId(), orderId, target, now) != 1) {
|
||||
throw new ResponseStatusException(HttpStatus.CONFLICT, "Pallet merge mark was not updated");
|
||||
}
|
||||
LastlegOrderOperationLog operation = new LastlegOrderOperationLog();
|
||||
operation.setId(IdWorker.getId());
|
||||
operation.setCustomerId(order.getCustomerId());
|
||||
operation.setOrderId(orderId);
|
||||
operation.setOperationNode(request.palletMergeRequired() ? "标记合托" : "取消合托标记");
|
||||
operation.setOperatorName(operatorName);
|
||||
operation.setResult(request.palletMergeRequired()
|
||||
? "PDA扫描本单箱唛时提示需要合托" : "已取消PDA合托提示");
|
||||
operation.setCreatedAt(now);
|
||||
operationLogMapper.insert(operation);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public int transferDestination(String customerId, LastlegOrderRequests.TransferDestination request) {
|
||||
List<Long> ids = request.orderIds().stream().filter(Objects::nonNull).distinct().toList();
|
||||
|
||||
+1
-1
@@ -83,8 +83,8 @@ public class LoadingCompletedConsumer {
|
||||
shippingGates.initialize(payload.containerBookingId(), envelope.tenantId(), "",
|
||||
payload.containerNo(), 0, envelope.handoverVersion());
|
||||
|
||||
String orderNo = orderNoGenerator.forContainerNo(payload.containerNo());
|
||||
JsonNode rawOrders = envelope.payload().path("orders");
|
||||
String orderNo = orderNoGenerator.forContainerNo(payload.containerNo());
|
||||
for (int index = 0; index < payload.orders().size(); index++) {
|
||||
var source = payload.orders().get(index);
|
||||
JsonNode rawSource = rawOrders.isArray() && index < rawOrders.size() ? rawOrders.get(index) : objectMapper.createObjectNode();
|
||||
|
||||
Reference in New Issue
Block a user