2024-07-10 16:22:54 +08:00
|
|
|
|
package com.wms.utils.storage;
|
|
|
|
|
|
|
|
|
|
|
|
import com.wms.constants.enums.LocationStatus;
|
2024-07-18 13:26:56 +08:00
|
|
|
|
import com.wms.entity.app.container.CreateInstoreTaskResponse;
|
|
|
|
|
|
import com.wms.entity.table.AppOrderIn;
|
2024-07-10 16:22:54 +08:00
|
|
|
|
import com.wms.entity.table.Location;
|
|
|
|
|
|
import com.wms.entity.table.Stock;
|
|
|
|
|
|
import com.wms.entity.table.Task;
|
|
|
|
|
|
import com.wms.mapper.LocationMapper;
|
|
|
|
|
|
import com.wms.mapper.StockMapper;
|
|
|
|
|
|
import com.wms.mapper.TaskMapper;
|
|
|
|
|
|
import lombok.RequiredArgsConstructor;
|
2024-07-18 13:26:56 +08:00
|
|
|
|
import org.slf4j.Logger;
|
|
|
|
|
|
import org.slf4j.LoggerFactory;
|
2024-07-10 16:22:54 +08:00
|
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
|
|
import org.springframework.stereotype.Component;
|
|
|
|
|
|
|
|
|
|
|
|
import java.util.List;
|
2024-07-18 13:26:56 +08:00
|
|
|
|
import java.util.Objects;
|
2024-07-10 16:22:54 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 库位工具类
|
|
|
|
|
|
*/
|
|
|
|
|
|
@Component
|
|
|
|
|
|
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
|
|
|
|
|
|
public class LocationUtils {
|
|
|
|
|
|
|
2024-07-18 13:26:56 +08:00
|
|
|
|
private static final Logger log = LoggerFactory.getLogger(LocationUtils.class);
|
2024-07-10 16:22:54 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 库存 Mapper
|
|
|
|
|
|
*/
|
|
|
|
|
|
private final StockMapper stockMapper;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 库位 Mapper
|
|
|
|
|
|
*/
|
|
|
|
|
|
private final LocationMapper locationMapper;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 任务mapper
|
|
|
|
|
|
*/
|
|
|
|
|
|
private final TaskMapper taskMapper;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取一个区域的可用的库位
|
2024-07-18 13:26:56 +08:00
|
|
|
|
*
|
|
|
|
|
|
* @param areaId 区域ID
|
|
|
|
|
|
* @param appOrderIn
|
2024-07-10 16:22:54 +08:00
|
|
|
|
* @return 可用的库位排序
|
|
|
|
|
|
*/
|
2024-07-18 13:26:56 +08:00
|
|
|
|
public List<Location> getNewLocation(Integer areaId, AppOrderIn appOrderIn) {
|
|
|
|
|
|
if (Objects.equals(appOrderIn.getWareHouse(), "A")){
|
|
|
|
|
|
Location query = new Location();
|
|
|
|
|
|
query.setAreaId(areaId);
|
|
|
|
|
|
query.setWareArea("A");
|
|
|
|
|
|
query.setLocationStatus(LocationStatus.EMPTY.getCode());
|
|
|
|
|
|
List<Location> canUseLocations = locationMapper.selNextLocation(query);
|
2025-03-01 23:47:04 +08:00
|
|
|
|
// if(canUseLocations.isEmpty()){
|
|
|
|
|
|
// log.info("A级优先级没有可用库位,开始寻找B级库位");
|
|
|
|
|
|
// query.setAreaId(areaId);
|
|
|
|
|
|
// query.setWareArea("B");
|
|
|
|
|
|
// query.setLocationStatus(LocationStatus.EMPTY.getCode());
|
|
|
|
|
|
// List<Location> canUseLocations2 = locationMapper.selNextLocation(query);
|
|
|
|
|
|
// if (canUseLocations2.isEmpty()){
|
|
|
|
|
|
// log.info("A,B级优先级没有可用库位,开始寻找C级库位");
|
|
|
|
|
|
// query.setAreaId(areaId);
|
|
|
|
|
|
// query.setWareArea("C");
|
|
|
|
|
|
// query.setLocationStatus(LocationStatus.EMPTY.getCode());
|
|
|
|
|
|
// return locationMapper.selNextLocation(query);
|
|
|
|
|
|
// }
|
|
|
|
|
|
// return canUseLocations2;
|
|
|
|
|
|
// }
|
2024-07-18 13:26:56 +08:00
|
|
|
|
return canUseLocations;
|
|
|
|
|
|
} else if (Objects.equals(appOrderIn.getWareHouse(), "B")) {
|
|
|
|
|
|
Location query = new Location();
|
|
|
|
|
|
query.setAreaId(areaId);
|
|
|
|
|
|
query.setWareArea("B");
|
|
|
|
|
|
query.setLocationStatus(LocationStatus.EMPTY.getCode());
|
|
|
|
|
|
List<Location> canUseLocations = locationMapper.selNextLocation(query);
|
2025-03-01 23:47:04 +08:00
|
|
|
|
// if(canUseLocations.isEmpty()){
|
|
|
|
|
|
// log.info("B级优先级没有可用库位,开始寻找C级库位");
|
|
|
|
|
|
// query.setAreaId(areaId);
|
|
|
|
|
|
// query.setWareArea("C");
|
|
|
|
|
|
// query.setLocationStatus(LocationStatus.EMPTY.getCode());
|
|
|
|
|
|
// return locationMapper.selNextLocation(query);
|
|
|
|
|
|
// }
|
2024-07-18 13:26:56 +08:00
|
|
|
|
return canUseLocations;
|
|
|
|
|
|
} else if (Objects.equals(appOrderIn.getWareHouse(), "C")) {
|
|
|
|
|
|
Location query = new Location();
|
|
|
|
|
|
query.setAreaId(areaId);
|
|
|
|
|
|
query.setWareArea(appOrderIn.getWareHouse());
|
|
|
|
|
|
query.setLocationStatus(LocationStatus.EMPTY.getCode());
|
|
|
|
|
|
return locationMapper.selNextLocation(query);
|
2025-03-01 23:47:04 +08:00
|
|
|
|
}else if (Objects.equals(appOrderIn.getWareHouse(), "D")) {
|
|
|
|
|
|
Location query = new Location();
|
|
|
|
|
|
query.setAreaId(areaId);
|
|
|
|
|
|
query.setWareArea(appOrderIn.getWareHouse());
|
|
|
|
|
|
query.setLocationStatus(LocationStatus.EMPTY.getCode());
|
|
|
|
|
|
return locationMapper.selNextLocation(query);
|
2024-07-18 13:26:56 +08:00
|
|
|
|
}else{
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-07-10 16:22:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 在一堆空闲的库位中寻找一个可用的入库库位
|
|
|
|
|
|
* @param canUseLocations 可用的库位
|
|
|
|
|
|
* @return 可用的库位,若没有可用的库位则返回 null
|
|
|
|
|
|
*/
|
|
|
|
|
|
public Location checkCanUse(List<Location> canUseLocations) {
|
|
|
|
|
|
if(canUseLocations == null || canUseLocations.isEmpty()) {
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
2025-03-01 23:47:04 +08:00
|
|
|
|
boolean canUse = true;
|
2024-07-10 16:22:54 +08:00
|
|
|
|
for (Location location : canUseLocations) {
|
2024-07-16 15:12:27 +08:00
|
|
|
|
if(location.getDepth() == 1) {
|
|
|
|
|
|
return location; // 1 深度的不需要检验
|
|
|
|
|
|
}
|
2024-07-10 16:22:54 +08:00
|
|
|
|
/* 校验此位置是否有遮挡 */ /* 如果这位置有库存(可能出现记错导致有库存),或者这位置其他深度(不论深度大小)有任务则不采用此位置 */
|
|
|
|
|
|
/* 1 判断库存 */
|
|
|
|
|
|
Stock checkStock = new Stock();
|
|
|
|
|
|
checkStock.setLocationId(location.getLocationId());
|
|
|
|
|
|
List<Stock> checkResult = stockMapper.selStocks(checkStock);
|
|
|
|
|
|
if(!checkResult.isEmpty()) {
|
|
|
|
|
|
continue; // 库存不为空,跳过
|
|
|
|
|
|
}
|
|
|
|
|
|
/* 2 判断同位置不同深度是否有任务 */
|
|
|
|
|
|
// 找出此位置不同深度的库位
|
|
|
|
|
|
Location queryDifferentDepthLocation = new Location();
|
|
|
|
|
|
queryDifferentDepthLocation.setAreaId(location.getAreaId());
|
|
|
|
|
|
queryDifferentDepthLocation.setQueue(location.getQueue());
|
2025-03-01 23:47:04 +08:00
|
|
|
|
queryDifferentDepthLocation.setTunnelId(location.getTunnelId());
|
2024-07-10 16:22:54 +08:00
|
|
|
|
queryDifferentDepthLocation.setLayer(location.getLayer());
|
|
|
|
|
|
List<Location> differentDepthLocations = locationMapper.selLocations(queryDifferentDepthLocation);
|
|
|
|
|
|
if(differentDepthLocations == null) {
|
|
|
|
|
|
continue; // 数据库查询失败
|
|
|
|
|
|
}
|
2025-03-01 23:47:04 +08:00
|
|
|
|
// boolean canUse = false; // 指示当前库位是否可用,若可用会置成 true
|
2024-07-10 16:22:54 +08:00
|
|
|
|
if(!differentDepthLocations.isEmpty()) {
|
|
|
|
|
|
// 存在干涉库位,检验其是否有未完成的任务
|
|
|
|
|
|
for (Location differentDepthLocation : differentDepthLocations) {
|
|
|
|
|
|
// 找出此位置不同深度的库位
|
|
|
|
|
|
Location queryLocationTask = new Location();
|
|
|
|
|
|
queryLocationTask.setLocationId(differentDepthLocation.getLocationId());
|
|
|
|
|
|
List<Task> locationTasks = taskMapper.haveNotCompleteTask(differentDepthLocation.getLocationId());
|
|
|
|
|
|
if(locationTasks == null) {
|
2025-03-01 23:47:04 +08:00
|
|
|
|
log.info("检查存在干涉库位失败,数据库异常");
|
|
|
|
|
|
canUse = false;
|
|
|
|
|
|
break; // 数据库查询失败
|
2024-07-10 16:22:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
if(!locationTasks.isEmpty()) {
|
2025-03-02 08:50:50 +08:00
|
|
|
|
log.info("检查存在干涉库位失败,此位置有未完成的任务,任务位置{}",differentDepthLocation.getLocationId());
|
2025-03-01 23:47:04 +08:00
|
|
|
|
canUse = false;
|
2024-07-10 16:22:54 +08:00
|
|
|
|
break; // 有任务这个库位不行
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if(canUse) {
|
|
|
|
|
|
return location;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|