no message

main
HUOJIN\92525 2025-11-09 19:36:08 +08:00
parent eb8cf7ca0b
commit de2ca95e1b
55 changed files with 2444 additions and 656 deletions

View File

@ -62,9 +62,12 @@ public class DictAspect {
* Pointcut
*/
@Pointcut("(@within(org.springframework.web.bind.annotation.RestController) || " +
"@within(org.springframework.stereotype.Controller) || @annotation(org.jeecg.common.aspect.annotation.AutoDict)) " +
"@within(org.springframework.stereotype.Controller) || " +
"@annotation(org.jeecg.common.aspect.annotation.AutoDict)) " +
"&& (execution(public org.jeecg.common.api.vo.Result org.jeecg..*.*(..)) || " +
"(execution(public * org.cpte..*.*Controller.*(..)) && !execution(public org.cpte.modules.hikAgv.response.* org.cpte.modules.hikAgv.controller.*.*(..))))")
"(execution(public * org.cpte..*.*Controller.*(..)) && " +
"!execution(public org.cpte.modules.hikAgv.response.* org.cpte.modules.hikAgv.controller.*.*(..)) && " +
"!execution(public org.cpte.modules.tesAgv.response.* org.cpte.modules.tesAgv.controller.*.*(..))))")
public void excudeService() {
}

View File

