<add>[important]基本完成给四向车的API接口

This commit is contained in:
葛林强 2024-07-10 16:22:54 +08:00
parent 15c027d03e
commit 4906e505fb
16 changed files with 933 additions and 6 deletions

View File

@ -0,0 +1,303 @@
package com.wms.bussiness;
import com.wms.constants.enums.LocationStatus;
import com.wms.constants.enums.StockStatus;
import com.wms.constants.enums.TaskType;
import com.wms.constants.enums.WmsTaskStatus;
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;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.swing.plaf.synth.Region;
import java.util.Date;
import java.util.List;
/**
* 对任务的操作
*/
@Slf4j
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class TaskOperation {
/**
* 库存 Mapper
*/
private final StockMapper stockMapper;
/**
* 任务表操作类
*/
private final TaskMapper taskMapper;
/**
* 库位表操作类
*/
private final LocationMapper locationMapper;
//region 完成任务
/**
* 完成任务
* @param task 要完成的任务
* @return 操作结果
*/
public boolean completeTask(Task task) {
if(task == null) {
return false;
}
TaskType taskType = TaskType.getTaskType(task.getTaskType());
if(taskType == null) {
return false;
}
/* 根据任务类型判断 */
return switch (taskType) {
case IN -> completeInTask(task);
case OUT -> completeOutTask(task);
case INVENTORY -> completeInventoryTask(task);
case MOVE -> completeMoveTask(task);
};
}
/**
* 完成入库任务
* @param task 要完成的入库任务
* @return 结果
*/
private boolean completeInTask(Task task) {
/* 将任务更新为完成,将库存更新为正常库存,将库位更新为占用 */
// 更新任务状态
Task updateTask = new Task();
updateTask.setTaskId(task.getTaskId());
updateTask.setTaskStatus(WmsTaskStatus.FINISH.getCode());
updateTask.setFinishTime(new Date());
int updateRow = taskMapper.executeTask(updateTask);
if(updateRow != 1) {
log.warn(String.format("完成入库任务更新任务状态失败,任务号:%s", task.getTaskId()));
return false;
}
// 更新库存状态
Stock stockQuery = new Stock();
stockQuery.setLocationId(task.getDestination());
List<Stock> stocks = stockMapper.selStocks(stockQuery);
if(stocks == null) {
log.warn(String.format("完成入库任务查询库存 查询数据库失败,任务号:%s", task.getTaskId()));
return false;
}
if(stocks.isEmpty()) {
log.warn(String.format("完成入库任务查询库存没有库存数据,任务号:%s", task.getTaskId()));
return false;
}
for(Stock stock : stocks) {
Stock updateStock = new Stock();
updateStock.setStockId(stock.getStockId());
updateStock.setStockStatus(StockStatus.OK.getCode());
updateStock.setLastUpdateTime(new Date());
updateStock.setCreateTime(new Date());
int updateStockResult = stockMapper.modifyStock(updateStock);
if(updateStockResult != 1) {
log.warn(String.format("完成入库任务更新库存状态失败,任务号:%s , 库存号:%s", task.getTaskId(), stock.getStockId()));
}
}
return true;
}
/**
* 完成出库任务
* @param task 要完成的出库任务
* @return 执行结果
*/
private boolean completeOutTask(Task task) {
/* 将任务更新为完成,删除库存,将库位释放 */
// 更新任务状态
Task updateTask = new Task();
updateTask.setTaskId(task.getTaskId());
updateTask.setTaskStatus(WmsTaskStatus.FINISH.getCode());
updateTask.setFinishTime(new Date());
int updateRow = taskMapper.executeTask(updateTask);
if(updateRow != 1) {
log.warn(String.format("完成出库任务更新任务状态失败,任务号:%s", task.getTaskId()));
return false;
}
// 删除库存
Stock stockQuery = new Stock();
stockQuery.setLocationId(task.getDestination());
List<Stock> stocks = stockMapper.selStocks(stockQuery);
if(stocks == null) {
log.warn(String.format("完成出库任务查询库存 查询数据库失败,任务号:%s", task.getTaskId()));
return false;
}
if(stocks.isEmpty()) {
log.warn(String.format("完成出库任务查询库存没有库存数据,任务号:%s", task.getTaskId()));
return false;
}
for(Stock stock : stocks) {
int deleteStockResult = stockMapper.deleteStock(stock.getStockId());
if(deleteStockResult != 1) {
log.warn(String.format("完成出库任务删除库存状态失败,任务号:%s , 库存号:%s", task.getTaskId(), stock.getStockId()));
}
}
// 释放库位
Location location = new Location();
location.setLocationId(task.getDestination());
location.setLocationStatus(LocationStatus.EMPTY.getCode());
locationMapper.modifyLocation(location);
return true;
}
private boolean completeInventoryTask(Task task) {
return true;
}
private boolean completeMoveTask(Task task) {
/* 将任务更新为完成;更新库存状态;更新库位状态 */
Task updateTask = new Task();
updateTask.setTaskId(task.getTaskId());
updateTask.setTaskStatus(WmsTaskStatus.FINISH.getCode());
updateTask.setFinishTime(new Date());
int updateRow = taskMapper.executeTask(updateTask);
if(updateRow != 1) {
log.warn(String.format("完成移库任务更新任务状态失败,任务号:%s", task.getTaskId()));
return false;
}
// 更新库存
int updateLocationResult = stockMapper.updateLocationAndStatus(task.getOrigin(), task.getDestination(), StockStatus.OK.getCode());
if(updateLocationResult < 1) {
log.warn(String.format("完成移库任务更新库存状态失败,任务号:%s ,原库位:%s新库位%s", task.getTaskId(), task.getOrigin(), task.getDestination()));
return false;
}
// 释放原库位
Location location = new Location();
location.setLocationId(task.getOrigin());
location.setLocationStatus(LocationStatus.EMPTY.getCode());
locationMapper.modifyLocation(location);
return true;
}
//endregion
//region 取消任务
/**
* 取消任务
* @param task 要完成的任务
* @return 操作结果
*/
public boolean cancelTask(Task task) {
if(task == null) {
return false;
}
TaskType taskType = TaskType.getTaskType(task.getTaskType());
if(taskType == null) {
return false;
}
/* 根据任务类型判断 */
return switch (taskType) {
case IN -> cancelInTask(task);
case OUT -> cancelOutTask(task);
case INVENTORY -> cancelInventoryTask(task);
case MOVE -> cancelMoveTask(task);
};
}
/**
* 取消入库任务
* @param task 要取消的入库任务
* @return 结果
*/
private boolean cancelInTask(Task task) {
/* 将任务更新为取消,将库存删除,将库位更新为空闲 */
// 更新任务状态
Task updateTask = new Task();
updateTask.setTaskId(task.getTaskId());
updateTask.setTaskStatus(WmsTaskStatus.CANCEL.getCode());
updateTask.setFinishTime(new Date());
int updateRow = taskMapper.executeTask(updateTask);
if(updateRow != 1) {
log.warn(String.format("取消入库任务更新任务状态失败,任务号:%s", task.getTaskId()));
return false;
}
// 删除库存
int deleteResult = stockMapper.deleteStockWithLocationId(task.getDestination());
if(deleteResult < 1) {
log.warn(String.format("取消入库删除库存失败,任务号:%s入库点位%s -> %s", task.getTaskId(), task.getOrigin(), task.getDestination()));
}
// 释放库位
Location location = new Location();
location.setLocationId(task.getDestination());
location.setLocationStatus(LocationStatus.EMPTY.getCode());
locationMapper.modifyLocation(location);
return true;
}
/**
* 取消出库任务
* @param task 要取消的出库任务
* @return 执行结果
*/
private boolean cancelOutTask(Task task) {
/* 将任务更新为取消,将库存更新为库存中 */
// 更新任务状态
Task updateTask = new Task();
updateTask.setTaskId(task.getTaskId());
updateTask.setTaskStatus(WmsTaskStatus.CANCEL.getCode());
updateTask.setFinishTime(new Date());
int updateRow = taskMapper.executeTask(updateTask);
if(updateRow != 1) {
log.warn(String.format("取消出库任务更新任务状态失败,任务号:%s", task.getTaskId()));
return false;
}
// 更新库存信息为库存中
int updateResult = stockMapper.updateStockStatusWithLocationId(task.getOrigin(), StockStatus.OK.getCode());
if(updateResult < 1) {
log.warn(String.format("取消出库任务更新库存状态失败,任务号:%s出库点位%s -> %s", task.getTaskId(), task.getOrigin(), task.getDestination()));
}
return true;
}
private boolean cancelInventoryTask(Task task) {
return true;
}
private boolean cancelMoveTask(Task task) {
/* 将任务更新为取消;更新库存状态为正常;释放终点库位 */
Task updateTask = new Task();
updateTask.setTaskId(task.getTaskId());
updateTask.setTaskStatus(WmsTaskStatus.CANCEL.getCode());
updateTask.setFinishTime(new Date());
int updateRow = taskMapper.executeTask(updateTask);
if(updateRow != 1) {
log.warn(String.format("完成移库任务更新任务状态失败,任务号:%s", task.getTaskId()));
return false;
}
// 更新库存信息为库存中
int updateResult = stockMapper.updateStockStatusWithLocationId(task.getOrigin(), StockStatus.OK.getCode());
if(updateResult < 1) {
log.warn(String.format("取消出库任务更新库存状态失败,任务号:%s出库点位%s -> %s", task.getTaskId(), task.getOrigin(), task.getDestination()));
}
// 释放新库位
Location location = new Location();
location.setLocationId(task.getDestination());
location.setLocationStatus(LocationStatus.EMPTY.getCode());
locationMapper.modifyLocation(location);
return true;
}
//endregion
}

