贴标申请,仓储转运

This commit is contained in:
2026-09-28 11:59:08 +08:00
parent 0e62b2f45b
commit 2bb98d2047
14 changed files with 278 additions and 38 deletions
@@ -19,7 +19,7 @@ public final class CargoDiscardRequests {
@NotBlank @Size(max = 255) String idempotencyKey,
@Size(max = 1000) String remark) {}
public record Item(@NotNull Long orderId, @NotBlank @Size(max = 128) String skuCode,
public record Item(Long orderId, Long returnCartonId, @NotBlank @Size(max = 128) String skuCode,
@Positive int discardPackages) {}
public record Review(@NotBlank String decision, @Size(max = 1000) String remark) {}
@@ -7,7 +7,8 @@ import java.util.List;
public final class CargoDiscardResponses {
private CargoDiscardResponses() {}
public record Candidate(Long orderId, String inboundCode, String inboundOrderNo,
public record Candidate(Long orderId, String sourceType, Long returnCartonId, String cartonMark,
String inboundCode, String inboundOrderNo,
String overseasWarehouseId, String overseasWarehouseName,
LocalDateTime inboundCreatedAt, long availablePackages,
List<CandidateSku> skus) {}
@@ -14,6 +14,8 @@ public class CargoDiscardItem {
private Long applicationId;
private String customerId;
private Long orderId;
private String sourceType;
private Long returnCartonId;
private String inboundCode;
private Long profileId;
private Long skuInventoryId;
@@ -10,6 +10,8 @@ import com.baiyue.lastleg.discard.service.CargoDiscardService;
import com.baiyue.lastleg.dropship.entity.DropshipOrderProfile;
import com.baiyue.lastleg.dropship.mapper.DropshipOrderProfileMapper;
import com.baiyue.lastleg.pda.security.PdaWarehouseIdentity;
import com.baiyue.lastleg.returnreceipt.entity.ReturnInventoryCarton;
import com.baiyue.lastleg.returnreceipt.mapper.ReturnInventoryCartonMapper;
import jakarta.annotation.Resource;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
@@ -27,6 +29,7 @@ public class PdaCargoDiscardService {
@Resource private DropshipOrderProfileMapper profiles;
@Resource private CargoDiscardInventoryAdjustmentService adjustments;
@Resource private CargoDiscardService discardService;
@Resource private ReturnInventoryCartonMapper returnCartons;
public List<PdaCargoDiscardDtos.PalletTask> tasks(PdaWarehouseIdentity identity) {
return applications.selectList(new LambdaQueryWrapper<CargoDiscardApplication>()
@@ -69,6 +72,9 @@ public class PdaCargoDiscardService {
item.setActualDiscardPackages(actuals.get(item.getId())); item.setPdaStatus("COMPLETED");
item.setPdaOperatorId(identity.operatorKey()); item.setPdaCompletedAt(now); items.updateById(item);
}
task.skus().stream().map(PdaCargoDiscardDtos.Sku::itemId).map(items::selectById)
.filter(this::isReturnItem).map(CargoDiscardItem::getReturnCartonId).filter(Objects::nonNull).distinct()
.forEach(cartonId -> adjustments.finishReturnCarton(application.getCustomerId(), cartonId));
if (items.listApplication(application.getCustomerId(), application.getId()).stream()
.allMatch(i -> "COMPLETED".equals(i.getPdaStatus()))) {
int actualTotal = items.listApplication(application.getCustomerId(), application.getId()).stream()
@@ -83,17 +89,31 @@ public class PdaCargoDiscardService {
private List<PdaCargoDiscardDtos.PalletTask> palletTasks(CargoDiscardApplication application) {
return items.listApplication(application.getCustomerId(), application.getId()).stream()
.collect(Collectors.groupingBy(CargoDiscardItem::getProfileId, LinkedHashMap::new, Collectors.toList()))
.collect(Collectors.groupingBy(this::physicalGroupKey, LinkedHashMap::new, Collectors.toList()))
.entrySet().stream().map(entry -> {
DropshipOrderProfile profile = profiles.selectById(entry.getKey());
if (profile == null || !application.getCustomerId().equals(profile.getCustomerId())) throw conflict("废弃明细关联托盘不存在");
CargoDiscardItem first = entry.getValue().get(0);
boolean returnSource = isReturnItem(first);
DropshipOrderProfile profile = returnSource ? null : profiles.selectById(first.getProfileId());
ReturnInventoryCarton returnCarton = returnSource ? returnCartons.selectById(first.getReturnCartonId()) : null;
if (!returnSource && (profile == null || !application.getCustomerId().equals(profile.getCustomerId()))) throw conflict("废弃明细关联托盘不存在");
if (returnSource && (returnCarton == null || !application.getCustomerId().equals(returnCarton.getCustomerId()))) throw conflict("废弃明细关联退货箱不存在");
List<PdaCargoDiscardDtos.Sku> skus = entry.getValue().stream().map(i -> new PdaCargoDiscardDtos.Sku(
i.getId(), i.getSkuCode(), i.getProductName(), i.getDiscardPackages(), i.getActualDiscardPackages(),
i.getPdaStatus() == null ? "PENDING" : i.getPdaStatus())).toList();
String status = skus.stream().allMatch(s -> "COMPLETED".equals(s.status())) ? "COMPLETED" : "PENDING";
return new PdaCargoDiscardDtos.PalletTask(application.getDiscardNo(), application.getCustomerId(),
application.getOverseasWarehouseId(), profile.getPalletNo(), profile.getId(), status, skus);
application.getOverseasWarehouseId(), returnSource ? firstNonBlank(returnCarton.getPalletCode(), returnCarton.getCartonMark()) : profile.getPalletNo(),
returnSource ? returnCarton.getId() : profile.getId(), status, skus);
}).toList();
}
private String physicalGroupKey(CargoDiscardItem item) {
return isReturnItem(item) ? "RETURN:" + item.getReturnCartonId() : "DROPSHIP:" + item.getProfileId();
}
private boolean isReturnItem(CargoDiscardItem item) {
return "RETURN_CARTON".equals(item.getSourceType()) || item.getReturnCartonId() != null;
}
private static String firstNonBlank(String first, String second) {
return first != null && !first.isBlank() ? first : second;
}
private static ResponseStatusException conflict(String message) { return new ResponseStatusException(HttpStatus.CONFLICT, message); }
}
@@ -15,6 +15,9 @@ import com.baiyue.lastleg.dropship.mapper.DropshipOrderProfileMapper;
import com.baiyue.lastleg.dropship.mapper.DropshipSkuInventoryMapper;
import com.baiyue.lastleg.inventory.mapper.InventoryPositionMapper;
import com.baiyue.lastleg.inventory.mapper.InventoryBalanceMapper;
import com.baiyue.lastleg.returnreceipt.entity.ReturnInventoryCartonItem;
import com.baiyue.lastleg.returnreceipt.mapper.ReturnInventoryCartonItemMapper;
import com.baiyue.lastleg.returnreceipt.mapper.ReturnInventoryCartonMapper;
import jakarta.annotation.Resource;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
@@ -37,11 +40,14 @@ public class CargoDiscardInventoryAdjustmentService {
@Resource private DropshipOrderProfileMapper profiles;
@Resource private InventoryPositionMapper positions;
@Resource private InventoryBalanceMapper balances;
@Resource private ReturnInventoryCartonMapper returnCartons;
@Resource private ReturnInventoryCartonItemMapper returnCartonItems;
@Transactional(propagation = Propagation.MANDATORY)
public AdjustmentResult discardPalletItem(String customerId, CargoDiscardApplication application,
CargoDiscardItem item, List<CargoDiscardCarton> links,
int actualPackages, String operatorId, LocalDateTime occurredAt) {
if (isReturnItem(item)) return discardReturnItem(customerId, item, actualPackages);
if (actualPackages < 0 || actualPackages > links.size()) throw conflict("实际废弃数量超出该托盘申请数量");
DropshipSkuInventory sku = inventory.lockSkuInventory(customerId, item.getSkuInventoryId());
if (sku == null) throw conflict("托盘 SKU 库存不存在: " + item.getSkuCode());
@@ -88,6 +94,36 @@ public class CargoDiscardInventoryAdjustmentService {
return new AdjustmentResult(before, actualPackages, after);
}
private AdjustmentResult discardReturnItem(String customerId, CargoDiscardItem item, int actualPackages) {
if (actualPackages < 0 || actualPackages > item.getDiscardPackages()) {
throw conflict("实际废弃数量超出退货库存申请数量");
}
ReturnInventoryCartonItem sku = returnCartonItems.lockSku(item.getReturnCartonId(), item.getSkuCode());
if (sku == null || !customerId.equals(sku.getCustomerId())) throw conflict("退货库存 SKU 不存在");
long before = value(sku.getQuantity());
if (before < actualPackages || (actualPackages > 0 && returnCartonItems.deduct(sku.getId(), actualPackages) != 1)) {
throw conflict("退货库存数量不足");
}
return new AdjustmentResult(before, actualPackages, before - actualPackages);
}
@Transactional(propagation = Propagation.MANDATORY)
public void finishReturnCarton(String customerId, long cartonId) {
var carton = returnCartons.lockId(cartonId);
if (carton == null || !customerId.equals(carton.getCustomerId())) throw conflict("退货库存箱不存在");
if ("AVAILABLE".equals(carton.getStatus()) || "DISCARDED".equals(carton.getStatus())) return;
long remaining = returnCartonItems.totalQuantity(cartonId);
int skuTypes = returnCartonItems.skuTypes(cartonId);
String status = remaining == 0 ? "DISCARDED" : "AVAILABLE";
if (returnCartons.finishDiscard(cartonId, customerId, status, remaining, skuTypes) != 1) {
throw conflict("退货库存箱状态已变化");
}
}
private static boolean isReturnItem(CargoDiscardItem item) {
return "RETURN_CARTON".equals(item.getSourceType()) || item.getReturnCartonId() != null;
}
@Transactional(propagation = Propagation.MANDATORY)
public AdjustmentResult discard(String customerId, CargoDiscardApplication application,
List<CargoDiscardItem> items,
@@ -22,6 +22,10 @@ import com.baiyue.lastleg.entity.LastlegOrder;
import com.baiyue.lastleg.entity.LastlegOrderStatusHistory;
import com.baiyue.lastleg.mapper.LastlegOrderMapper;
import com.baiyue.lastleg.mapper.LastlegOrderStatusHistoryMapper;
import com.baiyue.lastleg.returnreceipt.entity.ReturnInventoryCarton;
import com.baiyue.lastleg.returnreceipt.entity.ReturnInventoryCartonItem;
import com.baiyue.lastleg.returnreceipt.mapper.ReturnInventoryCartonItemMapper;
import com.baiyue.lastleg.returnreceipt.mapper.ReturnInventoryCartonMapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource;
@@ -64,6 +68,8 @@ public class CargoDiscardService {
@Resource private CargoDiscardInventoryAdjustmentService adjustments;
@Resource private LastlegOrderMapper orders;
@Resource private LastlegOrderStatusHistoryMapper orderHistories;
@Resource private ReturnInventoryCartonMapper returnCartons;
@Resource private ReturnInventoryCartonItemMapper returnCartonItems;
@Resource private ObjectMapper objectMapper;
@Value("${baiyue.lastleg.cargo-discard.fee-per-package-usd:5.00}")
private BigDecimal feePerPackage = new BigDecimal("5.00");
@@ -75,9 +81,25 @@ public class CargoDiscardService {
CandidateAccumulator value = grouped.computeIfAbsent(row.getOrderId(), ignored -> new CandidateAccumulator(row));
value.add(row);
}
return grouped.values().stream()
List<CargoDiscardResponses.Candidate> result = grouped.values().stream()
.map(value -> value.response(inventory.countAvailableOrder(customerId, value.first.getOrderId())))
.toList();
.collect(java.util.stream.Collectors.toCollection(java.util.ArrayList::new));
String keyword = trim(inboundCode);
if (returnCartons == null || returnCartonItems == null) return result;
for (ReturnInventoryCarton carton : returnCartons.findAvailable(customerId, null)) {
if (StringUtils.hasText(keyword) && !containsIgnoreCase(carton.getSourceReturnNo(), keyword)
&& !containsIgnoreCase(carton.getCartonMark(), keyword)) continue;
List<CargoDiscardResponses.CandidateSku> skus = returnCartonItems.listCarton(carton.getId()).stream()
.filter(item -> value(item.getQuantity()) > 0)
.map(item -> new CargoDiscardResponses.CandidateSku(item.getSkuCode(), item.getProductNameZh(), value(item.getQuantity())))
.toList();
long available = skus.stream().mapToLong(CargoDiscardResponses.CandidateSku::availablePackages).sum();
if (available <= 0) continue;
result.add(new CargoDiscardResponses.Candidate(null, "RETURN_CARTON", carton.getId(), carton.getCartonMark(),
carton.getSourceReturnNo(), carton.getSourceReturnNo(), carton.getOverseasWarehouseId(), null,
null, available, skus));
}
return result;
}
@Transactional
@@ -94,18 +116,39 @@ public class CargoDiscardService {
}
Set<String> requestedDimensions = new LinkedHashSet<>();
Map<Long, LastlegOrder> orderCache = new HashMap<>();
Map<Long, ReturnInventoryCarton> returnCartonCache = new HashMap<>();
String warehouseId = null;
String warehouseName = null;
int total = 0;
for (CargoDiscardRequests.Item input : request.items()) {
String dimension = input.orderId() + ":" + input.skuCode().trim();
boolean returnSource = input.returnCartonId() != null;
if (returnSource == (input.orderId() != null)) {
throw badRequest("Each discard item must identify exactly one inventory source");
}
String dimension = (returnSource ? "RETURN:" + input.returnCartonId() : "ORDER:" + input.orderId())
+ ":" + input.skuCode().trim();
if (!requestedDimensions.add(dimension)) throw badRequest("Duplicate order/SKU discard item: " + dimension);
LastlegOrder order = requireDropshipOrder(customerId, input.orderId());
orderCache.put(order.getId(), order);
String itemWarehouseId;
String itemWarehouseName;
if (returnSource) {
ReturnInventoryCarton carton = requireReturnCarton(customerId, input.returnCartonId());
ReturnInventoryCartonItem sku = returnCartonItems.lockSku(carton.getId(), input.skuCode().trim());
if (sku == null || value(sku.getQuantity()) < input.discardPackages()) {
throw conflict("Insufficient return inventory for SKU " + input.skuCode().trim());
}
returnCartonCache.put(carton.getId(), carton);
itemWarehouseId = carton.getOverseasWarehouseId();
itemWarehouseName = null;
} else {
LastlegOrder order = requireDropshipOrder(customerId, input.orderId());
orderCache.put(order.getId(), order);
itemWarehouseId = order.getOverseasWarehouseId();
itemWarehouseName = order.getOverseasWarehouseName();
}
if (warehouseId == null) {
warehouseId = required(order.getOverseasWarehouseId(), "Order has no operating overseas warehouse");
warehouseName = trim(order.getOverseasWarehouseName());
} else if (!warehouseId.equals(order.getOverseasWarehouseId())) {
warehouseId = required(itemWarehouseId, "Inventory has no operating overseas warehouse");
warehouseName = trim(itemWarehouseName);
} else if (!warehouseId.equals(itemWarehouseId)) {
throw conflict("One cargo discard application cannot span operating warehouses");
}
total = Math.addExact(total, input.discardPackages());
@@ -116,7 +159,9 @@ public class CargoDiscardService {
application.setId(IdWorker.getId()); application.setCustomerId(customerId);
application.setDiscardNo(orderNoGenerator.next("DISCARD", warehouseId, application.getId()));
application.setOverseasWarehouseId(warehouseId); application.setOverseasWarehouseName(warehouseName);
application.setInboundCodes(orderCache.values().stream().map(LastlegOrder::getInboundCode)
application.setInboundCodes(java.util.stream.Stream.concat(
orderCache.values().stream().map(LastlegOrder::getInboundCode),
returnCartonCache.values().stream().map(ReturnInventoryCarton::getSourceReturnNo))
.distinct().sorted().collect(java.util.stream.Collectors.joining(",")));
application.setTotalPackages(total); application.setFeePerPackage(feePerPackage);
application.setTotalFee(feePerPackage.multiply(BigDecimal.valueOf(total)));
@@ -157,8 +202,14 @@ public class CargoDiscardService {
initialOrderHistory.setEventId("CARGO_DISCARD_CREATE:" + application.getId()); initialOrderHistory.setRemark(trim(request.remark())); initialOrderHistory.setCreatedAt(now);
orderHistories.insert(initialOrderHistory);
Set<Long> reservedReturnCartons = new LinkedHashSet<>();
for (CargoDiscardRequests.Item input : request.items()) {
reserve(customerId, application, orderCache.get(input.orderId()), input, now);
if (input.returnCartonId() != null) {
reserveReturn(customerId, application, returnCartonCache.get(input.returnCartonId()), input, now,
reservedReturnCartons);
} else {
reserve(customerId, application, orderCache.get(input.orderId()), input, now);
}
}
history(customerId, application.getId(), null, PENDING_REVIEW, operatorId, request.remark(), now);
return detail(customerId, application.getDiscardNo());
@@ -215,7 +266,7 @@ public class CargoDiscardService {
.collect(java.util.stream.Collectors.groupingBy(CargoDiscardCarton::getItemId));
String historyRemark = request.remark();
if (REJECTED.equals(next)) {
release(customerId, links);
release(customerId, links, applicationItems);
}
LocalDateTime reviewedAt = now();
@@ -275,7 +326,7 @@ public class CargoDiscardService {
throw conflict("客户只能取消待审核的废弃申请");
}
List<CargoDiscardCarton> links = discardCartons.listApplication(customerId, application.getId());
release(customerId, links);
release(customerId, links, items.listApplication(customerId, application.getId()));
LocalDateTime at = now();
String from = application.getStatus();
application.setStatus(CANCELLED); application.setReviewedBy(platform ? operatorId : application.getReviewedBy());
@@ -309,6 +360,7 @@ public class CargoDiscardService {
if (sku == null) throw conflict("SKU inventory disappeared while reserving cargo");
CargoDiscardItem item = new CargoDiscardItem();
item.setId(IdWorker.getId()); item.setApplicationId(application.getId()); item.setCustomerId(customerId);
item.setSourceType("DROPSHIP");
item.setOrderId(order.getId()); item.setInboundCode(order.getInboundCode()); item.setProfileId(entry.getKey());
item.setSkuInventoryId(sku.getId()); item.setSkuCode(skuCode); item.setProductName(sku.getProductName());
item.setAvailablePackagesSnapshot(Math.toIntExact(inventory.countAvailableProfile(
@@ -326,14 +378,50 @@ public class CargoDiscardService {
}
}
private void release(String customerId, List<CargoDiscardCarton> links) {
private void release(String customerId, List<CargoDiscardCarton> links, List<CargoDiscardItem> applicationItems) {
for (CargoDiscardCarton link : links) {
if (inventory.changeCartonStatus(customerId, link.getCartonId(), "DISCARD_PENDING", "AVAILABLE") != 1) {
throw conflict("Reserved cargo status changed before rejection");
}
}
applicationItems.stream().filter(this::isReturnItem).map(CargoDiscardItem::getReturnCartonId)
.filter(java.util.Objects::nonNull).distinct().forEach(cartonId -> {
if (returnCartons.releaseDiscard(cartonId, customerId) != 1) {
throw conflict("Reserved return inventory status changed before rejection");
}
});
}
private void reserveReturn(String customerId, CargoDiscardApplication application, ReturnInventoryCarton carton,
CargoDiscardRequests.Item input, LocalDateTime now, Set<Long> reservedCartons) {
ReturnInventoryCartonItem sku = returnCartonItems.lockSku(carton.getId(), input.skuCode().trim());
if (sku == null || value(sku.getQuantity()) < input.discardPackages()) {
throw conflict("Available return inventory changed; retry the discard request");
}
if (reservedCartons.add(carton.getId()) && returnCartons.markDiscardPending(carton.getId(), customerId) != 1) {
throw conflict("Return inventory was reserved concurrently; retry the discard request");
}
CargoDiscardItem item = new CargoDiscardItem();
item.setId(IdWorker.getId()); item.setApplicationId(application.getId()); item.setCustomerId(customerId);
item.setSourceType("RETURN_CARTON"); item.setReturnCartonId(carton.getId()); item.setInboundCode(carton.getSourceReturnNo());
item.setSkuCode(sku.getSkuCode()); item.setProductName(sku.getProductNameZh());
item.setAvailablePackagesSnapshot(Math.toIntExact(value(sku.getQuantity())));
item.setDiscardPackages(input.discardPackages()); item.setCreatedAt(now); items.insert(item);
}
private ReturnInventoryCarton requireReturnCarton(String customerId, Long cartonId) {
ReturnInventoryCarton carton = returnCartons.lockId(cartonId);
if (carton == null || !customerId.equals(carton.getCustomerId())) throw notFound("Return inventory carton not found");
if (!"AVAILABLE".equals(carton.getStatus())) throw conflict("Return inventory carton is not available");
return carton;
}
private boolean isReturnItem(CargoDiscardItem item) {
return "RETURN_CARTON".equals(item.getSourceType()) || item.getReturnCartonId() != null;
}
private static long value(Long value) { return value == null ? 0L : value; }
private LastlegOrder requireDropshipOrder(String customerId, Long orderId) {
LastlegOrder order = orders.selectById(orderId);
if (order == null || !customerId.equals(order.getCustomerId())) throw notFound("Inbound order not found");
@@ -385,6 +473,9 @@ public class CargoDiscardService {
private static LocalDateTime now() { return LocalDateTime.now(); }
private static String trim(String value) { return value == null || value.isBlank() ? null : value.trim(); }
private static boolean containsIgnoreCase(String value, String keyword) {
return value != null && keyword != null && value.toLowerCase(java.util.Locale.ROOT).contains(keyword.toLowerCase(java.util.Locale.ROOT));
}
private static String required(String value, String message) { String result = trim(value); if (result == null) throw conflict(message); return result; }
private static ResponseStatusException badRequest(String message) { return new ResponseStatusException(HttpStatus.BAD_REQUEST, message); }
private static ResponseStatusException conflict(String message) { return new ResponseStatusException(HttpStatus.CONFLICT, message); }
@@ -401,7 +492,7 @@ public class CargoDiscardService {
private CargoDiscardResponses.Candidate response(long physicalPackages) {
List<CargoDiscardResponses.CandidateSku> skuViews = skus.values().stream()
.map(value -> new CargoDiscardResponses.CandidateSku(value.skuCode, value.productName, value.packages)).toList();
return new CargoDiscardResponses.Candidate(first.getOrderId(), first.getInboundCode(), first.getInboundOrderNo(),
return new CargoDiscardResponses.Candidate(first.getOrderId(), "DROPSHIP", null, null, first.getInboundCode(), first.getInboundOrderNo(),
first.getOverseasWarehouseId(), first.getOverseasWarehouseName(), first.getCreatedAt(), physicalPackages, skuViews);
}
}
@@ -5,6 +5,7 @@ import com.baiyue.lastleg.returnreceipt.entity.ReturnInventoryCartonItem;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import java.util.List;
@@ -14,4 +15,16 @@ public interface ReturnInventoryCartonItemMapper extends BaseMapper<ReturnInvent
List<ReturnInventoryCartonItem> listCarton(@Param("cartonId") long cartonId);
@Select("SELECT * FROM ll_return_inventory_carton_item WHERE carton_id=#{cartonId} ORDER BY sku_code FOR UPDATE")
List<ReturnInventoryCartonItem> lockCarton(@Param("cartonId") long cartonId);
@Select("SELECT * FROM ll_return_inventory_carton_item WHERE carton_id=#{cartonId} AND sku_code=#{skuCode} LIMIT 1 FOR UPDATE")
ReturnInventoryCartonItem lockSku(@Param("cartonId") long cartonId, @Param("skuCode") String skuCode);
@Update("UPDATE ll_return_inventory_carton_item SET quantity=quantity-#{quantity} WHERE id=#{id} AND quantity>=#{quantity}")
int deduct(@Param("id") long id, @Param("quantity") long quantity);
@Select("SELECT COALESCE(SUM(quantity),0) FROM ll_return_inventory_carton_item WHERE carton_id=#{cartonId}")
long totalQuantity(@Param("cartonId") long cartonId);
@Select("SELECT COUNT(*) FROM ll_return_inventory_carton_item WHERE carton_id=#{cartonId} AND quantity>0")
int skuTypes(@Param("cartonId") long cartonId);
}
@@ -25,7 +25,9 @@ public interface ReturnInventoryCartonMapper extends BaseMapper<ReturnInventoryC
List<ReturnInventoryCarton> merchantPage(@Param("customerId") String customerId,
@Param("query") com.baiyue.lastleg.returnreceipt.dto.ReturnInventoryRequests.Query query, @Param("offset") long offset);
@Select("SELECT * FROM ll_return_inventory_carton WHERE customer_id=#{customerId} AND overseas_warehouse_id=#{warehouseId} AND status='AVAILABLE' ORDER BY created_at DESC,id DESC LIMIT 500")
@Select("<script>SELECT * FROM ll_return_inventory_carton WHERE customer_id=#{customerId} AND status='AVAILABLE' " +
"<if test='warehouseId != null and warehouseId != \"\"'>AND overseas_warehouse_id=#{warehouseId} </if>" +
"ORDER BY created_at DESC,id DESC LIMIT 500</script>")
List<ReturnInventoryCarton> findAvailable(@Param("customerId") String customerId, @Param("warehouseId") String warehouseId);
@Select("SELECT * FROM ll_return_inventory_carton WHERE carton_mark=#{cartonMark} LIMIT 1")
ReturnInventoryCarton findMark(@Param("cartonMark") String cartonMark);
@@ -36,6 +38,17 @@ public interface ReturnInventoryCartonMapper extends BaseMapper<ReturnInventoryC
@Select("SELECT * FROM ll_return_inventory_carton WHERE id=#{id} FOR UPDATE")
ReturnInventoryCarton lockId(@Param("id") long id);
@Update("UPDATE ll_return_inventory_carton SET status='DISCARD_PENDING',updated_at=NOW(3) WHERE id=#{id} AND customer_id=#{customerId} AND status='AVAILABLE'")
int markDiscardPending(@Param("id") long id, @Param("customerId") String customerId);
@Update("UPDATE ll_return_inventory_carton SET status=#{status},total_quantity=#{totalQuantity},sku_types=#{skuTypes},updated_at=NOW(3) WHERE id=#{id} AND customer_id=#{customerId} AND status='DISCARD_PENDING'")
int finishDiscard(@Param("id") long id, @Param("customerId") String customerId,
@Param("status") String status, @Param("totalQuantity") long totalQuantity,
@Param("skuTypes") int skuTypes);
@Update("UPDATE ll_return_inventory_carton SET status='AVAILABLE',updated_at=NOW(3) WHERE id=#{id} AND customer_id=#{customerId} AND status='DISCARD_PENDING'")
int releaseDiscard(@Param("id") long id, @Param("customerId") String customerId);
@Select("SELECT COALESCE(SUM(ri.notified_package_count),0) FROM ll_relabel_item ri " +
"JOIN ll_relabel_application ra ON ra.id=ri.application_id " +
"WHERE ri.return_carton_id=#{cartonId} AND ri.sku_code=#{skuCode} " +