大幅更新,存档

This commit is contained in:
李宇奇 2025-09-21 12:52:56 +08:00
parent 3b53a31cb3
commit 0747c31143
34 changed files with 838 additions and 771 deletions

View File

@ -8,7 +8,7 @@ Content-Type: application/json
{
"taskId": "testOrderId9",
"vehicleNo": "1001"
"vehicleNo": "1002"
}
### 2. 出库订单接口
@ -17,7 +17,7 @@ Content-Type: application/json
{
"taskId": "testOrderId1",
"vehicleNo": "1009"
"vehicleNo": "1002"
}
### 3. 库存查询接口 - 仅按载具查询

View File

@ -7,8 +7,8 @@ POST {{baseUrl}}/wms/task/wcsRequestVehicleIn
Content-Type: application/json
{
"origin": "R1",
"vehicleNo": "1001",
"origin": "CR",
"vehicleNo": "1002",
"codeMessage": "test",
"remark": "载具入库测试"
}
@ -18,7 +18,7 @@ POST {{baseUrl}}/wms/task/sendTaskResult
Content-Type: application/json
{
"taskId": "1754999361391010000",
"taskId": "1756881794848010000",
"taskStatus": 100,
"vehicleNo": "1009",
"destination": "CR",

View File

@ -5,13 +5,13 @@ import com.wms_main.model.dto.request.mywms.OrderOutReq;
import com.wms_main.model.dto.request.mywms.StockReq;
import com.wms_main.model.dto.request.mywms.StockRespGoodsDetail;
import com.wms_main.model.dto.response.mywms.MyWmsResponse;
import com.wms_main.model.dto.response.mywms.OrderResponse;
import com.wms_main.service.controller.IMyWmsControllerService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import org.springframework.web.bind.annotation.GetMapping;
@RestController
@ResponseBody
@ -24,12 +24,12 @@ public class MyWmsController {
private final IMyWmsControllerService myWmsControllerService;
@PostMapping("/orderIn")
public MyWmsResponse<Object> orderIn(@RequestBody OrderInReq request) {
public OrderResponse orderIn(@RequestBody OrderInReq request) {
return myWmsControllerService.orderIn(request);
}
@PostMapping("/orderOut")
public MyWmsResponse<Object> orderOut(@RequestBody OrderOutReq request) {
public OrderResponse orderOut(@RequestBody OrderOutReq request) {
return myWmsControllerService.orderOut(request);
}

View File

@ -0,0 +1,28 @@
package com.wms_main.model.dto.response.mywms;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class OrderResponse {
@JsonProperty("code")
private Integer code;
@JsonProperty("message")
private String message;
public static OrderResponse success() {
return new OrderResponse(0, "success");
}
public static OrderResponse error(String message) {
return new OrderResponse(999, message);
}
}

View File

@ -505,6 +505,7 @@ public class StackerTaskServiceImpl implements IStackerTaskService {
.set(TAppLocation::getVehicleId, "")
.eq(TAppLocation::getLocationId, thisVehicle.getLocationId())
.eq(TAppLocation::getVehicleId, vehicleId));
appCommon.updateWorkingLocations(thisVehicle.getLocationId(), 0);
// 更新载具信息
thisVehicle.setVehicleStatus(WmsVehicleStatusEnums.OUT.getCode());
thisVehicle.setLocationId("");
@ -514,7 +515,6 @@ public class StackerTaskServiceImpl implements IStackerTaskService {
.set(TAppStock::getStockStatus, WmsStockStatusEnums.OUTED.getCode())
.set(TAppStock::getLocationId, "")
.eq(TAppStock::getVehicleId, vehicleId));
appCommon.updateWorkingLocations(thisVehicle.getLocationId(), 0);
agvLockService.releaseAllInboundPortLocks("CR");
// 当前载具的任务列表
List<TAppTask> thisVehicleOutTasks = vehicleIdToTaskMap.get(vehicleId);

View File

@ -5,13 +5,14 @@ import com.wms_main.model.dto.request.mywms.OrderOutReq;
import com.wms_main.model.dto.request.mywms.StockReq;
import com.wms_main.model.dto.request.mywms.StockRespGoodsDetail;
import com.wms_main.model.dto.response.mywms.MyWmsResponse;
import com.wms_main.model.dto.response.mywms.OrderResponse;
import java.util.List;
public interface IMyWmsControllerService {
MyWmsResponse<Object> orderIn(OrderInReq request);
OrderResponse orderIn(OrderInReq request);
MyWmsResponse<Object> orderOut(OrderOutReq request);
OrderResponse orderOut(OrderOutReq request);
MyWmsResponse<List<StockRespGoodsDetail>> stock(StockReq request);

View File

@ -1,9 +1,8 @@
package com.wms_main.service.controller.serviceImpl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.wms_main.app.AppCommon;
import com.wms_main.constant.enums.wms.OrderStatusEnum;
import com.wms_main.constant.enums.wms.WmsLocationOccupyStatusEnums;
import com.wms_main.constant.enums.wms.WmsStockStatusEnums;
import com.wms_main.dao.ITAppLocationService;
import com.wms_main.dao.ITAppOrderInService;
@ -12,6 +11,7 @@ import com.wms_main.dao.ITAppStockService;
import com.wms_main.model.dto.request.mywms.*;
import com.wms_main.model.dto.request.wcs.WcsCanFeedRequest;
import com.wms_main.model.dto.response.mywms.MyWmsResponse;
import com.wms_main.model.dto.response.mywms.OrderResponse;
import com.wms_main.model.dto.response.wcs.WcsApiResponse;
import com.wms_main.model.dto.response.wcs.WcsCanFeedResponse;
import com.wms_main.model.po.TAppLocation;
@ -22,7 +22,6 @@ import com.wms_main.repository.utils.StringUtils;
import com.wms_main.repository.utils.UUIDUtils;
import com.wms_main.service.api.IWcsApiService;
import com.wms_main.service.business.IAgvLockService;
import com.wms_main.service.business.IStackerTaskService;
import com.wms_main.service.controller.IMyWmsControllerService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@ -40,26 +39,30 @@ public class MyWmsControllerServiceImpl implements IMyWmsControllerService {
private final ITAppOrderOutService appOrderOutService;
private final ITAppStockService appStockService;
private final ITAppLocationService appLocationService;
private final IStackerTaskService stackerTaskService;
private final IAgvLockService agvLockService;
private final IWcsApiService wcsApiService;
private final AppCommon appCommon;
private static final String L_TEMP_FLAG = "temp";
@Override
public MyWmsResponse<Object> orderIn(OrderInReq request) {
public OrderResponse orderIn(OrderInReq request) {
try {
if (request == null) return MyWmsResponse.error("参数错误", null);
if (request == null)
return OrderResponse.error("参数错误");
if (!request.isValid()) {
return MyWmsResponse.error("参数错误", null);
return OrderResponse.error("参数错误");
}
// 校验是否存在相同的入库单
List<TAppOrderIn> withTaskId = appOrderInService.getWithTaskId(request.getTaskId());
if (withTaskId == null) {
return MyWmsResponse.error("数据服务异常,请稍后重试", null);
return OrderResponse.error("数据服务异常,请稍后重试");
}
if (!withTaskId.isEmpty()) {
return MyWmsResponse.error("入库单已存在,请勿重复推送", null);
return OrderResponse.error("入库单已存在,请勿重复推送");
}
Boolean isDup = appStockService
.exists(new LambdaQueryWrapper<TAppStock>().eq(TAppStock::getVehicleId, request.getVehicleNo())
.eq(TAppStock::getStockStatus, WmsStockStatusEnums.OK.getCode()));
if (isDup) {
return OrderResponse.error("库存重复,托盘号: " + request.getVehicleNo());
}
TAppOrderIn orderIn = new TAppOrderIn();
orderIn.setRecordId(UUIDUtils.getNewUUID());
@ -71,37 +74,37 @@ public class MyWmsControllerServiceImpl implements IMyWmsControllerService {
orderIn.setCreateTime(LocalDateTime.now());
orderIn.setUpdateTime(LocalDateTime.now());
if (!appOrderInService.save(orderIn)) {
return MyWmsResponse.error("入库单保存失败,请稍后再试", null);
return OrderResponse.error("入库单保存失败,请稍后再试");
}
return MyWmsResponse.success();
return OrderResponse.success();
} catch (Exception e) {
return MyWmsResponse.error("入库单添加异常", null);
return OrderResponse.error("入库单添加异常");
}
}
@Override
public MyWmsResponse<Object> orderOut(OrderOutReq request) {
public OrderResponse orderOut(OrderOutReq request) {
try {
if (request == null || StringUtils.isEmpty(request.getTaskId()) || StringUtils.isEmpty(request.getVehicleNo())) {
return MyWmsResponse.error("参数错误", null);
if (request == null || StringUtils.isEmpty(request.getTaskId())
|| StringUtils.isEmpty(request.getVehicleNo())) {
return OrderResponse.error("参数错误");
}
List<TAppOrderOut> orderOutCheckList = appOrderOutService.getWithTaskId(request.getTaskId());
if (orderOutCheckList == null) {
return MyWmsResponse.error("数据服务异常,请稍后重试", null);
return OrderResponse.error("数据服务异常,请稍后重试");
}
if (!orderOutCheckList.isEmpty()) {
return MyWmsResponse.error("出库单已存在,请勿重复推送", null);
return OrderResponse.error("出库单已存在,请勿重复推送");
}
List<TAppStock> vehicleStocks = appStockService.list(
new LambdaQueryWrapper<TAppStock>()
.eq(TAppStock::getVehicleId, request.getVehicleNo())
.eq(TAppStock::getStockStatus, WmsStockStatusEnums.OK.getCode())
);
.eq(TAppStock::getStockStatus, WmsStockStatusEnums.OK.getCode()));
if (vehicleStocks == null || vehicleStocks.isEmpty()) {
return MyWmsResponse.error("载具号" + request.getVehicleNo() + "无库存记录", null);
return OrderResponse.error("载具号" + request.getVehicleNo() + "无库存记录");
}
TAppOrderOut orderOut = new TAppOrderOut();
@ -113,18 +116,19 @@ public class MyWmsControllerServiceImpl implements IMyWmsControllerService {
orderOut.setUpdateTime(LocalDateTime.now());
if (!appOrderOutService.save(orderOut)) {
return MyWmsResponse.error("出库单保存失败,请稍后再试", null);
return OrderResponse.error("出库单保存失败,请稍后再试");
}
return MyWmsResponse.success();
return OrderResponse.success();
} catch (Exception e) {
log.error("出库任务添加失败", e);
return MyWmsResponse.error("出库任务添加失败,请稍后再试", null);
return OrderResponse.error("出库任务添加失败,请稍后再试");
}
}
@Override
public MyWmsResponse<List<StockRespGoodsDetail>> stock(StockReq request) {
if (request == null || request.empty()) return MyWmsResponse.error("参数错误", null);
if (request == null || request.empty())
return MyWmsResponse.error("参数错误", null);
List<TAppStock> stocks = new ArrayList<>();
Map<String, TAppStock> vehicleStockMap = new HashMap<>();
if (request.getDetails() == null || request.getDetails().isEmpty()) {
@ -133,9 +137,10 @@ public class MyWmsControllerServiceImpl implements IMyWmsControllerService {
for (StockReqGoodsDetail stockReqGoodsDetail : request.getDetails()) {
List<TAppStock> stockList = appStockService.list(
new LambdaQueryWrapper<TAppStock>()
.eq(StringUtils.isNotEmpty(stockReqGoodsDetail.getVehicleNo()), TAppStock::getVehicleId, stockReqGoodsDetail.getVehicleNo())
.eq(StringUtils.isNotEmpty(stockReqGoodsDetail.getLocationId()), TAppStock::getLocationId, stockReqGoodsDetail.getLocationId())
);
.eq(StringUtils.isNotEmpty(stockReqGoodsDetail.getVehicleNo()), TAppStock::getVehicleId,
stockReqGoodsDetail.getVehicleNo())
.eq(StringUtils.isNotEmpty(stockReqGoodsDetail.getLocationId()),
TAppStock::getLocationId, stockReqGoodsDetail.getLocationId()));
if (stockList != null && !stockList.isEmpty()) {
for (TAppStock stock : stockList) {
if (!vehicleStockMap.containsKey(stock.getVehicleId())) {
@ -165,16 +170,10 @@ public class MyWmsControllerServiceImpl implements IMyWmsControllerService {
public MyWmsResponse<Boolean> queryCanFeed() {
try {
// 1. 检查库位是否足够
TAppLocation location = stackerTaskService.requestOneLocation(null, L_TEMP_FLAG);
if (location == null || StringUtils.isEmpty(location.getLocationId())) {
if (!appLocationService.exists(new LambdaQueryWrapper<TAppLocation>().eq(TAppLocation::getIsOccupy,
WmsLocationOccupyStatusEnums.EMPTY.getCode()))) {
return MyWmsResponse.error("无剩余可用库位", false);
}
// 释放预占的库位
appLocationService.update(new LambdaUpdateWrapper<TAppLocation>()
.eq(TAppLocation::getLocationId, location.getLocationId())
.set(TAppLocation::getIsOccupy, 0)
.set(TAppLocation::getVehicleId, ""));
appCommon.updateWorkingLocations(location.getLocationId(), 0);
// 2. 调用wcs.canFeed检查wcs状态
WcsApiResponse<WcsCanFeedResponse> wcsResponse = wcsApiService.canFeed(new WcsCanFeedRequest("CR"));

View File

@ -6,7 +6,6 @@ import com.wms_main.constant.enums.wcs.WcsApiResponseCodeEnums;
import com.wms_main.constant.enums.wcs.WcsStackerTaskStatusEnums;
import com.wms_main.constant.enums.wcs.WcsStackerTaskTypeEnums;
import com.wms_main.constant.enums.wms.WmsStackerTaskStatusEnums;
import com.wms_main.constant.enums.wms.WmsTaskTypeEnums;
import com.wms_main.dao.ITAppTaskService;
import com.wms_main.dao.ITAppWcsTaskService;
import com.wms_main.model.bo.wcs.WcsStackerTask;

View File

@ -0,0 +1,117 @@
/*
* Copyright 2007-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.net.*;
import java.io.*;
import java.nio.channels.*;
import java.util.Properties;
public class MavenWrapperDownloader {
private static final String WRAPPER_VERSION = "0.5.6";
/**
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
*/
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
/**
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
* use instead of the default one.
*/
private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
".mvn/wrapper/maven-wrapper.properties";
/**
* Path where the maven-wrapper.jar will be saved to.
*/
private static final String MAVEN_WRAPPER_JAR_PATH =
".mvn/wrapper/maven-wrapper.jar";
/**
* Name of the property which should be used to override the default download url for the wrapper.
*/
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
public static void main(String args[]) {
System.out.println("- Downloader started");
File baseDirectory = new File(args[0]);
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
// If the maven-wrapper.properties exists, read it and check if it contains a custom
// wrapperUrl parameter.
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
String url = DEFAULT_DOWNLOAD_URL;
if(mavenWrapperPropertyFile.exists()) {
FileInputStream mavenWrapperPropertyFileInputStream = null;
try {
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
Properties mavenWrapperProperties = new Properties();
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
} catch (IOException e) {
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
} finally {
try {
if(mavenWrapperPropertyFileInputStream != null) {
mavenWrapperPropertyFileInputStream.close();
}
} catch (IOException e) {
// Ignore ...
}
}
}
System.out.println("- Downloading from: " + url);
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
if(!outputFile.getParentFile().exists()) {
if(!outputFile.getParentFile().mkdirs()) {
System.out.println(
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
}
}
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
try {
downloadFileFromURL(url, outputFile);
System.out.println("Done");
System.exit(0);
} catch (Throwable e) {
System.out.println("- Error downloading");
e.printStackTrace();
System.exit(1);
}
}
private static void downloadFileFromURL(String urlString, File destination) throws Exception {
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
String username = System.getenv("MVNW_USERNAME");
char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
}
URL website = new URL(urlString);
ReadableByteChannel rbc;
rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream(destination);
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
fos.close();
rbc.close();
}
}

View File

@ -0,0 +1,18 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.6/apache-maven-3.8.6-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar

View File

@ -7,8 +7,8 @@ POST {{baseUrl}}/mywms/orderIn
Content-Type: application/json
{
"taskId": "testOrderId2",
"vehicleNo": "1006"
"taskId": "testOrderId1",
"vehicleNo": "1003"
}
### 2. 出库订单接口
@ -17,40 +17,42 @@ Content-Type: application/json
{
"taskId": "testOrderId3",
"vehicleNo": "1007"
"vehicleNo": "1001"
}
### 3. 库存查询接口 - 仅按载具查询
POST {{baseUrl}}/mywms/stock
### 3. 发送任务结果 - 任务完成
POST {{baseUrl}}/wms/task/sendTaskResult
Content-Type: application/json
{
"requestId": "testOrderId1",
"details": [
{
"vehicleNo": "1005"
}
]
"taskId": "1757666162511010000",
"taskStatus": 100,
"vehicleNo": "1007",
"destination": "C1",
"message": "任务执行成功"
}
### 4. 库存查询接口 - 仅按库位查询
POST {{baseUrl}}/mywms/stock
### 4. 检查是否允许投料
POST {{baseUrl}}/mywms/agvNotify
Content-Type: application/json
{
"requestId": "testOrderId2",
"details": [
{
"locationId": "A01-01-01-02"
"standType": 1
}
]
}
### 5. 检查是否允许投料
GET {{baseUrl}}/mywms/allowFeed
### 5. 检查是否允许出库
GET {{baseUrl}}/mywms/allowOut
POST {{baseUrl}}/mywms/agvDone
### 6. 检查是否允许出库
GET {{baseUrl}}/mywms/test
### 7. 取消任务
POST {{baseUrl}}/mywms/cancelOrderIn
Content-Type: application/json
{
"vehicleNo": "1003"
}
### 测试数据说明
# 1. orderIn: 入库订单接口需要taskId和vehicleNo

View File

@ -1,60 +0,0 @@
### TaskController接口测试 - WMS任务控制接口
### 基础配置
@baseUrl = http://localhost:12315
### 1. WCS请求载具入库
POST {{baseUrl}}/wms/task/wcsRequestVehicleIn
Content-Type: application/json
{
"origin": "R1",
"vehicleNo": "1006",
"codeMessage": "test",
"remark": "载具入库测试"
}
### 2. 发送任务结果 - 任务完成
POST {{baseUrl}}/wms/task/sendTaskResult
Content-Type: application/json
{
"taskId": "1754997816795010000",
"taskStatus": 100,
"vehicleNo": "1007",
"destination": "C1",
"message": "任务执行成功"
}
### 测试数据说明
# 1. wcsRequestVehicleIn: WCS请求载具入库
# - origin: 点位(必填)
# - vehicleNo: 载具信息(必填)
# - codeMessage: 条码信息(可选)
# - remark: 备注(可选)
# 2. sendTaskResult: WCS反馈任务执行结果
# - taskId: 任务ID必填
# - taskStatus: 任务状态(必填)
# * 0: 等待执行
# * 1: 执行中
# * 2: 执行完成
# * 3: 执行失败
# - vehicleNo: 载具号(必填)
# - destination: 终点(可选)
# - message: 信息(可选)
### 响应格式说明
# wcsRequestVehicleIn返回WcsVehicleInResponse:
# {
# "success": true,
# "code": "SUCCESS",
# "message": "请求成功",
# "data": {}
# }
# sendTaskResult返回BaseWcsApiResponse:
# {
# "success": true,
# "code": "SUCCESS",
# "message": "任务结果接收成功"
# }

View File

@ -141,7 +141,7 @@
</dependencies>
<build>
<finalName>wms-box-server</finalName>
<finalName>wms-tp-server</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>

View File

@ -12,8 +12,6 @@ public enum AppConfigKeyEnums {
WCS_STACKER_TASK_URL("WcsStackerTaskUrl", "发送堆垛机任务地址"),
WCS_PICK_TASK_URL("WcsPickTaskUrl", "发送拣选任务地址"),
WCS_CANCEL_PICK_TASK_URL("WcsCancelPickTaskUrl", "发送取消拣选任务地址"),
WCS_CAN_FEED_URL("wcsCanFeedUrl", "查询wcs是否可上料"),
WCS_CAN_OUT_URL("wcsCanOutUrl", "wcsCanOutUrl"),
WCS_RELEASE_BOX_URL("WcsReleaseBoxUrl", "发送释放站台箱子地址"),
STAND_CAPACITY("StandCapacity", "站台容量"),
IMAGE_IP("ImageIp", "图片存放ip"),
@ -22,8 +20,9 @@ public enum AppConfigKeyEnums {
MES_GET_GOODS_URL("MesGetGoodsUrl", "获取物料信息地址"),
ERP_GET_VEHICLENO_DATA("ErpGetVehicleNoData", "根据托盘号查询简单生产入库单"),
WMS_ORDER_IN_CALLBACK("WmsOrderInCallback", "WMS接受的入库执行后回调地址"),
WMS_ORDER_OUT_CALLBACK("WmsOrderOutCallback", "WMS接受的出库执行后回调地址");
WMS_ORDER_OUT_CALLBACK("WmsOrderOutCallback", "WMS接受的出库执行后回调地址"),
WCS_QUERY_STAND_STATUS_URL("wcsQueryStandStatus", "查询AGV是否可取货"),
WCS_AGV_DONE("wcsAGVDone", "AGV取货完成通知");
private final String key;
private final String desc;

View File

@ -1,16 +1,22 @@
package com.wms_main.controller.mywms;
import com.wms_main.model.dto.request.mywms.OrderInCancel;
import com.wms_main.model.dto.request.mywms.OrderInReq;
import com.wms_main.model.dto.request.mywms.OrderOutReq;
import com.wms_main.model.dto.request.mywms.QueryStandStatusReq;
import com.wms_main.model.dto.request.mywms.StockReq;
import com.wms_main.model.dto.request.mywms.StockRespGoodsDetail;
import com.wms_main.model.dto.response.mywms.MyWmsResponse;
import com.wms_main.model.dto.response.mywms.OrderResponse;
import com.wms_main.service.controller.IMyWmsControllerService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.GetMapping;
@RestController
@ResponseBody
@ -23,12 +29,12 @@ public class MyWmsController {
private final IMyWmsControllerService myWmsControllerService;
@PostMapping("/orderIn")
public MyWmsResponse<Object> orderIn(@RequestBody OrderInReq request) {
public OrderResponse orderIn(@RequestBody OrderInReq request) {
return myWmsControllerService.orderIn(request);
}
@PostMapping("/orderOut")
public MyWmsResponse<Object> orderOut(@RequestBody OrderOutReq request) {
public OrderResponse orderOut(@RequestBody OrderOutReq request) {
return myWmsControllerService.orderOut(request);
}
@ -37,13 +43,24 @@ public class MyWmsController {
return myWmsControllerService.stock(request);
}
@GetMapping("/allowFeed")
public MyWmsResponse<Boolean> canFeed() {
return myWmsControllerService.queryCanFeed();
@PostMapping("/agvNotify")
public MyWmsResponse<Boolean> agvNotify(@RequestBody QueryStandStatusReq request) {
return myWmsControllerService.queryStandStatus(request);
}
@GetMapping("/allowOut")
public MyWmsResponse<Boolean> canOut() {
return myWmsControllerService.queryCanOut();
@PostMapping("/agvDone")
public MyWmsResponse<Object> agvDone() {
return myWmsControllerService.agvDone();
}
@PostMapping("/cancelOrderIn")
public String cancelOrderIn(@RequestBody OrderInCancel request) {
return myWmsControllerService.cancelOrderIn(request);
}
@GetMapping("/test")
public String test() {
return "success";
}
}

View File

@ -0,0 +1,15 @@
package com.wms_main.model.dto.request.mywms;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Data
public class OrderInCancel {
@JsonProperty("vehicleNo")
private String vehicleNo;
}

View File

@ -0,0 +1,11 @@
package com.wms_main.model.dto.request.mywms;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class QueryStandStatusReq {
@JsonProperty("standType")
private Integer standType;
}

View File

@ -1,13 +1,16 @@
package com.wms_main.model.dto.request.wcs;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class WcsCanFeedRequest {
public class WcsQueryStandStatusRequest {
/**
* 入库口编号默认为单一入库口
*/
private String inboundPort;
@JsonProperty("standType")
private Integer standType;
}

View File

@ -17,7 +17,10 @@ public class MesApiResponse {
@JsonProperty("message")
private String message;
@JsonProperty("data")
private Boolean data;
public static MesApiResponse error(String msg) {
return new MesApiResponse(999, msg);
return new MesApiResponse(999, msg, false);
}
}

View File

@ -0,0 +1,28 @@
package com.wms_main.model.dto.response.mywms;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class OrderResponse {
@JsonProperty("code")
private Integer code;
@JsonProperty("message")
private String message;
public static OrderResponse success() {
return new OrderResponse(0, "success");
}
public static OrderResponse error(String message) {
return new OrderResponse(999, message);
}
}

View File

@ -29,6 +29,7 @@ public class HttpClient {
/**
* 发送一个 Get 请求
*
* @param request 请求数据
* @return 响应数据
*/
@ -87,9 +88,9 @@ public class HttpClient {
}
}
/**
* 发送一个 Post 请求
*
* @param request 请求数据
* @return 响应数据
*/
@ -113,11 +114,12 @@ public class HttpClient {
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
HttpPost postRequest = new HttpPost(url);
postRequest.setHeader("Content-Type", request.getContentType());
postRequest.setHeader("Authorization", request.getToken());
postRequest.setHeader("Expect", "100-continue");
// postRequest.setHeader("Authorization", request.getToken());
// 设置请求头
for(Map.Entry<String, String> entry : request.getHeader().entrySet()){
postRequest.setHeader(entry.getKey(), entry.getValue());
}
// for(Map.Entry<String, String> entry : request.getHeader().entrySet()){
// postRequest.setHeader(entry.getKey(), entry.getValue());
// }
postRequest.setEntity(new StringEntity(request.getData()));
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(request.getTimeout())
@ -153,6 +155,7 @@ public class HttpClient {
/**
* 发送一个 delete 请求
*
* @param request 请求数据
* @return 响应数据
*/

View File

@ -2,8 +2,8 @@ package com.wms_main.service.api;
import com.wms_main.model.bo.wcs.WcsPickTask;
import com.wms_main.model.bo.wcs.WcsStackerTask;
import com.wms_main.model.dto.request.wcs.WcsCanFeedRequest;
import com.wms_main.model.dto.request.wcs.WcsPickTaskRequest;
import com.wms_main.model.dto.request.wcs.WcsQueryStandStatusRequest;
import com.wms_main.model.dto.request.wcs.WcsReleaseBoxRequest;
import com.wms_main.model.dto.request.wcs.WcsStackerTaskRequest;
import com.wms_main.model.dto.response.wcs.BaseWcsApiResponse;
@ -47,7 +47,7 @@ public interface IWcsApiService {
* @param request 查询请求信息
* @return 查询结果
*/
WcsApiResponse<WcsCanFeedResponse> canFeed(WcsCanFeedRequest request);
WcsApiResponse<WcsCanFeedResponse> queryStandStatus(WcsQueryStandStatusRequest request);
WcsApiResponse<WcsCanFeedResponse> canOut(WcsCanFeedRequest request);
BaseWcsApiResponse agvDone();
}

View File

@ -4,8 +4,8 @@ import com.wms_main.app.AppCommon;
import com.wms_main.constant.enums.wms.AppConfigKeyEnums;
import com.wms_main.model.bo.wcs.WcsPickTask;
import com.wms_main.model.bo.wcs.WcsStackerTask;
import com.wms_main.model.dto.request.wcs.WcsCanFeedRequest;
import com.wms_main.model.dto.request.wcs.WcsPickTaskRequest;
import com.wms_main.model.dto.request.wcs.WcsQueryStandStatusRequest;
import com.wms_main.model.dto.request.wcs.WcsReleaseBoxRequest;
import com.wms_main.model.dto.request.wcs.WcsStackerTaskRequest;
import com.wms_main.model.dto.response.wcs.BaseWcsApiResponse;
@ -19,8 +19,6 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
/**
* Wcs接口服务实现
*/
@ -33,32 +31,36 @@ public class WcsApiServiceImpl implements IWcsApiService {
/**
* 发送堆垛机任务
*
* @param request 任务请求
* @return 响应结果
*/
@Override
public WcsApiResponse<WcsStackerTask> sendWcsStackerTask(WcsStackerTaskRequest request) {
// 设置http请求
HttpRequest httpRequest = HttpRequest.postInstanceOf(appCommon.getConfigByKey(AppConfigKeyEnums.WCS_STACKER_TASK_URL.getKey()), request);
// HttpResponse httpResponse = httpClient.httpPost(httpRequest);
// if (httpResponse != null && httpResponse.isSuccess()) {
// WcsApiResponse<WcsStackerTask> response = new WcsApiResponse<>();
// response = httpResponse.getData(response.getClass().asSubclass(WcsApiResponse.class));
// return response;
// }
// TODO success -> error
return WcsApiResponse.success("请求未获得响应信息。", null);
HttpRequest httpRequest = HttpRequest
.postInstanceOf(appCommon.getConfigByKey(AppConfigKeyEnums.WCS_STACKER_TASK_URL.getKey()), request);
HttpResponse httpResponse = httpClient.httpPost(httpRequest);
if (httpResponse != null && httpResponse.isSuccess()) {
WcsApiResponse<WcsStackerTask> response = new WcsApiResponse<>();
response = httpResponse.getData(response.getClass().asSubclass(WcsApiResponse.class));
return response;
}
return WcsApiResponse.error("请求未获得响应信息。", null);
// return WcsApiResponse.success("请求未获得响应信息。", null);
}
/**
* 发送拣选任务
*
* @param request 任务请求
* @return 响应结果
*/
@Override
public WcsApiResponse<WcsPickTask> sendPickTask(WcsPickTaskRequest request) {
// 设置http请求
HttpRequest httpRequest = HttpRequest.postInstanceOf(appCommon.getConfigByKey(AppConfigKeyEnums.WCS_PICK_TASK_URL.getKey()), request);
HttpRequest httpRequest = HttpRequest
.postInstanceOf(appCommon.getConfigByKey(AppConfigKeyEnums.WCS_PICK_TASK_URL.getKey()), request);
HttpResponse httpResponse = httpClient.httpPost(httpRequest);
if (httpResponse != null && httpResponse.isSuccess()) {
WcsApiResponse<WcsPickTask> response = new WcsApiResponse<>();
@ -70,13 +72,15 @@ public class WcsApiServiceImpl implements IWcsApiService {
/**
* 发送释放载具请求
*
* @param request 释放请求信息
* @return 响应结果
*/
@Override
public BaseWcsApiResponse releaseBox(WcsReleaseBoxRequest request) {
// 设置http请求
HttpRequest httpRequest = HttpRequest.postInstanceOf(appCommon.getConfigByKey(AppConfigKeyEnums.WCS_RELEASE_BOX_URL.getKey()), request);
HttpRequest httpRequest = HttpRequest
.postInstanceOf(appCommon.getConfigByKey(AppConfigKeyEnums.WCS_RELEASE_BOX_URL.getKey()), request);
HttpResponse httpResponse = httpClient.httpPost(httpRequest);
if (httpResponse != null && httpResponse.isSuccess()) {
return httpResponse.getData(BaseWcsApiResponse.class);
@ -86,13 +90,15 @@ public class WcsApiServiceImpl implements IWcsApiService {
/**
* 取消拣选任务请求
*
* @param request 取消请求信息
* @return 响应结果
*/
@Override
public WcsApiResponse<WcsPickTask> cancelPickTask(WcsPickTaskRequest request) {
// 设置http请求
HttpRequest httpRequest = HttpRequest.postInstanceOf(appCommon.getConfigByKey(AppConfigKeyEnums.WCS_CANCEL_PICK_TASK_URL.getKey()), request);
HttpRequest httpRequest = HttpRequest
.postInstanceOf(appCommon.getConfigByKey(AppConfigKeyEnums.WCS_CANCEL_PICK_TASK_URL.getKey()), request);
HttpResponse httpResponse = httpClient.httpPost(httpRequest);
if (httpResponse != null && httpResponse.isSuccess()) {
WcsApiResponse<WcsPickTask> response = new WcsApiResponse<>();
@ -104,47 +110,39 @@ public class WcsApiServiceImpl implements IWcsApiService {
/**
* 查询WCS系统是否可上料
*
* @param request 查询请求信息
* @return 查询结果
*/
@Override
public WcsApiResponse<WcsCanFeedResponse> canFeed(WcsCanFeedRequest request) {
HttpRequest httpRequest = HttpRequest.postInstanceOf(appCommon.getConfigByKey(AppConfigKeyEnums.WCS_CAN_FEED_URL.getKey()), request);
// HttpResponse httpResponse = httpClient.httpPost(httpRequest);
// if (httpResponse != null && httpResponse.isSuccess()) {
// WcsApiResponse<WcsCanFeedResponse> response = new WcsApiResponse<>();
// response = httpResponse.getData(response.getClass().asSubclass(WcsApiResponse.class));
// return response;
// }
// TODO error -> success
// return WcsApiResponse.error("请求未获得响应信息。", null);
WcsCanFeedResponse wcsCanFeedResponse = new WcsCanFeedResponse();
wcsCanFeedResponse.setResponseTime(LocalDateTime.now());
wcsCanFeedResponse.setMsg("success");
wcsCanFeedResponse.setAllowAction(true);
return WcsApiResponse.success("成功", wcsCanFeedResponse);
public WcsApiResponse<WcsCanFeedResponse> queryStandStatus(WcsQueryStandStatusRequest request) {
HttpRequest httpRequest = HttpRequest.postInstanceOf(
appCommon.getConfigByKey(AppConfigKeyEnums.WCS_QUERY_STAND_STATUS_URL.getKey()), request);
HttpResponse httpResponse = httpClient.httpPost(httpRequest);
if (httpResponse != null && httpResponse.isSuccess()) {
WcsApiResponse<WcsCanFeedResponse> response = new WcsApiResponse<>();
response = httpResponse.getData(response.getClass().asSubclass(WcsApiResponse.class));
return response;
}
return WcsApiResponse.error("请求未获得响应信息。", null);
// WcsCanFeedResponse wcsCanFeedResponse = new WcsCanFeedResponse();
// wcsCanFeedResponse.setResponseTime(LocalDateTime.now());
// wcsCanFeedResponse.setMsg("success");
// wcsCanFeedResponse.setAllowAction(true);
// return WcsApiResponse.success("成功", wcsCanFeedResponse);
}
/**
* 查询WCS系统是否可出库
* @param request 查询请求信息
* @return 查询结果
*/
@Override
public WcsApiResponse<WcsCanFeedResponse> canOut(WcsCanFeedRequest request) {
HttpRequest httpRequest = HttpRequest.postInstanceOf(appCommon.getConfigByKey(AppConfigKeyEnums.WCS_CAN_OUT_URL.getKey()), request);
// HttpResponse httpResponse = httpClient.httpPost(httpRequest);
// if (httpResponse != null && httpResponse.isSuccess()) {
// WcsApiResponse<WcsCanFeedResponse> response = new WcsApiResponse<>();
// response = httpResponse.getData(response.getClass().asSubclass(WcsApiResponse.class));
// return response;
// }
// TODO error -> success
// return WcsApiResponse.error("请求未获得响应信息。", null);
WcsCanFeedResponse wcsCanFeedResponse = new WcsCanFeedResponse();
wcsCanFeedResponse.setResponseTime(LocalDateTime.now());
wcsCanFeedResponse.setMsg("success");
wcsCanFeedResponse.setAllowAction(true);
return WcsApiResponse.success("成功", wcsCanFeedResponse);
public BaseWcsApiResponse agvDone() {
HttpRequest httpRequest = HttpRequest.postInstanceOf(
appCommon.getConfigByKey(AppConfigKeyEnums.WCS_AGV_DONE.getKey()), null);
HttpResponse httpResponse = httpClient.httpPost(httpRequest);
if (httpResponse != null && httpResponse.isSuccess()) {
BaseWcsApiResponse response = new BaseWcsApiResponse();
response = httpResponse.getData(response.getClass().asSubclass(BaseWcsApiResponse.class));
return response;
}
return BaseWcsApiResponse.error("请求未获得响应信息。");
// return WcsApiResponse.success("成功", true);
}
}

View File

@ -9,6 +9,7 @@ import com.wms_main.constant.enums.wms.*;
import com.wms_main.dao.*;
import com.wms_main.model.dto.request.mywms.OrderInCBReq;
import com.wms_main.model.dto.request.mywms.OrderOutCBReq;
import com.wms_main.model.dto.response.mes.MesApiResponse;
import com.wms_main.model.po.*;
import com.wms_main.repository.utils.ConvertUtils;
import com.wms_main.repository.utils.StringUtils;
@ -25,7 +26,6 @@ import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
/**
* 服务实现
*/
@ -92,9 +92,9 @@ public class StackerTaskServiceImpl implements IStackerTaskService {
.set(TAppTask::getWcsTaskId, wcsTask.getWcsTaskId())
.set(TAppTask::getTaskStatus, WmsStackerTaskStatusEnums.EXECUTED.getCode())
.eq(TAppTask::getVehicleId, wcsTask.getVehicleId())
.eq(TAppTask::getTaskType, ConvertUtils.convertStackerTaskTypeFromWcsToWms(wcsTask.getWcsTaskType()))
.eq(TAppTask::getTaskStatus, WmsStackerTaskStatusEnums.WAIT.getCode())
);
.eq(TAppTask::getTaskType,
ConvertUtils.convertStackerTaskTypeFromWcsToWms(wcsTask.getWcsTaskType()))
.eq(TAppTask::getTaskStatus, WmsStackerTaskStatusEnums.WAIT.getCode()));
}
/**
@ -150,14 +150,17 @@ public class StackerTaskServiceImpl implements IStackerTaskService {
// 判断是否输入了subArea
if (locationFilter != null && StringUtils.isNotEmpty(locationFilter.getSubArea())) {
// 对candidateLocationList进行排序
List<TAppLocation> firstList = candidateLocationList.stream().filter(item -> item.getSubArea().equals(locationFilter.getSubArea())).toList();
List<TAppLocation> lastList = candidateLocationList.stream().filter(item -> !item.getSubArea().equals(locationFilter.getSubArea())).toList();
List<TAppLocation> firstList = candidateLocationList.stream()
.filter(item -> item.getSubArea().equals(locationFilter.getSubArea())).toList();
List<TAppLocation> lastList = candidateLocationList.stream()
.filter(item -> !item.getSubArea().equals(locationFilter.getSubArea())).toList();
candidateLocationList = new ArrayList<>(firstList);// 先添加符合subArea的库位
candidateLocationList.addAll(lastList);// 再添加不符合subArea的库位
}
// 找一个空闲的库位
for (TAppLocation candidateLocation : candidateLocationList) {
if (candidateLocation.getIsWorking() == 1 || candidateLocation.getIsLock() == 1 || candidateLocation.getIsOccupy() == 1) {
if (candidateLocation.getIsWorking() == 1 || candidateLocation.getIsLock() == 1
|| candidateLocation.getIsOccupy() == 1) {
continue;
}
if (isMaxDepthAvailable(locationList, candidateLocation)) {
@ -167,8 +170,7 @@ public class StackerTaskServiceImpl implements IStackerTaskService {
.set(TAppLocation::getIsOccupy, 1)
.set(TAppLocation::getVehicleId, requestVehicleId)
.eq(TAppLocation::getLocationId, candidateLocation.getLocationId())
.eq(TAppLocation::getIsOccupy, 0)
)) {
.eq(TAppLocation::getIsOccupy, 0))) {
// 当前库位可用
targetLocation = candidateLocation;
break;
@ -193,14 +195,17 @@ public class StackerTaskServiceImpl implements IStackerTaskService {
/**
* 获取一个堆垛机库的空库位
*
* @param equipmentId 设备号
* @return 返回的库位信息
*/
@Override
public TAppLocation getEmptyLocation(Integer equipmentId, WmsLocationTypeEnums type) {
if(equipmentId == null) return null;
if (equipmentId == null)
return null;
List<TAppLocation> allLocations = appLocationService.getAllLocation(equipmentId);
if(allLocations == null || allLocations.isEmpty()) return null;
if (allLocations == null || allLocations.isEmpty())
return null;
for (TAppLocation location : allLocations) {
if (location.getIsOccupy() != 0 || location.getIsLock() != 0 || location.getIsWorking() != 0) {
continue; // 不可用货位
@ -214,9 +219,12 @@ public class StackerTaskServiceImpl implements IStackerTaskService {
boolean canUse = true;
for (int i = lDepth - 1; i > 0; i--) {
int checkDepth = i;
List<TAppLocation> sameColLocations = allLocations.stream().filter(item ->
item.getLRow().equals(location.getLRow()) && item.getLCol().equals(location.getLCol())
&& item.getLLayer().equals(location.getLLayer()) && item.getLDepth().equals(checkDepth)).toList();
List<TAppLocation> sameColLocations = allLocations.stream()
.filter(item -> item.getLRow().equals(location.getLRow())
&& item.getLCol().equals(location.getLCol())
&& item.getLLayer().equals(location.getLLayer())
&& item.getLDepth().equals(checkDepth))
.toList();
if (sameColLocations.isEmpty()) {
continue; // 库位不存在可能
}
@ -273,11 +281,12 @@ public class StackerTaskServiceImpl implements IStackerTaskService {
return false;
}
// 查询到排列层对应的库位列表
List<TAppLocation> diffDepthLocationList = appLocationList.stream().filter(item ->
Objects.equals(item.getLRow(), appLocation.getLRow()) &&
List<TAppLocation> diffDepthLocationList = appLocationList.stream()
.filter(item -> Objects.equals(item.getLRow(), appLocation.getLRow()) &&
Objects.equals(item.getLCol(), appLocation.getLCol()) &&
Objects.equals(item.getLLayer(), appLocation.getLLayer()) &&
!Objects.equals(item.getLDepth(), appLocation.getLDepth())).toList();
!Objects.equals(item.getLDepth(), appLocation.getLDepth()))
.toList();
// 结果
boolean result = true;
for (TAppLocation diffDepthLocation : diffDepthLocationList) {
@ -324,20 +333,24 @@ public class StackerTaskServiceImpl implements IStackerTaskService {
// 查找到所有的入库任务列表---非暂存和完成状态
List<TAppTask> inTasks = appTaskService.list(new LambdaQueryWrapper<TAppTask>()
.eq(TAppTask::getTaskType, WmsTaskTypeEnums.IN.getCode())
.notIn(TAppTask::getTaskStatus, WmsStackerTaskStatusEnums.FINISH.getCode(), WmsStackerTaskStatusEnums.TEMP.getCode()));
.notIn(TAppTask::getTaskStatus, WmsStackerTaskStatusEnums.FINISH.getCode(),
WmsStackerTaskStatusEnums.TEMP.getCode()));
if (inTasks == null || inTasks.isEmpty()) {
for (TAppLocation appLocation : emptyLocationList) {
if (equipCountMap.containsKey(appLocation.getEquipmentId())) {
equipCountMap.replace(appLocation.getEquipmentId(), equipCountMap.get(appLocation.getEquipmentId()) + 1);
equipCountMap.replace(appLocation.getEquipmentId(),
equipCountMap.get(appLocation.getEquipmentId()) + 1);
}
}
} else {
for (TAppTask inTask : inTasks) {
if (StringUtils.isNotEmpty(inTask.getDestination())) {
// 当前目标库位的设备号
TAppLocation destinationEquipmentId = appCommon.getInstantLocationByLocationId(inTask.getDestination());
TAppLocation destinationEquipmentId = appCommon
.getInstantLocationByLocationId(inTask.getDestination());
if (equipCountMap.containsKey(destinationEquipmentId.getEquipmentId())) {
equipCountMap.replace(destinationEquipmentId.getEquipmentId(), equipCountMap.get(destinationEquipmentId.getEquipmentId()) + 1);
equipCountMap.replace(destinationEquipmentId.getEquipmentId(),
equipCountMap.get(destinationEquipmentId.getEquipmentId()) + 1);
}
}
}
@ -352,7 +365,6 @@ public class StackerTaskServiceImpl implements IStackerTaskService {
.toList();
}
/**
* 实现
*
@ -393,28 +405,6 @@ public class StackerTaskServiceImpl implements IStackerTaskService {
.eq(TAppStock::getVehicleId, orderIn.getVehicleNo()));
}
OrderInCBReq orderInCBReq = new OrderInCBReq();
orderInCBReq.setTaskId(orderIn.getOrderId());
orderInCBReq.setVehicleNo(wmsTask.getVehicleId());
orderInCBReq.setLocationId(wmsTask.getDestination());
orderInCBReq.setResult(OrderInCBEnums.COMPLETE.getCode());
orderInCBReq.setResultMessage("入库完成");
// int times = 0;
// MesApiResponse response = null;
// do {
// Thread.sleep(15000L * times);
// response = externalApiService.invokeOrderInCB(orderInCBReq);
// times++;
// } while (response.getCode() != 0 && times <= 10);
// if (response.getCode() != 0) {
// log.error("[wms]上报失败");
// } else {
// log.info("[wms]上报成功");
// }
if (!appOrderInService.removeById(orderIn.getRecordId())) {
log.info("整箱入库完成删除入库单失败,任务:{},原因:删除入库单失败", wmsTask.getTaskId());
}
TAppVehicle vehicle = new TAppVehicle();
vehicle.setVehicleId(wmsTask.getVehicleId());
vehicle.setVehicleStatus(WmsVehicleStatusEnums.ON.getCode());
@ -432,6 +422,32 @@ public class StackerTaskServiceImpl implements IStackerTaskService {
if (!appTaskBakService.save(wmsTask.of())) {
log.info("备份入库任务失败,任务:{}", wmsTask.getTaskId());
}
if (!appOrderInService.removeById(orderIn.getRecordId())) {
log.info("整箱入库完成删除入库单失败,任务:{},原因:删除入库单失败", wmsTask.getTaskId());
}
OrderInCBReq orderInCBReq = new OrderInCBReq();
orderInCBReq.setTaskId(orderIn.getOrderId());
orderInCBReq.setVehicleNo(wmsTask.getVehicleId());
orderInCBReq.setLocationId(wmsTask.getDestination());
orderInCBReq.setResult(OrderInCBEnums.COMPLETE.getCode());
orderInCBReq.setResultMessage("入库完成");
int times = 0;
MesApiResponse response = null;
do {
if (times > 5) {
break;
}
Thread.sleep(15000L * times);
response = externalApiService.invokeOrderInCB(orderInCBReq);
times++;
} while (response.getCode() != 0);
if (response.getCode() != 0) {
log.error("[wms]上报失败");
} else {
log.info("[wms]上报成功");
}
}
}
@ -449,16 +465,14 @@ public class StackerTaskServiceImpl implements IStackerTaskService {
appStockService.update(new LambdaUpdateWrapper<TAppStock>()
.in(TAppStock::getStockId, thisVehicleStocks.stream().map(TAppStock::getStockId).toList())
.set(TAppStock::getLocationId, wmsTask.getDestination())
.set(TAppStock::getStockStatus, WmsStockStatusEnums.OK.getCode())
);
.set(TAppStock::getStockStatus, WmsStockStatusEnums.OK.getCode()));
appLocationService.update(new LambdaUpdateWrapper<TAppLocation>()
.eq(TAppLocation::getLocationId, wmsTask.getOrigin())
.set(TAppLocation::getIsOccupy, WmsLocationOccupyStatusEnums.EMPTY.getCode())
.set(TAppLocation::getVehicleId, ""));
appVehicleService.update(new LambdaUpdateWrapper<TAppVehicle>()
.eq(TAppVehicle::getVehicleId, wmsTask.getVehicleId())
.set(TAppVehicle::getLocationId, wmsTask.getDestination())
);
.set(TAppVehicle::getLocationId, wmsTask.getDestination()));
appCommon.updateWorkingLocations(wmsTask.getDestination(), 0);
appCommon.updateWorkingLocations(wmsTask.getOrigin(), 0);
appTaskService.removeById(wmsTask.getTaskId());
@ -482,7 +496,8 @@ public class StackerTaskServiceImpl implements IStackerTaskService {
// 5. 添加出库记录
// 根据载具号map一下
Map<String, List<TAppTask>> vehicleIdToTaskMap = stackerOutTasks.stream()
.filter(outTask -> Objects.equals(outTask.getTaskType(), WmsTaskTypeEnums.OUT.getCode()) && Objects.equals(outTask.getTaskStatus(), WmsStackerTaskStatusEnums.FINISH.getCode()))
.filter(outTask -> Objects.equals(outTask.getTaskType(), WmsTaskTypeEnums.OUT.getCode())
&& Objects.equals(outTask.getTaskStatus(), WmsStackerTaskStatusEnums.FINISH.getCode()))
.collect(Collectors.groupingBy(TAppTask::getVehicleId));
for (String vehicleId : vehicleIdToTaskMap.keySet()) {
// 查询当前载具的数据
@ -506,6 +521,7 @@ public class StackerTaskServiceImpl implements IStackerTaskService {
.eq(TAppLocation::getLocationId, thisVehicle.getLocationId())
.eq(TAppLocation::getVehicleId, vehicleId));
// 更新载具信息
appCommon.updateWorkingLocations(thisVehicle.getLocationId(), 0);
thisVehicle.setVehicleStatus(WmsVehicleStatusEnums.OUT.getCode());
thisVehicle.setLocationId("");
appVehicleService.updateById(thisVehicle);
@ -514,7 +530,6 @@ public class StackerTaskServiceImpl implements IStackerTaskService {
.set(TAppStock::getStockStatus, WmsStockStatusEnums.OUTED.getCode())
.set(TAppStock::getLocationId, "")
.eq(TAppStock::getVehicleId, vehicleId));
appCommon.updateWorkingLocations(thisVehicle.getLocationId(), 0);
agvLockService.releaseStationLocks("C1", WmsTaskTypeEnums.OUT.getCode());
// 当前载具的任务列表
List<TAppTask> thisVehicleOutTasks = vehicleIdToTaskMap.get(vehicleId);
@ -539,26 +554,29 @@ public class StackerTaskServiceImpl implements IStackerTaskService {
appOrderOutService.removeBatchByIds(orderOuts);
}
}
// for (TAppOrderOut orderOut : orderOuts) {
// OrderOutCBReq orderOutCBReq = new OrderOutCBReq();
// orderOutCBReq.setTaskId(orderOut.getOrderId());
// orderOutCBReq.setVehicleNo(vehicleId);
// orderOutCBReq.setResult(OrderOutCBEnums.COMPLETE.getCode());
// orderOutCBReq.setResultMessage("出库完成");
for (TAppOrderOut orderOut : orderOuts) {
OrderOutCBReq orderOutCBReq = new OrderOutCBReq();
orderOutCBReq.setTaskId(orderOut.getOrderId());
orderOutCBReq.setVehicleNo(vehicleId);
orderOutCBReq.setResult(OrderOutCBEnums.COMPLETE.getCode());
orderOutCBReq.setResultMessage("出库完成");
// int times = 0;
// MesApiResponse response = null;
// do {
// response = externalApiService.invokeOrderOutCB(orderOutCBReq);
// times++;
// Thread.sleep(15000L * times);
// } while (response.getCode() != 0 && times <= 10);
// if (response.getCode() != 0) {
// log.error("[WMS]上报失败");
// } else {
// log.info("[WMS]上报成功");
// }
// }
int times = 0;
MesApiResponse response = null;
do {
if (times > 5) {
break;
}
response = externalApiService.invokeOrderOutCB(orderOutCBReq);
times++;
Thread.sleep(15000L * times);
} while (response.getCode() != 0);
if (response.getCode() != 0) {
log.error("[WMS]上报失败");
} else {
log.info("[WMS]上报成功");
}
}
}
}
}

View File

@ -1,21 +1,26 @@
package com.wms_main.service.controller;
import com.wms_main.model.dto.request.mywms.OrderInCancel;
import com.wms_main.model.dto.request.mywms.OrderInReq;
import com.wms_main.model.dto.request.mywms.OrderOutReq;
import com.wms_main.model.dto.request.mywms.QueryStandStatusReq;
import com.wms_main.model.dto.request.mywms.StockReq;
import com.wms_main.model.dto.request.mywms.StockRespGoodsDetail;
import com.wms_main.model.dto.response.mywms.MyWmsResponse;
import com.wms_main.model.dto.response.mywms.OrderResponse;
import java.util.List;
public interface IMyWmsControllerService {
MyWmsResponse<Object> orderIn(OrderInReq request);
OrderResponse orderIn(OrderInReq request);
MyWmsResponse<Object> orderOut(OrderOutReq request);
OrderResponse orderOut(OrderOutReq request);
MyWmsResponse<List<StockRespGoodsDetail>> stock(StockReq request);
MyWmsResponse<Boolean> queryCanFeed();
MyWmsResponse<Boolean> queryStandStatus(QueryStandStatusReq request);
MyWmsResponse<Boolean> queryCanOut();
String cancelOrderIn(OrderInCancel request);
MyWmsResponse<Object> agvDone();
}

View File

@ -1,19 +1,32 @@
package com.wms_main.service.controller.serviceImpl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.wms_main.app.AppCommon;
import com.wms_main.constant.enums.wcs.WcsApiResponseCodeEnums;
import com.wms_main.constant.enums.wms.OrderStatusEnum;
import com.wms_main.constant.enums.wms.WmsLocationOccupyStatusEnums;
import com.wms_main.constant.enums.wms.WmsStockStatusEnums;
import com.wms_main.constant.enums.wms.WmsTaskTypeEnums;
import com.wms_main.dao.ITAppLocationService;
import com.wms_main.dao.ITAppOrderInService;
import com.wms_main.dao.ITAppOrderOutService;
import com.wms_main.dao.ITAppStockService;
import com.wms_main.dao.ITAppTaskService;
import com.wms_main.dao.ITAppWcsTaskService;
import com.wms_main.model.dto.request.mywms.*;
import com.wms_main.model.dto.request.wcs.WcsCanFeedRequest;
import com.wms_main.model.dto.request.wcs.WcsQueryStandStatusRequest;
import com.wms_main.model.dto.response.mywms.MyWmsResponse;
import com.wms_main.model.dto.response.mywms.OrderResponse;
import com.wms_main.model.dto.response.wcs.BaseWcsApiResponse;
import com.wms_main.model.dto.response.wcs.WcsApiResponse;
import com.wms_main.model.dto.response.wcs.WcsCanFeedResponse;
import com.wms_main.model.po.TAppLocation;
import com.wms_main.model.po.TAppOrderIn;
import com.wms_main.model.po.TAppOrderOut;
import com.wms_main.model.po.TAppStock;
import com.wms_main.model.po.TAppTask;
import com.wms_main.model.po.TAppWcsTask;
import com.wms_main.repository.utils.StringUtils;
import com.wms_main.repository.utils.UUIDUtils;
import com.wms_main.service.api.IWcsApiService;
@ -36,14 +49,18 @@ public class MyWmsControllerServiceImpl implements IMyWmsControllerService {
private final ITAppStockService appStockService;
private final IAgvLockService agvLockService;
private final IWcsApiService wcsApiService;
private final ITAppTaskService appTaskService;
private final ITAppWcsTaskService appWcsTaskService;
private final ITAppLocationService appLocationService;
private final AppCommon appCommon;
@Override
public MyWmsResponse<Object> orderIn(OrderInReq request) {
public OrderResponse orderIn(OrderInReq request) {
try {
if (request == null)
return MyWmsResponse.error("参数错误", null);
return OrderResponse.error("参数错误");
if (!request.isValid()) {
return MyWmsResponse.error("参数错误", null);
return OrderResponse.error("参数错误");
}
// 检查入库口是否可用
@ -51,16 +68,22 @@ public class MyWmsControllerServiceImpl implements IMyWmsControllerService {
boolean canFeed = agvLockService.canFeedToInboundPort(inboundPort);
if (!canFeed) {
String portStatus = agvLockService.getInboundPortStatus(inboundPort);
return MyWmsResponse.error("入库口当前" + portStatus + ",无法生成入库订单,请稍后重试", null);
return OrderResponse.error("入库口当前" + portStatus + ",无法生成入库订单,请稍后重试");
}
// 校验是否存在相同的入库单
List<TAppOrderIn> withTaskId = appOrderInService.getWithTaskId(request.getTaskId());
if (withTaskId == null) {
return MyWmsResponse.error("数据服务异常,请稍后重试", null);
return OrderResponse.error("数据服务异常,请稍后重试");
}
if (!withTaskId.isEmpty()) {
return MyWmsResponse.error("入库单已存在,请勿重复推送", null);
return OrderResponse.error("入库单已存在,请勿重复推送");
}
Boolean isDup = appStockService
.exists(new LambdaQueryWrapper<TAppStock>().eq(TAppStock::getVehicleId, request.getVehicleNo())
.eq(TAppStock::getStockStatus, WmsStockStatusEnums.OK.getCode()));
if (isDup) {
return OrderResponse.error("库存重复,托盘号: " + request.getVehicleNo());
}
TAppOrderIn orderIn = new TAppOrderIn();
orderIn.setRecordId(UUIDUtils.getNewUUID());
@ -72,28 +95,28 @@ public class MyWmsControllerServiceImpl implements IMyWmsControllerService {
orderIn.setCreateTime(LocalDateTime.now());
orderIn.setUpdateTime(LocalDateTime.now());
if (!appOrderInService.save(orderIn)) {
return MyWmsResponse.error("入库单保存失败,请稍后再试", null);
return OrderResponse.error("入库单保存失败,请稍后再试");
}
return MyWmsResponse.success();
return OrderResponse.success();
} catch (Exception e) {
return MyWmsResponse.error("入库单添加异常", null);
return OrderResponse.error("入库单添加异常");
}
}
@Override
public MyWmsResponse<Object> orderOut(OrderOutReq request) {
public OrderResponse orderOut(OrderOutReq request) {
try {
if (request == null || StringUtils.isEmpty(request.getTaskId())
|| StringUtils.isEmpty(request.getVehicleNo())) {
return MyWmsResponse.error("参数错误", null);
return OrderResponse.error("参数错误");
}
List<TAppOrderOut> orderOutCheckList = appOrderOutService.getWithTaskId(request.getTaskId());
if (orderOutCheckList == null) {
return MyWmsResponse.error("数据服务异常,请稍后重试", null);
return OrderResponse.error("数据服务异常,请稍后重试");
}
if (!orderOutCheckList.isEmpty()) {
return MyWmsResponse.error("出库单已存在,请勿重复推送", null);
return OrderResponse.error("出库单已存在,请勿重复推送");
}
List<TAppStock> vehicleStocks = appStockService.list(
@ -102,7 +125,7 @@ public class MyWmsControllerServiceImpl implements IMyWmsControllerService {
.eq(TAppStock::getStockStatus, WmsStockStatusEnums.OK.getCode()));
if (vehicleStocks == null || vehicleStocks.isEmpty()) {
return MyWmsResponse.error("载具号" + request.getVehicleNo() + "无库存记录", null);
return OrderResponse.error("载具号" + request.getVehicleNo() + "无库存记录");
}
TAppOrderOut orderOut = new TAppOrderOut();
@ -113,12 +136,12 @@ public class MyWmsControllerServiceImpl implements IMyWmsControllerService {
orderOut.setCreateTime(LocalDateTime.now());
orderOut.setUpdateTime(LocalDateTime.now());
if (!appOrderOutService.save(orderOut)) {
return MyWmsResponse.error("出库单保存失败,请稍后再试", null);
return OrderResponse.error("出库单保存失败,请稍后再试");
}
return MyWmsResponse.success();
return OrderResponse.success();
} catch (Exception e) {
log.error("出库任务添加失败", e);
return MyWmsResponse.error("出库任务添加失败,请稍后再试", null);
return OrderResponse.error("出库任务添加失败,请稍后再试");
}
}
@ -164,17 +187,27 @@ public class MyWmsControllerServiceImpl implements IMyWmsControllerService {
}
@Override
public MyWmsResponse<Boolean> queryCanFeed() {
public MyWmsResponse<Boolean> queryStandStatus(QueryStandStatusReq request) {
if (Objects.equals(request.getStandType(), WmsTaskTypeEnums.IN.getCode())) {
return queryStandStatusIn(request);
} else if (Objects.equals(request.getStandType(), WmsTaskTypeEnums.OUT.getCode())) {
return queryStandStatusOut(request);
} else {
return MyWmsResponse.error("WCS系统不允许AGV上料或取货", false);
}
}
private MyWmsResponse<Boolean> queryStandStatusIn(QueryStandStatusReq request) {
try {
// TODO canFeed
WcsApiResponse<WcsCanFeedResponse> wcsResponse = wcsApiService.canFeed(new WcsCanFeedRequest("R1"));
WcsApiResponse<WcsCanFeedResponse> wcsResponse = wcsApiService
.queryStandStatus(new WcsQueryStandStatusRequest(request.getStandType()));
if (wcsResponse == null || wcsResponse.getData() == null) {
return MyWmsResponse.error("WCS系统查询失败", false);
}
Boolean wcsAllow = wcsResponse.getData().isAllowAction();
if (!wcsAllow) {
return MyWmsResponse.error("WCS系统不允许入库", false);
return MyWmsResponse.error("WCS系统不允许AGV上料", false);
}
Boolean wmsAllow = agvLockService.canFeedToInboundPort("R1");
@ -187,19 +220,18 @@ public class MyWmsControllerServiceImpl implements IMyWmsControllerService {
}
}
@Override
public MyWmsResponse<Boolean> queryCanOut() {
private MyWmsResponse<Boolean> queryStandStatusOut(QueryStandStatusReq request) {
try {
// 1. 调用wcs.canFeed检查wcs状态 (使用R1口)
// TODO canFeed
WcsApiResponse<WcsCanFeedResponse> wcsResponse = wcsApiService.canFeed(new WcsCanFeedRequest("R1"));
WcsApiResponse<WcsCanFeedResponse> wcsResponse = wcsApiService
.queryStandStatus(new WcsQueryStandStatusRequest(request.getStandType()));
if (wcsResponse == null || wcsResponse.getData() == null) {
return MyWmsResponse.error("WCS系统查询失败", false);
}
Boolean wcsAllow = wcsResponse.getData().isAllowAction();
if (!wcsAllow) {
return MyWmsResponse.error("WCS系统不允许出库", false);
return MyWmsResponse.error("WCS系统不允许AGV取货", false);
}
// 2. 检查agvLock服务获取wms状态 (使用R1口)
@ -213,4 +245,58 @@ public class MyWmsControllerServiceImpl implements IMyWmsControllerService {
return MyWmsResponse.error("系统异常,请稍后重试", false);
}
}
@Override
public MyWmsResponse<Object> agvDone() {
try {
BaseWcsApiResponse wcsResponse = wcsApiService.agvDone();
if (wcsResponse == null) {
return MyWmsResponse.error("WCS系统查询失败", null);
}
if (!Objects.equals(wcsResponse.getCode(), WcsApiResponseCodeEnums.SUCCESS.getCode())) {
return MyWmsResponse.error("WCS系统重置信号失败", null);
}
return MyWmsResponse.success(null);
} catch (Exception e) {
return MyWmsResponse.error("系统异常,请稍后重试", null);
}
}
@Override
public String cancelOrderIn(OrderInCancel request) {
String vehicleNo = request.getVehicleNo();
if (!appOrderInService.remove(new LambdaQueryWrapper<TAppOrderIn>().eq(StringUtils.isNotEmpty(vehicleNo),
TAppOrderIn::getVehicleNo, vehicleNo))) {
log.info("fail to delete orderIn, vehicleNo: " + vehicleNo);
}
if (!appTaskService.remove(new LambdaQueryWrapper<TAppTask>().eq(StringUtils.isNotEmpty(vehicleNo),
TAppTask::getVehicleId, vehicleNo))) {
log.info("fail to delete wmsTask, vehicleNo: " + vehicleNo);
}
if (!appWcsTaskService.remove(new LambdaQueryWrapper<TAppWcsTask>().eq(StringUtils.isNotEmpty(vehicleNo),
TAppWcsTask::getVehicleId, vehicleNo))) {
log.info("fail to delete wcsTask, vehicleNo: " + vehicleNo);
}
List<TAppLocation> locationList = appLocationService.list(
new LambdaQueryWrapper<TAppLocation>().eq(StringUtils.isNotEmpty(vehicleNo), TAppLocation::getVehicleId,
vehicleNo));
TAppLocation location = null;
if (locationList != null && locationList.size() > 0) {
location = locationList.getFirst();
}
if (location != null && !appStockService.exists(new LambdaQueryWrapper<TAppStock>().eq(StringUtils.isNotEmpty(vehicleNo),
TAppStock::getVehicleId, vehicleNo).eq(TAppStock::getStockStatus, WmsStockStatusEnums.OK.getCode()))) {
if (!appLocationService.update(
new LambdaUpdateWrapper<TAppLocation>().eq(TAppLocation::getLocationId, location.getLocationId())
.set(TAppLocation::getIsOccupy, WmsLocationOccupyStatusEnums.EMPTY.getCode())
.set(TAppLocation::getVehicleId, ""))) {
log.info("fail to update location, vehicleNo: {}, location: {}", vehicleNo, location.getLocationId());
}
appCommon.updateWorkingLocations(location.getLocationId(), 0);
return "成功清理";
} else {
return "该载具已在库中,无法清除库位信息 / 库位表中无数据";
}
}
}

View File

@ -0,0 +1,97 @@
package com.wms_main.service.quartz_job.job_executor;
import java.time.LocalDateTime;
import java.util.List;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.wms_main.constant.enums.wms.OrderStatusEnum;
import com.wms_main.constant.enums.wms.WmsStackerTaskStatusEnums;
import com.wms_main.constant.enums.wms.WmsTaskTypeEnums;
import com.wms_main.dao.ITAppOrderInService;
import com.wms_main.dao.ITAppTaskService;
import com.wms_main.model.po.TAppLocation;
import com.wms_main.model.po.TAppOrderIn;
import com.wms_main.model.po.TAppTask;
import com.wms_main.repository.utils.UUIDUtils;
import com.wms_main.service.business.IStackerTaskService;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.PersistJobDataAfterExecution;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@PersistJobDataAfterExecution
// 以下注解用于实现fixed_delay
@DisallowConcurrentExecution
@RequiredArgsConstructor
public class MyInExecutor implements Job {
private final ITAppOrderInService appOrderInService;
private final IStackerTaskService stackerTaskService;
private final ITAppTaskService appWmsTaskService;
private static String ORIGIN = "R1";
@Override
public void execute(JobExecutionContext context) {
processInOrders();
}
private void processInOrders() {
List<TAppOrderIn> orders = appOrderInService.list(
new LambdaQueryWrapper<TAppOrderIn>()
.eq(TAppOrderIn::getOrderStatus, OrderStatusEnum.CREATE.getCode()));
orders.forEach(this::processSingleOrder);
}
private void processSingleOrder(TAppOrderIn orderIn) {
if (orderIn == null) {
return;
}
/* 查找可用库位 */
TAppLocation useLocation = stackerTaskService.requestOneLocation(null, orderIn.getVehicleNo());
if (useLocation == null) {
log.error("暂没有可以直接使用的库位,因为存在互锁的库位,请等待当前任务都执行完成后再试");
return;
}
TAppTask newInTask = appWmsTaskService.getOne(new LambdaQueryWrapper<TAppTask>()
.eq(TAppTask::getVehicleId, orderIn.getVehicleNo())
.eq(TAppTask::getTaskType, WmsTaskTypeEnums.IN.getCode()));
if (newInTask != null) {
newInTask.setTaskStatus(WmsStackerTaskStatusEnums.WAIT.getCode());
newInTask.setDestination(useLocation.getLocationId());
newInTask.setTaskGroup(orderIn.getOrderId());
if (!appWmsTaskService.updateById(newInTask)) {
log.error("生成任务失败,无法插入新的入库任务");
return;
}
} else {
newInTask = new TAppTask();
newInTask.setTaskId(UUIDUtils.getNewUUID());
newInTask.setTaskGroup(orderIn.getOrderId());
newInTask.setTaskType(WmsTaskTypeEnums.IN.getCode());
newInTask.setTaskStatus(WmsStackerTaskStatusEnums.WAIT.getCode());
newInTask.setOrigin(ORIGIN);
newInTask.setDestination(useLocation.getLocationId());
newInTask.setCreateTime(LocalDateTime.now());
newInTask.setOpUser("wcs");
newInTask.setVehicleId(orderIn.getVehicleNo());
newInTask.setTaskPriority(1);
if (!appWmsTaskService.save(newInTask)) {
log.error("生成任务失败,无法插入新的入库任务");
return;
}
}
appOrderInService.update(
new LambdaUpdateWrapper<TAppOrderIn>()
.eq(TAppOrderIn::getRecordId, orderIn.getRecordId())
.set(TAppOrderIn::getOrderStatus, OrderStatusEnum.RUNNING.getCode())
.set(TAppOrderIn::getUpdateTime, LocalDateTime.now()));
return;
}
}

View File

@ -6,7 +6,6 @@ import com.wms_main.constant.enums.wcs.WcsApiResponseCodeEnums;
import com.wms_main.constant.enums.wcs.WcsStackerTaskStatusEnums;
import com.wms_main.constant.enums.wcs.WcsStackerTaskTypeEnums;
import com.wms_main.constant.enums.wms.WmsStackerTaskStatusEnums;
import com.wms_main.constant.enums.wms.WmsTaskTypeEnums;
import com.wms_main.dao.ITAppTaskService;
import com.wms_main.dao.ITAppWcsTaskService;
import com.wms_main.model.bo.wcs.WcsStackerTask;
@ -74,8 +73,14 @@ public class WcsStackerTaskSender implements Job {
waitSendWcsTaskList.sort((task1, task2) -> Integer.compare(task2.getTaskPriority(), task1.getTaskPriority()));
// 发送任务
TAppWcsTask wcsTask = waitSendWcsTaskList.getFirst();
Boolean wmsAllow = false;
if (wcsTask.getWcsTaskType().equals(WcsStackerTaskTypeEnums.OUT.getCode())) {
Boolean wmsAllow = agvLockService.canFeedToInboundPort(wcsTask.getDestination());
wmsAllow = agvLockService.canFeedToOutboundPort(wcsTask.getDestination());
} else if (wcsTask.getWcsTaskType().equals(WcsStackerTaskTypeEnums.IN.getCode())) {
wmsAllow = agvLockService.canFeedToInboundPort(wcsTask.getOrigin());
}
if (wcsTask.getWcsTaskType().equals(WcsStackerTaskTypeEnums.OUT.getCode())
|| wcsTask.getWcsTaskType().equals(WcsStackerTaskTypeEnums.IN.getCode())) {
if (!wmsAllow) {
return;
}
@ -105,7 +110,7 @@ public class WcsStackerTaskSender implements Job {
if (wcsTask.getWcsTaskType().equals(WcsStackerTaskTypeEnums.OUT.getCode())) {
try {
agvLockService.lockInboundPort("AGV", wcsTask.getDestination());
agvLockService.lockOutboundPort("AGV", wcsTask.getDestination());
} catch (Exception e) {
log.error("任务发送成功后锁定{}口失败任务ID: {}", wcsTask.getDestination(), wcsTask.getWcsTaskId());
}

View File

@ -5,13 +5,13 @@ spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
# 本地
url: jdbc:mysql://localhost:3306/wms_mengyang_tp?characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowMultiQueries=true&rewriteBatchedStatements=true
username: root
password: root
# url: jdbc:mysql://localhost:3306/wms_mengyang_tp?characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowMultiQueries=true&rewriteBatchedStatements=true
# username: root
# password: root
# 服务器
# url: jdbc:mysql://10.18.58.21:3306/wms_yachi_nantong?characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowMultiQueries=true&rewriteBatchedStatements=true
# username: user
# password: user
url: jdbc:mysql://localhost:3306/wms_mengyang_tp?characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowMultiQueries=true&rewriteBatchedStatements=true
username: user
password: user
profiles:
active: online
@ -33,10 +33,10 @@ mybatis-plus:
configuration:
map-underscore-to-camel-case: true # 开启驼峰映射
cache-enabled: false # 是否开启二级缓存
global-config:
db-config:
id-type: assign_id
update-strategy: not_null
# global-config:
# db-config:
# id-type: assign_id
# update-strategy: not_null
logging:
config: classpath:logback-spring.xml

View File

@ -2,7 +2,7 @@ import request from "@/http/request";
const submitOrderInForm = (params) => {
return request({
url: '/ycwms/orderIn',
url: '/mywms/orderIn',
method: 'post',
data: params
})

View File

@ -1,8 +1,8 @@
import axios from 'axios'
const request = axios.create({
baseURL: 'http://10.18.58.21:12315',
// baseURL: 'http://localhost:12315',
// baseURL: 'http://10.18.58.21:12315',
baseURL: 'http://localhost:12315',
timeout: 5000
})

View File

@ -7,86 +7,20 @@
<el-form ref="orderInFormRef" :model="orderInForm" :rules="rules" label-width="100px"
:label-position="labelPosition" status-icon>
<el-row :gutter="20">
<el-col :xs="24" :sm="12" :md="6" :lg="5">
<el-form-item label="料箱号" prop="vehicleNo">
<el-input v-model="orderInForm.vehicleNo" clearable @keyup.enter="handleEnter('vehicleSize')"
ref="vehicleNoRef"/>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="6" :lg="5">
<el-form-item label="料箱尺寸" prop="vehicleSize">
<el-input v-model="orderInForm.vehicleSize" clearable @keyup.enter="handleEnter('inStand')"
ref="vehicleSizeRef"/>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="6" :lg="5">
<el-form-item label="入库站台" prop="inStand">
<el-input v-model="orderInForm.inStand" clearable @keyup.enter="handleEnter('clientId')"
ref="inStandRef"/>
<el-col :xs="24" :sm="12" :md="8" :lg="6">
<el-form-item label="托盘号" prop="vehicleNo">
<el-input v-model="orderInForm.vehicleNo" clearable @keyup.enter="submitOrderIn"
placeholder="请输入托盘号" ref="vehicleNoRef"/>
</el-form-item>
</el-col>
</el-row>
</el-form>
</fieldset>
<fieldset class="goods-detail-area">
<legend>物料明细</legend>
<div style="display: flex; justify-content: space-between; margin-bottom: 15px;">
<div>
<el-button type="primary" @click="addGoodsDetail">添加物料</el-button>
<el-button type="danger" @click="clearGoodsDetail">清空物料</el-button>
</div>
<div>
<el-button type="success" @click="submitOrderIn">提交入库单</el-button>
</div>
</div>
<div class="table-area">
<el-table :data="orderInForm.goodsDetail" border stripe :max-height="maxHeight"
:header-cell-style="{ 'text-align': 'center' }"
:cell-style="{ 'text-align': 'center', 'padding': '12px 0' }"
class="table-class" width="100%" :row-style="{ height: '60px' }">
<el-table-column prop="goodsId" label="物料编号" min-width="120">
<template #default="scope">
<el-input v-model="scope.row.goodsId" placeholder="请输入物料编号" size="small"/>
</template>
</el-table-column>
<el-table-column prop="goodsName" label="物料名称" min-width="120">
<template #default="scope">
<el-input v-model="scope.row.goodsName" placeholder="请输入物料名称" size="small"/>
</template>
</el-table-column>
<el-table-column prop="batch" label="批次" min-width="120">
<template #default="scope">
<el-input v-model="scope.row.batch" placeholder="请输入批次" size="small"/>
</template>
</el-table-column>
<el-table-column prop="goodsType" label="物料类型" min-width="120">
<template #default="scope">
<el-input v-model="scope.row.goodsType" placeholder="请输入物料类型" size="small"/>
</template>
</el-table-column>
<el-table-column prop="specification" label="规格" min-width="120">
<template #default="scope">
<el-input v-model="scope.row.specification" placeholder="请输入规格" size="small"/>
</template>
</el-table-column>
<el-table-column prop="quantity" label="数量" min-width="120">
<template #default="scope">
<el-input-number v-model="scope.row.quantity" :min="1" :controls="false" size="small"/>
</template>
</el-table-column>
<el-table-column prop="goodsDesc" label="物料描述" min-width="120">
<template #default="scope">
<el-input v-model="scope.row.goodsDesc" placeholder="请输入物料描述" size="small"/>
</template>
</el-table-column>
<el-table-column label="操作" width="80" fixed="right">
<template #default="scope">
<el-button type="danger" size="small" @click="removeGoodsDetail(scope.$index)">删除</el-button>
</template>
</el-table-column>
</el-table>
<fieldset class="submit-area">
<legend>操作区域</legend>
<div style="display: flex; justify-content: center; margin-bottom: 15px;">
<el-button type="success" @click="submitOrderIn" size="large">提交入库单</el-button>
</div>
</fieldset>
@ -301,28 +235,19 @@ import {errorBox} from '@/utils/myMessageBox.js'
import {labelPosition} from '@/constant/form'
import {submitOrderInForm, getOrderIns, updateOrderIn, deleteOrderIn} from '@/api/orderIn.js'
//
const generateOrderId = () => {
const now = new Date()
const year = now.getFullYear()
const month = String(now.getMonth() + 1).padStart(2, '0')
const day = String(now.getDate()).padStart(2, '0')
const hours = String(now.getHours()).padStart(2, '0')
const minutes = String(now.getMinutes()).padStart(2, '0')
const seconds = String(now.getSeconds()).padStart(2, '0')
const milliseconds = String(now.getMilliseconds()).padStart(3, '0')
return `baokai${year}${month}${day}${hours}${minutes}${seconds}${milliseconds}`
// UUID
const generateUUID = () => {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
const r = Math.random() * 16 | 0
const v = c === 'x' ? r : (r & 0x3 | 0x8)
return v.toString(16)
})
}
//
const orderInFormRef = ref()
const orderInForm = reactive({
orderId: generateOrderId(),
vehicleNo: '',
vehicleSize: '',
inStand: '',
clientId: 'WMS',
goodsDetail: []
vehicleNo: ''
})
//
@ -346,15 +271,11 @@ const queryForm = reactive({
//
const rules = reactive({
vehicleNo: [{required: true, message: '请输入料箱号', trigger: 'blur'}],
vehicleSize: [{required: true, message: '请输入料箱尺寸', trigger: 'blur'}],
inStand: [{required: true, message: '请输入入库站台', trigger: 'blur'}],
vehicleNo: [{required: true, message: '请输入托盘号', trigger: 'blur'}]
})
// DOM
const vehicleNoRef = ref()
const vehicleSizeRef = ref()
const inStandRef = ref()
//
const responseDialogVisible = ref(false)
@ -385,79 +306,33 @@ const resizeHeight = () => {
maxHeight.value = window.innerHeight * 0.4
}
//
const handleEnter = (nextField) => {
const refMap = {
'vehicleNo': vehicleNoRef,
'vehicleSize': vehicleSizeRef,
'inStand': inStandRef
}
if (refMap[nextField]) {
refMap[nextField].value.focus()
}
}
//
const addGoodsDetail = () => {
orderInForm.goodsDetail.push({
goodsId: '',
goodsName: '',
batch: '',
goodsType: '',
specification: '',
quantity: 1,
goodsDesc: ''
})
}
//
const removeGoodsDetail = (index) => {
orderInForm.goodsDetail.splice(index, 1)
}
//
const clearGoodsDetail = () => {
orderInForm.goodsDetail = []
}
//
//
const resetOrderInForm = () => {
orderInForm.orderId = generateOrderId()
orderInForm.vehicleNo = ''
orderInForm.vehicleSize = ''
orderInForm.inStand = ''
orderInForm.goodsDetail = []
}
//
const submitOrderIn = () => {
orderInFormRef.value.validate((valid) => {
if (valid) {
if (orderInForm.goodsDetail.length === 0) {
errorBox('请至少添加一条物料明细')
return
}
//
for (let i = 0; i < orderInForm.goodsDetail.length; i++) {
const item = orderInForm.goodsDetail[i]
if (!item.goodsId || !item.goodsName || !item.batch || !item.goodsType || !item.specification || !item.quantity) {
errorBox(`${i + 1}行物料明细填写不完整,请检查`)
return
}
//
const requestData = {
taskId: generateUUID(),
vehicleNo: orderInForm.vehicleNo
}
//
loading.open()
submitOrderInForm(orderInForm)
submitOrderInForm(requestData)
.then(res => {
responseResult.value = res.data
responseDialogVisible.value = true
if (res.data.code === 0) {
ElMessage.success('入库单提交成功')
//
//
resetOrderInForm()
} else {
errorBox(`入库单提交失败: ${res.data.message}`)
@ -626,7 +501,7 @@ const deleteOrderInRecord = (row) => {
box-sizing: border-box;
}
.main-area, .goods-detail-area, .query-area, .query-result-area {
.main-area, .submit-area, .query-area, .query-result-area {
width: 100%;
margin-bottom: 20px;
padding: 15px;

View File

@ -3,67 +3,28 @@
<el-container class="content">
<div class="work-area">
<fieldset class="main-area">
<legend>物料查询</legend>
<el-form ref="queryFormRef" :model="queryForm" label-width="70px" :label-position="labelPosition">
<el-row :gutter="5" class="form-row">
<el-col :xs="24" :sm="4" :md="4" :lg="4">
<el-form-item label="内部编号">
<el-input v-model="queryForm.neibubianhao" clearable class="custom-input" />
<legend>出库单信息</legend>
<el-form ref="orderOutFormRef" :model="orderOutForm" :rules="rules" label-width="100px"
:label-position="labelPosition" status-icon>
<el-row :gutter="20">
<el-col :xs="24" :sm="12" :md="8" :lg="6">
<el-form-item label="托盘号" prop="vehicleNo">
<el-input v-model="orderOutForm.vehicleNo" clearable @keyup.enter="submitOrderOut"
placeholder="请输入托盘号" ref="vehicleNoRef"/>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="4" :md="4" :lg="4">
<el-form-item label="规格">
<el-input v-model="queryForm.goodsType" clearable class="custom-input" />
</el-form-item>
</el-col>
<el-col :xs="24" :sm="4" :md="4" :lg="4">
<el-form-item label="销售单号">
<el-input v-model="queryForm.xsfbillno" clearable class="custom-input" />
</el-form-item>
</el-col>
<el-col :xs="24" :sm="4" :md="4" :lg="4" class="btn-col">
<el-button type="primary" @click="queryGoods">查询</el-button>
<el-button type="info" @click="resetQueryForm">重置</el-button>
</el-col>
</el-row>
</el-form>
</fieldset>
<fieldset v-if="tableData.length > 0" class="main-area">
<legend>查询结果</legend>
<div v-for="(locationItem, locationIndex) in tableData" :key="locationIndex" class="location-group">
<div class="location-header">
<h3>库位: {{ locationItem.location }} | 托盘号: {{ locationItem.vehicleNo }}</h3>
</div>
<el-table
:data="locationItem.goodsDetail"
border
stripe
style="width: 100%"
@selection-change="(selection) => handleSelectionChange(selection, locationItem.vehicleNo)"
:ref="`table_${locationIndex}`">
<el-table-column type="selection" width="55" />
<el-table-column prop="goodsId" label="物料编号" />
<el-table-column prop="goodsName" label="物料名称" />
<el-table-column prop="goodsType" label="规格" />
<el-table-column prop="specification" label="说明" />
<el-table-column prop="quantity" label="数量" />
<el-table-column prop="neibubianhao" label="内部编号" />
<el-table-column prop="xsfbillno" label="销售单号" />
<el-table-column prop="xsfseq" label="行号" />
<el-table-column prop="storeTime" label="入库时间">
<template #default="scope">
{{ scope.row.storeTime ? scope.row.storeTime.split('T')[0] + ' ' + scope.row.storeTime.split('T')[1] : '' }}
</template>
</el-table-column>
</el-table>
</div>
<div class="batch-action-bar">
<el-button type="danger" @click="batchOut" :disabled="getTotalSelectedCount() === 0">出库</el-button>
<span class="selection-info">已选择 {{ getTotalSelectedCount() }} </span>
<fieldset class="submit-area">
<legend>操作区域</legend>
<div style="display: flex; justify-content: center; margin-bottom: 15px;">
<el-button type="danger" @click="submitOrderOut" size="large">提交出库单</el-button>
</div>
</fieldset>
<el-dialog v-model="responseDialogVisible" title="请求结果" width="500px">
<pre>{{ responseResult }}</pre>
<template #footer>
@ -84,54 +45,32 @@ import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import { loading } from '@/utils/loading.js'
import { errorBox } from '@/utils/myMessageBox.js'
import { labelPosition } from '@/constant/form'
import { submitOrderOutForm, localQuery } from '@/api/orderOut.js'
import { submitOrderOutForm } from '@/api/orderOut.js'
//
const generateOrderId = () => {
const now = new Date()
const year = now.getFullYear()
const month = String(now.getMonth() + 1).padStart(2, '0')
const day = String(now.getDate()).padStart(2, '0')
const hours = String(now.getHours()).padStart(2, '0')
const minutes = String(now.getMinutes()).padStart(2, '0')
const seconds = String(now.getSeconds()).padStart(2, '0')
const milliseconds = String(now.getMilliseconds()).padStart(3, '0')
return `baokai${year}${month}${day}${hours}${minutes}${seconds}${milliseconds}`
// UUID
const generateUUID = () => {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
const r = Math.random() * 16 | 0
const v = c === 'x' ? r : (r & 0x3 | 0x8)
return v.toString(16)
})
}
//
const orderOutFormRef = ref()
const orderOutForm = reactive({
orderId: generateOrderId(),
neibubianhao: '',
xsfbillno: '',
goodsType: '',
clientId: "WMS"
vehicleNo: ''
})
//
const queryFormRef = ref()
const queryForm = reactive({
neibubianhao: '',
goodsType: '',
xsfbillno: ''
})
//
const tableData = ref([])
const selectedItemsMap = ref(new Map()) // Map
//
const rules = reactive({
neibubianhao: [{ required: true, message: '请输入内部编号', trigger: 'blur' }],
xsfbillno: [{ required: true, message: '请输入销售单号', trigger: 'blur' }],
goodsType: [{ required: true, message: '请输入规格', trigger: 'blur' }]
vehicleNo: [{ required: true, message: '请输入托盘号', trigger: 'blur' }]
})
// DOM
const neibubianhaoRef = ref()
const xsfbillnoRef = ref()
const goodsTypeRef = ref()
const vehicleNoRef = ref()
//
const responseDialogVisible = ref(false)
@ -140,138 +79,56 @@ const responseResult = ref({})
//
onMounted(() => {
nextTick(() => {
neibubianhaoRef.value.focus()
window.addEventListener('resize', resizeHeight)
vehicleNoRef.value.focus()
})
})
onBeforeUnmount(() => {
window.removeEventListener('resize', resizeHeight)
})
//
const resizeHeight = () => {
//
}
//
const handleEnter = (nextField) => {
const refMap = {
'neibubianhao': neibubianhaoRef,
'xsfbillno': xsfbillnoRef,
'goodsType': goodsTypeRef
}
if (refMap[nextField]) {
refMap[nextField].value.focus()
}
}
//
const resetForm = () => {
orderOutFormRef.value.resetFields()
//
orderOutForm.orderId = generateOrderId()
orderOutForm.vehicleNo = ''
nextTick(() => {
neibubianhaoRef.value.focus()
vehicleNoRef.value.focus()
})
}
//
const resetQueryForm = () => {
queryFormRef.value.resetFields()
tableData.value = []
selectedItemsMap.value.clear()
//
const submitOrderOut = () => {
orderOutFormRef.value.validate((valid) => {
if (valid) {
//
const requestData = {
taskId: generateUUID(),
vehicleNo: orderOutForm.vehicleNo
}
//
const queryGoods = () => {
//
loading.open()
localQuery(queryForm)
.then(res => {
if (res.data.code === 0) {
tableData.value = res.data.returnData || []
selectedItemsMap.value.clear() //
if (tableData.value.length === 0) {
ElMessage.info('未查询到相关物料信息')
}
} else {
errorBox(`查询失败: ${res.data.message}`)
}
})
.catch(err => {
console.error(err)
errorBox('查询物料时发生错误')
})
.finally(() => {
loading.close()
})
}
//
const handleSelectionChange = (selection, vehicleNo) => {
//
if (selection.length > 0) {
selectedItemsMap.value.set(vehicleNo, selection)
} else {
selectedItemsMap.value.delete(vehicleNo)
}
}
//
const getTotalSelectedCount = () => {
let count = 0
selectedItemsMap.value.forEach(items => {
count += items.length
})
return count
}
//
const batchOut = () => {
if (getTotalSelectedCount() === 0) {
ElMessage.warning('请至少选择一项物料')
return
}
//
const selectedVehicleNos = []
selectedItemsMap.value.forEach((selectedItems, vehicleNo) => {
//
selectedItems.forEach(item => {
selectedVehicleNos.push(vehicleNo)
})
})
console.log('选中的载具号列表:', selectedVehicleNos)
if (selectedVehicleNos.length === 0) {
ElMessage.warning('无法获取选中物料的载具号')
return
}
loading.open()
submitOrderOutForm(selectedVehicleNos)
submitOrderOutForm(requestData)
.then(res => {
responseResult.value = res.data
responseDialogVisible.value = true
if (res.data.code === 0) {
ElMessage.success(`出库成功,共处理 ${selectedVehicleNos.length} 项物料`)
//
queryGoods()
ElMessage.success('出库单提交成功')
//
resetForm()
} else {
errorBox(`出库失败: ${res.data.message}`)
errorBox(`出库单提交失败: ${res.data.message}`)
}
})
.catch(err => {
console.error(err)
errorBox('出库时发生错误')
errorBox('提交出库单时发生错误')
})
.finally(() => {
loading.close()
})
} else {
errorBox('请填写完整的出库单信息')
}
})
}
</script>
@ -291,7 +148,7 @@ const batchOut = () => {
box-sizing: border-box;
}
.main-area {
.main-area, .submit-area {
width: 100%;
margin-bottom: 20px;
padding: 15px;
@ -320,60 +177,5 @@ pre {
width: 100%;
}
.form-row {
display: flex;
align-items: center;
}
:deep(.custom-input) {
width: 100%;
}
:deep(.custom-input .el-input__inner),
:deep(.custom-input .el-input-number__decrease),
:deep(.custom-input .el-input-number__increase),
:deep(.custom-input .el-input-number__inner) {
height: 40px;
line-height: 40px;
}
.btn-col {
display: flex;
align-items: center;
justify-content: space-around;
}
.btn-col .el-button {
margin-left: 0;
height: 40px;
}
.location-group {
margin-bottom: 20px;
}
.location-header {
background-color: #f5f7fa;
padding: 8px 15px;
border-radius: 4px 4px 0 0;
margin-bottom: 5px;
}
.location-header h3 {
margin: 0;
font-size: 14px;
color: #606266;
}
.batch-action-bar {
margin-top: 15px;
display: flex;
align-items: center;
}
.selection-info {
margin-left: 15px;
color: #606266;
font-size: 14px;
}
</style>

View File

@ -11,8 +11,6 @@ const routes = [
redirect: '/stock',
children: [
{ path: '/stock', component: () => import('@/layout/stock.vue')},// 库存
{ path: '/goodsIn', component: () => import('@/layout/goodsIn.vue') },// 入库
{ path: '/goodsOut', component: () => import('@/layout/goodsOut.vue') },// 出库
{ path: '/kitting', component: () => import('@/layout/kitting.vue') },// 配料
{ path: '/inTaskRecord', component: () => import('@/layout/inTaskRecord.vue') },// 入库记录
{ path: '/outTaskRecord', component: () => import('@/layout/outTaskRecord.vue') },// 出库记录