View File

@ -6,7 +6,8 @@ package com.wms.constants.enums;
public enum TaskType { public enum TaskType {
IN(1, "入库"), IN(1, "入库"),
OUT(2, "出库"), OUT(2, "出库"),
INVENTORY(3, "盘点"); INVENTORY(3, "盘点"),
MOVE(9, "移库");
private final Integer code; private final Integer code;
@ -24,4 +25,13 @@ public enum TaskType {
public String getValue() { public String getValue() {
return value; return value;
} }
public static TaskType getTaskType(Integer code) {
for (TaskType taskType : TaskType.values()) {
if (taskType.getCode().equals(code)) {
return taskType;
}
}
return null;
}
} }

View File

@ -1,23 +1,50 @@
package com.wms.controller.parent; package com.wms.controller.parent;
import com.wms.controller.BaseController; import com.wms.controller.BaseController;
import com.wms.entity.app.container.ContainerApiLocalResponse;
import com.wms.entity.app.container.CreateInstoreTaskRequest;
import com.wms.entity.app.container.CreateInstoreTaskResponse;
import com.wms.entity.app.container.TaskStateNoticeRequest;
import com.wms.service.ContainerService;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.*;
/** /**
* 四向车交互 * 四向车交互
* @author icewint * @author icewint
*/ */
@Controller @RestController
@CrossOrigin @CrossOrigin
@RequestMapping(value = "/wms/mes") @RequestMapping(value = "/api/container")
@RequiredArgsConstructor(onConstructor = @__(@Autowired)) @RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class ContainerController extends BaseController { public class ContainerController extends BaseController {
private final ContainerService containerService;
/**
* 接收四向车扫码入库信息
* @param request 请求信息
* @return 返回信息
*/
@PostMapping("/CreateInstoreTask")
public CreateInstoreTaskResponse createInstoreTask(@RequestBody @Validated CreateInstoreTaskRequest request) {
return containerService.createInstoreTask(request);
}
/**
* 接收四向车任务状态通知
* @param request 请求信息
* @return 响应信息
*/
@PostMapping("/TaskStateNotice")
public ContainerApiLocalResponse taskStateNotice(@RequestBody @Validated TaskStateNoticeRequest request){
return containerService.taskStateNotice(request);
}
} }

View File

@ -0,0 +1,42 @@
package com.wms.entity.app.container;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
/**
* 给四向车服务的通用返回类
*/
@Data
public class ContainerApiLocalResponse {
public ContainerApiLocalResponse(String code, String message) {
this.code = code;
this.message = message;
}
public ContainerApiLocalResponse(String code, String wmsTaskId, String message) {
this.code = code;
this.wmsTaskId = wmsTaskId;
this.message = message;
}
/**
* 响应代码
*/
@JsonProperty("code")
private String code;
/**
* wms 任务号
*/
@JsonProperty("wmstaskid")
private String wmsTaskId;
/**
* 响应信息
*/
@JsonProperty("message")
private String message;
}

View File

@ -0,0 +1,56 @@
package com.wms.entity.app.container;
import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import lombok.Data;
/**
* 四向车扫码入库的请求
*/
@Data
public class CreateInstoreTaskRequest {
/**
* 请求号
*/
@NotBlank(message = "请求号不允许为空")
@JsonProperty("requestid")
private String requestId;
/**
* 密钥
*/
@NotBlank(message = "密钥不允许为空")
@JsonProperty("key")
private String key;
/**
* 托盘号
*/
@NotBlank(message = "托盘号不允许为空")
@JsonProperty("palletno")
private String palletNo;
/**
*
*/
@Pattern(regexp = "^\\d+$", message = "长不允许为空或者为非数字")
@JsonProperty("height")
private String height;
/**
*
*/
@Pattern(regexp = "^\\d+$", message = "宽不允许为空或者为非数字")
@JsonProperty("weight")
private String weight;
/**
* 起点位置
*/
@NotBlank(message = "起点位置不允许为空")
@JsonProperty("fromcellno")
private String fromCellNo;
}

View File

@ -0,0 +1,57 @@
package com.wms.entity.app.container;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
/**
* 四向车扫码入库的接口的返回响应
*/
@Data
public class CreateInstoreTaskResponse {
public CreateInstoreTaskResponse(String code, String message) {
this.code = code;
this.message = message;
}
public CreateInstoreTaskResponse() {
}
/**
* 响应代码
*/
@JsonProperty("code")
private String code;
/**
* wms 任务号
*/
@JsonProperty("wmstaskid")
private String wmsTaskId;
/**
* 载具号
*/
@JsonProperty("palletno")
private String palletNo;
/**
* 起始位置
*/
@JsonProperty("fromcellno")
private String fromCellNo;
/**
* 目的位置
*/
@JsonProperty("tocellno")
private String toCellNo;
/**
* 信息
*/
@JsonProperty("message")
private String message;
}

View File

@ -0,0 +1,39 @@
package com.wms.entity.app.container;
import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
@Data
public class TaskStateNoticeRequest {
/**
* 请求ID
*/
@NotBlank
@JsonProperty("requestid")
private String requestId;
/**
* 密钥
*/
@NotBlank
@JsonProperty("key")
private String key;
/**
* wms任务号
*/
@NotBlank
@JsonProperty("wmstaskid")
private String wmsTaskId;
/**
* 任务状态
*/
@NotBlank
@JsonProperty("taskstate")
private String taskState;
}

View File

@ -1,6 +1,7 @@
package com.wms.filter; package com.wms.filter;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.wms.entity.app.container.ContainerApiLocalResponse;
import com.wms.entity.app.mes.MesApiLocalResponse; import com.wms.entity.app.mes.MesApiLocalResponse;
import org.springframework.context.support.DefaultMessageSourceResolvable; import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.validation.ObjectError; import org.springframework.validation.ObjectError;
@ -26,8 +27,13 @@ public class GlobalExceptionHandler {
Class<?> controllerClass = method.getDeclaringClass(); Class<?> controllerClass = method.getDeclaringClass();
String className = controllerClass.getName(); String className = controllerClass.getName();
if(className.contains("MesController")) { if(className.contains("MesController")) {
/* 给mes返回的异常信息 */
return JSON.toJSONString(new MesApiLocalResponse(0, message)); return JSON.toJSONString(new MesApiLocalResponse(0, message));
} }
if(className.contains("ContainerController")) {
/* 给四向车返回的异常信息 */
return JSON.toJSONString(new ContainerApiLocalResponse("999", message));
}
} }
return String.format("{\"code\": 999, \"message\": \"%s\"}", message); return String.format("{\"code\": 999, \"message\": \"%s\"}", message);
} }

