no message

main
HUOJIN\92525 2024-08-01 18:19:43 +08:00
parent 60c35db239
commit e82b9bc435
14 changed files with 133 additions and 162 deletions

View File

@ -53,7 +53,8 @@ public interface PointRepository extends JpaRepository<Point, Long>, JpaSpecific
"and (:type IS NULL or point.type = :type) " +
"and (:goodType IS NULL or point.description = :goodType) " +
"and (:areaCode IS NULL or point.area.code = :areaCode) " +
"and (:itemHeight IS NULL or point.itemHeight = :itemHeight)")
"and (:itemHeight IS NULL or point.itemHeight = :itemHeight)" +
"order by point.posX desc,point.posY asc,point.posZ asc ")
List<Point> findByCode(String code, String status, String type, String areaCode, String goodType, Double itemHeight);
@Query(" from Point p where p.code in :pointCodes")

View File

@ -20,6 +20,7 @@ import com.youchain.appupdate.ReturnJson.ReturnTaskVo;
import com.youchain.basicdata.domain.Stock;
import com.youchain.basicdata.service.dto.StockDto;
import com.youchain.basicdata.service.dto.StockQueryCriteria;
import com.youchain.businessdata.domain.Pick;
import org.springframework.data.domain.Pageable;
import java.util.Map;
@ -199,6 +200,16 @@ public interface StockService {
*/
void cpCallStock();
/**
*
* @param stockCode
*/
void unBindContainer(String stockCode);
/**
*
* @param pick
*/
void callJlTask(Pick pick);
}

View File

