feat: auto assign overseas pallet locations

This commit is contained in:
2026-09-24 16:37:13 +08:00
parent 91464e031f
commit f7b009bcdf
4 changed files with 22 additions and 3 deletions
@@ -46,7 +46,7 @@ public interface WarehouseResourceLockMapper extends BaseMapper<WarehouseResourc
UPDATE wh_location
SET status = 'OCCUPIED', updated_at = CURRENT_TIMESTAMP(3), version = version + 1
WHERE id = #{locationId} AND customer_id = #{customerId} AND warehouse_id = #{warehouseId}
AND status = 'IDLE' AND deleted = 0
AND status IN ('ACTIVE','IDLE') AND deleted = 0
""")
int occupyLocation(@Param("customerId") long customerId, @Param("warehouseId") long warehouseId,
@Param("locationId") long locationId);
@@ -11,6 +11,7 @@ import com.baiyue.warehouse.mapper.WarehouseLocationMapper;
import com.baiyue.warehouse.mapper.WarehousePalletMapper;
import com.baiyue.warehouse.mapper.WarehousePalletBindingMapper;
import com.baiyue.warehouse.entity.WarehousePalletBindingEntity;
import com.baiyue.warehouse.service.WarehouseResourceService;
import org.springframework.stereotype.Repository;
import org.springframework.util.StringUtils;
import jakarta.annotation.Resource;
@@ -47,6 +48,17 @@ public class WarehouseResourceRepository {
.last("LIMIT 1"));
}
/** Phase-one rule: choose the first enabled normal location by code. */
public WarehouseLocationEntity findFirstAutoAssignableLocation(long warehouseId) {
return locations.selectOne(new LambdaQueryWrapper<WarehouseLocationEntity>()
.eq(WarehouseLocationEntity::getCustomerId, WarehouseResourceService.PUBLIC_RESOURCE_SCOPE)
.eq(WarehouseLocationEntity::getWarehouseId, warehouseId)
.notIn(WarehouseLocationEntity::getLocationType, "VIRTUAL", "SHARED_OVERFLOW")
.in(WarehouseLocationEntity::getStatus, "ACTIVE", "IDLE")
.orderByAsc(WarehouseLocationEntity::getLocationCode)
.last("LIMIT 1"));
}
public WarehouseLocationEntity findSharedOverflowLocation(long warehouseId) {
return locations.selectOne(new LambdaQueryWrapper<WarehouseLocationEntity>()
.eq(WarehouseLocationEntity::getCustomerId, 0L)
@@ -91,9 +91,11 @@ public class WarehousePalletBatchService {
WarehousePalletEntity createdPallet = resources.reusablePublicPallet(
normalized.warehouseId(), requested.palletCode());
if (createdPallet == null) {
var autoLocation = repository.findFirstAutoAssignableLocation(normalized.warehouseId());
Long locationId = autoLocation == null ? null : autoLocation.getId();
Long palletId = resources.createPallet(WarehouseResourceService.PUBLIC_RESOURCE_SCOPE,
normalized.warehouseId(), new PalletRequests.SaveRequest(requested.palletCode(), "WOOD",
AUTO_PALLET_CAPACITY_CBM, AUTO_PALLET_UNIT_PRICE_USD, "IDLE", null, AUTO_PALLET_REMARK,
AUTO_PALLET_CAPACITY_CBM, AUTO_PALLET_UNIT_PRICE_USD, "IDLE", locationId, AUTO_PALLET_REMARK,
requested.fbaWarehouseCode()));
createdPallet = resources.pallet(WarehouseResourceService.PUBLIC_RESOURCE_SCOPE,
normalized.warehouseId(), palletId);
@@ -16,6 +16,7 @@ import jakarta.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Objects;
import java.util.Set;
@Service
public class WarehouseResourceLockService {
@@ -35,7 +36,11 @@ public class WarehouseResourceLockService {
throw new BizException(ResultCode.NOT_FOUND, "Pallet or location does not belong to the tenant warehouse");
}
boolean nonExclusiveLocation = isNonExclusive(location);
boolean locationAvailable = nonExclusiveLocation ? "ACTIVE".equals(location.getStatus()) : "IDLE".equals(location.getStatus());
// ACTIVE is the UI-facing enabled/unused state; IDLE is retained for
// locations created by the older lifecycle.
boolean locationAvailable = nonExclusiveLocation
? "ACTIVE".equals(location.getStatus())
: Set.of("ACTIVE", "IDLE").contains(location.getStatus());
if (!"IDLE".equals(pallet.getStatus()) || !locationAvailable) {
WarehouseResourceLockEntity concurrent =
repository.findByReservationKey(request.customerId(), request.reservationKey());