View File

@ -37,6 +37,23 @@ public interface StockMapper {
*/ */
int modifyStock(Stock stock); int modifyStock(Stock stock);
/**
* 修改库存存储的位置
* @param oldLocationId 旧库位
* @param newLocationId 新库位
* @return 结果
*/
int updateLocation(@Param("oldLocationId") String oldLocationId, @Param("newLocationId") String newLocationId);
/**
* 更新库存里的库位和库存状态
* @param oldLocationId 旧库位
* @param newLocationId 新库位
* @param status 状态
* @return 结果
*/
int updateLocationAndStatus(@Param("oldLocationId") String oldLocationId, @Param("newLocationId") String newLocationId, @Param("status") Integer status);
/** /**
* 删除库存 * 删除库存
* @param stockId * @param stockId
@ -44,6 +61,21 @@ public interface StockMapper {
*/ */
int deleteStock(String stockId); int deleteStock(String stockId);
/**
* 根据库位删除库存
* @param locationId 库位
* @return 删除结果
*/
int deleteStockWithLocationId(@Param("locationId") String locationId);
/**
* 根据库位更新库位状态
* @param locationId 库位
* @param status 状态
* @return 更新结果
*/
int updateStockStatusWithLocationId(@Param("locationId") String locationId, @Param("status") Integer status);
List<Stock> selStocksByGoodsId(Stock stock); List<Stock> selStocksByGoodsId(Stock stock);
List<Stock> selStockOutOfDate(); List<Stock> selStockOutOfDate();

View File

@ -35,4 +35,7 @@ public interface TaskMapper {
* @return * @return
*/ */
int deleteTask(String taskId); int deleteTask(String taskId);
List<Task> haveNotCompleteTask(String location);
} }