@ -64,6 +64,7 @@ public class StockServiceImpl implements StockService {
private final StockRepository stockRepository;
private final PointRepository pointRepository;
private final PickRepository pickRepository;
private final PickDetailRepository pickDetailRepository;
private final TaskRepository taskRepository;
private final AgvTaskRepository agvTaskRepository;
@ -214,11 +215,11 @@ public class StockServiceImpl implements StockService {
public void containerIn(String containerCode, String position) {
Stock stock = validateStock(containerCode);//验证容器
Point point = validateSrcPoint(position);//验证点位
if (!isRestrictedArea(point.getArea().getCode())) {
if (!isRestrictedArea(point.getType())) {
throw new RuntimeException(point.getCode() + "点位不能入场!");
}
validateAgvResponse(UrlApi.containerIn(), containerInJson(containerCode, position));//验证AGV返回信息
validateAgvContainerIn(UrlApi.containerIn(), containerInJson(containerCode, position));//验证AGV返回信息
//入空车
@ -230,7 +231,7 @@ public class StockServiceImpl implements StockService {
@Transactional(rollbackFor = Exception.class)
public void containerOut(String containerCode) {
Stock stock = validateStock(containerCode);//验证容器
validateAgvResponse(UrlApi.containerOut(), containerOutJson(stock.getCode()));//验证AGV返回信息
validateAgvContainerOut(UrlApi.containerOut(), containerOutJson(stock.getCode()));//验证AGV返回信息
clearInventory(stock);//清空库存
Point point = stock.getPoint();
if (point != null) {
@ -335,12 +336,6 @@ public class StockServiceImpl implements StockService {
throw new RuntimeException("一个托盘只能放同一种物料!");
}
Set<String> boxNumbers = Collections.newSetFromMap(new ConcurrentHashMap<>());
boolean allUnique = barCodeVos.parallelStream().anyMatch(vo -> !boxNumbers.add(vo.getBoxNumber()));
if (allUnique) {
throw new RuntimeException("箱号不能重复!");
}
Set<String> barNumbers = barCodeVos.stream().map(BarCodeVo::getBoxNumber).collect(Collectors.toSet());
List<AsnDetail> asnDetails = asnDetailService.existsByboxNumber(barNumbers);
if (!asnDetails.isEmpty()) {
@ -376,7 +371,6 @@ public class StockServiceImpl implements StockService {
AsnDetail asnDetail = createAsnDetail(item, stock, srcPoint, barCodeVo.getPropC1(), barCodeVo.getBoxNumber(), barCodeVo.getPropC3(), Timestamp.valueOf(DateUtil.formatDateTime(DateUtil.parse(barCodeVo.getPropD1()))), barCodeVo.getOrderQty(), barCodeVo.getMo());
createAsnDetails.add(asnDetail);
ItemKey itemKey = itemKeyService.getItemKey(item, barCodeVo.getPropC1(), barCodeVo.getBoxNumber());
Task task = createAsnTask(item, itemKey, asnDetail, stock, srcPoint, endPoint, agvTask);
createAsnTasks.add(task);
}
@ -500,6 +494,8 @@ public class StockServiceImpl implements StockService {
/**验证任务*/
Task task = validateTask(taskId, orderNumber);
Pick pick = task.getPickDetail().getPick();
/**验证目标容器*/
Stock dstStock = validatedstStock(dstStockCode);
@ -509,6 +505,16 @@ public class StockServiceImpl implements StockService {
/**库存移位*/
moveInventory(task, dstStock, moveQty);
if (pick.getStock() == null) {
pick.setStock(dstStock);
pickRepository.save(pick);
} else {
Stock oldStock = pick.getStock();
if (!dstStockCode.equals(pick.getStock().getCode())) {
throw new RuntimeException(pick.getGdCode() + "工单只能放入同一个货架!" + "请放入" + oldStock.getCode() + "货架!");
}
}
/**刷新拣货状态*/
refreshPickStatus(task, moveQty);
@ -584,6 +590,25 @@ public class StockServiceImpl implements StockService {
stockRepository.save(stock);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void callJlTask(Pick pick) {
if (pick.getStock() == null) {
throw new RuntimeException(pick.getGdCode() + "请翻包拣货!");
}
if (pick.getCallPoint() == null) {
throw new RuntimeException(pick.getGdCode() + "叫料点位不能为空!");
}
Point srcPoint = pick.getStock().getPoint();
Point endPoint = pick.getCallPoint();
Stock stock = pick.getStock();
endPoint.setStatus(BaseStatus.USED);
pointRepository.save(endPoint);
AgvTask agvTask = new AgvTask(BizStatus.CALL_PICK, stock.getCode(), srcPoint.getCode(), endPoint.getCode(), BizStatus.OPEN, "RACK_MOVE");
agvTaskService.create(agvTask);
agvTaskService.sendAgvTaskHJImpl(agvTask);
}
/**
*
*
@ -680,6 +705,7 @@ public class StockServiceImpl implements StockService {
status = BizStatus.PICKUP;
}
pick.setStatus(status);
pickRepository.save(pick);
}
private void returnFBAgvTask(Point srcPoint, Stock stock, Item item) {
@ -766,7 +792,7 @@ public class StockServiceImpl implements StockService {
*
* @param jsonObject
*/
private void validateAgvResponse(String url, String jsonObject) {
private void validateAgvContainerIn(String url, String jsonObject) {
String resultJson = HttpPostUtil.sendPostReq(url, jsonObject);
if (StringUtils.isEmpty(resultJson)) {
throw new RuntimeException("AGV返回信息:容器入场接口调用失败!");
@ -782,8 +808,24 @@ public class StockServiceImpl implements StockService {
}
}
private boolean isRestrictedArea(String areaName) {
return areaName.equals(AreaNameDic.CPRKQ) || areaName.equals(AreaNameDic.CPRKHCQ) || areaName.equals(AreaNameDic.DXJRKQ);
private void validateAgvContainerOut(String url, String jsonObject) {
String resultJson = HttpPostUtil.sendPostReq(url, jsonObject);
if (StringUtils.isEmpty(resultJson)) {
throw new RuntimeException("AGV返回信息:容器出场接口调用失败!");
}
JSONObject resultObject = JSON.parseObject(resultJson);
if (resultObject == null) {
throw new RuntimeException("AGV返回信息:容器出场接口数据返回为空!");
}
String code = resultObject.getString("code");
String message = resultObject.getString("message");
if (!"0".equals(code)) {
throw new RuntimeException("AGV返回信息:容器出场接口调用失败!" + message);
}
}
private boolean isRestrictedArea(String pointType) {
return BaseStatus.BOX.equals(pointType);
}

View File

@ -17,6 +17,7 @@ package com.youchain.businessdata.domain;
import com.youchain.base.BaseEntity;
import com.youchain.basicdata.domain.Point;
import com.youchain.basicdata.domain.Stock;
import com.youchain.modules.system.domain.Dept;
import lombok.Data;
import cn.hutool.core.bean.BeanUtil;
@ -91,6 +92,11 @@ public class Pick extends BaseEntity implements Serializable {
@ApiModelProperty(value = "单据类型")
private String orderType;
@OneToOne
@JoinColumn(name = "`stock_id`")
@ApiModelProperty(value = "容器")
private Stock stock;
@Column(name = "`source_id`")
@ApiModelProperty(value = "来源ID")
private Long sourceId;

View File

@ -30,10 +30,10 @@ import java.util.List;
**/
public interface PickRepository extends JpaRepository<Pick, Long>, JpaSpecificationExecutor<Pick> {
@Query(value = " FROM Pick p WHERE p.status in :status order by p.createTime,p.lineNo ")
List<Pick> findByPickStatus(List<String> status);
@Query(value = " FROM Pick p WHERE p.status in :status and p.isCall=:isCall order by p.createTime,p.lineNo ")
List<Pick> findByPickStatus(List<String> status,Boolean isCall);
@Query(value = " FROM Pick p WHERE p.code=?1 and p.code=?2 and p.code=?3 ")
@Query(value = " FROM Pick p WHERE p.gdCode=:gdNo and p.cpCodeOrDpCode=:completeCode and p.station=:station ")
Pick findByPick(String gdNo, String completeCode, String station);
@Query(value = " from Pick p WHERE p.gdCode=:gdCode ")

View File

@ -68,7 +68,7 @@ public interface TaskRepository extends JpaRepository<Task, Long>, JpaSpecificat
@Query(value = " FROM Task t WHERE t.pickDetail.pick.id=?1 and t.taskType='PICK' and t.planQty>t.moveQty ")
List<Task> findByNotPickTask(Long pickId);
@Query(value = " select count(t.id) FROM Task t WHERE t.srcStock.code=:stockCode and t.taskType='PICK' and t.taskStatus not in ('FINISH') ")
@Query(value = " select count(t.id) FROM Task t WHERE t.srcStock.code=:stockCode and t.taskType='PICK' and t.taskStatus not in ('FINISH','CANCEL') ")
int existsByStock(String stockCode);
@Query(value = " from Task t WHERE t.taskType='PICK' and t.taskStatus='ARRIVED' and t.srcStock.code=:srcStockCode ")

View File

@ -54,7 +54,7 @@ public class MesController {
pickService.itemCall(orderNo, itemCode, station, pointCode);
return successResponse("叫料成功!");
} catch (Exception e) {
return badResponse("叫料失败!" + e.getMessage());
return badResponse("叫料失败:" + e.getMessage());
}
}

View File

@ -16,6 +16,7 @@
package com.youchain.businessdata.service.dto;
import com.youchain.basicdata.domain.Point;
import com.youchain.basicdata.domain.Stock;
import com.youchain.modules.system.domain.Dept;
import lombok.Data;
@ -86,6 +87,11 @@ public class PickDto implements Serializable {
*/
private String orderType;
/**
*
*/
private Stock stock;
/**
*
*/

View File

@ -23,6 +23,7 @@ import com.youchain.basicdata.domain.Stock;
import com.youchain.basicdata.repository.StockRepository;
import com.youchain.basicdata.service.PointService;
import com.youchain.businessdata.domain.*;
import com.youchain.businessdata.repository.InventoryRepository;
import com.youchain.businessdata.repository.TaskRepository;
import com.youchain.businessdata.service.*;
import com.youchain.modules.quartz.utils.TimeNumberUtils;
@ -61,6 +62,7 @@ public class AgvTaskServiceImpl implements AgvTaskService {
private final TaskRepository taskRepository;
private final InventoryService inventoryService;
private final InventoryLogService inventoryLogService;
private final InventoryRepository inventoryRepository;
private final PointService pointService;
private final AsnDetailService asnDetailService;
private final StockRepository stockRepository;
@ -160,7 +162,11 @@ public class AgvTaskServiceImpl implements AgvTaskService {
Map<String, Object> missionDataMap = new LinkedHashMap<>();
missionDataMap.put("sequence", 1);//序号
missionDataMap.put("position", agvTasks.getStartSlotCode());//点位
missionDataMap.put("nodeType", "NODE_POINT");//
String nodeType = "NODE_POINT";
if (BizStatus.PICK.equals(agvTasks.getType())) {
nodeType = "NODE_SLOT";
}
missionDataMap.put("nodeType", nodeType);//
missionDataMap.put("stackNumber", 0);
missionDataMap.put("actionConfirm", false);
missionDataObj.putAll(missionDataMap);
@ -170,7 +176,11 @@ public class AgvTaskServiceImpl implements AgvTaskService {
Map<String, Object> missionDataMap2 = new LinkedHashMap<>();
missionDataMap2.put("sequence", 2);//序号
missionDataMap2.put("position", agvTasks.getEndSlotCode());//目标点
missionDataMap2.put("nodeType", "NODE_SLOT");//
String nodeType2 = "NODE_SLOT";
if (BizStatus.PICK.equals(agvTasks.getType())) {
nodeType2 = "NODE_POINT";
}
missionDataMap2.put("nodeType", nodeType2);//
missionDataMap2.put("stackNumber", 0);
missionDataMap2.put("actionConfirm", false);
missionDataObj2.putAll(missionDataMap2);
@ -458,12 +468,13 @@ public class AgvTaskServiceImpl implements AgvTaskService {
switch (endAreaName) {
case AreaNameDic.XJQ:
case AreaNameDic.DJQ:
handleXJDJ(agvTask, taskList, stock);//入库
handleXJDJ(agvTask, taskList, stock);//入库完成
break;
case AreaNameDic.FBQ:
case AreaNameDic.XJFBQ:
handleFBQ(taskList, stock, endPoint);//备料完成
break;
case AreaNameDic.JLQ:
// handleJL(taskList, endPoint, stock);//满车出库
handleJL(stock, endPoint);//叫料完成
break;
case AreaNameDic.CPXXQ:
case AreaNameDic.CPRKQ:
@ -604,22 +615,17 @@ public class AgvTaskServiceImpl implements AgvTaskService {
/**
*
*
* @param taskList
* @param stock
*/
private void handleJL(List<Task> taskList, Point endPoint, Stock stock) {
//容器到达叫料线边扣减库存,容器自动出场
for (Task task : taskList) {
try {
taskService.pickConfirm(task.getId(), task.getPlanQty());
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
private void handleJL(Stock stock, Point endPoint) {
List<Inventory> inventoryList = inventoryService.queryInventory(stock);
if (!inventoryList.isEmpty()) {
inventoryService.deleteAll(inventoryList.stream().map(Inventory::getId).toArray(Long[]::new));
}
containerOut(stock.getCode());
endPoint.setStatus(BaseStatus.FREE);
stock.setPoint(endPoint);
stockRepository.save(stock);
endPoint.setStatus(BaseStatus.USED);
pointService.update(endPoint);
}
/**
@ -661,132 +667,17 @@ public class AgvTaskServiceImpl implements AgvTaskService {
throw new RuntimeException(containerCode + "容器不存在! 请维护");
}
switch (endAreaName) {
case AreaNameDic.JLQ:
handleJLCancel(agvTask, containerCode, endPoint);//满车到2F达产线取消
break;
case AreaNameDic.XJQ:
case AreaNameDic.DJQ:
handleFBFCCancel(agvTask, endPoint, stock);//入库取消
break;
}
agvTask.setStatus(BizStatus.CANCEL);
agvTask.setEndTime(new Timestamp(new Date().getTime()));
this.update(agvTask);
}
private void handleFKCancel(AgvTask agvTask, Point endPoint, Stock stock) {
//回空车取消
Point srcPoint = pointService.findByCode(agvTask.getStartSlotCode(), null, null, null, null, null);
//起点点位释放
releasePoint(srcPoint);
stock.setPoint(null);
stock.setStatus(BaseStatus.FREE);
stockRepository.save(stock);
//终点点位释放
releasePoint(endPoint);
}
/**
* 1F线
*/
private void handleFKCCancel(AgvTask agvTask, String containerCode, Point endPoint) {
/*String jsonObject = this.containerQuery(containerCode);
String resultJson = HttpPostUtil.sendPostReq(UrlApi.containerQuery(), jsonObject);
if (StringUtils.isEmpty(resultJson)) {
throw new RuntimeException("AGV返回信息:容器查询接口调用失败!");
}
JSONObject resulObject = JSON.parseObject(resultJson);
if (resulObject == null) {
throw new RuntimeException("AGV返回信息:容器查询接口数据返回为空!");
}
String code = resulObject.getString("code") == null ? "" : resulObject.getString("code");
if (!"0".equals(code)) {
throw new RuntimeException("AGV返回信息:" + resulObject.getString("message"));
}
String data1 = resulObject.getString("data") == null ? "" : resulObject.getString("data");
JSONArray jsonArray = JSON.parseArray(data1);
if (jsonArray.isEmpty()) {
throw new RuntimeException("AGV返回信息:容器查询接口数据格式错误!");
}
JSONObject dataObject = JSON.parseObject(jsonArray.get(0).toString());
if (dataObject == null) {
throw new RuntimeException("AGV返回信息:容器查询接口数据格式错误!");
}
String isCarry = dataObject.getString("isCarry") == null ? "" : dataObject.getString("isCarry");*/
String isCarry = "0";
if (isCarry.equals("0")) {
//容器未移动,容器点位回原点
log.info(agvTask.getId() + "任务" + containerCode + "容器未移动!");
Stock stock = stockRepository.findByCode(containerCode, null);
if (stock != null) {
Point srcPoint = pointService.findByCode(agvTask.getStartSlotCode(), null, null, null, null, null);
stock.setPoint(srcPoint);
stockRepository.save(stock);
}
} else {
//容器已经移动,则人工处理容器出场
}
//线边点位释放
releasePoint(endPoint);
}
private void handleJLCancel(AgvTask agvTask, String containerCode, Point endPoint) {
/*String jsonObject = this.containerQuery(containerCode);
String resultJson = HttpPostUtil.sendPostReq(UrlApi.containerQuery(), jsonObject);
if (StringUtils.isEmpty(resultJson)) {
throw new RuntimeException("AGV返回信息:容器查询接口调用失败!");
}
JSONObject resulObject = JSON.parseObject(resultJson);
if (resulObject == null) {
throw new RuntimeException("AGV返回信息:容器查询接口数据返回为空!");
}
String code = resulObject.getString("code") == null ? "" : resulObject.getString("code");
if (!"0".equals(code)) {
throw new RuntimeException("AGV返回信息:" + resulObject.getString("message"));
}
String data1 = resulObject.getString("data") == null ? "" : resulObject.getString("data");
JSONArray jsonArray = JSON.parseArray(data1);
if (jsonArray.isEmpty()) {
throw new RuntimeException("AGV返回信息:容器查询接口数据格式错误!");
}
JSONObject dataObject = JSON.parseObject(jsonArray.get(0).toString());
if (dataObject == null) {
throw new RuntimeException("AGV返回信息:容器查询接口数据格式错误!");
}
String isCarry = dataObject.getString("isCarry") == null ? "" : dataObject.getString("isCarry");*/
String isCarry = "1";
if (isCarry.equals("0")) {
//容器未移动,则还原库存
Stock stock = stockRepository.findByCode(containerCode, null);
if (stock != null) {
List<Inventory> inventoryList = inventoryService.queryInventory(stock);
for (Inventory inventory : inventoryList) {
inventory.setQueuedQty(0d);
inventoryService.update(inventory);
}
}
log.info(agvTask.getId() + "任务的容器未移动,还原库存信息!");
} else {
//容器已经移动,则直接出库
List<Task> taskList = taskService.getAgvTaskList(agvTask.getId());
for (Task task : taskList) {
try {
taskService.pickConfirm(task.getId(), task.getPlanQty());
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
}
}
//终点点位释放
releasePoint(endPoint);
}
private void handleFBFCCancel(AgvTask agvTask, Point endPoint, Stock stock) {
//回存储区取消任务,不生成库存 入库任务取消即可
List<Task> taskList = taskService.getAgvTaskList(agvTask.getId());

View File

@ -314,7 +314,7 @@ public class PickDetailServiceImpl implements PickDetailService {
//目标库位
Point endPoint = null;
if (pick.getPoint() == null) {
List<Point> pointList = pointRepository.findByCode(null, BaseStatus.FREE, BaseStatus.BOX, AreaNameDic.FBQ, null, null);
List<Point> pointList = pointRepository.findByCode(null, BaseStatus.FREE, BaseStatus.BOX, AreaNameDic.XJFBQ, null, null);
if (pointList.isEmpty()) {
logService.saveLogInfo(pick.getCode(), pick.getCode(), "/pick/allocatePick", "分配失败,翻包区没有空闲点位!", "出库单分配", 200, "info");
throw new IllegalArgumentException(pick.getCode() + "分配失败,翻包区没有空闲点位!");

View File

@ -349,7 +349,7 @@ public class PickServiceImpl implements PickService {
if (agvTaskList.size() > 0) {
agvTask = agvTaskList.get(0);
} else {
agvTask = new AgvTask(BizStatus.PICK, task.getSrcStockCode(), task.getSrcPointCode(), task.getDstPointCode(), BizStatus.OPEN, "");
agvTask = new AgvTask(BizStatus.PICK, task.getSrcStockCode(), task.getSrcPointCode(), task.getDstPointCode(), BizStatus.OPEN, "FORKLIFT_MOVE");
agvTaskRepository.save(agvTask);
}
task.setAgvTask(agvTask);

View File

@ -36,7 +36,7 @@ public class pickTask {
*/
public void allocatePick() {
List<String> statuses = Arrays.asList(BizStatus.OPEN, BizStatus.ASSIGN);
List<Pick> pickList = pickRepository.findByPickStatus(statuses);
List<Pick> pickList = pickRepository.findByPickStatus(statuses,false);
if (pickList.isEmpty()) {
throw new RuntimeException("无待分配的出库单,分配失败!");
} else {
@ -52,7 +52,7 @@ public class pickTask {
public void pickAgvTask() {
/*查询分配完成的出库单*/
List<String> statuses = Arrays.asList(BizStatus.ALLOCATE);
List<Pick> pickList = pickRepository.findByPickStatus(statuses);
List<Pick> pickList = pickRepository.findByPickStatus(statuses,false);
if (pickList.isEmpty()) {
throw new RuntimeException("无已分配的出库单,下发任务失败!");
} else {
@ -69,4 +69,18 @@ public class pickTask {
stockService.cpCallStock();
}
public void callJlTask() {
/*查询拣货完成完成的出库单*/
List<String> statuses = Arrays.asList(BizStatus.PICK_ALL);
List<Pick> pickList = pickRepository.findByPickStatus(statuses,true);
if (pickList.isEmpty()) {
throw new RuntimeException("无拣货完成的出库单,呼叫货架失败!");
} else {
for (Pick pick : pickList) {
stockService.callJlTask(pick);
}
}
}
}

View File

@ -23,14 +23,14 @@ public interface AreaNameDic {
public static String XJQ = "XJQ";
/**
*
*
*/
public static String FBQ = "FBQ";
public static String XJFBQ = "XJFBQ";
/**
*
*
*/
public static String FBCQ = "FBCQ";
public static String XJFBCQ = "XJFBCQ";
/**
*

View File

@ -19,15 +19,15 @@ public class UrlApi {
public static String submitMission(){
return (String)getByKey("submitMission"+"_url");
return (String)getByKey("submitMission_url");
}
public static String containerIn(){
return (String)getByKey("containerIn"+"_url");
return (String)getByKey("containerIn_url");
}
public static String containerOut(){
return (String)getByKey("containerOut"+"_url");
return (String)getByKey("containerOut_url");
}
public static String containerQuery(){