@ -36,7 +36,7 @@ import java.util.List;
*/
@Slf4j
@Configuration
@MapperScan(value={"org.jeecg.**.mapper*","org.cpte.**.mapper*"})
@MapperScan(value={"org.jeecg.modules.**.mapper*", "org.jeecg.**.mapper*","org.cpte.modules.**.mapper*", "org.cpte.**.mapper*"})
public class MybatisPlusSaasConfig {
@Autowired
private DataSource dataSource;

View File

@ -32,19 +32,12 @@ public class AgvTask implements Serializable {
private static final long serialVersionUID = 1L;
/**
* id
* ID
*/
@TableId(type = IdType.ASSIGN_ID)
@Schema(description = "id")
private java.lang.String id;
/**
*
*/
@Excel(name = "任务编号", width = 15)
@Schema(description = "任务编号")
private java.lang.String agvCode;
/**
*
*/
@ -76,7 +69,7 @@ public class AgvTask implements Serializable {
@Excel(name = "任务状态", width = 15)
@Schema(description = "任务状态")
@Dict(dicCode = "agv_task_status")
private java.lang.String status;
private java.lang.Integer status;
/**
*
*/
@ -95,6 +88,15 @@ public class AgvTask implements Serializable {
@Excel(name = "终点位置", width = 15)
@Schema(description = "终点位置")
private java.lang.String endCode;
/**
* AGV
*/
@Excel(name = "AGV供应商", width = 15)
@Schema(description = "AGV供应商")
@Dict(dicCode = "agv_vendor")
private java.lang.String agvVendor;
/**
*
*/

View File

@ -1,12 +1,12 @@
package org.cpte.modules.agvTask.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.cpte.modules.agvTask.entity.AgvTask;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import java.util.List;
/**
* @Description: AGV
* @author: cpte
@ -14,6 +14,21 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
* @Version: V1.0
*/
public interface AgvTaskMapper extends BaseMapper<AgvTask> {
@Select(value = "select count(agv.id) from data_agv_task where carrier_code = #{carrierCode} and start_code = #{startCode} and end_code= #{endCode} and status in ('CREATED','ARRIVED','EXECUTING') ")
Long isAGVTaskDuplicate(String carrierCode, String startCode, String endCode);
/**
* AGV
*
* @param carrierCode
* @param agvVendor ;AGV/TES
*/
@Select(value = "select count(id) from data_agv_task where carrier_code = #{carrierCode} and agv_vendor = #{agvVendor} and status in (1,2,3) ")
Long existsAGVTask(@Param("carrierCode") String carrierCode, @Param("agvVendor") String agvVendor);
/**
* AGV
*
* @param status
* @param agvVendor ;AGV/TES
*/
@Select(value = "select * from data_agv_task where status = #{status} and agv_vendor = #{agvVendor}")
List<AgvTask> queryAgvTaskList(@Param("status") Integer status, @Param("agvVendor") String agvVendor);
}

View File

@ -21,13 +21,8 @@ public interface IAgvTaskService extends IService<AgvTask> {
* @param endCode
* @param taskType
* @param type
* @param agvVendor
*/
AgvTask createAgvTask(String status, String carrierCode, String startCode, String endCode, String taskType,String type);
AgvTask createAgvTask(Integer status, String carrierCode, String startCode, String endCode, String taskType, String type, String agvVendor);
/**
* agvTask
*
* @param status
*/
List<AgvTask> queryAgvTaskList(String status);
}

View File

@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.cpte.modules.agvTask.entity.AgvTask;
import org.cpte.modules.agvTask.mapper.AgvTaskMapper;
import org.cpte.modules.agvTask.service.IAgvTaskService;
import org.cpte.modules.constant.enums.AgvVendorEnum;
import org.cpte.modules.constant.enums.StockTypeEnum;
import org.springframework.stereotype.Service;
@ -23,7 +24,11 @@ public class AgvTaskServiceImpl extends ServiceImpl<AgvTaskMapper, AgvTask> impl
@Override
@Transactional(rollbackFor = Exception.class)
public AgvTask createAgvTask(String status, String carrierCode, String startCode, String endCode, String taskType, String type) {
public AgvTask createAgvTask(Integer status, String carrierCode, String startCode, String endCode, String taskType, String type, String agvVendor) {
Integer priority = 99;
if (AgvVendorEnum.TES.getValue().equals(agvVendor)) {
priority = 3;
}
AgvTask agvTask = AgvTask.builder()
.carrierCode(carrierCode)
.type(type)
@ -32,15 +37,9 @@ public class AgvTaskServiceImpl extends ServiceImpl<AgvTaskMapper, AgvTask> impl
.endCode(endCode)
.carrierType(StockTypeEnum.TRAY.getValue())
.taskType(taskType)
.priority(99)
.priority(priority)
.agvVendor(agvVendor)
.build();
return this.save(agvTask) ? agvTask : null;
}
@Override
public List<AgvTask> queryAgvTaskList(String status) {
LambdaQueryWrapper<AgvTask> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(AgvTask::getStatus, status);
return this.list(queryWrapper);
}
}

View File

@ -37,5 +37,4 @@ public interface IStockService extends IService<Stock> {
*/
Map<String, Stock> queryByStockCodesToMap(List<String> stockCodes);
}

View File

@ -10,27 +10,27 @@ import lombok.Getter;
@Getter
public enum AgvStatusEnum {
CREATED("CREATED", "已创建"),
CREATED(1, "已创建"),
EXECUTING("EXECUTING", "执行中"),
EXECUTING(2, "执行中"),
ARRIVED("ARRIVED", "已到达"),
ARRIVED(3, "已到达"),
COMPLETED("COMPLETED", "已完成"),
COMPLETED(4, "已完成"),
CANCELLED("CANCELLED", "已取消"),
CANCELLED(5, "已取消"),
;
/**
*
*/
private final String value;
private final Integer value;
/**
*
*/
private final String desc;
AgvStatusEnum(String value, String desc) {
AgvStatusEnum(Integer value, String desc) {
this.value = value;
this.desc = desc;
}

View File

@ -0,0 +1,32 @@
package org.cpte.modules.constant.enums;
import lombok.Getter;
/**
* agv
*
* @author: cpte
*/
@Getter
public enum AgvVendorEnum {
HIK("HIK", "海康AGV"),
TES("TES", "旷视四向车"),
;
/**
*
*/
private final String value;
/**
*
*/
private final String desc;
AgvVendorEnum(String value, String desc) {
this.value = value;
this.desc = desc;
}
}

View File

@ -10,21 +10,18 @@ import lombok.Getter;
@Getter
public enum AsnStatusEnum {
CREATED("CREATED", "已创建"),
CREATED(1, "已创建"),
ACTIVE("ACTIVE", "已审核"),
RECEIVING(2, "部分收货"),
RECEIVING("RECEIVING", "部分收货"),
RECEIVED(3, "收货完成"),
RECEIVED("RECEIVED", "收货完成"),
CANCELED(4, "已取消"),
CLOSE("CLOSE", "已关闭"),
CANCEL("CANCEL", "已取消"),
;
AsnStatusEnum(String value, String desc) {
AsnStatusEnum(Integer value, String desc) {
this.value = value;
this.desc = desc;
}
@ -32,7 +29,7 @@ public enum AsnStatusEnum {
/**
*
*/
final String value;
final Integer value;
/**
*

View File

@ -0,0 +1,63 @@
package org.cpte.modules.constant.enums;
import lombok.Data;
import lombok.Getter;
/**
*
*
* @author: cpte
*/
@Getter
public enum InventoryStatusEnum {
/**
*
*/
AVAILABLE(1, "可用"),
/**
*
*/
ALLOCATED(2, "已分配"),
/**
*
*/
OUTBOUND(3, "出库中"),
/**
*
*/
TRANSFER(4, "移位中"),
/**
*
*/
COUNTING(5, "盘点中"),
/**
*
*/
FROZEN(6, "冻结"),
/**
*
*/
DEFECTIVE(7, "残次品");
InventoryStatusEnum(Integer value, String desc) {
this.value = value;
this.desc = desc;
}
/**
*
*/
final Integer value;
/**
*
*/
final String desc;
}

View File

@ -1,6 +1,5 @@
package org.cpte.modules.conveyorLine.controller;
import com.alibaba.fastjson.JSON;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;

View File

@ -1,6 +1,15 @@
package org.cpte.modules.conveyorLine.service.impl;
import lombok.extern.slf4j.Slf4j;
import org.cpte.modules.agvTask.mapper.AgvTaskMapper;
import org.cpte.modules.agvTask.service.IAgvTaskService;
import org.cpte.modules.base.entity.Stock;
import org.cpte.modules.base.mapper.StockMapper;
import org.cpte.modules.base.service.IStockService;
import org.cpte.modules.constant.enums.AgvStatusEnum;
import org.cpte.modules.constant.enums.AgvVendorEnum;
import org.cpte.modules.constant.enums.AsnStatusEnum;
import org.cpte.modules.constant.enums.BusinessTypeEnum;
import org.cpte.modules.conveyorLine.request.ScanTrayRequest;
import org.cpte.modules.conveyorLine.service.IConveyorLineService;
import org.cpte.modules.receive.entity.AsnDetail;
@ -12,15 +21,40 @@ import org.springframework.stereotype.Service;
@Service
@Slf4j
public class IConveyorLineServiceImpl implements IConveyorLineService {
@Autowired
private AsnDetailMapper asnDetailMapper;
@Autowired
private IStockService iStockService;
@Autowired
private AgvTaskMapper agvTaskMapper;
@Autowired
private IAgvTaskService iAgvTaskService;
@Override
public void scanTray(ScanTrayRequest scanTrayRequest) {
AsnDetail asnDetail=asnDetailMapper.queryByStockCode(scanTrayRequest.getStockCode());
if(asnDetail==null){
throw new RuntimeException("【"+scanTrayRequest.getStockCode()+"】托盘,无入库信息");
//验证托盘
Stock stock = iStockService.validateStock(scanTrayRequest.getStockCode());
//验证入库信息
AsnDetail asnDetail = asnDetailMapper.queryByStockCode(stock.getId(), AsnStatusEnum.CREATED.getValue());
if (asnDetail == null) {
throw new RuntimeException("【" + scanTrayRequest.getStockCode() + "】托盘,无入库信息");
}
//验证当前托盘是否有库存
//通过算法获取目标点位
String endCode = "CCQ01";
//验证当前托盘是否生成了TES任务
if (agvTaskMapper.existsAGVTask(stock.getStockCode(), AgvVendorEnum.TES.getValue()) > 0) {
throw new RuntimeException("【" + scanTrayRequest.getStockCode() + "】托盘已扫描,请勿重复扫描");
}
//验证通过生成Tes任务
iAgvTaskService.createAgvTask(AgvStatusEnum.CREATED.getValue(), stock.getStockCode(), null, endCode, null, BusinessTypeEnum.INBOUND.getValue(), AgvVendorEnum.TES.getValue());
}
}

View File

@ -1,20 +1,17 @@
package org.cpte.modules.hikAgv.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.cpte.modules.hikAgv.request.submit.SubmitRequest;
import org.cpte.modules.hikAgv.request.taskReporter.TaskReporterRequest;
import org.cpte.modules.hikAgv.response.ResponesData;
import org.cpte.modules.hikAgv.request.SubmitRequest;
import org.cpte.modules.hikAgv.request.TaskReporterRequest;
import org.cpte.modules.hikAgv.service.IHikAgvService;
import org.jeecg.common.api.vo.Result;
import org.cpte.modules.hikAgv.response.HikResult;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.config.shiro.IgnoreAuth;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
@ -27,34 +24,38 @@ import org.springframework.web.bind.annotation.RestController;
public class HikAgvController {
@Autowired
private IHikAgvService hikAgvService;
private IHikAgvService iHikAgvService;
/**
*
*
* @param submitRequest
*/
@AutoLog(value = "任务下发")
@AutoLog(value = "海康AGV-任务下发")
@Operation(summary = "海康AGV-任务下发")
@PostMapping(value = "/controller/task/submit")
@IgnoreAuth
public Result<String> submit(@RequestBody SubmitRequest submitRequest) {
hikAgvService.sendAgvTask("http://localhost:8000/cpte-wms/rcs/rtas/api/robot/controller/task/submit", JSON.toJSONString(submitRequest), null);
iHikAgvService.sendHikAgvTask(
"http://localhost:8000/cpte-wms/rcs/rtas/api/robot/controller/task/submit",
JSON.toJSONString(submitRequest),
null
);
return Result.OK("下发成功!");
}
@AutoLog(value = "任务上报")
@AutoLog(value = "海康AGV-任务上报")
@Operation(summary = "海康AGV-任务上报")
@PostMapping(value = "/reporter/task")
@IgnoreAuth
public HikResult taskReporter(@RequestBody TaskReporterRequest taskReporterRequest) {
try {
hikAgvService.taskReporter(taskReporterRequest);
ResponesData data = new ResponesData();
iHikAgvService.taskReporter(taskReporterRequest);
HikResult.ResponesData data = new HikResult.ResponesData();
data.setRobotTaskCode(taskReporterRequest.getRobotTaskCode());
return HikResult.success(data);
} catch (Exception e) {
return HikResult.error("上报失败: " + e.getMessage());
return HikResult.error("系统异常: " + e.getMessage());
}
}
}

View File

@ -0,0 +1,266 @@
package org.cpte.modules.hikAgv.request;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import lombok.Data;
import java.util.List;
/**
* AGV
* <p>
* AGVDTO
*
*/
@JsonPropertyOrder({
"taskType",
"targetRoute",
"initPriority",
"deadline",
"robotType",
"robotCode",
"interrupt",
"robotTaskCode",
"groupCode",
"extra"
})
@Data
public class SubmitRequest {
/**
*
* AGV
*/
@JsonProperty("taskType")
private String taskType;
/**
*
*
*/
@JsonProperty("targetRoute")
private List<TargetRoute> targetRoute;
/**
*
*
*/
@JsonProperty("initPriority")
private Integer initPriority;
/**
*
* ISO 86012021-04-04T12:23:55Z
*/
@JsonProperty("deadline")
private String deadline;
/**
*
*
* GROUPS:
* ROBOTS:
*/
@JsonProperty("robotType")
private String robotType;
/**
*
* robotType
*/
@JsonProperty("robotCode")
private List<String> robotCode;
/**
*
*
* 1: -
* 0: -
*/
@JsonProperty("interrupt")
private Integer interrupt;
/**
*
*
*/
@JsonProperty("robotTaskCode")
private String robotTaskCode;
/**
*
*
*/
@JsonProperty("groupCode")
private String groupCode;
/**
*
*
*
*/
@JsonProperty("extra")
private Extra extra;
@JsonPropertyOrder({
"seq",
"type",
"code",
"operation",
"robotType",
"robotCode",
"extra"
})
@Data
public static class TargetRoute {
/**
*
* 0
*/
@JsonProperty("seq")
private Integer seq;
/**
*
*
*/
@JsonProperty("type")
private String type;
/**
*
*
*/
@JsonProperty("code")
private String code;
/**
*
* AMR
*
* COLLECT:
* DELIVERY:
* ROTATE:
*/
@JsonProperty("operation")
private String operation;
/**
*
*
* GROUPS:
* ROBOTS:
*/
@JsonProperty("robotType")
private String robotType;
/**
*
* [robotType]
*/
@JsonProperty("robotCode")
private List<String> robotCode;
/**
*
* 使
*/
@JsonProperty("extra")
private Extra extra;
}
/**
*
* <p>
* AGV
*/
@JsonPropertyOrder({
"angleInfo",
"carrierInfo"
})
@Data
public static class Extra {
/**
*
* AGV
*/
@JsonProperty("angleInfo")
private AngleInfo angleInfo;
/**
*
*
*
*/
@JsonProperty("carrierInfo")
private List<CarrierInfo> carrierInfo;
}
/**
*
* <p>
* AGV
*/
@JsonPropertyOrder({
"type",
"code"
})
@Data
public static class AngleInfo {
/**
*
*
* ABSOLUTE:
*/
@JsonProperty("type")
private String type;
/**
*
* type
* [0, 90, 180, -90, 360]
*/
@JsonProperty("code")
private String code;
}
/**
*
* <p>
* AGV
*/
@JsonPropertyOrder({
"carrierType",
"carrierCode",
"layer"
})
@Data
public static class CarrierInfo {
/**
*
*
*/
@JsonProperty("carrierType")
private String carrierType;
/**
*
*
*/
@JsonProperty("carrierCode")
private String carrierCode;
/**
*
* 0
*/
@JsonProperty("layer")
private String layer;
}
}

View File

@ -0,0 +1,168 @@
package org.cpte.modules.hikAgv.request;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import lombok.Data;
/**
* AGV
* <p>
* AGVDTO
*
*/
@Data
public class TaskReporterRequest {
/**
*
*
*/
@JsonProperty("robotTaskCode")
private String robotTaskCode;
/**
*
* AGV
*/
@JsonProperty("singleRobotCode")
private String singleRobotCode;
/**
*
*
*/
@JsonProperty("extra")
private Extra extra;
@Data
public static class Extra {
@JsonProperty("async")
private String async;
//节点信息
@JsonProperty("values")
private Values values;
}
/**
* AGV
* <p>
* AGV
*/
@Data
public static class Values {
/**
*
* AGV
*/
@JsonProperty("mapCode")
private String mapCode;
/**
*
*
* BIN -
* SITE -
*/
@JsonProperty("slotCategory")
private String slotCategory;
/**
*
* AGV
*/
@JsonProperty("slotCode")
private String slotCode;
/**
*
* 1.
* 2.
*/
@JsonProperty("slotName")
private String slotName;
/**
* x
* AGVX
*/
@JsonProperty("x")
private Integer x;
/**
* y
* AGVY
*/
@JsonProperty("y")
private Integer y;
/**
*
* 使:
* start :
* outbin :
* end :
*/
@JsonProperty("method")
private String method;
/**
*
*
*/
@JsonProperty("carrierCategory")
private String carrierCategory;
/**
*
*
*/
@JsonProperty("carrierType")
private String carrierType;
/**
*
*
*/
@JsonProperty("carrierCode")
private String carrierCode;
/**
*
*
*/
@JsonProperty("amrCategory")
private String amrCategory;
/**
*
*
*/
@JsonProperty("amrType")
private String amrType;
/**
*
*
*/
@JsonProperty("amrCode")
private String amrCode;
/**
*
*
*/
@JsonProperty("carrierName")
private String carrierName;
/**
*
*
*/
@JsonProperty("carrierDir")
private String carrierDir;
}
}

View File

@ -1,28 +0,0 @@
package org.cpte.modules.hikAgv.request.submit;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
/**
*
*
* AGV
*/
@Data
public class AngleInfo {
/**
*
*
* ABSOLUTE:
*/
@JsonProperty("type")
private String type;
/**
*
* type
* [0, 90, 180, -90, 360]
*/
@JsonProperty("code")
private String code;
}

View File

@ -1,34 +0,0 @@
package org.cpte.modules.hikAgv.request.submit;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
/**
*
*
* AGV
*/
@Data
public class CarrierInfo {
/**
*
*
*/
@JsonProperty("carrierType")
private String carrierType;
/**
*
*
*/
@JsonProperty("carrierCode")
private String carrierCode;
/**
*
* 0
*/
@JsonProperty("layer")
private String layer;
}

View File

@ -1,30 +0,0 @@
package org.cpte.modules.hikAgv.request.submit;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
/**
*
*
* AGV
*/
@Data
public class Extra {
/**
*
* AGV
*/
@JsonProperty("angleInfo")
private AngleInfo angleInfo;
/**
*
*
*
*/
@JsonProperty("carrierInfo")
private List<CarrierInfo> carrierInfo;
}

View File

@ -1,104 +0,0 @@
package org.cpte.modules.hikAgv.request.submit;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import lombok.Data;
import java.util.List;
/**
* AGV
* <p>
* AGVDTO
*
*/
@JsonPropertyOrder({
"taskType",
"targetRoute",
"initPriority",
"deadline",
"robotType",
"robotCode",
"interrupt",
"robotTaskCode",
"groupCode",
"extra"
})
@Data
public class SubmitRequest {
/**
*
* AGV
*/
@JsonProperty("taskType")
private String taskType;
/**
*
*
*/
@JsonProperty("targetRoute")
private List<TargetRoute> targetRoute;
/**
*
*
*/
@JsonProperty("initPriority")
private Integer initPriority;
/**
*
* ISO 86012021-04-04T12:23:55Z
*/
@JsonProperty("deadline")
private String deadline;
/**
*
*
* GROUPS:
* ROBOTS:
*/
@JsonProperty("robotType")
private String robotType;
/**
*
* robotType
*/
@JsonProperty("robotCode")
private List<String> robotCode;
/**
*
*
* 1: -
* 0: -
*/
@JsonProperty("interrupt")
private Integer interrupt;
/**
*
*
*/
@JsonProperty("robotTaskCode")
private String robotTaskCode;
/**
*
*
*/
@JsonProperty("groupCode")
private String groupCode;
/**
*
*
*
*/
@JsonProperty("extra")
private Extra extra;
}

View File

@ -1,70 +0,0 @@
package org.cpte.modules.hikAgv.request.submit;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
/**
*
*
* AGV
*/
@Data
public class TargetRoute {
/**
*
* 0
*/
@JsonProperty("seq")
private Integer seq;
/**
*
*
*/
@JsonProperty("type")
private String type;
/**
*
*
*/
@JsonProperty("code")
private String code;
/**
*
* AMR
*
* COLLECT:
* DELIVERY:
* ROTATE:
*/
@JsonProperty("operation")
private String operation;
/**
*
*
* GROUPS:
* ROBOTS:
*/
@JsonProperty("robotType")
private String robotType;
/**
*
* [robotType]
*/
@JsonProperty("robotCode")
private List<String> robotCode;
/**
*
* 使
*/
@JsonProperty("extra")
private Extra extra;
}

View File

@ -1,15 +0,0 @@
package org.cpte.modules.hikAgv.request.taskReporter;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@Data
public class Extra {
@JsonProperty("async")
private String async;
//节点信息
@JsonProperty("values")
private Values values;
}

View File

@ -1,36 +0,0 @@
package org.cpte.modules.hikAgv.request.taskReporter;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
/**
* AGV
* <p>
* AGVDTO
*
*/
@Data
public class TaskReporterRequest {
/**
*
*
*/
@JsonProperty("robotTaskCode")
private String robotTaskCode;
/**
*
* AGV
*/
@JsonProperty("singleRobotCode")
private String singleRobotCode;
/**
*
*
*/
@JsonProperty("extra")
private Extra extra;
}

View File

@ -1,124 +0,0 @@
package org.cpte.modules.hikAgv.request.taskReporter;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
/**
* AGV
* <p>
* AGV
*/
@Data
public class Values {
/**
*
* AGV
*/
@JsonProperty("mapCode")
private String mapCode;
/**
*
*
* BIN -
* SITE -
*/
@JsonProperty("slotCategory")
private String slotCategory;
/**
*
* AGV
*/
@JsonProperty("slotCode")
private String slotCode;
/**
*
* 1.
* 2.
*/
@JsonProperty("slotName")
private String slotName;
/**
* x
* AGVX
*/
@JsonProperty("x")
private Integer x;
/**
* y
* AGVY
*/
@JsonProperty("y")
private Integer y;
/**
*
* 使:
* start :
* outbin :
* end :
*/
@JsonProperty("method")
private String method;
/**
*
*
*/
@JsonProperty("carrierCategory")
private String carrierCategory;
/**
*
*
*/
@JsonProperty("carrierType")
private String carrierType;
/**
*
*
*/
@JsonProperty("carrierCode")
private String carrierCode;
/**
*
*
*/
@JsonProperty("amrCategory")
private String amrCategory;
/**
*
*
*/
@JsonProperty("amrType")
private String amrType;
/**
*
*
*/
@JsonProperty("amrCode")
private String amrCode;
/**
*
*
*/
@JsonProperty("carrierName")
private String carrierName;
/**
*
*
*/
@JsonProperty("carrierDir")
private String carrierDir;
}

View File

@ -1,7 +1,10 @@
package org.cpte.modules.hikAgv.response;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
/**
@ -11,24 +14,38 @@ import java.io.Serializable;
* @email cpteos@163.com
* @date 2019119
*/
@JsonPropertyOrder({
"code",
"message",
"data"
})
@Data
public class HikResult implements Serializable {
/**
*
*/
@JsonProperty("code")
private String code = "";
/**
*
*/
@JsonProperty("message")
private String message = "";
/**
* data
*/
@JsonProperty("data")
private ResponesData data;
@Data
public static class ResponesData {
@JsonProperty("robotTaskCode")
private String robotTaskCode;
}
public static HikResult success(ResponesData data) {
HikResult response = new HikResult();
response.code = "SUCCESS";

View File

@ -1,10 +0,0 @@
package org.cpte.modules.hikAgv.response;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@Data
public class ResponesData {
@JsonProperty("robotTaskCode")
private String robotTaskCode;
}

View File

@ -1,8 +1,8 @@
package org.cpte.modules.hikAgv.service;
import org.cpte.modules.agvTask.entity.AgvTask;
import org.cpte.modules.hikAgv.request.submit.SubmitRequest;
import org.cpte.modules.hikAgv.request.taskReporter.TaskReporterRequest;
import org.cpte.modules.hikAgv.request.SubmitRequest;
import org.cpte.modules.hikAgv.request.TaskReporterRequest;
public interface IHikAgvService {
/**
@ -10,7 +10,7 @@ public interface IHikAgvService {
*
* @param agvTask
*/
SubmitRequest generateAgvTaskJson(AgvTask agvTask);
String generateHikAgvTaskJson(AgvTask agvTask);
/**
*
@ -19,7 +19,7 @@ public interface IHikAgvService {
* @param json json
* @param agvTask
*/
void sendAgvTask(String url, String json, AgvTask agvTask);
void sendHikAgvTask(String url, String json, AgvTask agvTask);
/**
*

View File

@ -8,8 +8,8 @@ import org.cpte.modules.agvTask.entity.AgvTask;
import org.cpte.modules.agvTask.mapper.AgvTaskMapper;
import org.cpte.modules.agvTask.service.IAgvTaskService;
import org.cpte.modules.constant.enums.*;
import org.cpte.modules.hikAgv.request.submit.*;
import org.cpte.modules.hikAgv.request.taskReporter.TaskReporterRequest;
import org.cpte.modules.hikAgv.request.SubmitRequest;
import org.cpte.modules.hikAgv.request.TaskReporterRequest;
import org.cpte.modules.hikAgv.service.IHikAgvService;
import org.jeecg.modules.system.mapper.SysDictMapper;
import org.springframework.beans.factory.annotation.Autowired;
@ -25,12 +25,21 @@ import java.util.*;
@Slf4j
public class IHikAgvServiceImpl implements IHikAgvService {
// 接口开关
/**
*
*/
final String open_flag = "OPEN";
// 成功码
/**
*
*/
final String success_code = "SUCCESS";
/**
*
*/
final String fail_code = "FAILED";
@Autowired
private SysDictMapper sysDictMapper;
@ -41,18 +50,18 @@ public class IHikAgvServiceImpl implements IHikAgvService {
private IAgvTaskService iAgvTaskService;
@Override
public SubmitRequest generateAgvTaskJson(AgvTask agvTask) {
public String generateHikAgvTaskJson(AgvTask agvTask) {
SubmitRequest submitRequest = new SubmitRequest();
submitRequest.setTaskType("PF-LMR-COMMON");
// 设置起点路径
TargetRoute srcTargetRoute = createSrcTargetRoute(agvTask);
SubmitRequest.TargetRoute srcTargetRoute = createSrcTargetRoute(agvTask);
// 设置终点路径
TargetRoute dstTargetRoute = createDstTargetRoute(agvTask);
SubmitRequest.TargetRoute dstTargetRoute = createDstTargetRoute(agvTask);
submitRequest.setTargetRoute(Arrays.asList(srcTargetRoute, dstTargetRoute));
submitRequest.setInitPriority(agvTask == null ? 99 : agvTask.getPriority());
submitRequest.setInitPriority( agvTask.getPriority());
LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC);
String deadline = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'"));
@ -61,23 +70,23 @@ public class IHikAgvServiceImpl implements IHikAgvService {
submitRequest.setRobotType("GROUPS");
submitRequest.setRobotCode(Collections.singletonList("c3a1e7bb"));
Extra extra1 = new Extra();
extra1.setCarrierInfo(createCarrierInfoList(agvTask == null ? "" : agvTask.getCarrierCode()));
SubmitRequest.Extra extra1 = new SubmitRequest.Extra();
extra1.setCarrierInfo(createCarrierInfoList(agvTask.getCarrierCode()));
submitRequest.setExtra(extra1);
submitRequest.setInterrupt(0);
submitRequest.setRobotTaskCode(agvTask == null ? "" : agvTask.getId());
submitRequest.setGroupCode(agvTask == null ? "" : agvTask.getId());
submitRequest.setRobotTaskCode(agvTask.getId().toString());
submitRequest.setGroupCode(agvTask.getId().toString());
return submitRequest;
return JSON.toJSONString(submitRequest);
}
@Override
public void sendAgvTask(String url, String json, AgvTask agvTask) {
public void sendHikAgvTask(String url, String json, AgvTask agvTask) {
log.info("请求报文:{}", json);
// 检查接口开关, 未开启则返回
if (sysDictMapper.queryByDictCode(open_flag) == null) {
updateAgvTaskResponse(agvTask, "接口未开启", "FAILED");
updateAgvTaskResponse(agvTask, "接口未开启", fail_code);
return;
}
@ -111,7 +120,7 @@ public class IHikAgvServiceImpl implements IHikAgvService {
updateAgvTaskResponse(agvTask, message, code);
} catch (Exception e) {
// 记录异常到 AgvTask
updateAgvTaskResponse(agvTask, e.getMessage(), "FAILED");
updateAgvTaskResponse(agvTask, e.getMessage(), fail_code);
throw e; // 继续向上抛出异常供 Controller 层处理
}
}
@ -120,6 +129,9 @@ public class IHikAgvServiceImpl implements IHikAgvService {
@Transactional(rollbackFor = Exception.class)
public void taskReporter(TaskReporterRequest taskReporterRequest) {
AgvTask agvTask = agvTaskMapper.selectById(taskReporterRequest.getRobotTaskCode());
if (agvTask == null) {
throw new RuntimeException("【" + taskReporterRequest.getRobotTaskCode() + "】任务不存在");
}
String status = taskReporterRequest.getExtra().getValues().getMethod();
switch (status) {
case "outbin":
@ -161,19 +173,19 @@ public class IHikAgvServiceImpl implements IHikAgvService {
/**
*
*
* @param agvTask
* @param agvTask
*/
private void handleResend(AgvTask agvTask) {
Long count = agvTaskMapper.isAGVTaskDuplicate(agvTask.getCarrierCode(), agvTask.getStartCode(), agvTask.getEndCode());
Long count = agvTaskMapper.existsAGVTask(agvTask.getCarrierCode(),AgvVendorEnum.HIK.getValue());
if (count > 0) {
throw new RuntimeException("任务已重新生成,请勿重复操作! ");
}
AgvTask newAgvTask = iAgvTaskService.createAgvTask(AgvStatusEnum.CREATED.getValue(), agvTask.getCarrierCode(), agvTask.getStartCode(), agvTask.getEndCode(), agvTask.getTaskType(), agvTask.getType());
AgvTask newAgvTask = iAgvTaskService.createAgvTask(AgvStatusEnum.CREATED.getValue(), agvTask.getCarrierCode(), agvTask.getStartCode(), agvTask.getEndCode(), null, agvTask.getType(),AgvVendorEnum.HIK.getValue());
switch (agvTask.getType()) {
case "INBOUND":
case "OUTBOUND":
//下发任务
sendAgvTask("", "", newAgvTask);
//下发海康AGV任务
sendHikAgvTask("", "", newAgvTask);
break;
default:
throw new RuntimeException("任务类型不支持: " + agvTask.getType());
@ -198,11 +210,11 @@ public class IHikAgvServiceImpl implements IHikAgvService {
* @param agvTask
* @return TargetRoute
*/
private TargetRoute createSrcTargetRoute(AgvTask agvTask) {
TargetRoute srcTargetRoute = new TargetRoute();
private SubmitRequest.TargetRoute createSrcTargetRoute(AgvTask agvTask) {
SubmitRequest.TargetRoute srcTargetRoute = new SubmitRequest.TargetRoute();
srcTargetRoute.setSeq(0);
srcTargetRoute.setType("ZONE");
srcTargetRoute.setCode(agvTask == null ? "" : agvTask.getStartCode());
srcTargetRoute.setCode(agvTask.getStartCode());
srcTargetRoute.setOperation("COLLECT");
srcTargetRoute.setExtra(null);
srcTargetRoute.setRobotType("GROUPS");
@ -216,29 +228,29 @@ public class IHikAgvServiceImpl implements IHikAgvService {
* @param agvTask
* @return TargetRoute
*/
private TargetRoute createDstTargetRoute(AgvTask agvTask) {
TargetRoute dstTargetRoute = new TargetRoute();
private SubmitRequest.TargetRoute createDstTargetRoute(AgvTask agvTask) {
SubmitRequest.TargetRoute dstTargetRoute = new SubmitRequest.TargetRoute();
dstTargetRoute.setSeq(1);
dstTargetRoute.setType("SITE");
dstTargetRoute.setCode(agvTask == null ? "" : agvTask.getEndCode());
dstTargetRoute.setCode(agvTask.getEndCode());
dstTargetRoute.setOperation("DELIVERY");
Extra extra = new Extra();
SubmitRequest.Extra extra = new SubmitRequest.Extra();
AngleInfo angleInfo = new AngleInfo();
SubmitRequest.AngleInfo angleInfo = new SubmitRequest.AngleInfo();
angleInfo.setType("RELATIVE");
angleInfo.setCode("90");
extra.setAngleInfo(angleInfo);
extra.setCarrierInfo(createCarrierInfoList(agvTask == null ? "" : agvTask.getCarrierCode()));
extra.setCarrierInfo(createCarrierInfoList(agvTask.getCarrierCode()));
dstTargetRoute.setExtra(extra);
return dstTargetRoute;
}
private List<CarrierInfo> createCarrierInfoList(String carrierCode) {
List<CarrierInfo> carrierInfoList = new ArrayList<>();
CarrierInfo cif = new CarrierInfo();
private List<SubmitRequest.CarrierInfo> createCarrierInfoList(String carrierCode) {
List<SubmitRequest.CarrierInfo> carrierInfoList = new ArrayList<>();
SubmitRequest.CarrierInfo cif = new SubmitRequest.CarrierInfo();
cif.setCarrierType("1"); // 建议替换为常量
cif.setCarrierCode(carrierCode);
cif.setLayer("0");

View File

@ -0,0 +1,182 @@
package org.cpte.modules.inventory.controller;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.query.QueryRuleEnum;
import org.jeecg.common.util.oConvertUtils;
import org.cpte.modules.inventory.entity.Inventory;
import org.cpte.modules.inventory.service.IInventoryService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.jeecg.common.system.base.controller.JeecgController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;
import com.alibaba.fastjson.JSON;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.apache.shiro.authz.annotation.RequiresPermissions;
/**
* @Description:
* @author: cpte
* @Date: 2025-11-08
* @Version: V1.0
*/
@Tag(name="库存表")
@RestController
@RequestMapping("/inventory")
@Slf4j
public class InventoryController extends JeecgController<Inventory, IInventoryService> {
@Autowired
private IInventoryService inventoryService;
/**
*
*
* @param inventory
* @param pageNo
* @param pageSize
* @param req
* @return
*/
//@AutoLog(value = "库存表-分页列表查询")
@Operation(summary="库存表-分页列表查询")
@GetMapping(value = "/list")
public Result<IPage<Inventory>> queryPageList(Inventory inventory,
@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
HttpServletRequest req) {
QueryWrapper<Inventory> queryWrapper = QueryGenerator.initQueryWrapper(inventory, req.getParameterMap());
Page<Inventory> page = new Page<Inventory>(pageNo, pageSize);
IPage<Inventory> pageList = inventoryService.page(page, queryWrapper);
return Result.OK(pageList);
}
/**
*
*
* @param inventory
* @return
*/
@AutoLog(value = "库存表-添加")
@Operation(summary="库存表-添加")
@RequiresPermissions("inventory:data_inventory:add")
@PostMapping(value = "/add")
public Result<String> add(@RequestBody Inventory inventory) {
inventoryService.save(inventory);
return Result.OK("添加成功!");
}
/**
*
*
* @param inventory
* @return
*/
@AutoLog(value = "库存表-编辑")
@Operation(summary="库存表-编辑")
@RequiresPermissions("inventory:data_inventory:edit")
@RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST})
public Result<String> edit(@RequestBody Inventory inventory) {
inventoryService.updateById(inventory);
return Result.OK("编辑成功!");
}
/**
* id
*
* @param id
* @return
*/
@AutoLog(value = "库存表-通过id删除")
@Operation(summary="库存表-通过id删除")
@RequiresPermissions("inventory:data_inventory:delete")
@DeleteMapping(value = "/delete")
public Result<String> delete(@RequestParam(name="id",required=true) String id) {
inventoryService.removeById(id);
return Result.OK("删除成功!");
}
/**
*
*
* @param ids
* @return
*/
@AutoLog(value = "库存表-批量删除")
@Operation(summary="库存表-批量删除")
@RequiresPermissions("inventory:data_inventory:deleteBatch")
@DeleteMapping(value = "/deleteBatch")
public Result<String> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
this.inventoryService.removeByIds(Arrays.asList(ids.split(",")));
return Result.OK("批量删除成功!");
}
/**
* id
*
* @param id
* @return
*/
//@AutoLog(value = "库存表-通过id查询")
@Operation(summary="库存表-通过id查询")
@GetMapping(value = "/queryById")
public Result<Inventory> queryById(@RequestParam(name="id",required=true) String id) {
Inventory inventory = inventoryService.getById(id);
if(inventory==null) {
return Result.error("未找到对应数据");
}
return Result.OK(inventory);
}
/**
* excel
*
* @param request
* @param inventory
*/
@RequiresPermissions("inventory:data_inventory:exportXls")
@RequestMapping(value = "/exportXls")
public ModelAndView exportXls(HttpServletRequest request, Inventory inventory) {
return super.exportXls(request, inventory, Inventory.class, "库存表");
}
/**
* excel
*
* @param request
* @param response
* @return
*/
@RequiresPermissions("inventory:data_inventory:importExcel")
@RequestMapping(value = "/importExcel", method = RequestMethod.POST)
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
return super.importExcel(request, response, Inventory.class);
}
}

View File

@ -0,0 +1,156 @@
package org.cpte.modules.inventory.entity;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.TableLogic;
import lombok.*;
import org.jeecg.common.constant.ProvinceCityArea;
import org.jeecg.common.util.SpringContextUtils;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.jeecg.common.aspect.annotation.Dict;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.experimental.Accessors;
/**
* @Description:
* @author: cpte
* @Date: 2025-11-08
* @Version: V1.0
*/
@Schema(description = "库存表")
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@TableName("data_inventory")
public class Inventory implements Serializable {
private static final long serialVersionUID = 1L;
/**
* ID
*/
@TableId(type = IdType.AUTO)
@Schema(description = "ID")
private java.lang.Integer id;
/**
* ID
*/
@Excel(name = "物料ID", width = 15)
@Schema(description = "物料ID")
@Dict(dictTable = "base_item", dicCode = "id", dicText = "item_code")
private java.lang.String itemId;
/**
* ID
*/
@Excel(name = "库位ID", width = 15)
@Schema(description = "库位ID")
@Dict(dictTable = "base_point", dicCode = "id", dicText = "point_code")
private java.lang.String pointId;
/**
* ID
*/
@Excel(name = "容器ID", width = 15)
@Schema(description = "容器ID")
@Dict(dictTable = "base_stock", dicCode = "id", dicText = "stock_code")
private java.lang.String stockId;
/**
*
*/
@Excel(name = "数量", width = 15)
@Schema(description = "数量")
private java.math.BigDecimal quantity;
/**
*
*/
@Excel(name = "分配数", width = 15)
@Schema(description = "分配数")
private java.math.BigDecimal queuedQty;
/**
*
*/
@Excel(name = "外部仓库", width = 15)
@Schema(description = "外部仓库")
private java.lang.String whCode;
/**
*
*/
@Excel(name = "批次号", width = 15)
@Schema(description = "批次号")
private java.lang.String propC1;
/**
*
*/
@Excel(name = "序列号", width = 15)
@Schema(description = "序列号")
private java.lang.String propC2;
/**
*
*/
@Excel(name = "外部库存状态", width = 15)
@Schema(description = "外部库存状态")
private java.lang.String propC3;
/**
*
*/
@Excel(name = "库存状态", width = 15)
@Schema(description = "库存状态")
@Dict(dicCode = "inventory_status")
private java.lang.Integer status;
/**
*
*/
@Excel(name = "生产日期", width = 15, format = "yyyy-MM-dd")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
@Schema(description = "生产日期")
private java.util.Date propD1;
/**
*
*/
@Excel(name = "描述", width = 15)
@Schema(description = "描述")
private java.lang.String description;
/**
*
*/
@Schema(description = "所属部门")
private java.lang.String sysOrgCode;
/**
* ID
*/
@Excel(name = "租户ID", width = 15)
@Schema(description = "租户ID")
private java.lang.Integer tenantId;
/**
*
*/
@Schema(description = "创建人")
private java.lang.String createBy;
/**
*
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Schema(description = "创建日期")
private java.util.Date createTime;
/**
*
*/
@Schema(description = "更新人")
private java.lang.String updateBy;
/**
*
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Schema(description = "更新日期")
private java.util.Date updateTime;
}

View File

@ -0,0 +1,26 @@
package org.cpte.modules.inventory.mapper;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.cpte.modules.inventory.entity.Inventory;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @Description:
* @author: cpte
* @Date: 2025-11-08
* @Version: V1.0
*/
public interface InventoryMapper extends BaseMapper<Inventory> {
/**
*
*
* @param stockId
* @return
*/
@Select("select * from data_inventory where stock_id = #{stockId} ")
Inventory selectByStockId(@Param("stockId") String stockId);
}

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.cpte.modules.inventory.mapper.InventoryMapper">
</mapper>

View File

@ -0,0 +1,14 @@
package org.cpte.modules.inventory.service;
import org.cpte.modules.inventory.entity.Inventory;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* @Description:
* @author: cpte
* @Date: 2025-11-08
* @Version: V1.0
*/
public interface IInventoryService extends IService<Inventory> {
}

View File

@ -0,0 +1,19 @@
package org.cpte.modules.inventory.service.impl;
import org.cpte.modules.inventory.entity.Inventory;
import org.cpte.modules.inventory.mapper.InventoryMapper;
import org.cpte.modules.inventory.service.IInventoryService;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
/**
* @Description:
* @author: cpte
* @Date: 2025-11-08
* @Version: V1.0
*/
@Service
public class InventoryServiceImpl extends ServiceImpl<InventoryMapper, Inventory> implements IInventoryService {
}

View File

@ -1,12 +1,11 @@
package org.cpte.modules.quartz.job;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.cpte.modules.agvTask.entity.AgvTask;
import org.cpte.modules.agvTask.service.IAgvTaskService;
import org.cpte.modules.agvTask.mapper.AgvTaskMapper;
import org.cpte.modules.constant.enums.AgvStatusEnum;
import org.cpte.modules.constant.enums.AgvVendorEnum;
import org.cpte.modules.hikAgv.service.IHikAgvService;
import org.jeecg.common.util.DateUtils;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
@ -15,9 +14,9 @@ import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
@Slf4j
public class AgvTaskJob implements Job {
public class HikAgvJob implements Job {
@Autowired
private IAgvTaskService agvTaskService;
private AgvTaskMapper agvTaskMapper;
@Autowired
private IHikAgvService hikAgvService;
@ -25,11 +24,15 @@ public class AgvTaskJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
// 查询待执行任务
List<AgvTask> agvTaskList = agvTaskService.queryAgvTaskList(AgvStatusEnum.CREATED.getValue());
List<AgvTask> agvTaskList = agvTaskMapper.queryAgvTaskList(AgvStatusEnum.CREATED.getValue(), AgvVendorEnum.HIK.getValue());
String taskSubmitUrl = "http://localhost:8000/cpte-wms/rcs/rtas/api/robot/controller/task/submit";
for (AgvTask agvTask : agvTaskList) {
try {
hikAgvService.sendAgvTask(taskSubmitUrl, JSON.toJSONString(hikAgvService.generateAgvTaskJson(agvTask)), agvTask);
hikAgvService.sendHikAgvTask(
taskSubmitUrl,
hikAgvService.generateHikAgvTaskJson(agvTask),
agvTask
);
} catch (Exception e) {
log.error("发送AGV任务失败任务ID: {}", agvTask.getId(), e);
}

View File

@ -0,0 +1,42 @@
package org.cpte.modules.quartz.job;
import lombok.extern.slf4j.Slf4j;
import org.cpte.modules.agvTask.entity.AgvTask;
import org.cpte.modules.agvTask.mapper.AgvTaskMapper;
import org.cpte.modules.constant.enums.AgvStatusEnum;
import org.cpte.modules.constant.enums.AgvVendorEnum;
import org.cpte.modules.hikAgv.service.IHikAgvService;
import org.cpte.modules.tesAgv.service.ITesAgvService;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
@Slf4j
public class TesAgvJob implements Job {
@Autowired
private AgvTaskMapper agvTaskMapper;
@Autowired
private ITesAgvService tesAgvService;
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
// 查询待执行任务
List<AgvTask> agvTaskList = agvTaskMapper.queryAgvTaskList(AgvStatusEnum.CREATED.getValue(), AgvVendorEnum.TES.getValue());
String taskSubmitUrl = "http://localhost:8000/cpte-wms/tes/apiv2/newMovePodTask";
for (AgvTask agvTask : agvTaskList) {
try {
tesAgvService.sendTesAgvTask(
taskSubmitUrl,
tesAgvService.generateTesAgvTaskJson(agvTask),
agvTask
);
} catch (Exception e) {
log.error("发送AGV任务失败任务ID: {}", agvTask.getId(), e);
}
}
}
}

View File

@ -82,11 +82,12 @@ public class Asn implements Serializable {
private java.lang.Integer orderType;
/**
*
* 1.;2.;3.;4.
*/
@Excel(name = "订单状态", width = 15)
@Schema(description = "订单状态")
@Dict(dicCode = "asn_status")
private java.lang.String status;
private java.lang.Integer status;
/**
*
*/

View File

@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.annotation.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.NoArgsConstructor;
import org.jeecg.common.aspect.annotation.Dict;
import org.jeecg.common.constant.ProvinceCityArea;
import org.jeecg.common.util.SpringContextUtils;
import lombok.Data;
@ -100,6 +101,14 @@ public class AsnDetail implements Serializable {
@Excel(name = "收货数量", width = 15)
@Schema(description = "收货数量")
private java.math.BigDecimal receivedQty;
/**
*
* 1.;2.;3.;4.
*/
@Excel(name = "状态", width = 15)
@Schema(description = "状态")
@Dict(dicCode = "asn_status")
private java.lang.Integer status;
/**
*
*/
@ -185,4 +194,7 @@ public class AsnDetail implements Serializable {
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Schema(description = "更新日期")
private java.util.Date updateTime;
@Version
private Integer updateCount;
}

View File

@ -0,0 +1,118 @@
package org.cpte.modules.receive.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
@Schema(description = "入库记录")
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@TableName("data_receive_record")
public class ReceiveRecord implements Serializable {
private static final long serialVersionUID = 1L;
/**
*
*/
@TableId(type = IdType.ASSIGN_ID)
@Schema(description = "主键")
private java.lang.String id;
/**
*
*/
@Schema(description = "入库明细")
private java.lang.String asnDetailId;
/**
*
*/
@Schema(description = "容器")
private java.lang.String stockId;
/**
*
*/
@Schema(description = "库位")
private java.lang.String pointId;
/**
*
*/
@Schema(description = "物料")
private java.lang.String itemId;
/**
*
*/
@Schema(description = "收货数量")
private java.math.BigDecimal receivedQty;
/**
*
*/
@Schema(description = "批次号")
private java.lang.String propC1;
/**
*
*/
@Schema(description = "序列号")
private java.lang.String propC2;
/**
*
*/
@Schema(description = "库存状态")
private java.lang.String propC3;
/**
*
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
@Schema(description = "生产日期")
private java.util.Date propD1;
/**
*
*/
@Schema(description = "备注")
private java.lang.String description;
/**
* ID
*/
@Schema(description = "仓库ID")
private java.lang.Integer tenantId;
/**
*
*/
@Schema(description = "所属部门")
private java.lang.String sysOrgCode;
/**
*
*/
@Schema(description = "创建人")
private java.lang.String createBy;
/**
*
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Schema(description = "创建日期")
private java.util.Date createTime;
/**
*
*/
@Schema(description = "更新人")
private java.lang.String updateBy;
/**
*
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Schema(description = "更新日期")
private java.util.Date updateTime;
}

View File

@ -34,15 +34,12 @@ public interface AsnDetailMapper extends BaseMapper<AsnDetail> {
/**
*
* ID
*
* @param stockCode
* @param stockId id
* @param status
* @return AsnDetail
*/
@Select("select * from data_asn_detail " +
"join data_asn on data_asn.id=data_asn_detail.asn_id " +
"join base_stock on data_asn_detail.stock_id=base_stock.id " +
"where base_stock.stock_code = #{stockCode} " +
"and data_asn.status='CREATED' ")
AsnDetail queryByStockCode(@Param("stockCode") String stockCode);
@Select("select * from data_asn_detail where stock_id = #{stockId} and status = #{status} ")
AsnDetail queryByStockCode(@Param("stockId") String stockId, @Param("status") Integer status);
}

View File

@ -0,0 +1,7 @@
package org.cpte.modules.receive.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.cpte.modules.receive.entity.ReceiveRecord;
public interface ReceiveRecordMapper extends BaseMapper<ReceiveRecord> {
}

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.cpte.modules.receive.mapper.ReceiveRecordMapper">
</mapper>

View File

@ -4,6 +4,7 @@ import org.cpte.modules.receive.entity.AsnDetail;
import org.cpte.modules.receive.entity.Asn;
import com.baomidou.mybatisplus.extension.service.IService;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.List;
@ -45,5 +46,11 @@ public interface IAsnService extends IService<Asn> {
*/
public void delBatchMain (Collection<? extends Serializable> idList);
/**
*
*
* @param stockCode
*/
void receiveGoods(String stockCode);
}

View File

@ -1,12 +1,25 @@
package org.cpte.modules.receive.service.impl;
import lombok.extern.slf4j.Slf4j;
import org.cpte.modules.base.entity.Point;
import org.cpte.modules.base.entity.Stock;
import org.cpte.modules.base.mapper.PointMapper;
import org.cpte.modules.base.mapper.StockMapper;
import org.cpte.modules.base.service.IStockService;
import org.cpte.modules.constant.enums.AsnStatusEnum;
import org.cpte.modules.constant.enums.CommonStatusEnum;
import org.cpte.modules.constant.enums.InventoryStatusEnum;
import org.cpte.modules.inventory.entity.Inventory;
import org.cpte.modules.inventory.mapper.InventoryMapper;
import org.cpte.modules.receive.entity.Asn;
import org.cpte.modules.receive.entity.AsnDetail;
import org.cpte.modules.receive.entity.ReceiveRecord;
import org.cpte.modules.receive.mapper.AsnDetailMapper;
import org.cpte.modules.receive.mapper.AsnMapper;
import org.cpte.modules.receive.mapper.ReceiveRecordMapper;
import org.cpte.modules.receive.service.IAsnService;
import org.cpte.modules.utils.BigDecimalUtil;
import org.jeecg.common.constant.CommonSendStatus;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
@ -15,6 +28,7 @@ import org.springframework.transaction.annotation.Transactional;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Collection;
import java.util.concurrent.atomic.AtomicInteger;
@ -26,12 +40,23 @@ import java.util.concurrent.atomic.AtomicInteger;
* @Version: V1.0
*/
@Service
@Slf4j
public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnService {
@Autowired
private StockMapper stockMapper;
@Autowired
private PointMapper pointMapper;
@Autowired
private AsnMapper asnMapper;
@Autowired
private AsnDetailMapper asnDetailMapper;
@Autowired
private ReceiveRecordMapper receiveRecordMapper;
@Autowired
private InventoryMapper inventoryMapper;
@Autowired
private IStockService iStockService;
@Override
@Transactional(rollbackFor = Exception.class)
@ -46,7 +71,6 @@ public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnS
entity.setAsnId(asn.getId());
asnDetailMapper.insert(entity);
}
}
//刷新入库单
refreshAsn(asn, asnDetailList);
@ -65,7 +89,7 @@ public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnS
BigDecimal receivedQty = asnDetails.stream().map(AsnDetail::getReceivedQty).reduce(BigDecimal.ZERO, BigDecimal::add);
//当前状态
String status = asn.getStatus();
Integer status = asn.getStatus();
if (orderQty.compareTo(BigDecimal.ZERO) >= 0 && receivedQty.compareTo(BigDecimal.ZERO) == 0) {
status = AsnStatusEnum.CREATED.getValue();
@ -84,22 +108,21 @@ public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnS
@Override
@Transactional(rollbackFor = Exception.class)
public void updateMain(Asn asn, List<AsnDetail> asnDetailList) {
// 直接更新主表
asnMapper.updateById(asn);
//1.先删除子表数据
asnDetailMapper.deleteByMainId(asn.getId());
//2.子表数据重新插入
// 更新明细表 - 只更新传入的明细数据
if (asnDetailList != null && !asnDetailList.isEmpty()) {
AtomicInteger lineNoCounter = new AtomicInteger(1);
for (AsnDetail entity : asnDetailList) {
if (entity.getLineNo() == null || entity.getLineNo() == 0) {
entity.setLineNo(lineNoCounter.getAndIncrement());
}
entity.setAsnId(asn.getId());
asnDetailMapper.insert(entity);
// 直接更新,而不是删除后重新插入
if (entity.getId() != null) {
asnDetailMapper.updateById(entity);
}
}
}
// 刷新入库单状态
refreshAsn(asn, asnDetailList);
}
@ -107,6 +130,10 @@ public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnS
@Override
@Transactional(rollbackFor = Exception.class)
public void delMain(String id) {
Asn asn = this.getById(id);
if(!AsnStatusEnum.CREATED.getValue().equals(asn.getStatus())){
throw new RuntimeException("操作失败:【" + asn.getOrderNo() + "】入库单,非创建状态不允许删除");
}
asnDetailMapper.deleteByMainId(id);
asnMapper.deleteById(id);
}
@ -114,10 +141,119 @@ public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnS
@Override
@Transactional(rollbackFor = Exception.class)
public void delBatchMain(Collection<? extends Serializable> idList) {
List<String> orderNoList = new ArrayList<>();
for (Serializable id : idList) {
Asn asn = this.getById(id);
if(!AsnStatusEnum.CREATED.getValue().equals(asn.getStatus())){
orderNoList.add(asn.getOrderNo());
continue;
}
asnDetailMapper.deleteByMainId(id.toString());
asnMapper.deleteById(id);
}
if(!orderNoList.isEmpty()){
throw new RuntimeException("操作失败:【" + orderNoList + "】入库单,非创建状态不允许删除");
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public void receiveGoods(String stockCode) {
//验证容器
Stock stock = iStockService.validateStock(stockCode);
AsnDetail asnDetail = asnDetailMapper.queryByStockCode(stock.getId(), AsnStatusEnum.CREATED.getValue());
if (asnDetail == null) {
throw new RuntimeException("【" + stockCode + "】托盘,无入库信息");
}
Asn asn = this.getById(asnDetail.getAsnId());
//更新收货数量
BigDecimal receivedQty = BigDecimalUtil.add(asnDetail.getReceivedQty(), asnDetail.getOrderQty(), 0);
asnDetail.setReceivedQty(receivedQty);
//更新明细状态
if (receivedQty.compareTo(asnDetail.getOrderQty()) >= 0) {
asnDetail.setStatus(AsnStatusEnum.RECEIVED.getValue());
} else {
asnDetail.setStatus(AsnStatusEnum.RECEIVING.getValue());
}
asnDetailMapper.updateById(asnDetail);
// 根据容器ID查询库存
Inventory existingInventory = inventoryMapper.selectByStockId(asnDetail.getStockId());
if (existingInventory != null) {
// 更新库存
existingInventory.setQuantity(receivedQty);
existingInventory.setQueuedQty(BigDecimal.ZERO);
existingInventory.setStatus(InventoryStatusEnum.AVAILABLE.getValue());
inventoryMapper.updateById(existingInventory);
} else {
//生成新库存
Inventory inventory = Inventory.builder()
.itemId(asnDetail.getItemId())
.pointId(asnDetail.getPointId())
.stockId(asnDetail.getStockId())
.quantity(receivedQty)
.queuedQty(BigDecimal.ZERO)
.whCode(asn.getWhCode())
.propC1(asnDetail.getPropC1())
.propC2(asnDetail.getPropC2())
.propC3(asnDetail.getPropC3())
.status(InventoryStatusEnum.AVAILABLE.getValue())
.propD1(asnDetail.getPropD1())
.description(asnDetail.getDescription())
.tenantId(asnDetail.getTenantId())
.sysOrgCode(asnDetail.getSysOrgCode())
.createBy(asnDetail.getCreateBy())
.createTime(new Date())
.build();
inventoryMapper.insert(inventory);
}
//更新容器状态和位置
updateStockPoint(asnDetail.getStockId(), asnDetail.getPointId());
//更新入库单
refreshAsn(asn, asnDetailMapper.selectByMainId(asn.getId()));
//创建入库记录
ReceiveRecord receiveRecord = ReceiveRecord.builder()
.asnDetailId(asnDetail.getId())
.stockId(asnDetail.getStockId())
.pointId(asnDetail.getPointId())
.itemId(asnDetail.getItemId())
.receivedQty(receivedQty)
.propC1(asnDetail.getPropC1())
.propC2(asnDetail.getPropC2())
.propC3(asnDetail.getPropC3())
.propD1(asnDetail.getPropD1())
.description(asnDetail.getDescription())
.tenantId(asnDetail.getTenantId())
.sysOrgCode(asnDetail.getSysOrgCode())
.createBy(asnDetail.getCreateBy())
.createTime(new Date())
.build();
receiveRecordMapper.insert(receiveRecord);
//TODO: 在此处添加库存操作日志
}
/**
*
*/
private void updateStockPoint(String stockId, String pointId) {
Stock stock = stockMapper.selectById(stockId);
stock.setPointId(pointId);
stock.setStatus(CommonStatusEnum.USED.getValue());
stockMapper.updateById(stock);
// 更新库位状态为占用
Point point = pointMapper.selectById(pointId);
point.setStatus(CommonStatusEnum.USED.getValue()); // 占用状态
pointMapper.updateById(point);
}
}

View File

@ -3,13 +3,9 @@ package org.cpte.modules.saiWms.controller;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import kotlin.jvm.Volatile;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.cpte.modules.base.entity.Area;
import org.cpte.modules.base.service.IAreaService;
import org.cpte.modules.saiWms.request.inbound.InboundRequest;
import org.cpte.modules.saiWms.service.IInBoundService;
import org.cpte.modules.saiWms.request.InboundRequest;
import org.cpte.modules.saiWms.service.ISaiWmsService;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.config.shiro.IgnoreAuth;
@ -23,10 +19,10 @@ import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/saiWms/inBound")
@Slf4j
public class InBoundController {
public class SaiWmsController {
@Autowired
private IInBoundService iInBoundService;
private ISaiWmsService iInBoundService;
/**
*
@ -39,6 +35,6 @@ public class InBoundController {
@IgnoreAuth
public Result<String> inBoundTask(@RequestBody @Valid InboundRequest inboundRequest) {
iInBoundService.inBoundTask(inboundRequest);
return Result.OK("添加成功!");
return Result.OK("下发成功!");
}
}

View File

@ -1,4 +1,4 @@
package org.cpte.modules.saiWms.request.inbound;
package org.cpte.modules.saiWms.request;
import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.validation.Valid;
@ -6,6 +6,7 @@ import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
/**
@ -47,4 +48,49 @@ public class InboundRequest {
@JsonProperty("details")
@Valid
private List<InboundDetail> details;
@Data
public static class InboundDetail {
// 行号
@NotBlank(message = "行号不能为空")
@JsonProperty("LineNo")
private String lineNo;
// 物料
@NotBlank(message = "物料不能为空")
@JsonProperty("Item")
private String item;
// 单位
@NotBlank(message = "单位不能为空")
@JsonProperty("Unit")
private String unit;
// 数量
@NotNull(message = "数量不能为空")
@JsonProperty("Qty")
private BigDecimal qty;
// 托盘号
@NotNull(message = "托盘号不能为空")
@JsonProperty("Lpn")
private String lpn;
// 项目号
@JsonProperty("Project")
private String project;
// 任务号
@JsonProperty("TaskNo")
private String taskNo;
// 批次号
@JsonProperty("LotAtt04")
private String lotAtt04;
// 库存状态
@JsonProperty("LotAtt010")
private String lotAtt010;
}
}

View File

@ -1,52 +0,0 @@
package org.cpte.modules.saiWms.request.inbound;
import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class InboundDetail {
// 行号
@NotBlank(message = "行号不能为空")
@JsonProperty("LineNo")
private String lineNo;
// 物料
@NotBlank(message = "物料不能为空")
@JsonProperty("Item")
private String item;
// 单位
@NotBlank(message = "单位不能为空")
@JsonProperty("Unit")
private String unit;
// 数量
@NotNull(message = "数量不能为空")
@JsonProperty("Qty")
private BigDecimal qty;
// 托盘号
@NotNull(message = "托盘号不能为空")
@JsonProperty("Lpn")
private String lpn;
// 项目号
@JsonProperty("Project")
private String project;
// 任务号
@JsonProperty("TaskNo")
private String taskNo;
// 批次号
@JsonProperty("LotAtt04")
private String lotAtt04;
// 库存状态
@JsonProperty("LotAtt010")
private String lotAtt010;
}

View File

@ -1,8 +1,8 @@
package org.cpte.modules.saiWms.service;
import org.cpte.modules.saiWms.request.inbound.InboundRequest;
import org.cpte.modules.saiWms.request.InboundRequest;
public interface IInBoundService {
public interface ISaiWmsService {
/**
*
*

View File

@ -1,13 +1,10 @@
package org.cpte.modules.saiWms.service.impl;
import lombok.extern.slf4j.Slf4j;
import org.cpte.modules.agvTask.entity.AgvTask;
import org.cpte.modules.agvTask.service.IAgvTaskService;
import org.cpte.modules.base.entity.Item;
import org.cpte.modules.base.entity.Point;
import org.cpte.modules.base.entity.Stock;
import org.cpte.modules.base.mapper.ItemMapper;
import org.cpte.modules.base.mapper.StockMapper;
import org.cpte.modules.base.service.IItemService;
import org.cpte.modules.base.service.IPointService;
import org.cpte.modules.base.service.IStockService;
@ -16,23 +13,20 @@ import org.cpte.modules.receive.entity.Asn;
import org.cpte.modules.receive.entity.AsnDetail;
import org.cpte.modules.receive.mapper.AsnMapper;
import org.cpte.modules.receive.service.IAsnService;
import org.cpte.modules.saiWms.request.inbound.InboundDetail;
import org.cpte.modules.saiWms.request.inbound.InboundRequest;
import org.cpte.modules.saiWms.service.IInBoundService;
import org.cpte.modules.saiWms.request.InboundRequest;
import org.cpte.modules.saiWms.service.ISaiWmsService;
import org.cpte.modules.utils.CodeGeneratorUtil;
import org.jeecg.common.config.TenantContext;
import org.jeecg.common.util.oConvertUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
@Service
@Slf4j
public class IInBoundServiceImpl implements IInBoundService {
public class ISaiWmsServiceImpl implements ISaiWmsService {
@Autowired
private AsnMapper asnMapper;
@ -66,7 +60,7 @@ public class IInBoundServiceImpl implements IInBoundService {
}
// 获取唯一的明细
InboundDetail detail = inboundRequest.getDetails().get(0);
InboundRequest.InboundDetail detail = inboundRequest.getDetails().get(0);
// 验证基础数据
String srcPointCode = inboundRequest.getLocationFrom();
@ -92,7 +86,7 @@ public class IInBoundServiceImpl implements IInBoundService {
asnService.saveMain(createAsn, Collections.singletonList(asnDetail));
//创建AGV任务
iAgvTaskService.createAgvTask(AgvStatusEnum.CREATED.getValue(), stock.getStockCode(), srcPoint.getPointCode(), dstPoint.getPointCode(), "PF-LMR-COMMON", BusinessTypeEnum.INBOUND.getValue());
iAgvTaskService.createAgvTask(AgvStatusEnum.CREATED.getValue(), stock.getStockCode(), srcPoint.getPointCode(), dstPoint.getPointCode(), null, BusinessTypeEnum.INBOUND.getValue(),AgvVendorEnum.HIK.getValue());
}
/**
@ -118,7 +112,7 @@ public class IInBoundServiceImpl implements IInBoundService {
/**
*
*/
private AsnDetail buildAsnDetail(InboundDetail detail, Point srcPoint, Item item, Stock stock) {
private AsnDetail buildAsnDetail(InboundRequest.InboundDetail detail, Point srcPoint, Item item, Stock stock) {
// 由于明细只有一条,直接构建单个明细对象
return AsnDetail.builder()
.lineNo(Integer.parseInt(detail.getLineNo()))
@ -127,6 +121,7 @@ public class IInBoundServiceImpl implements IInBoundService {
.orderQty(detail.getQty())
.stockId(stock.getId())
.pointId(srcPoint.getId())
.status(AsnStatusEnum.CREATED.getValue())
.project(detail.getProject())
.taskNo(detail.getTaskNo())
.propC1(detail.getLotAtt04())

View File

@ -0,0 +1,64 @@
package org.cpte.modules.tesAgv.controller;
import com.alibaba.fastjson.JSON;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.cpte.modules.tesAgv.request.NewMovePodTaskRequest;
import org.cpte.modules.tesAgv.request.TesCallbackRequest;
import org.cpte.modules.tesAgv.response.TesResult;
import org.cpte.modules.tesAgv.service.ITesAgvService;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.config.shiro.IgnoreAuth;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Tag(name = "TesAGV")
@RestController
@RequestMapping("/tes/apiv2")
@Slf4j
public class TesAgvController {
@Autowired
private ITesAgvService iTesAgvService;
/**
*
*
* @param newMovePodTaskRequest
*/
@AutoLog(value = "TesAGV-任务下发")
@Operation(summary = "TesAGV-任务下发")
@PostMapping(value = "/newMovePodTask")
@IgnoreAuth
public Result<String> newMovePodTask(@RequestBody NewMovePodTaskRequest newMovePodTaskRequest) {
iTesAgvService.sendTesAgvTask(
"http://localhost:8000/cpte-wms/tes/apiv2/newMovePodTask",
JSON.toJSONString(newMovePodTaskRequest),
null
);
return Result.OK("下发成功!");
}
/**
*
*
* @param tesCallbackRequest
*/
@AutoLog(value = "TesAGV-任务上报")
@Operation(summary = "TesAGV-任务上报")
@PostMapping(value = "/callBackTask")
@IgnoreAuth
public TesResult callBackTask(@RequestBody TesCallbackRequest tesCallbackRequest) {
try {
iTesAgvService.callBackTask(tesCallbackRequest);
return TesResult.success();
} catch (Exception e) {
return TesResult.error("系统异常: " + e.getMessage());
}
}
}

View File

@ -0,0 +1,383 @@
package org.cpte.modules.tesAgv.request;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import lombok.Data;
import java.util.List;
/**
*
* 使
*
*/
@JsonPropertyOrder({
"warehouseID",
"requestID",
"clientCode",
"priority",
"srcType",
"podID",
"bizID",
"replacePodTask",
"destination",
"desType",
"desNodeID",
"desStorageID",
"desZoneCode",
"desStationCodes",
"storagePreference",
"taskExt",
"desExt",
"bizExt"
})
@Data
public class NewMovePodTaskRequest {
/**
* ID
*/
@JsonProperty("warehouseID")
private String warehouseID;
/**
* ID
*/
@JsonProperty("requestID")
private String requestID;
/**
*
*/
@JsonProperty("clientCode")
private String clientCode;
/**
* (1-9)9
*/
@JsonProperty("priority")
private Integer priority = 3;
/**
* 1
*/
@JsonProperty("srcType")
private Integer srcType = 1;
/**
*
*/
@JsonProperty("podID")
private String podID;
/**
* IDID
*/
@JsonProperty("bizID")
private String bizID;
/**
*
* - 0,
* - 1:
*/
@JsonProperty("replacePodTask")
private Integer replacePodTask = 0;
/**
*
* destination desTypedesType
* (,)
*/
@JsonProperty("destination")
private String destination;
/**
* :
* - 1:;
* - 2:;
* - 3:;
* - 5:
* - 6:
* - 7:
*/
@JsonProperty("desType")
private Integer desType;
/**
* IDdesType=1
*/
@JsonProperty("desNodeID")
private String desNodeID;
/**
* desType=2
*/
@JsonProperty("desStorageID")
private String desStorageID;
/**
* desType=3,7
*/
@JsonProperty("desZoneCode")
private String desZoneCode;
/**
* desType=5,6
*/
@JsonProperty("desStationCodes")
private String desStationCodes;
/**
*
*/
@JsonProperty("storagePreference")
private StoragePreference storagePreference;
/**
*
*/
@JsonProperty("taskExt")
private TaskExt taskExt;
/**
*
*/
@JsonProperty("desExt")
private DesExt desExt;
/**
*
*/
@JsonProperty("bizExt")
private BizExt bizExt;
/**
*
* desType=7
*/
@JsonPropertyOrder({
"candidateStorageIDs",
"materialClass"
})
@Data
public static class StoragePreference {
/**
*
*
* desType=7
*/
@JsonProperty("candidateStorageIDs")
private List<String> candidateStorageIDs;
/**
* desType=7
* candidateStorageIDs
*/
@JsonProperty("materialClass")
private String materialClass;
}
/**
*
*/
@JsonPropertyOrder({
"robotGroupID",
"turnMode",
"maxSpeed",
"timeoutFailed",
"autoToRest",
"keepRobot",
"keepRobotTimeout",
"foldType",
"foldNum",
"check",
"cover",
"wrap",
"cargoType",
"whenTargetDisabled",
"delayDispatch"
})
@Data
public static class TaskExt {
/**
*
*/
@JsonProperty("robotGroupID")
private String robotGroupID;
/**
*
* - 0
* - 1
*/
@JsonProperty("turnMode")
private Integer turnMode;
/**
* (mm/s)
*/
@JsonProperty("maxSpeed")
private Integer maxSpeed;
/**
* ()
*/
@JsonProperty("timeoutFailed")
private Integer timeoutFailed = 86400;
/**
*
* - 0
* - 1
*/
@JsonProperty("autoToRest")
private Integer autoToRest;
/**
*
* - 0
* - 1
*/
@JsonProperty("keepRobot")
private Integer keepRobot;
/**
* ()
*/
@JsonProperty("keepRobotTimeout")
private Integer keepRobotTimeout;
/**
*
* - 0
* - 2
*/
@JsonProperty("foldType")
private Integer foldType;
/**
*
* - 1
* - >1
*/
@JsonProperty("foldNum")
private Integer foldNum;
/**
*
* - 0
* - 1
*/
@JsonProperty("check")
private Integer check;
/**
*
* - 0
* - 1
*/
@JsonProperty("cover")
private Integer cover;
/**
*
* - 0
* - 1
*/
@JsonProperty("wrap")
private Integer wrap;
/**
* plc
* - "000001"
* - "000002"
*/
@JsonProperty("cargoType")
private String cargoType;
/**
*
* - taskFail
* - taskWait
*/
@JsonProperty("whenTargetDisabled")
private String whenTargetDisabled;
/**
*
*/
@JsonProperty("delayDispatch")
private Integer delayDispatch;
}
/**
*
*/
@JsonPropertyOrder({
"unload",
"robotFace",
"podFace"
})
@Data
public static class DesExt {
/**
*
* - 0
* - 1
*/
@JsonProperty("unload")
private Integer unload = 0;
/**
* 姿
*
* - 0(x)
* - 1.57(y)
* - 3.14(x)
* - 4.71(y)
*/
@JsonProperty("robotFace")
private Double robotFace;
/**
* 姿
*
* - 0(x)
* - 1.57(y)
* - 3.14(x)
* - 4.71(y)
*/
@JsonProperty("podFace")
private Double podFace;
}
/**
*
*/
@JsonPropertyOrder({
"bizType",
"waveID"
})
@Data
public static class BizExt {
/**
*
*/
@JsonProperty("bizType")
private String bizType;
/**
*
*
* 1.
* 2. step
* 3.
* 4.
* 5. //
* 6. ABA
*/
@JsonProperty("waveID")
private String waveID;
}
}

View File

@ -0,0 +1,179 @@
package org.cpte.modules.tesAgv.request;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@Data
public class TesCallbackRequest {
/**
*
*/
@JsonProperty("messageID")
private String messageID;
/**
*
*/
@JsonProperty("messageType")
private Integer messageType;
/**
* ID
*/
@JsonProperty("warehouseID")
private String warehouseID;
/**
*
*/
@JsonProperty("createTime")
private String createTime;
@JsonProperty("content")
private Content content;
/**
*
*/
@Data
public static class Content {
/**
* SUPER
*/
@JsonProperty("clientCode")
private String clientCode;
/**
* ID
*/
@JsonProperty("taskID")
private Integer taskID;
/**
* ID
*/
@JsonProperty("bizID")
private String bizID;
/**
* (1-99)
*/
@JsonProperty("priority")
private Integer priority;
/**
* ()
* 2.
* 3.
* 4.
*/
@JsonProperty("taskType")
private Integer taskType;
/**
* ()
* 0.
* 1.
* 2.
* 3.
* 4.
* 5.
* 6.
* 8.
* 10.
*/
@JsonProperty("status")
private Integer status;
/**
* ()
*/
@JsonProperty("errorCode")
private Integer errorCode;
/**
* ()
*/
@JsonProperty("errorReason")
private String errorReason;
/**
*
*/
@JsonProperty("robotID")
private String robotID;
/**
*
*/
@JsonProperty("podID")
private String podID;
/**
*
*/
@JsonProperty("desType")
private Integer desType;
/**
* ID
*/
@JsonProperty("desNodeID")
private String desNodeID;
/**
* ID
*/
@JsonProperty("desStorageID")
private String desStorageID;
/**
* ID
*/
@JsonProperty("desZoneCode")
private String desZoneCode;
/**
*
*/
@JsonProperty("desStationCodes")
private String desStationCodes;
/**
*
*/
@JsonProperty("createTime")
private String createTime;
/**
*
*/
@JsonProperty("finishTime")
private String finishTime;
/**
*
*/
@JsonProperty("podInfo")
private PodInfo podInfo;
}
/**
*
*/
@Data
public static class PodInfo {
/**
*
*/
@JsonProperty("positionType")
private Integer positionType;
/**
*
*/
@JsonProperty("nodeID")
private String nodeID;
}
}

View File

@ -0,0 +1,45 @@
package org.cpte.modules.tesAgv.response;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.io.Serializable;
/**
*
*
* @author scott
* @email cpteos@163.com
* @date 2019119
*/
@Data
public class TesResult implements Serializable {
/**
*
* 0
*/
@JsonProperty("returnCode")
private Integer returnCode;
/**
*
*/
@JsonProperty("returnMsg")
private String returnMsg;
public static TesResult success() {
TesResult response = new TesResult();
response.returnCode = 0;
response.returnMsg = "succ";
return response;
}
public static TesResult error(String returnMsg) {
TesResult response = new TesResult();
response.returnCode = 500;
response.returnMsg = returnMsg;
return response;
}
}

View File

@ -0,0 +1,29 @@
package org.cpte.modules.tesAgv.service;
import org.cpte.modules.agvTask.entity.AgvTask;
import org.cpte.modules.tesAgv.request.TesCallbackRequest;
public interface ITesAgvService {
/**
* JSON
*
* @param agvTask
*/
String generateTesAgvTaskJson(AgvTask agvTask);
/**
*
*
* @param url
* @param json json
* @param agvTask
*/
void sendTesAgvTask(String url, String json, AgvTask agvTask);
/**
*
*
* @param tesCallbackRequest
*/
void callBackTask(TesCallbackRequest tesCallbackRequest);
}

View File

@ -0,0 +1,222 @@
package org.cpte.modules.tesAgv.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.cpte.modules.agvTask.entity.AgvTask;
import org.cpte.modules.agvTask.mapper.AgvTaskMapper;
import org.cpte.modules.agvTask.service.IAgvTaskService;
import org.cpte.modules.constant.enums.AgvStatusEnum;
import org.cpte.modules.constant.enums.AgvVendorEnum;
import org.cpte.modules.receive.service.IAsnService;
import org.cpte.modules.tesAgv.request.NewMovePodTaskRequest;
import org.cpte.modules.tesAgv.request.TesCallbackRequest;
import org.cpte.modules.tesAgv.service.ITesAgvService;
import org.jeecg.modules.system.mapper.SysDictMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
@Service
@Slf4j
public class ITesAgvServiceImpl implements ITesAgvService {
/**
*
*/
final String open_flag = "OPEN";
/**
*
*/
final Integer success_code = 0;
/**
*
*/
final Integer fail_code = 500;
@Autowired
private SysDictMapper sysDictMapper;
@Autowired
private AgvTaskMapper agvTaskMapper;
@Autowired
private IAsnService iAsnService;
@Autowired
private IAgvTaskService iAgvTaskService;
@Override
public String generateTesAgvTaskJson(AgvTask agvTask) {
NewMovePodTaskRequest newMovePodTaskRequest = new NewMovePodTaskRequest();
newMovePodTaskRequest.setWarehouseID("HETU");
newMovePodTaskRequest.setRequestID(String.valueOf(System.currentTimeMillis()));
newMovePodTaskRequest.setClientCode("WCS");
newMovePodTaskRequest.setPriority(agvTask.getPriority());
newMovePodTaskRequest.setSrcType(1);
newMovePodTaskRequest.setPodID(agvTask.getCarrierCode());
newMovePodTaskRequest.setBizID(agvTask.getId().toString());
newMovePodTaskRequest.setReplacePodTask(0);
newMovePodTaskRequest.setDesType(1);
newMovePodTaskRequest.setDesNodeID(agvTask.getEndCode());
NewMovePodTaskRequest.DesExt desExt = new NewMovePodTaskRequest.DesExt();
desExt.setUnload(1);
desExt.setRobotFace(3.14);
newMovePodTaskRequest.setDesExt(desExt);
NewMovePodTaskRequest.TaskExt taskExt = new NewMovePodTaskRequest.TaskExt();
taskExt.setAutoToRest(1);
taskExt.setTimeoutFailed(86400);
newMovePodTaskRequest.setTaskExt(taskExt);
return JSON.toJSONString(newMovePodTaskRequest);
}
@Override
public void sendTesAgvTask(String url, String json, AgvTask agvTask) {
log.info("请求报文:{}", json);
// 检查接口开关, 未开启则返回
if (sysDictMapper.queryByDictCode(open_flag) == null) {
updateAgvTaskResponse(agvTask, "接口未开启", fail_code);
return;
}
Integer returnCode = null;
String returnMsg = null;
try {
//String result = HttpPostUtil.sendPostReq(url, json);
String result = "{" +
" \"returnCode\":0," +
" \"returnMsg\":\"succ\"," +
" \"returnUserMsg\":\"成功\"," +
" \"data\":{" +
" \"taskID\":74602" +
" }\n" +
"}";
if (StringUtils.isEmpty(result)) {
returnMsg = "Tes返回信息:下发任务接口调用失败";
throw new RuntimeException(returnMsg);
}
JSONObject resulObject = JSON.parseObject(result);
if (resulObject == null) {
returnMsg = "Tes返回信息:下发任务接口返回为空";
throw new RuntimeException(returnMsg);
}
returnCode = resulObject.getInteger("returnCode");
returnMsg = resulObject.getString("returnUserMsg");
if (!success_code.equals(returnCode)) {
throw new RuntimeException("Tes返回消息:" + returnMsg);
}
// 更新任务状态
updateAgvTaskResponse(agvTask, returnMsg, returnCode);
} catch (Exception e) {
// 记录异常到 AgvTask
updateAgvTaskResponse(agvTask, e.getMessage(), fail_code);
throw e; // 继续向上抛出异常供 Controller 层处理
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public void callBackTask(TesCallbackRequest tesCallbackRequest) {
//根据任务ID查询任务
AgvTask agvTask = agvTaskMapper.selectById(tesCallbackRequest.getContent().getBizID());
String stockCode=tesCallbackRequest.getContent().getPodID();
if (agvTask == null) {
throw new RuntimeException("【" + tesCallbackRequest.getContent().getBizID() + "】任务不存在");
}
int status = tesCallbackRequest.getContent().getStatus();
switch (status) {
case 4:
//4.成功-任务完成
handleEnd(stockCode,agvTask);
break;
case 6:
//6.已取消-任务取消
handleCelled(agvTask);
break;
case 7:
//7.自定义-重新发送任务
handleResend(agvTask);
break;
}
}
/**
*
*
* @param agvTask
*/
private void handleEnd(String stockCode,AgvTask agvTask) {
iAsnService.receiveGoods(stockCode);
agvTask.setStatus(AgvStatusEnum.COMPLETED.getValue());
agvTask.setEndTime(new Date());
agvTaskMapper.updateById(agvTask);
}
/**
*
*
* @param agvTask
*/
private void handleCelled(AgvTask agvTask) {
agvTask.setStatus(AgvStatusEnum.CANCELLED.getValue());
agvTask.setEndTime(new Date());
agvTaskMapper.updateById(agvTask);
}
/**
*
*
* @param agvTask
*/
private void handleResend(AgvTask agvTask) {
Long count = agvTaskMapper.existsAGVTask(agvTask.getCarrierCode(),AgvVendorEnum.TES.getValue());
if (count > 0) {
throw new RuntimeException("任务已重新生成,请勿重复操作! ");
}
AgvTask newAgvTask = iAgvTaskService.createAgvTask(AgvStatusEnum.CREATED.getValue(), agvTask.getCarrierCode(), agvTask.getStartCode(), agvTask.getEndCode(), null, agvTask.getType(), AgvVendorEnum.TES.getValue());
switch (agvTask.getType()) {
case "INBOUND":
case "OUTBOUND":
//下发四向车任务
sendTesAgvTask("", "", newAgvTask);
break;
default:
throw new RuntimeException("任务类型不支持: " + agvTask.getType());
}
}
/**
*
*
* @param agvTask
* @param message
* @param code
*/
private void updateAgvTaskResponse(AgvTask agvTask, String message, Integer code) {
if (agvTask != null) {
if (success_code.equals(code)) {
agvTask.setStatus(AgvStatusEnum.EXECUTING.getValue());
}
agvTask.setResMessage(message);
agvTask.setStartTime(new Date());
agvTaskMapper.updateById(agvTask);
}
}
}