View File

@ -0,0 +1,27 @@
package com.wms.service;
import com.wms.entity.app.container.ContainerApiLocalResponse;
import com.wms.entity.app.container.CreateInstoreTaskRequest;
import com.wms.entity.app.container.CreateInstoreTaskResponse;
import com.wms.entity.app.container.TaskStateNoticeRequest;
/**
* 四向车api的Service
*/
public interface ContainerService {
/**
* 接收四向车扫码入库信息
* @param request 请求信息
* @return 返回信息
*/
CreateInstoreTaskResponse createInstoreTask(CreateInstoreTaskRequest request);
/**
* 接收四向车任务状态通知
* @param request 请求信息
* @return 响应信息
*/
ContainerApiLocalResponse taskStateNotice( TaskStateNoticeRequest request);
}

View File

@ -0,0 +1,174 @@
package com.wms.service.serviceImplements.parent;
import com.wms.bussiness.TaskOperation;
import com.wms.constants.enums.LocationStatus;
import com.wms.constants.enums.StockStatus;
import com.wms.constants.enums.TaskType;
import com.wms.constants.enums.WmsTaskStatus;
import com.wms.entity.app.container.ContainerApiLocalResponse;
import com.wms.entity.app.container.CreateInstoreTaskRequest;
import com.wms.entity.app.container.CreateInstoreTaskResponse;
import com.wms.entity.app.container.TaskStateNoticeRequest;
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 com.wms.service.ContainerService;
import com.wms.utils.StringUtils;
import com.wms.utils.storage.LocationUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
/**
* 四向车 api service 的实现
*/
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class ContainerImplement implements ContainerService {
/**
* 库存 Mapper
*/
private final StockMapper stockMapper;
/**
* 库位操作类
*/
private final LocationUtils locationUtils;
/**
* 任务表操作类
*/
private final TaskMapper taskMapper;
/**
* 库位 Mapper
*/
private final LocationMapper locationMapper;
/**
* 任务操作类
*/
private final TaskOperation taskOperation;
/**
* 接收四向车请求扫码入库
* @param request 请求信息
* @return 响应信息
*/
@Override
public CreateInstoreTaskResponse createInstoreTask(CreateInstoreTaskRequest request) {
String md5 = StringUtils.containerMd5(request.getRequestId());
if(!md5.equals(request.getKey())) {
return new CreateInstoreTaskResponse("400", "请求失败,密钥校验未通过");
}
/* 判断条码是否存在任务,条码扫出来的是批次号 */
Stock waitInStockQuery = new Stock();
waitInStockQuery.setBatchNo(request.getPalletNo());
waitInStockQuery.setStockStatus(StockStatus.WAIT_IN.getCode());
List<Stock> waitInStockList = stockMapper.selStocks(waitInStockQuery); // 查找待入库的批次号
if(waitInStockList.isEmpty()) {
return new CreateInstoreTaskResponse("400", String.format("条码:%s 不存在待入库的任务", request.getPalletNo()));
}
/* 查找可用库位 */
List<Location> canUseLocations = locationUtils.getNewLocation(2);
if(canUseLocations.isEmpty()){
return new CreateInstoreTaskResponse("400", "没有可用库位");
}
Location useLocation = locationUtils.checkCanUse(canUseLocations);
if(useLocation == null) {
return new CreateInstoreTaskResponse("400", "暂没有可以直接使用的库位,因为存在互锁的库位,请等待当前任务都执行完成后再试");
}
/* 找到可用的库位 */ /* 生成任务(生成的任务直接运行中,因为此处会把任务直接回回去),更新库存表内状态为入库中 */
// 新建任务 插入任务表
Task newInTask = new Task();
newInTask.setTaskId(UUID.randomUUID().toString());
newInTask.setTaskGroup(UUID.randomUUID().toString());
newInTask.setTaskType(TaskType.IN.getCode());
newInTask.setTaskStatus(WmsTaskStatus.WAIT.getCode()); // 因为任务是直接返回去的所以直接是已下发状态
newInTask.setOrigin(request.getFromCellNo());
newInTask.setDestination(useLocation.getLocationId());
newInTask.setGoodsId(String.format("%s 等 %d 个物料", waitInStockList.get(0).getGoodsId(), waitInStockList.size()));
newInTask.setWeight(Double.valueOf(request.getWeight()));
newInTask.setCreateTime(new java.util.Date());
newInTask.setUserName("四向车API");
newInTask.setVehicleSize(Integer.valueOf(request.getHeight()));
newInTask.setVehicleNo(request.getPalletNo());
newInTask.setTaskPriority(1);
int insertTaskResult = taskMapper.addTask(newInTask); // 添加入库任务
if(insertTaskResult < 1) {
return new CreateInstoreTaskResponse("400", "生成任务失败,无法插入新的入库任务");
}
// 更新库存中的待入库记录为入库中并将库位更新进去
for(Stock waitInStock : waitInStockList) {
Stock updateStock = new Stock();
updateStock.setStockId(waitInStock.getStockId());
updateStock.setStockStatus(StockStatus.IN_ING.getCode());
updateStock.setLocationId(useLocation.getLocationId());
stockMapper.modifyStock(updateStock);
}
// 释放库位
Location location = new Location();
location.setLocationId(useLocation.getLocationId());
location.setLocationStatus(LocationStatus.EMPTY.getCode());
locationMapper.modifyLocation(location);
CreateInstoreTaskResponse success = new CreateInstoreTaskResponse();
success.setCode("200");
success.setMessage("生成入库任务成功");
success.setWmsTaskId(newInTask.getTaskId());
success.setPalletNo(request.getPalletNo());
success.setFromCellNo(request.getFromCellNo());
success.setToCellNo(useLocation.getLocationId());
return success;
}
/**
* 接收四向车任务状态通知
* @param request 请求信息
* @return 响应信息
*/
@Override
public ContainerApiLocalResponse taskStateNotice(TaskStateNoticeRequest request) {
String md5 = StringUtils.containerMd5(request.getRequestId());
if(!md5.equals(request.getKey())) {
return new ContainerApiLocalResponse("400", "请求失败,密钥校验未通过");
}
/* 查找出相关任务 */
Task queryTask = new Task();
queryTask.setTaskId(request.getWmsTaskId());
List<Task> taskList = taskMapper.selTasks(queryTask);
if(taskList == null) {
return new ContainerApiLocalResponse("400", String.format("任务:%s 未找到任务,数据库查询失败", request.getWmsTaskId()));
}
if(taskList.isEmpty()) {
return new ContainerApiLocalResponse("400", String.format("任务:%s 不存在", request.getWmsTaskId()));
}
Task thisTask = taskList.get(0);
if(request.getTaskState().equals("20")) { // 任务完成
boolean completeResult = taskOperation.completeTask(thisTask);
if(!completeResult) {
return new ContainerApiLocalResponse("400", String.format("任务:%s 完成事件异常,请重试", request.getWmsTaskId()));
}
return new ContainerApiLocalResponse("200", "任务完成");
}
if(request.getTaskState().equals("21")) { // 任务取消
boolean cancelResult = taskOperation.cancelTask(thisTask);
if(!cancelResult) {
return new ContainerApiLocalResponse("400", String.format("任务:%s 取消事件异常,请重试", request.getWmsTaskId()));
}
return new ContainerApiLocalResponse("200", "任务取消");
}
return new ContainerApiLocalResponse("400", String.format("不支持的任务状态:%s", request.getTaskState()));
}
}

View File

@ -1,6 +1,8 @@
package com.wms.utils; package com.wms.utils;
import javax.xml.crypto.Data; import org.slf4j.Logger;
import org.springframework.util.DigestUtils;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
@ -10,6 +12,9 @@ import java.util.Date;
* &#064;date 2023/2/13 * &#064;date 2023/2/13
*/ */
public class StringUtils { public class StringUtils {
private static final Logger logger = org.slf4j.LoggerFactory.getLogger(StringUtils.class);
/** 空字符串 */ /** 空字符串 */
private static final String NULLSTR = ""; private static final String NULLSTR = "";
@ -127,4 +132,16 @@ public class StringUtils {
return new Date(0); return new Date(0);
} }
} }
private static final String containerMd5Key = "safer*123"; // 四向车接口密钥
/**
* 四向车 MD5 加密
* @param string 要加密的字符串
* @return 加密之后的值
*/
public static String containerMd5(String string) {
String needMd5Str = string + containerMd5Key;
return DigestUtils.md5DigestAsHex(needMd5Str.getBytes());
}
} }

View File

@ -0,0 +1,106 @@
package com.wms.utils.storage;
import com.wms.constants.enums.LocationStatus;
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;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 库位工具类
*/
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class LocationUtils {
/**
* 库存 Mapper
*/
private final StockMapper stockMapper;
/**
* 库位 Mapper
*/
private final LocationMapper locationMapper;
/**
* 任务mapper
*/
private final TaskMapper taskMapper;
/**
* 获取一个区域的可用的库位
* @param areaId 区域ID
* @return 可用的库位排序
*/
public List<Location> getNewLocation(Integer areaId) {
Location query = new Location();
query.setAreaId(areaId);
query.setLocationStatus(LocationStatus.EMPTY.getCode());
return locationMapper.selNextLocation(query);
}
/**
* 在一堆空闲的库位中寻找一个可用的入库库位
* @param canUseLocations 可用的库位
* @return 可用的库位若没有可用的库位则返回 null
*/
public Location checkCanUse(List<Location> canUseLocations) {
if(canUseLocations == null || canUseLocations.isEmpty()) {
return null;
}
for (Location location : canUseLocations) {
/* 校验此位置是否有遮挡 */ /* 如果这位置有库存(可能出现记错导致有库存),或者这位置其他深度(不论深度大小)有任务则不采用此位置 */
/* 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.setEquipmentId(location.getEquipmentId());
queryDifferentDepthLocation.setQueue(location.getQueue());
queryDifferentDepthLocation.setLine(location.getLine());
queryDifferentDepthLocation.setLayer(location.getLayer());
List<Location> differentDepthLocations = locationMapper.selLocations(queryDifferentDepthLocation);
if(differentDepthLocations == null) {
continue; // 数据库查询失败
}
boolean canUse = false; // 指示当前库位是否可用若可用会置成 true
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) {
continue; // 数据库查询失败
}
if(!locationTasks.isEmpty()) {
break; // 有任务这个库位不行
}
}
canUse = true;
}
if(canUse) {
return location;
}
}
return null;
}
}

View File

@ -183,6 +183,15 @@
where stock_id = #{stockId} where stock_id = #{stockId}
</update> </update>
<update id="updateLocation">
update tbl_app_stock set location_id = #{newLocationId} where location_id = #{oldLocationId}
</update>
<update id="updateLocationAndStatus">
update tbl_app_stock set location_id = #{newLocationId}, stock_status = #{status} where location_id = #{oldLocationId}
</update>
<update id="resetStock" parameterType="Stock"> <update id="resetStock" parameterType="Stock">
update tbl_app_stock set available_num = real_num; update tbl_app_stock set available_num = real_num;
</update> </update>
@ -191,4 +200,14 @@
<delete id="deleteStock" parameterType="String"> <delete id="deleteStock" parameterType="String">
delete from tbl_app_stock where stock_id = #{stockId} delete from tbl_app_stock where stock_id = #{stockId}
</delete> </delete>
<delete id="deleteStockWithLocationId" parameterType="String">
delete from tbl_app_stock where location_id = #{locationId}
</delete>
<update id="updateStockStatusWithLocationId">
update tbl_app_stock set stock_status = #{status} where location_id = #{locationId}
</update>
</mapper> </mapper>

View File

@ -146,4 +146,13 @@
<delete id="deleteTask" parameterType="String"> <delete id="deleteTask" parameterType="String">
delete from tbl_app_task where task_id = #{taskId} delete from tbl_app_task where task_id = #{taskId}
</delete> </delete>
<select id="haveNotCompleteTask" resultMap="TaskMap" parameterType="string">
select task_id, task_type, task_status, task_group, origin, destination, pick_stand, weight, vehicle_no, vehicle_size, create_time,
user_name, goods_id, goods_name, operate_num, total_num, etag_location, task_priority, production_date, expiration_date, kate_task_id, remark1
from tbl_app_task
where task_status <![CDATA[<]]> 100 and (origin = #{location} or destination = #{location})
order by task_priority desc, task_status desc, create_time desc
</select>
</mapper> </mapper>