三方调度相关接口开发0724

This commit is contained in:
2025-07-24 14:19:42 +08:00
parent 39a92d61f3
commit b6ac89fffc
45 changed files with 1717 additions and 252 deletions

View File

@@ -120,6 +120,7 @@ public class SecurityConfig
"/system/config/**", "/system/config/**",
"/AutoInventory/**", "/AutoInventory/**",
"/ws/**", "/ws/**",
"/mock/**",
"/information/device/**", "/information/device/**",
"/MatchScan/**", "/MatchScan/**",
"/wisdom/task/**", "/wisdom/task/**",

View File

@@ -0,0 +1,54 @@
package com.zg.project.information.controller;
import java.util.List;
import com.zg.common.utils.poi.ExcelUtil;
import com.zg.framework.web.controller.BaseController;
import com.zg.framework.web.domain.AjaxResult;
import com.zg.framework.web.page.TableDataInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.zg.project.information.domain.Mtd;
import com.zg.project.information.service.IMtdService;
@RestController
@RequestMapping("/information/mtd")
public class MtdController extends BaseController {
@Autowired
private IMtdService mtdService;
@GetMapping("/list")
public TableDataInfo list(Mtd mtd) {
startPage();
List<Mtd> list = mtdService.selectMtdList(mtd);
return getDataTable(list);
}
@PostMapping
public AjaxResult add(@RequestBody Mtd mtd) {
return toAjax(mtdService.insertMtd(mtd));
}
@PutMapping
public AjaxResult edit(@RequestBody Mtd mtd) {
return toAjax(mtdService.updateMtd(mtd));
}
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids) {
return toAjax(mtdService.deleteMtdByIds(ids));
}
@GetMapping("/export")
public AjaxResult export(Mtd mtd) {
List<Mtd> list = mtdService.selectMtdList(mtd);
ExcelUtil<Mtd> util = new ExcelUtil<>(Mtd.class);
return util.exportExcel(list, "物料信息");
}
@GetMapping("/{id}")
public AjaxResult getInfo(@PathVariable Long id) {
return AjaxResult.success(mtdService.selectMtdById(id));
}
}

View File

@@ -67,7 +67,7 @@ public class PcdeDetailController extends BaseController
} }
/** /**
* 导入供应计划数据(全部新增,不校验重复) * 导入库位明细数据
*/ */
@PreAuthorize("@ss.hasPermi('information:pcdedetail:import')") @PreAuthorize("@ss.hasPermi('information:pcdedetail:import')")
@Log(title = "库位明细", businessType = BusinessType.IMPORT) @Log(title = "库位明细", businessType = BusinessType.IMPORT)

View File

@@ -0,0 +1,141 @@
package com.zg.project.information.domain;
import com.zg.framework.aspectj.lang.annotation.Excel;
import com.zg.framework.web.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
public class Mtd extends BaseEntity {
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 物料号 */
@Excel(name = "物料号")
private String mid;
/** 物料描述 */
@Excel(name = "物料描述")
private String desMat;
/** 物料组 */
@Excel(name = "物料组")
private String grp;
/** 单位 */
@Excel(name = "单位")
private String unt;
/** 单价 */
@Excel(name = "单价")
private String uprc;
/** 类型1 */
@Excel(name = "btpe")
private String btpe;
/** 类型2 */
@Excel(name = "mtpe")
private String mtpe;
/** 类型3 */
@Excel(name = "stpe")
private String stpe;
// ---------------- Getter & Setter ----------------
public void setId(Long id) {
this.id = id;
}
public Long getId() {
return id;
}
public void setMid(String mid) {
this.mid = mid;
}
public String getMid() {
return mid;
}
public void setDesMat(String desMat) {
this.desMat = desMat;
}
public String getDesMat() {
return desMat;
}
public void setGrp(String grp) {
this.grp = grp;
}
public String getGrp() {
return grp;
}
public void setUnt(String unt) {
this.unt = unt;
}
public String getUnt() {
return unt;
}
public void setUprc(String uprc) {
this.uprc = uprc;
}
public String getUprc() {
return uprc;
}
public void setBtpe(String btpe) {
this.btpe = btpe;
}
public String getBtpe() {
return btpe;
}
public void setMtpe(String mtpe) {
this.mtpe = mtpe;
}
public String getMtpe() {
return mtpe;
}
public void setStpe(String stpe) {
this.stpe = stpe;
}
public String getStpe() {
return stpe;
}
// ---------------- ToString ----------------
@Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("mid", getMid())
.append("desMat", getDesMat())
.append("grp", getGrp())
.append("unt", getUnt())
.append("uprc", getUprc())
.append("btpe", getBtpe())
.append("mtpe", getMtpe())
.append("stpe", getStpe())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.toString();
}
}

View File

@@ -13,8 +13,7 @@ import com.zg.framework.web.domain.BaseEntity;
* @author zg * @author zg
* @date 2025-05-29 * @date 2025-05-29
*/ */
public class PcdeDetail extends BaseEntity public class PcdeDetail extends BaseEntity {
{
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** 主键ID */ /** 主键ID */
@@ -25,16 +24,20 @@ public class PcdeDetail extends BaseEntity
private String pcode; private String pcode;
/** 所属场景 */ /** 所属场景 */
@Excel(name = "所属场景名称")
private String scene; private String scene;
/** 所属场景名称 */ /** 所属场景名称 */
@Excel(name = "所属场景名称")
private String sceneName; private String sceneName;
/** 所属仓库 */ /** 所属仓库 */
@Excel(name = "所属仓库") @Excel(name = "所属仓库")
private String warehouse; private String warehouse;
/** 所属仓库名称 */
@Excel(name = "所属仓库名称")
private String warehouseName;
/** 编码后ID */ /** 编码后ID */
@Excel(name = "编码后ID") @Excel(name = "编码后ID")
private String encodedId; private String encodedId;
@@ -64,141 +67,129 @@ public class PcdeDetail extends BaseEntity
@JsonFormat(pattern = "yyyy-MM-dd") @JsonFormat(pattern = "yyyy-MM-dd")
private Date updatedAt; private Date updatedAt;
public void setId(Long id) // Getter & Setter
{
public void setId(Long id) {
this.id = id; this.id = id;
} }
public Long getId() public Long getId() {
{
return id; return id;
} }
public String getPcode() { public String getPcode() {
return pcode; return pcode;
} }
public void setPcode(String pcode) { public void setPcode(String pcode) {
this.pcode = pcode; this.pcode = pcode;
} }
public void setScene(String scene) public void setScene(String scene) {
{
this.scene = scene; this.scene = scene;
} }
public String getScene() public String getScene() {
{
return scene; return scene;
} }
public void setSceneName(String sceneName) public void setSceneName(String sceneName) {
{
this.sceneName = sceneName; this.sceneName = sceneName;
} }
public String getSceneName() public String getSceneName() {
{
return sceneName; return sceneName;
} }
public void setWarehouse(String warehouse) public void setWarehouse(String warehouse) {
{
this.warehouse = warehouse; this.warehouse = warehouse;
} }
public String getWarehouse() public String getWarehouse() {
{
return warehouse; return warehouse;
} }
public void setEncodedId(String encodedId) public void setWarehouseName(String warehouseName) {
{ this.warehouseName = warehouseName;
}
public String getWarehouseName() {
return warehouseName;
}
public void setEncodedId(String encodedId) {
this.encodedId = encodedId; this.encodedId = encodedId;
} }
public String getEncodedId() public String getEncodedId() {
{
return encodedId; return encodedId;
} }
public void setTag(String tag) public void setTag(String tag) {
{
this.tag = tag; this.tag = tag;
} }
public String getTag() public String getTag() {
{
return tag; return tag;
} }
public void setRemark(String remark) public void setRemark(String remark) {
{
this.remark = remark; this.remark = remark;
} }
public String getRemark() public String getRemark() {
{
return remark; return remark;
} }
public void setIsDelete(String isDelete) public void setIsDelete(String isDelete) {
{
this.isDelete = isDelete; this.isDelete = isDelete;
} }
public String getIsDelete() public String getIsDelete() {
{
return isDelete; return isDelete;
} }
public void setCreatedBy(String createdBy) public void setCreatedBy(String createdBy) {
{
this.createdBy = createdBy; this.createdBy = createdBy;
} }
public String getCreatedBy() public String getCreatedBy() {
{
return createdBy; return createdBy;
} }
public void setCreatedAt(Date createdAt) public void setCreatedAt(Date createdAt) {
{
this.createdAt = createdAt; this.createdAt = createdAt;
} }
public Date getCreatedAt() public Date getCreatedAt() {
{
return createdAt; return createdAt;
} }
public void setUpdatedBy(String updatedBy) public void setUpdatedBy(String updatedBy) {
{
this.updatedBy = updatedBy; this.updatedBy = updatedBy;
} }
public String getUpdatedBy() public String getUpdatedBy() {
{
return updatedBy; return updatedBy;
} }
public void setUpdatedAt(Date updatedAt) public void setUpdatedAt(Date updatedAt) {
{
this.updatedAt = updatedAt; this.updatedAt = updatedAt;
} }
public Date getUpdatedAt() public Date getUpdatedAt() {
{
return updatedAt; return updatedAt;
} }
@Override @Override
public String toString() { public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId()) .append("id", getId())
.append("pcode", getPcode()) .append("pcode", getPcode())
.append("scene", getScene()) .append("scene", getScene())
.append("sceneName", getSceneName()) .append("sceneName", getSceneName())
.append("warehouse", getWarehouse()) .append("warehouse", getWarehouse())
.append("warehouseName", getWarehouseName())
.append("encodedId", getEncodedId()) .append("encodedId", getEncodedId())
.append("tag", getTag()) .append("tag", getTag())
.append("remark", getRemark()) .append("remark", getRemark())

View File

@@ -0,0 +1,20 @@
package com.zg.project.information.mapper;
import java.util.List;
import com.zg.project.information.domain.Mtd;
public interface MtdMapper {
Mtd selectMtdById(Long id);
List<Mtd> selectMtdList(Mtd mtd);
int insertMtd(Mtd mtd);
int updateMtd(Mtd mtd);
int deleteMtdById(Long id);
int deleteMtdByIds(Long[] ids);
/**
* 根据物料编码查询物料描述
* @param materialCode
* @return
*/
String selectWlmsByWlbh(String materialCode);
}

View File

@@ -60,10 +60,9 @@ public interface PcdeDetailMapper
public int deletePcdeDetailByIds(Long[] ids); public int deletePcdeDetailByIds(Long[] ids);
/** /**
* 根据库编码查询库位信息 * 根据库编码查询库位信息
* @param locationCode * @param pcode
* @return * @return
*/ */
PcdeDetail selectByLocationCode(String locationCode); PcdeDetail selectByPcode(String pcode);
} }

View File

@@ -0,0 +1,13 @@
package com.zg.project.information.service;
import java.util.List;
import com.zg.project.information.domain.Mtd;
public interface IMtdService {
Mtd selectMtdById(Long id);
List<Mtd> selectMtdList(Mtd mtd);
int insertMtd(Mtd mtd);
int updateMtd(Mtd mtd);
int deleteMtdById(Long id);
int deleteMtdByIds(Long[] ids);
}

View File

@@ -0,0 +1,44 @@
package com.zg.project.information.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.zg.project.information.mapper.MtdMapper;
import com.zg.project.information.domain.Mtd;
import com.zg.project.information.service.IMtdService;
@Service
public class MtdServiceImpl implements IMtdService {
@Autowired
private MtdMapper mtdMapper;
@Override
public Mtd selectMtdById(Long id) {
return mtdMapper.selectMtdById(id);
}
@Override
public List<Mtd> selectMtdList(Mtd mtd) {
return mtdMapper.selectMtdList(mtd);
}
@Override
public int insertMtd(Mtd mtd) {
return mtdMapper.insertMtd(mtd);
}
@Override
public int updateMtd(Mtd mtd) {
return mtdMapper.updateMtd(mtd);
}
@Override
public int deleteMtdById(Long id) {
return mtdMapper.deleteMtdById(id);
}
@Override
public int deleteMtdByIds(Long[] ids) {
return mtdMapper.deleteMtdByIds(ids);
}
}

View File

@@ -1,15 +1,17 @@
package com.zg.project.information.service.impl; package com.zg.project.information.service.impl;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.zg.common.exception.ServiceException; import com.zg.common.exception.ServiceException;
import com.zg.common.utils.DateUtils; import com.zg.common.utils.DateUtils;
import com.zg.project.wisdom.domain.GysJh; import com.zg.framework.manager.AsyncManager;
import com.zg.project.wisdom.domain.RkInfo;
import com.zg.project.wisdom.mapper.RkInfoMapper; import com.zg.project.wisdom.mapper.RkInfoMapper;
import com.zg.project.wisdom.service.IRkInfoService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import com.zg.project.information.mapper.PcdeDetailMapper; import com.zg.project.information.mapper.PcdeDetailMapper;
@@ -155,36 +157,56 @@ public class PcdeDetailServiceImpl implements IPcdeDetailService
throw new ServiceException("导入数据不能为空!"); throw new ServiceException("导入数据不能为空!");
} }
int successNum = 0; AtomicInteger successNum = new AtomicInteger(0);
int failureNum = 0; AtomicInteger failureNum = new AtomicInteger(0);
StringBuilder failureMsg = new StringBuilder(); List<String> failureMsgs = Collections.synchronizedList(new ArrayList<>());
for (PcdeDetail detail : pcdeList) { for (PcdeDetail detail : pcdeList) {
try { TimerTask task = new TimerTask() {
PcdeDetail exist = pcdeDetailMapper.selectByLocationCode(detail.getPcode()); @Override
if (exist == null) { public void run() {
detail.setCreateBy(operName); try {
detail.setCreateTime(DateUtils.getNowDate()); PcdeDetail exist = pcdeDetailMapper.selectByPcode(detail.getPcode());
pcdeDetailMapper.insertPcdeDetail(detail); if (exist == null) {
successNum++; detail.setCreateBy(operName);
} else { detail.setCreateTime(DateUtils.getNowDate());
failureNum++; pcdeDetailMapper.insertPcdeDetail(detail);
failureMsg.append("<br/>库位编号 ").append(detail.getPcode()).append(" 已存在"); successNum.incrementAndGet();
} else {
failureNum.incrementAndGet();
failureMsgs.add("库位编号 = " + detail.getPcode() + " 已存在");
}
} catch (Exception e) {
failureNum.incrementAndGet();
failureMsgs.add("库位编号 = " + detail.getPcode() + " 导入失败:" + e.getMessage());
}
} }
} catch (Exception e) { };
failureNum++;
failureMsg.append("<br/>库位编号 ").append(detail.getPcode()).append(" 导入失败:").append(e.getMessage()); // ✅ 使用自定义线程池工具类提交任务
} AsyncManager.me().execute(task);
} }
if (failureNum > 0) { // ❗此处无法精确等待全部线程完成,只做简单延时(如需精确等待建议用 CountDownLatch
failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据有误,错误如下:"); try {
throw new ServiceException(failureMsg.toString()); Thread.sleep(2000); // 根据量级可调,比如 100 条记录等 1~2 秒
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
if (failureNum.get() > 0) {
StringBuilder msg = new StringBuilder();
msg.append("很抱歉,导入失败!共 ").append(failureNum.get()).append(" 条数据有误,错误如下:");
for (String fail : failureMsgs) {
msg.append("<br/>").append(fail);
}
throw new ServiceException(msg.toString());
} else { } else {
return "恭喜您,数据已全部导入成功!共 " + successNum + " 条。"; return "恭喜您,数据已全部导入成功!共 " + successNum.get() + " 条。";
} }
} }
/** /**
* 获取未被入库单据使用的库位列表 * 获取未被入库单据使用的库位列表
*/ */

View File

@@ -1,24 +1,107 @@
package com.zg.project.wisdom.controller; package com.zg.project.wisdom.controller;
import com.zg.common.exception.ServiceException;
import com.zg.common.utils.StringUtils;
import com.zg.framework.web.controller.BaseController; import com.zg.framework.web.controller.BaseController;
import com.zg.framework.web.domain.AjaxResult; import com.zg.framework.web.domain.AjaxResult;
import com.zg.framework.web.page.TableDataInfo; import com.zg.framework.web.page.TableDataInfo;
import com.zg.project.wisdom.domain.AgvTaskResult; import com.zg.project.wisdom.domain.AgvTaskResult;
import com.zg.project.wisdom.domain.WcsTaskResult;
import com.zg.project.wisdom.domain.dto.AgvDTO; import com.zg.project.wisdom.domain.dto.AgvDTO;
import com.zg.project.wisdom.domain.dto.OutGoodsDTO;
import com.zg.project.wisdom.service.IAgvTaskResultService; import com.zg.project.wisdom.service.IAgvTaskResultService;
import com.zg.project.wisdom.service.IWcsTaskResultService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.Date;
import java.util.List; import java.util.List;
@RestController @RestController
@RequestMapping("/wisdom/agv") @RequestMapping("/wisdom")
public class AgvTaskResultController extends BaseController { public class AgvTaskResultController extends BaseController {
@Autowired @Autowired
private IAgvTaskResultService agvTaskResultService; private IAgvTaskResultService agvTaskResultService;
@Autowired
private IWcsTaskResultService wcsTaskResultService;
/**
* AGV任务执行结果回调
*/
@PostMapping("/agv/callback")
public AjaxResult receiveCallback(@RequestBody AgvDTO dto) {
agvTaskResultService.handleAgvCallback(dto);
return AjaxResult.success("AGV回调接收成功");
}
/**
* WCS 回调接口
*/
@PostMapping("/wcs/callback")
public AjaxResult receiveWcsCallback(@RequestBody WcsTaskResult dto) {
wcsTaskResultService.handleWcsCallback(dto);
return AjaxResult.success("WCS 回调接收成功");
}
/**
* 查询 AGV 状态
*/
@PostMapping("/agv/query")
public AjaxResult queryAgvStatus(@RequestBody AgvDTO dto) {
String requestId = dto.getRequestId();
String status = dto.getStatus();
boolean exists = agvTaskResultService.existsByRequestIdAndStatus(requestId, status);
int resultCode = exists ? 200 : 201;
return AjaxResult.success(resultCode);
}
/**
* 检查任务状态TaskStatus = 1 是否存在)
*
* @param taskId 任务ID
*/
@GetMapping("/wcs/query")
public AjaxResult checkTaskStatus(@RequestParam("TaskID") String taskId) {
boolean exists = wcsTaskResultService.checkTaskStatusExists(taskId);
return AjaxResult.success(exists ? "200" : "201");
}
/**
* 上架
* @param dto
* @return
*/
@PostMapping("/upGoods")
public AjaxResult upGoods(@RequestBody OutGoodsDTO dto) {
if (StringUtils.isBlank(dto.getTaskNo())) {
throw new ServiceException("taskNo 不能为空");
}
agvTaskResultService.handleUpGoods(dto.getTaskNo(), dto.getMaterialStatus());
return AjaxResult.success("上架任务已提交至WCS");
}
/**
* 下架
* @param dto
* @return
*/
@PostMapping("/outGoods")
public AjaxResult outGoods(@RequestBody OutGoodsDTO dto) {
try {
agvTaskResultService.handleOutGoods(dto);
return AjaxResult.success("下架任务已提交成功");
} catch (Exception e) {
return AjaxResult.error("下架失败:" + e.getMessage());
}
}
/** /**
* 查询AGV任务结果列表分页 * 查询AGV任务结果列表分页
*/ */
@@ -60,26 +143,4 @@ public class AgvTaskResultController extends BaseController {
public AjaxResult remove(@PathVariable Long[] ids) { public AjaxResult remove(@PathVariable Long[] ids) {
return toAjax(agvTaskResultService.deleteAgvTaskResultByIds(ids)); return toAjax(agvTaskResultService.deleteAgvTaskResultByIds(ids));
} }
/**
* AGV任务执行结果回调
*/
@PostMapping("/callback")
public AjaxResult receiveCallback(@RequestBody AgvDTO dto) {
agvTaskResultService.handleAgvCallback(dto);
return AjaxResult.success("AGV回调接收成功");
}
/**
* 检查AGV任务执行结果状态
*/
@PostMapping("/checkStatus")
public AjaxResult checkAgvTaskStatus(@RequestBody AgvDTO dto) {
boolean exists = agvTaskResultService.existsByRequestIdAndStatus(dto.getRequestId(), dto.getStatus());
if (exists) {
return AjaxResult.success("已达到指定状态:" + dto.getStatus());
} else {
return AjaxResult.error("未达到指定状态:" + dto.getStatus());
}
}
} }

View File

@@ -9,6 +9,7 @@ import com.zg.framework.web.controller.BaseController;
import com.zg.framework.web.domain.AjaxResult; import com.zg.framework.web.domain.AjaxResult;
import com.zg.framework.web.page.TableDataInfo; import com.zg.framework.web.page.TableDataInfo;
import com.zg.project.wisdom.domain.DdTask; import com.zg.project.wisdom.domain.DdTask;
import com.zg.project.wisdom.domain.dto.TaskExecuteDTO;
import com.zg.project.wisdom.domain.vo.TaskExecuteResultVO; import com.zg.project.wisdom.domain.vo.TaskExecuteResultVO;
import com.zg.project.wisdom.service.IDdTaskService; import com.zg.project.wisdom.service.IDdTaskService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -27,10 +28,28 @@ public class DdTaskController extends BaseController {
@Autowired @Autowired
private IDdTaskService ddTaskService; private IDdTaskService ddTaskService;
/**
* 新增调度任务
*/
@PostMapping("/add")
public AjaxResult add(@RequestBody DdTask ddTask) {
return toAjax(ddTaskService.insertDdTask(ddTask));
}
/**
* 执行任务
* @param
* @return
*/
@PostMapping("/execute")
public AjaxResult execute(@RequestBody TaskExecuteDTO dto) {
TaskExecuteResultVO vo = ddTaskService.executeTask(dto);
return AjaxResult.success(vo);
}
/** /**
* 查询调度任务列表 * 查询调度任务列表
*/ */
// @PreAuthorize("@ss.hasPermi('wisdom:task:list')")
@GetMapping("/list") @GetMapping("/list")
public TableDataInfo list(DdTask ddTask) { public TableDataInfo list(DdTask ddTask) {
startPage(); startPage();
@@ -38,10 +57,18 @@ public class DdTaskController extends BaseController {
return getDataTable(list); return getDataTable(list);
} }
/**
* 获取调度任务详情
*/
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id) {
return success(ddTaskService.selectDdTaskById(id));
}
/** /**
* 导出调度任务列表 * 导出调度任务列表
*/ */
// @PreAuthorize("@ss.hasPermi('wisdom:task:export')")
@Log(title = "调度任务", businessType = BusinessType.EXPORT) @Log(title = "调度任务", businessType = BusinessType.EXPORT)
@PostMapping("/export") @PostMapping("/export")
public AjaxResult export(DdTask ddTask) { public AjaxResult export(DdTask ddTask) {
@@ -50,29 +77,9 @@ public class DdTaskController extends BaseController {
return util.exportExcel(list, "调度任务数据"); return util.exportExcel(list, "调度任务数据");
} }
/**
* 获取调度任务详情
*/
// @PreAuthorize("@ss.hasPermi('wisdom:task:query')")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id) {
return success(ddTaskService.selectDdTaskById(id));
}
/**
* 新增调度任务
*/
// @PreAuthorize("@ss.hasPermi('wisdom:task:add')")
@Log(title = "调度任务", businessType = BusinessType.INSERT)
@PostMapping("/add")
public AjaxResult add(@RequestBody DdTask ddTask) {
return toAjax(ddTaskService.insertDdTask(ddTask));
}
/** /**
* 修改调度任务 * 修改调度任务
*/ */
// @PreAuthorize("@ss.hasPermi('wisdom:task:edit')")
@Log(title = "调度任务", businessType = BusinessType.UPDATE) @Log(title = "调度任务", businessType = BusinessType.UPDATE)
@PutMapping @PutMapping
public AjaxResult edit(@RequestBody DdTask ddTask) { public AjaxResult edit(@RequestBody DdTask ddTask) {
@@ -82,23 +89,10 @@ public class DdTaskController extends BaseController {
/** /**
* 删除调度任务 * 删除调度任务
*/ */
// @PreAuthorize("@ss.hasPermi('wisdom:task:remove')")
@Log(title = "调度任务", businessType = BusinessType.DELETE) @Log(title = "调度任务", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}") @DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids) { public AjaxResult remove(@PathVariable Long[] ids) {
return toAjax(ddTaskService.deleteDdTaskByIds(ids)); return toAjax(ddTaskService.deleteDdTaskByIds(ids));
} }
/**
* 执行任务
* @param
* @return
*/
@PreAuthorize("@ss.hasPermi('wisdom:task:execute')")
@PostMapping("/execute")
public AjaxResult execute(@RequestParam Long id) {
TaskExecuteResultVO vo = ddTaskService.executeTask(id);
return AjaxResult.success(vo);
}
} }

View File

@@ -69,7 +69,7 @@ public class GysJhController extends BaseController
/** /**
* 导入供应计划数据(全部新增,不校验重复) * 导入供应计划数据(全部新增,不校验重复)
*/ */
@PreAuthorize("@ss.hasPermi('wisdom:jh:import')") @PreAuthorize("@ss.hasPermi('plan:jh:import')")
@Log(title = "供应计划", businessType = BusinessType.IMPORT) @Log(title = "供应计划", businessType = BusinessType.IMPORT)
@PostMapping("/importData") @PostMapping("/importData")
public AjaxResult importData(@RequestParam("file") MultipartFile file) throws Exception { public AjaxResult importData(@RequestParam("file") MultipartFile file) throws Exception {

View File

@@ -0,0 +1,119 @@
package com.zg.project.wisdom.controller;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zg.common.utils.http.HttpUtils;
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;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/mock")
public class MockRemoteController {
@PostMapping("/wcs/task/create")
public Map<String, Object> mockWcs(@RequestBody Map<String, Object> param) {
System.out.println("【MOCK-WCS】接收到下架或上架任务" + param);
Map<String, Object> result = new HashMap<>();
result.put("code", 0);
result.put("msg", "WCS任务已接收");
return result;
}
/**
* 模拟 WCS 状态回调接口(发送 taskId 和状态数字 1~4
*/
@PostMapping("/wcs/task/callback")
public Map<String, Object> mockWcsCallback(@RequestBody Map<String, Object> param) {
System.out.println("【MOCK-WCS】模拟立库回调任务" + param);
String taskId = String.valueOf(param.get("taskId"));
String callbackUrl = "http://localhost:8080/wisdom/wcs/callback"; // 改成你项目实际地址
// 状态顺序:接收成功 → 开始执行 → 执行成功 → 执行失败
List<String> statusList = Arrays.asList("1", "2", "3", "4");
new Thread(() -> {
ObjectMapper mapper = new ObjectMapper();
for (String status : statusList) {
Map<String, Object> callback = new HashMap<>();
callback.put("taskId", taskId);
callback.put("status", status);
callback.put("msg", "模拟WCS状态" + status);
try {
String json = mapper.writeValueAsString(callback);
String resp = HttpUtils.sendPost(callbackUrl, json);
System.out.println("【MOCK-WCS】已回调状态" + status + " → 响应:" + resp);
} catch (Exception e) {
System.err.println("【MOCK-WCS】回调失败" + status + "" + e.getMessage());
}
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}).start();
Map<String, Object> result = new HashMap<>();
result.put("code", 0);
result.put("msg", "WCS模拟状态已开始逐步回调");
return result;
}
/**
* 模拟 AGV 状态回调接口(发送 requestId 和多个执行阶段状态)
*/
@PostMapping("/agv/task/create")
public Map<String, Object> mockAgv(@RequestBody Map<String, Object> param) {
System.out.println("【MOCK-AGV】接收到搬运任务" + param);
String requestId = String.valueOf(param.get("requestId"));
String callbackUrl = "http://localhost:8080/wisdom/agv/callback"; // 改成你实际项目地址
// AGV 的标准执行流程状态
List<String> statusList = Arrays.asList(
"CREATED",
"ALLOCATED",
"WAITING_PICK_UP",
"PICK_UP_COMPLETED",
"WAITING_TAKE_DOWN",
"END_ARRIVE",
"TAKE_DOWN_COMPLETED",
"FINISHED"
);
new Thread(() -> {
ObjectMapper mapper = new ObjectMapper();
for (String status : statusList) {
Map<String, Object> callback = new HashMap<>();
callback.put("requestId", requestId);
callback.put("status", status);
callback.put("msg", "模拟AGV状态" + status);
try {
String json = mapper.writeValueAsString(callback);
String resp = HttpUtils.sendPost(callbackUrl, json);
System.out.println("【MOCK-AGV】已回调状态" + status + " → 响应:" + resp);
} catch (Exception e) {
System.err.println("【MOCK-AGV】回调失败" + status + "" + e.getMessage());
}
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}).start();
Map<String, Object> result = new HashMap<>();
result.put("code", 0);
result.put("msg", "AGV模拟状态已开始逐步回调");
return result;
}
}

View File

@@ -60,20 +60,7 @@ public class AgvTaskResult extends BaseEntity {
@Excel(name = "AGV更新时间") @Excel(name = "AGV更新时间")
private String updatedAt; private String updatedAt;
/** 执行状态如END_ARRIVE等 */ /** 执行状态 */
/**
* 执行状态AGV任务阶段
* CREATED - 创建任务;
* ALLOCATED - 分配资源;
* WAITING_PICK_UP - 等待取货;
* PICK_UP_COMPLETED - 取货完成;
* WAITING_TAKE_DOWN - 等待卸货;
* END_ARRIVE - 到达终点;
* TAKE_DOWN_COMPLETED - 卸货完成;
* FINISHED - 任务完成;
* FAILURE - 执行失败;
* PROCESSING - 任务执行中。
*/
@Excel(name = "执行状态") @Excel(name = "执行状态")
private String status; private String status;
@@ -84,6 +71,33 @@ public class AgvTaskResult extends BaseEntity {
/** 是否删除0正常 1删除 */ /** 是否删除0正常 1删除 */
private String isDelete; private String isDelete;
/** 物料状态0空托1有货 */
private Integer midStatus;
/** 物料编码 */
@Excel(name = "物料编码")
private String mid;
/** 物料数量 */
@Excel(name = "物料数量")
private Integer num;
/** 物料状态类型 */
@Excel(name = "物料状态类型")
private String midType;
/** 执行次数 */
@Excel(name = "执行次数")
private Integer doCount;
/** 绑定单据ID */
@Excel(name = "绑定单据ID")
private String rid;
/** 封签/派工单号 */
@Excel(name = "封签/派工单号")
private String prf;
// getter/setter // getter/setter
public Long getId() { public Long getId() {
@@ -198,6 +212,62 @@ public class AgvTaskResult extends BaseEntity {
this.isDelete = isDelete; this.isDelete = isDelete;
} }
public Integer getMidStatus() {
return midStatus;
}
public void setMidStatus(Integer midStatus) {
this.midStatus = midStatus;
}
public String getMid() {
return mid;
}
public void setMid(String mid) {
this.mid = mid;
}
public Integer getNum() {
return num;
}
public void setNum(Integer num) {
this.num = num;
}
public String getMidType() {
return midType;
}
public void setMidType(String midType) {
this.midType = midType;
}
public Integer getDoCount() {
return doCount;
}
public void setDoCount(Integer doCount) {
this.doCount = doCount;
}
public String getRid() {
return rid;
}
public void setRid(String rid) {
this.rid = rid;
}
public String getPrf() {
return prf;
}
public void setPrf(String prf) {
this.prf = prf;
}
@Override @Override
public String toString() { public String toString() {
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
@@ -214,6 +284,13 @@ public class AgvTaskResult extends BaseEntity {
.append("updatedAt", getUpdatedAt()) .append("updatedAt", getUpdatedAt())
.append("status", getStatus()) .append("status", getStatus())
.append("msg", getMsg()) .append("msg", getMsg())
.append("midStatus", getMidStatus())
.append("mid", getMid())
.append("num", getNum())
.append("midType", getMidType())
.append("doCount", getDoCount())
.append("rid", getRid())
.append("prf", getPrf())
.append("createBy", getCreateBy()) .append("createBy", getCreateBy())
.append("createTime", getCreateTime()) .append("createTime", getCreateTime())
.append("updateBy", getUpdateBy()) .append("updateBy", getUpdateBy())

View File

@@ -0,0 +1,26 @@
package com.zg.project.wisdom.domain;
public class AgyWcs {
private Integer id;
private String requestId; // AGV任务ID
private String taskId; // WCS任务ID
// getter/setter
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
public String getRequestId() { return requestId; }
public void setRequestId(String requestId) { this.requestId = requestId; }
public String getTaskId() { return taskId; }
public void setTaskId(String taskId) { this.taskId = taskId; }
@Override
public String toString() {
return "AgyWcs{" +
"id=" + id +
", requestId='" + requestId + '\'' +
", taskId='" + taskId + '\'' +
'}';
}
}

View File

@@ -0,0 +1,187 @@
package com.zg.project.wisdom.domain;
import com.zg.framework.aspectj.lang.annotation.Excel;
import com.zg.framework.web.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import java.util.Date;
public class WcsTaskResult extends BaseEntity {
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 请求ID */
@Excel(name = "请求ID")
private String taskId;
/** 状态 */
@Excel(name = "状态")
private String TaskStatus;
/** 说明 */
@Excel(name = "状态说明")
private String msg;
/** 任务编号 */
@Excel(name = "WCS任务编号")
private String jobId;
/** 所有者 */
@Excel(name = "任务所有者")
private String owner;
/** 类型 */
@Excel(name = "任务类型")
private String type;
/** 优先级 */
@Excel(name = "优先级")
private String priority;
/** 起始位置 */
@Excel(name = "起始位置")
private String sourceName;
/** 目标位置 */
@Excel(name = "目标位置")
private String targetName;
@Excel(name = "创建时间")
private Date createTime;
@Excel(name = "更新时间")
private Date updateTime;
/** 是否删除 */
private String isDelete;
// Getter / Setter
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTaskId() {
return taskId;
}
public void setTaskId(String taskId) {
this.taskId = taskId;
}
public String getTaskStatus() {
return TaskStatus;
}
public void setTaskStatus(String TaskStatus) {
this.TaskStatus = TaskStatus;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public String getJobId() {
return jobId;
}
public void setJobId(String jobId) {
this.jobId = jobId;
}
public String getOwner() {
return owner;
}
public void setOwner(String owner) {
this.owner = owner;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getPriority() {
return priority;
}
public void setPriority(String priority) {
this.priority = priority;
}
public String getSourceName() {
return sourceName;
}
public void setSourceName(String sourceName) {
this.sourceName = sourceName;
}
public String getTargetName() {
return targetName;
}
public void setTargetName(String targetName) {
this.targetName = targetName;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
public String getIsDelete() {
return isDelete;
}
public void setIsDelete(String isDelete) {
this.isDelete = isDelete;
}
@Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("taskId", getTaskId())
.append("TaskStatus", getTaskStatus())
.append("msg", getMsg())
.append("jobId", getJobId())
.append("owner", getOwner())
.append("type", getType())
.append("priority", getPriority())
.append("sourceName", getSourceName())
.append("targetName", getTargetName())
.append("isDelete", getIsDelete())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.toString();
}
}

View File

@@ -5,6 +5,7 @@ import lombok.Data;
@Data @Data
public class AgvDTO { public class AgvDTO {
private String requestId; private String requestId;
private String taskId;
private String jobId; private String jobId;
private String owner; private String owner;
private String type; private String type;

View File

@@ -0,0 +1,9 @@
package com.zg.project.wisdom.domain.dto;
import lombok.Data;
@Data
public class OutGoodsDTO {
private String taskNo;
private Integer materialStatus; // 0=空托1=有货(影响是否传物料信息)
}

View File

@@ -10,9 +10,6 @@ import java.util.List;
@Data @Data
public class PcRkInfoBatchDTO { public class PcRkInfoBatchDTO {
/** 供应计划主键ID */
private Long gysJhId;
/** 审核人用户ID */ /** 审核人用户ID */
private String approverId; private String approverId;

View File

@@ -0,0 +1,14 @@
package com.zg.project.wisdom.domain.dto;
import lombok.Data;
@Data
public class TaskExecuteDTO {
private Long id; // 必传任务ID
private String targetName; // 目标位置
private Integer materialStatus; //前端传入0=空托盘1=有货
}

View File

@@ -1,6 +1,7 @@
package com.zg.project.wisdom.mapper; package com.zg.project.wisdom.mapper;
import com.zg.project.wisdom.domain.AgvTaskResult; import com.zg.project.wisdom.domain.AgvTaskResult;
import org.apache.ibatis.annotations.Param;
import java.util.List; import java.util.List;
@@ -18,5 +19,19 @@ public interface AgvTaskResultMapper {
int deleteAgvTaskResultByIds(Long[] ids); int deleteAgvTaskResultByIds(Long[] ids);
int selectCountByRequestIdAndStatus(String requestId, String status); /**
* 根据requestId查询任务结果
*
* @param requestId
* @return
*/
AgvTaskResult selectByRequestId(String requestId);
/**
* 统计指定 requestId + status 的记录数量
*/
int countByRequestIdAndStatus(@Param("requestId") String requestId,
@Param("status") String status);
AgvTaskResult selectByTaskNo(String taskNo);
} }

View File

@@ -0,0 +1,7 @@
package com.zg.project.wisdom.mapper;
import com.zg.project.wisdom.domain.AgyWcs;
public interface AgyWcsMapper {
int insertAgyWcs(AgyWcs aw);
}

View File

@@ -85,7 +85,7 @@ public interface AuditSignatureMapper
/** /**
* 查询现场图片URL按入库ID * 查询现场图片URL按入库ID
*/ */
AuditSignature selectPhotoUrlByBillNo(@Param("billNo") String billNo); AuditSignature selectPhotoUrlByRkId(@Param("rkId") Long rkId);
/** /**
* 查询审批记录列表按主表ID * 查询审批记录列表按主表ID

View File

@@ -1,6 +1,8 @@
package com.zg.project.wisdom.mapper; package com.zg.project.wisdom.mapper;
import com.zg.project.wisdom.domain.DdTask; import com.zg.project.wisdom.domain.DdTask;
import org.apache.ibatis.annotations.Param;
import java.util.List; import java.util.List;
/** /**
@@ -39,4 +41,16 @@ public interface DdTaskMapper {
* 删除单个调度任务 * 删除单个调度任务
*/ */
int deleteDdTaskById(Long id); int deleteDdTaskById(Long id);
/**
* 根据任务编号更新任务状态
*/
void updateTaskStatusByTaskNo(String taskNo, int i);
/**
* 根据任务编号查询调度任务
* @param taskNo 任务编号
* @return DdTask 对象
*/
DdTask selectByTaskNo(@Param("taskNo") String taskNo);
} }

View File

@@ -1,7 +1,10 @@
package com.zg.project.wisdom.mapper; package com.zg.project.wisdom.mapper;
import java.util.List; import java.util.List;
import java.util.Set;
import com.zg.project.wisdom.domain.GysJh; import com.zg.project.wisdom.domain.GysJh;
import org.apache.ibatis.annotations.Param;
/** /**
* 供应计划Mapper接口 * 供应计划Mapper接口
@@ -77,4 +80,22 @@ public interface GysJhMapper
* @param sapNos * @param sapNos
*/ */
void resetGysJhStatusBySapNos(List<String> sapNos); void resetGysJhStatusBySapNos(List<String> sapNos);
/**
* 根据sapNo和xmNo和wlNo查询
* @param sapNo
* @param xmNo
* @param wlNo
* @return
*/
boolean existsByUniqueKeys(@Param("sapNo") String sapNo,
@Param("xmNo") String xmNo,
@Param("wlNo") String wlNo);
/**
* 批量修改状态
* @param
*/
void batchUpdateStatusByIds(@Param("idSet") Set<Long> idSet);
} }

View File

@@ -0,0 +1,11 @@
package com.zg.project.wisdom.mapper;
import com.zg.project.wisdom.domain.WcsTaskResult;
public interface WcsTaskResultMapper {
void insertWcsTaskResult(WcsTaskResult result);
int countByTaskId(String taskId);
}

View File

@@ -2,6 +2,7 @@ package com.zg.project.wisdom.service;
import com.zg.project.wisdom.domain.AgvTaskResult; import com.zg.project.wisdom.domain.AgvTaskResult;
import com.zg.project.wisdom.domain.dto.AgvDTO; import com.zg.project.wisdom.domain.dto.AgvDTO;
import com.zg.project.wisdom.domain.dto.OutGoodsDTO;
import java.util.List; import java.util.List;
@@ -27,6 +28,18 @@ public interface IAgvTaskResultService {
/** 处理AGV回调 */ /** 处理AGV回调 */
void handleAgvCallback(AgvDTO dto); void handleAgvCallback(AgvDTO dto);
/** 根据请求ID和状态判断AGV任务结果是否存在 */
/** 上架 */
void handleUpGoods(String taskNo,Integer materialStatus );
/** 下架 */
void handleOutGoods(OutGoodsDTO dto);
/**
* 判断指定 requestId + status 是否存在记录
* @param requestId 请求唯一标识
* @param status 状态码
* @return true 存在false 不存在
*/
boolean existsByRequestIdAndStatus(String requestId, String status); boolean existsByRequestIdAndStatus(String requestId, String status);
} }

View File

@@ -2,6 +2,7 @@ package com.zg.project.wisdom.service;
import com.zg.framework.web.domain.AjaxResult; import com.zg.framework.web.domain.AjaxResult;
import com.zg.project.wisdom.domain.DdTask; import com.zg.project.wisdom.domain.DdTask;
import com.zg.project.wisdom.domain.dto.TaskExecuteDTO;
import com.zg.project.wisdom.domain.vo.TaskExecuteResultVO; import com.zg.project.wisdom.domain.vo.TaskExecuteResultVO;
import java.util.List; import java.util.List;
@@ -42,9 +43,8 @@ public interface IDdTaskService {
* 删除单个调度任务 * 删除单个调度任务
*/ */
int deleteDdTaskById(Long id); int deleteDdTaskById(Long id);
/** /**
* 执行任务 * 执行任务
*/ */
TaskExecuteResultVO executeTask(Long id); TaskExecuteResultVO executeTask(TaskExecuteDTO dto);
} }

View File

@@ -0,0 +1,10 @@
package com.zg.project.wisdom.service;
import com.zg.project.wisdom.domain.WcsTaskResult;
public interface IWcsTaskResultService {
void handleWcsCallback(WcsTaskResult dto);
boolean checkTaskStatusExists(String taskId);
}

View File

@@ -1,15 +1,34 @@
package com.zg.project.wisdom.service.impl; package com.zg.project.wisdom.service.impl;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.zg.common.exception.ServiceException;
import com.zg.common.utils.DateUtils; import com.zg.common.utils.DateUtils;
import com.zg.common.utils.SecurityUtils; import com.zg.common.utils.SecurityUtils;
import com.zg.common.utils.StringUtils;
import com.zg.common.utils.http.HttpUtils;
import com.zg.project.information.mapper.MtdMapper;
import com.zg.project.wisdom.domain.AgvTaskResult; import com.zg.project.wisdom.domain.AgvTaskResult;
import com.zg.project.wisdom.domain.AgyWcs;
import com.zg.project.wisdom.domain.DdTask;
import com.zg.project.wisdom.domain.WcsTaskResult;
import com.zg.project.wisdom.domain.dto.AgvDTO; import com.zg.project.wisdom.domain.dto.AgvDTO;
import com.zg.project.wisdom.domain.dto.OutGoodsDTO;
import com.zg.project.wisdom.mapper.AgvTaskResultMapper; import com.zg.project.wisdom.mapper.AgvTaskResultMapper;
import com.zg.project.wisdom.mapper.AgyWcsMapper;
import com.zg.project.wisdom.mapper.DdTaskMapper;
import com.zg.project.wisdom.mapper.WcsTaskResultMapper;
import com.zg.project.wisdom.service.IAgvTaskResultService; import com.zg.project.wisdom.service.IAgvTaskResultService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Objects;
import static com.zg.framework.datasource.DynamicDataSourceContextHolder.log;
@Service @Service
public class AgvTaskResultServiceImpl implements IAgvTaskResultService { public class AgvTaskResultServiceImpl implements IAgvTaskResultService {
@@ -17,6 +36,31 @@ public class AgvTaskResultServiceImpl implements IAgvTaskResultService {
@Autowired @Autowired
private AgvTaskResultMapper agvTaskResultMapper; private AgvTaskResultMapper agvTaskResultMapper;
@Autowired
private WcsTaskResultMapper wcsTaskResultMapper;
@Autowired
private DdTaskMapper ddTaskMapper;
@Autowired
private MtdMapper mtdMapper;
@Autowired
private AgyWcsMapper agyWcsMapper;
// @Value("${agv.job.create-url}")
// private String agvJobCreateUrl;
//
// @Value("${wcs.job.create-url}")
// private String wcsJobCreateUrl;
@Value("${mock.agv-job-create-url}")
private String agvJobCreateUrl;
@Value("${mock.wcs-job-create-url}")
private String wcsJobCreateUrl;
@Override @Override
public AgvTaskResult selectAgvTaskResultById(Long id) { public AgvTaskResult selectAgvTaskResultById(Long id) {
return agvTaskResultMapper.selectAgvTaskResultById(id); return agvTaskResultMapper.selectAgvTaskResultById(id);
@@ -50,12 +94,17 @@ public class AgvTaskResultServiceImpl implements IAgvTaskResultService {
} }
@Override @Override
@Transactional(rollbackFor = Exception.class)
public void handleAgvCallback(AgvDTO dto) { public void handleAgvCallback(AgvDTO dto) {
String requestId = dto.getRequestId(); String requestId = dto.getRequestId();
String taskNo = requestId != null && requestId.length() > 2 if (StringUtils.isBlank(requestId)) {
? requestId.substring(0, requestId.length() - 2) throw new ServiceException("requestId不能为空");
: requestId; }
// 截取 taskNo去除 -AGV 等后缀)
String taskNo = requestId.substring(0, requestId.length() - 2);
// 写入 AGV 回调状态记录(每个状态都一条,不覆盖)
AgvTaskResult result = new AgvTaskResult(); AgvTaskResult result = new AgvTaskResult();
result.setRequestId(requestId); result.setRequestId(requestId);
result.setTaskNo(taskNo); result.setTaskNo(taskNo);
@@ -65,19 +114,211 @@ public class AgvTaskResultServiceImpl implements IAgvTaskResultService {
result.setPriority(dto.getPriority()); result.setPriority(dto.getPriority());
result.setSourceName(dto.getSourceName()); result.setSourceName(dto.getSourceName());
result.setTargetName(dto.getTargetName()); result.setTargetName(dto.getTargetName());
result.setCreatedAt(dto.getCreatedAt());
result.setUpdatedAt(dto.getUpdatedAt());
result.setStatus(dto.getStatus()); result.setStatus(dto.getStatus());
result.setMsg(dto.getMsg()); result.setMsg(dto.getMsg());
result.setCreateBy("agv"); result.setCreateBy("agv");
result.setCreateTime(DateUtils.getNowDate()); result.setCreateTime(DateUtils.getNowDate());
result.setUpdateTime(DateUtils.getNowDate());
result.setIsDelete("0"); result.setIsDelete("0");
agvTaskResultMapper.insertAgvTaskResult(result); agvTaskResultMapper.insertAgvTaskResult(result);
// 如果状态为 FINISHED则将 dd_task 中状态置为 2已完成
if ("FINISHED".equalsIgnoreCase(dto.getStatus())) {
ddTaskMapper.updateTaskStatusByTaskNo(taskNo, 2);
}
} }
/**
* 货物上架
* @param
*/
@Override
public void handleUpGoods(String taskNo, Integer materialStatus) {
String userId = SecurityUtils.getUserId().toString();
Date now = DateUtils.getNowDate();
// 1. 查询调度任务
DdTask ddTask = ddTaskMapper.selectByTaskNo(taskNo);
if (ddTask == null) {
throw new ServiceException("未找到调度任务taskNo = " + taskNo);
}
// 2. 构造 WCS 请求参数
String taskId = taskNo + "21"; // 上架任务编号taskNo + 21
JSONObject wcsParam = new JSONObject();
wcsParam.put("TaskID", taskId);
wcsParam.put("TrayNo", ""); // 固定空
wcsParam.put("Materialstatus", materialStatus);
if (materialStatus != null && materialStatus == 1) {
String materialCode = ddTask.getMid();
String specification = mtdMapper.selectWlmsByWlbh(materialCode);
wcsParam.put("MaterialCode", materialCode);
wcsParam.put("Specification", specification != null ? specification : "");
wcsParam.put("Quantity", ddTask.getNum() != null ? ddTask.getNum() : "");
} else {
wcsParam.put("MaterialCode", "");
wcsParam.put("Specification", "");
wcsParam.put("Quantity", "");
}
wcsParam.put("Mlocation", ddTask.getSourceName());
wcsParam.put("Tlocation", ddTask.getTargetName());
log.info("[上架] 调用 WCS 接口: {}", wcsParam.toJSONString());
String wcsResp = HttpUtils.sendPost(wcsJobCreateUrl, wcsParam.toJSONString());
if (StringUtils.isBlank(wcsResp)) {
throw new ServiceException("WCS 接口无响应");
}
JSONObject json = JSON.parseObject(wcsResp);
if (!Objects.equals(json.getInteger("code"), 0)) {
throw new ServiceException("WCS 上架失败:" + json.getString("msg"));
}
// 3. 写入 WCS 执行结果记录
WcsTaskResult wcs = new WcsTaskResult();
wcs.setTaskId(taskId);
wcs.setTaskStatus("1"); // 等待WCS回调
wcs.setMsg(json.getString("msg"));
wcs.setOwner("wms");
wcs.setType("1"); // 上架
wcs.setPriority("1");
wcs.setSourceName(ddTask.getSourceName());
wcs.setTargetName(ddTask.getTargetName());
wcs.setIsDelete("0");
wcs.setCreateBy(userId);
wcs.setCreateTime(now);
wcs.setUpdateTime(now);
wcsTaskResultMapper.insertWcsTaskResult(wcs);
log.info("[上架] 执行成功,任务 {} 状态已更新为已完成", taskNo);
}
/**
* 货物下架
* @param
*/
@Override
public void handleOutGoods(OutGoodsDTO dto) {
String taskNo = dto.getTaskNo();
Integer materialStatus = dto.getMaterialStatus(); // ✅ 关键判断字段
String userId = SecurityUtils.getUserId().toString();
Date now = DateUtils.getNowDate();
// 1. 查询 AGV 原任务记录
AgvTaskResult task = agvTaskResultMapper.selectByTaskNo(taskNo);
if (task == null) {
throw new ServiceException("未找到任务:" + taskNo);
}
// 2. 调用 WCS 下架接口
String wcsTaskId = taskNo + "22";
JSONObject wcsParam = new JSONObject();
wcsParam.put("TaskID", wcsTaskId);
wcsParam.put("TrayNo", "");
wcsParam.put("Materialstatus", materialStatus);
if (Objects.equals(materialStatus, 1)) {
wcsParam.put("MaterialCode", task.getMid());
wcsParam.put("Quantity", task.getNum());
String spec = mtdMapper.selectWlmsByWlbh(task.getMid());
wcsParam.put("Specification", spec != null ? spec : "");
} else {
wcsParam.put("MaterialCode", "");
wcsParam.put("Quantity", "");
wcsParam.put("Specification", "");
}
wcsParam.put("Mlocation", task.getSourceName()); // 来源库位
wcsParam.put("Tlocation", task.getTargetName()); // 目标库位
wcsParam.put("outBack", 1); // 固定值
log.info("[下架] 调用 WCS 接口: {}", wcsParam.toJSONString());
String wcsResp = HttpUtils.sendPost(wcsJobCreateUrl, wcsParam.toJSONString());
if (StringUtils.isBlank(wcsResp)) {
throw new ServiceException("WCS接口无响应");
}
JSONObject wcsJson = JSON.parseObject(wcsResp);
if (!Objects.equals(wcsJson.getInteger("code"), 0)) {
throw new ServiceException("WCS下架失败" + wcsJson.getString("msg"));
}
// 3. 记录 WCS 任务
WcsTaskResult wcs = new WcsTaskResult();
wcs.setTaskId(wcsTaskId);
wcs.setTaskStatus("3"); // 等待下架
wcs.setMsg(wcsJson.getString("msg"));
wcs.setOwner("wms");
wcs.setType("2");
wcs.setPriority("1");
wcs.setSourceName(task.getSourceName());
wcs.setTargetName(task.getTargetName());
wcs.setIsDelete("0");
wcs.setCreateBy(userId);
wcs.setCreateTime(now);
wcs.setUpdateTime(now);
wcsTaskResultMapper.insertWcsTaskResult(wcs);
// 4. 调用 AGV 出库搬运(下架点 → 出口)
String agvRequestId = taskNo + "12";
JSONObject agvParam = new JSONObject();
agvParam.put("requestId", agvRequestId);
agvParam.put("taskNo", taskNo);
agvParam.put("owner", "wms");
agvParam.put("type", 2); // 下架搬运
agvParam.put("priority", "1");
agvParam.put("sourceName", task.getTargetName());
agvParam.put("targetName", "出口口A");
log.info("[下架] 调用 AGV 接口: {}", agvParam.toJSONString());
String agvResp = HttpUtils.sendPost(agvJobCreateUrl, agvParam.toJSONString());
if (StringUtils.isBlank(agvResp)) {
throw new ServiceException("AGV接口无响应");
}
JSONObject agvJson = JSON.parseObject(agvResp);
if (!Objects.equals(agvJson.getInteger("code"), 0)) {
throw new ServiceException("AGV搬运失败" + agvJson.getString("msg"));
}
// 5. 保存 AGV 出库搬运记录
AgvTaskResult agv = new AgvTaskResult();
agv.setRequestId(agvRequestId);
agv.setStatus("CREATED");
agv.setMsg(agvJson.getString("msg"));
agv.setOwner("wms");
agv.setType("2");
agv.setPriority("1");
agv.setTaskNo(taskNo);
agv.setSourceName(task.getTargetName());
agv.setTargetName("出口口A");
agv.setIsDelete("0");
agv.setCreateBy(userId);
agv.setCreateTime(now);
agv.setUpdateTime(now);
agvTaskResultMapper.insertAgvTaskResult(agv);
// 6. 保存 AGV/WCS 对应关系
AgyWcs mapping = new AgyWcs();
mapping.setRequestId(agvRequestId);
mapping.setTaskId(wcsTaskId);
agyWcsMapper.insertAgyWcs(mapping);
log.info("[下架] AGV 搬运任务提交成功");
}
@Override @Override
public boolean existsByRequestIdAndStatus(String requestId, String status) { public boolean existsByRequestIdAndStatus(String requestId, String status) {
return agvTaskResultMapper.selectCountByRequestIdAndStatus(requestId, status) > 0; return agvTaskResultMapper.countByRequestIdAndStatus(requestId, status) > 0;
} }
} }

View File

@@ -8,9 +8,15 @@ import com.zg.common.utils.SecurityUtils;
import com.zg.common.utils.StringUtils; import com.zg.common.utils.StringUtils;
import com.zg.common.utils.http.HttpUtils; import com.zg.common.utils.http.HttpUtils;
import com.zg.framework.web.domain.AjaxResult; import com.zg.framework.web.domain.AjaxResult;
import com.zg.project.information.mapper.MtdMapper;
import com.zg.project.wisdom.domain.AgvTaskResult;
import com.zg.project.wisdom.domain.DdTask; import com.zg.project.wisdom.domain.DdTask;
import com.zg.project.wisdom.domain.WcsTaskResult;
import com.zg.project.wisdom.domain.dto.TaskExecuteDTO;
import com.zg.project.wisdom.domain.vo.TaskExecuteResultVO; import com.zg.project.wisdom.domain.vo.TaskExecuteResultVO;
import com.zg.project.wisdom.mapper.AgvTaskResultMapper;
import com.zg.project.wisdom.mapper.DdTaskMapper; import com.zg.project.wisdom.mapper.DdTaskMapper;
import com.zg.project.wisdom.mapper.WcsTaskResultMapper;
import com.zg.project.wisdom.service.IDdTaskService; import com.zg.project.wisdom.service.IDdTaskService;
import org.apache.commons.lang3.RandomUtils; import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.math.NumberUtils; import org.apache.commons.lang3.math.NumberUtils;
@@ -25,6 +31,8 @@ import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.*; import java.util.*;
import static com.zg.framework.datasource.DynamicDataSourceContextHolder.log;
/** /**
* 调度任务 Service 实现类 * 调度任务 Service 实现类
* *
@@ -36,9 +44,27 @@ public class DdTaskServiceImpl implements IDdTaskService {
@Autowired @Autowired
private DdTaskMapper ddTaskMapper; private DdTaskMapper ddTaskMapper;
@Value("${agv.job.create-url}") @Autowired
private WcsTaskResultMapper wcsTaskResultMapper;
@Autowired
private AgvTaskResultMapper agvTaskResultMapper;
@Autowired
private MtdMapper mtdMapper;
//
// @Value("${agv.job.create-url}")
// private String agvJobCreateUrl;
//
// @Value("${wcs.job.create-url}")
// private String wcsJobCreateUrl;
@Value("${mock.agv-job-create-url}")
private String agvJobCreateUrl; private String agvJobCreateUrl;
@Value("${mock.wcs-job-create-url}")
private String wcsJobCreateUrl;
@Override @Override
public List<DdTask> selectDdTaskList(DdTask ddTask) { public List<DdTask> selectDdTaskList(DdTask ddTask) {
return ddTaskMapper.selectDdTaskList(ddTask); return ddTaskMapper.selectDdTaskList(ddTask);
@@ -102,74 +128,141 @@ public class DdTaskServiceImpl implements IDdTaskService {
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public TaskExecuteResultVO executeTask(Long id) { public TaskExecuteResultVO executeTask(TaskExecuteDTO dto) {
Long id = dto.getId();
String targetName = dto.getTargetName();
Integer materialStatus = dto.getMaterialStatus(); // Materialstatus 前端传入
if (StringUtils.isBlank(targetName)) {
throw new ServiceException("targetName 不能为空");
}
// 1. 查询任务 // 1. 查询任务
DdTask task = ddTaskMapper.selectDdTaskById(id); DdTask task = ddTaskMapper.selectDdTaskById(id);
if (task == null) { if (task == null) {
throw new ServiceException("任务不存在ID = " + id); throw new ServiceException("任务不存在ID = " + id);
} }
if (task.getTaskStatus() == null || task.getTaskStatus() != 0) { if (!Objects.equals(task.getTaskStatus(), 0)) {
throw new ServiceException("任务状态不是待执行,当前状态为:" + task.getTaskStatus()); throw new ServiceException("任务状态不是待执行,当前状态为:" + task.getTaskStatus());
} }
// 2. 构造 requestId String taskNo = task.getTaskNo();
String requestId; String taskType = task.getTaskType(); // 0入库1出库2移库
if (StringUtils.isBlank(task.getTaskNo())) { String requestId = null; // ✅ AGV 使用
String timeStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("MMddHHmmss")); String taskIdParam = null; // ✅ WCS 使用,提前声明防作用域错误
int rand = new Random().nextInt(900) + 100; String response;
requestId = timeStr + rand; int code;
int num = Optional.ofNullable(task.getNum()).orElse(0); String msg;
requestId += String.format("%02d", num);
} else {
requestId = task.getTaskNo();
}
requestId += "1"; // AGV 固定值
int type = NumberUtils.toInt(task.getTaskType(), 0);
requestId += (type + 1); // 1上架、2下架、3移库
// 3. 构造 AGV 参数 // 2. 构造参数
JSONObject param = new JSONObject(); JSONObject param = new JSONObject();
param.put("requestId", requestId);
param.put("taskNo", task.getTaskNo());
param.put("owner", "wms"); param.put("owner", "wms");
param.put("type", type); param.put("type", taskType);
param.put("priority", 1); param.put("priority", 1);
param.put("sourceName", task.getSourceName()); param.put("sourceName", task.getSourceName());
param.put("targetName", task.getTargetName()); param.put("targetName", targetName);
// 4. 调用 AGV 接口 if ("0".equals(taskType) || "2".equals(taskType)) {
String result = HttpUtils.sendPost(agvJobCreateUrl, param.toJSONString()); // ✅ 入库/移库 → AGV
if (StringUtils.isBlank(result)) { requestId = taskNo + ("0".equals(taskType) ? "11" : "12"); // 拼接规则11 入库12 移库
throw new ServiceException("AGV接口无响应"); param.put("taskNo", taskNo);
param.put("requestId", requestId);
log.info("[任务执行] 类型={}AGVrequestId={}, param={}", taskType, requestId, param);
response = HttpUtils.sendPost(agvJobCreateUrl, param.toJSONString());
} else if ("1".equals(taskType)) {
// ✅ 出库 → WCS下架不传 requestId只传 TaskID
taskIdParam = taskNo + "22";
param.put("TaskID", taskIdParam);
param.put("Materialstatus", materialStatus);
param.put("outBack", 1);
param.put("TrayNo", "");
param.put("Mlocation", task.getSourceName());
if (materialStatus == 0) {
param.put("MaterialCode", "");
param.put("Specification", "");
param.put("Quantity", "");
} else {
String materialCode = task.getMid();
String quantity = task.getNum().toString();
String specification = mtdMapper.selectWlmsByWlbh(materialCode);
param.put("MaterialCode", materialCode);
param.put("Quantity", quantity);
param.put("Specification", specification == null ? "" : specification);
}
log.info("[任务执行] 类型=出库WCS下架TaskID={}, param={}", taskIdParam, param);
response = HttpUtils.sendPost(wcsJobCreateUrl, param.toJSONString());
} else {
throw new ServiceException("未知任务类型: " + taskType);
} }
Integer code; // 3. 解析响应
String msg; JSONObject respJson;
try { try {
JSONObject json = JSON.parseObject(result); respJson = JSON.parseObject(response);
code = json.getInteger("code"); code = respJson.getInteger("code");
msg = json.getString("msg"); msg = respJson.getString("msg");
} catch (Exception e) { } catch (Exception e) {
throw new ServiceException("AGV响应解析失败" + result); throw new ServiceException("响应解析失败: " + response);
} }
if (!Objects.equals(code, 0)) { if (code != 200) {
throw new ServiceException("AGV调用失败" + msg); throw new ServiceException("任务执行失败: " + msg);
} }
// 5. 更新任务状态 // 4. 更新任务状态为已提交
task.setTaskStatus(1); task.setTaskStatus(1);
task.setDoCount(task.getDoCount() != null ? task.getDoCount() + 1 : 1); task.setDoCount(Optional.ofNullable(task.getDoCount()).orElse(0) + 1);
task.setUpdateBy(SecurityUtils.getUserId().toString()); task.setUpdateBy(SecurityUtils.getUserId().toString());
task.setUpdateTime(DateUtils.getNowDate()); task.setUpdateTime(DateUtils.getNowDate());
ddTaskMapper.updateDdTask(task); ddTaskMapper.updateDdTask(task);
// 6. 返回结果 // 5. 写入执行记录
TaskExecuteResultVO resultVO = new TaskExecuteResultVO(); String userId = SecurityUtils.getUserId().toString();
resultVO.setRequestId(requestId); Date now = DateUtils.getNowDate();
resultVO.setCode(code);
resultVO.setMsg(msg); if ("0".equals(taskType) || "2".equals(taskType)) {
return resultVO; AgvTaskResult agv = new AgvTaskResult();
agv.setRequestId(requestId);
agv.setTaskNo(taskNo);
agv.setStatus("CREATED");
agv.setMsg(msg);
agv.setOwner("wms");
agv.setType(taskType);
agv.setPriority("1");
agv.setSourceName(task.getSourceName());
agv.setTargetName(targetName);
agv.setIsDelete("0");
agv.setCreateBy(userId);
agv.setCreateTime(now);
agv.setUpdateTime(now);
agvTaskResultMapper.insertAgvTaskResult(agv);
} else if ("1".equals(taskType)) {
WcsTaskResult wcs = new WcsTaskResult();
wcs.setTaskId(taskIdParam);
wcs.setTaskStatus("1");
wcs.setMsg(msg);
wcs.setJobId(null);
wcs.setOwner("wms");
wcs.setType(taskType);
wcs.setPriority("1");
wcs.setSourceName(task.getSourceName());
wcs.setTargetName(targetName);
wcs.setIsDelete("0");
wcs.setCreateBy(userId);
wcs.setCreateTime(now);
wcs.setUpdateTime(now);
wcsTaskResultMapper.insertWcsTaskResult(wcs);
}
// 6. 返回执行结果
TaskExecuteResultVO vo = new TaskExecuteResultVO();
vo.setRequestId(("0".equals(taskType) || "2".equals(taskType)) ? requestId : null);
vo.setCode(code);
vo.setMsg(msg);
return vo;
} }
} }

View File

@@ -114,6 +114,17 @@ public class GysJhServiceImpl implements IGysJhService
for (GysJh jh : jhList) { for (GysJh jh : jhList) {
try { try {
// 唯一性校验:订单号 + 项目号 + 物料号
boolean exists = gysJhMapper.existsByUniqueKeys(jh.getSapNo(), jh.getXmNo(), jh.getWlNo());
if (exists) {
failureNum++;
failureMsg.append("<br/>订单号:").append(jh.getSapNo())
.append(",项目号:").append(jh.getXmNo())
.append(",物料号:").append(jh.getWlNo())
.append(" 已存在,跳过导入。");
continue;
}
jh.setCreateBy(operName); jh.setCreateBy(operName);
jh.setStatus("0"); jh.setStatus("0");
jh.setIsDelete("0"); jh.setIsDelete("0");
@@ -121,7 +132,8 @@ public class GysJhServiceImpl implements IGysJhService
successNum++; successNum++;
} catch (Exception e) { } catch (Exception e) {
failureNum++; failureNum++;
failureMsg.append("<br/>项目号:").append(jh.getXmNo()) failureMsg.append("<br/>订单号:").append(jh.getSapNo())
.append(",项目号:").append(jh.getXmNo())
.append(",物料号:").append(jh.getWlNo()) .append(",物料号:").append(jh.getWlNo())
.append(" 导入失败:").append(e.getMessage()); .append(" 导入失败:").append(e.getMessage());
} }
@@ -135,6 +147,7 @@ public class GysJhServiceImpl implements IGysJhService
return "导入成功,共 " + successNum + " 条数据"; return "导入成功,共 " + successNum + " 条数据";
} }
/** /**
* 根据SAP编号查询 * 根据SAP编号查询
* @param sapNo * @param sapNo

View File

@@ -96,7 +96,7 @@ public class RkInfoServiceImpl implements IRkInfoService
} }
// 查询现场图片 + 审核结果image_type = '1' // 查询现场图片 + 审核结果image_type = '1'
AuditSignature signature = auditSignatureMapper.selectPhotoUrlByBillNo(info.getBillNo()); AuditSignature signature = auditSignatureMapper.selectPhotoUrlByRkId(info.getId());
if (signature != null) { if (signature != null) {
info.setScenePhotoUrl(signature.getSignUrl()); info.setScenePhotoUrl(signature.getSignUrl());
info.setAuditResult(signature.getAuditResult()); info.setAuditResult(signature.getAuditResult());
@@ -171,24 +171,24 @@ public class RkInfoServiceImpl implements IRkInfoService
List<AuditSignature> records = new ArrayList<>(); List<AuditSignature> records = new ArrayList<>();
// ✅ 第一步:构造 RkInfo 列表(不保存照片 // ✅ 第一步:构造 RkInfo 列表(包含 gysJhId
for (PcRkInfoItemDTO item : list) { for (PcRkInfoItemDTO item : list) {
RkInfo rk = new RkInfo(); RkInfo rk = new RkInfo();
BeanUtils.copyProperties(item, rk); BeanUtils.copyProperties(item, rk);
rk.setBillNo(billNo); rk.setBillNo(billNo);
rk.setGysJhId(dto.getGysJhId());
rk.setRkType(dto.getRkType()); rk.setRkType(dto.getRkType());
rk.setWlType(dto.getWlType()); rk.setWlType(dto.getWlType());
rk.setLihuoY(dto.getLihuoY()); rk.setLihuoY(dto.getLihuoY());
rk.setGysJhId(dto.getGysJhId());
rk.setRkTime(now); rk.setRkTime(now);
rk.setCangku(dto.getCangku()); rk.setCangku(dto.getCangku());
rk.setCreateBy(userId); rk.setCreateBy(userId);
rk.setCreateTime(now); rk.setCreateTime(now);
rk.setIsDelete("0"); rk.setIsDelete("0");
rk.setGysJhId(item.getGysJhId()); // ✅ 正确设置 gysJhId
if (needAudit) { if (needAudit) {
rk.setStatus("0"); // 入库待审核 rk.setStatus("0"); // 待审核
rk.setIsChuku("2"); // 待入库(审核中) rk.setIsChuku("2"); // 待入库(审核中)
} else { } else {
rk.setStatus("1"); // 审核通过 rk.setStatus("1"); // 审核通过
@@ -198,23 +198,23 @@ public class RkInfoServiceImpl implements IRkInfoService
rkInfos.add(rk); rkInfos.add(rk);
} }
// ✅ 第二步:批量保存入库记录,回填主键 ID // ✅ 第二步:批量保存入库记录
rkInfoMapper.batchInsertRkInfo(rkInfos); rkInfoMapper.batchInsertRkInfo(rkInfos);
// ✅ 第三步:根据主键构造照片记录 // ✅ 第三步:构造照片记录(审核开启时)
for (int i = 0; i < rkInfos.size(); i++) { for (int i = 0; i < rkInfos.size(); i++) {
RkInfo rk = rkInfos.get(i); RkInfo rk = rkInfos.get(i);
PcRkInfoItemDTO item = list.get(i); PcRkInfoItemDTO item = list.get(i);
if (needAudit && StringUtils.isNotBlank(item.getPhotoUrl())) { if (needAudit && StringUtils.isNotBlank(item.getPhotoUrl())) {
AuditSignature photo = new AuditSignature(); AuditSignature photo = new AuditSignature();
photo.setRkId(rk.getId()); // ✅ 此时已填充 ID photo.setRkId(rk.getId());
photo.setBillNo(billNo); photo.setBillNo(billNo);
photo.setBillType("0"); photo.setBillType("0");
photo.setAuditResult("2"); photo.setAuditResult("2");
photo.setSignerId(userId); photo.setSignerId(userId);
photo.setSignerRole("2"); // 拍照人 photo.setSignerRole("2");
photo.setImageType("1"); // 现场图 photo.setImageType("1"); // 现场图
photo.setSignUrl(item.getPhotoUrl()); photo.setSignUrl(item.getPhotoUrl());
photo.setSignTime(now); photo.setSignTime(now);
photo.setPcode(item.getPcode()); photo.setPcode(item.getPcode());
@@ -228,9 +228,8 @@ public class RkInfoServiceImpl implements IRkInfoService
} }
} }
// ✅ 第四步:如果启用审核,添加发起人签字记录 // ✅ 第四步:审核开启时添加发起人签字记录
if (needAudit) { if (needAudit) {
// === 检查是否已有发起人签字记录 ===
boolean hasOldSign = auditSignatureMapper.existsCurrentSigner(billNo, "0"); boolean hasOldSign = auditSignatureMapper.existsCurrentSigner(billNo, "0");
if (hasOldSign) { if (hasOldSign) {
auditSignatureMapper.updateIsCurrentToZero(billNo, "0"); auditSignatureMapper.updateIsCurrentToZero(billNo, "0");
@@ -252,15 +251,21 @@ public class RkInfoServiceImpl implements IRkInfoService
mainSign.setCreateTime(now); mainSign.setCreateTime(now);
records.add(mainSign); records.add(mainSign);
// ✅ 写入照片 + 签字图
if (!records.isEmpty()) { if (!records.isEmpty()) {
auditSignatureMapper.batchInsert(records); auditSignatureMapper.batchInsert(records);
} }
} }
// ✅ 更新供应计划状态-》修改逻辑,审核通过后再修改供应计划状态 // ✅ 第五步:如果审核关闭,立即批量更新供应计划状态
if (!needAudit && dto.getGysJhId() != null) { if (!needAudit) {
gysJhMapper.updateStatusById(dto.getGysJhId()); Set<Long> jhIdSet = list.stream()
.map(PcRkInfoItemDTO::getGysJhId)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
if (!jhIdSet.isEmpty()) {
gysJhMapper.batchUpdateStatusByIds(jhIdSet);
}
} }
} }

View File

@@ -0,0 +1,44 @@
package com.zg.project.wisdom.service.impl;
import com.zg.common.utils.DateUtils;
import com.zg.project.wisdom.domain.WcsTaskResult;
import com.zg.project.wisdom.mapper.WcsTaskResultMapper;
import com.zg.project.wisdom.service.IWcsTaskResultService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Date;
@Service
public class WcsTaskResultServiceImpl implements IWcsTaskResultService {
@Autowired
private WcsTaskResultMapper wcsTaskResultMapper;
@Override
public void handleWcsCallback(WcsTaskResult dto) {
String taskId = dto.getTaskId();
WcsTaskResult result = new WcsTaskResult();
result.setTaskId(taskId);
result.setTaskStatus(dto.getTaskStatus());
result.setMsg(dto.getMsg());
result.setJobId(dto.getJobId());
result.setOwner(dto.getOwner());
result.setType(dto.getType());
result.setPriority(dto.getPriority());
result.setSourceName(dto.getSourceName());
result.setTargetName(dto.getTargetName());
result.setCreateBy("wcs");
result.setCreateTime(DateUtils.getNowDate());
result.setUpdateTime(DateUtils.getNowDate());
result.setIsDelete("0");
wcsTaskResultMapper.insertWcsTaskResult(result);
}
@Override
public boolean checkTaskStatusExists(String taskId) {
return wcsTaskResultMapper.countByTaskId(taskId) > 0;
}
}

View File

@@ -145,7 +145,11 @@ gen:
agv: agv:
job: job:
create-url: http://192.168.1.155:1880/api/job/create create-url: http://192.168.1.245:9012/agv/task/create
wcs:
job:
create-url: http://192.168.1.230:8188/wcs/task/create
#rfid: #rfid:
# device: # device:
@@ -156,3 +160,7 @@ minio:
accessKey: admin accessKey: admin
secretKey: admin123 secretKey: admin123
bucketName: jaz bucketName: jaz
mock:
agv-job-create-url: http://localhost:8086/mock/agv/task/create
wcs-job-create-url: http://localhost:8086/mock/wcs/task/create

View File

@@ -0,0 +1,66 @@
<?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="com.zg.project.information.mapper.MtdMapper">
<resultMap id="MtdResultMap" type="com.zg.project.information.domain.Mtd">
<id property="id" column="id"/>
<result property="mid" column="mid"/>
<result property="desMat" column="des_mat"/>
<result property="grp" column="grp"/>
<result property="unt" column="unt"/>
<result property="uprc" column="uprc"/>
<result property="btpe" column="btpe"/>
<result property="mtpe" column="mtpe"/>
<result property="stpe" column="stpe"/>
</resultMap>
<select id="selectMtdById" parameterType="Long" resultMap="MtdResultMap">
SELECT * FROM mtd WHERE id = #{id}
</select>
<select id="selectMtdList" parameterType="Mtd" resultMap="MtdResultMap">
SELECT * FROM mtd
<where>
<if test="mid != null and mid != ''">AND mid = #{mid}</if>
<if test="desMat != null and desMat != ''">AND des_mat like concat('%', #{desMat}, '%')</if>
<if test="grp != null and grp != ''">AND grp = #{grp}</if>
<if test="unt != null and unt != ''">AND unt = #{unt}</if>
</where>
</select>
<select id="selectWlmsByWlbh" resultType="java.lang.String" parameterType="java.lang.String">
SELECT des_mat FROM mtd WHERE mid = #{materialCode}
</select>
<insert id="insertMtd" parameterType="Mtd">
INSERT INTO mtd (mid, des_mat, grp, unt, uprc, btpe, mtpe, stpe)
VALUES (#{mid}, #{desMat}, #{grp}, #{unt}, #{uprc}, #{btpe}, #{mtpe}, #{stpe})
</insert>
<update id="updateMtd" parameterType="Mtd">
UPDATE mtd
SET mid = #{mid},
des_mat = #{desMat},
grp = #{grp},
unt = #{unt},
uprc = #{uprc},
btpe = #{btpe},
mtpe = #{mtpe},
stpe = #{stpe}
WHERE id = #{id}
</update>
<delete id="deleteMtdById" parameterType="Long">
DELETE FROM mtd WHERE id = #{id}
</delete>
<delete id="deleteMtdByIds" parameterType="Long">
DELETE FROM mtd WHERE id IN
<foreach collection="array" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>

View File

@@ -4,28 +4,31 @@
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zg.project.information.mapper.PcdeDetailMapper"> <mapper namespace="com.zg.project.information.mapper.PcdeDetailMapper">
<resultMap type="PcdeDetail" id="PcdeDetailResult"> <resultMap type="PcdeDetail" id="PcdeDetailResult">
<result property="id" column="id"/> <result property="id" column="id"/>
<result property="pcode" column="pcode"/> <result property="pcode" column="pcode"/>
<result property="scene" column="scene"/> <result property="scene" column="scene"/>
<result property="sceneName" column="scene_name"/> <result property="sceneName" column="scene_name"/>
<result property="warehouse" column="warehouse"/> <result property="warehouse" column="warehouse"/>
<result property="encodedId" column="encoded_id"/> <result property="warehouseName" column="warehouse_name"/>
<result property="tag" column="tag"/> <result property="encodedId" column="encoded_id"/>
<result property="remark" column="remark"/> <result property="tag" column="tag"/>
<result property="isDelete" column="is_delete"/> <result property="remark" column="remark"/>
<result property="createdBy" column="created_by"/> <result property="isDelete" column="is_delete"/>
<result property="createdAt" column="created_at"/> <result property="createdBy" column="created_by"/>
<result property="updatedBy" column="updated_by"/> <result property="createdAt" column="created_at"/>
<result property="updatedAt" column="updated_at"/> <result property="updatedBy" column="updated_by"/>
<result property="updatedAt" column="updated_at"/>
</resultMap> </resultMap>
<sql id="selectPcdeDetailVo"> <sql id="selectPcdeDetailVo">
select d.id, d.pcode, d.scene, m.scene_name, d.warehouse, select d.id, d.pcode, d.scene, m.scene_name, d.warehouse, w.warehouse_name,
d.encoded_id, d.tag, d.remark, d.is_delete, d.encoded_id, d.tag, d.remark, d.is_delete,
d.created_by, d.created_at, d.updated_by, d.updated_at d.created_by, d.created_at, d.updated_by, d.updated_at
from pcde_detail d from pcde_detail d
left join scene_mapping m on d.scene = m.scene_code left join scene_mapping m on d.scene = m.scene_code
left join warehouse_info w on d.warehouse = w.warehouse_code
</sql> </sql>
<select id="selectPcdeDetailList" parameterType="PcdeDetail" resultMap="PcdeDetailResult"> <select id="selectPcdeDetailList" parameterType="PcdeDetail" resultMap="PcdeDetailResult">
@@ -55,6 +58,7 @@
created_by, created_at, updated_by, updated_at, remark created_by, created_at, updated_by, updated_at, remark
from pcde_detail from pcde_detail
where pcode = #{pcode} where pcode = #{pcode}
AND is_delete = '0'
</select> </select>
<insert id="insertPcdeDetail" parameterType="PcdeDetail" useGeneratedKeys="true" keyProperty="id"> <insert id="insertPcdeDetail" parameterType="PcdeDetail" useGeneratedKeys="true" keyProperty="id">

View File

@@ -35,14 +35,21 @@
</where> </where>
</select> </select>
<select id="selectCountByRequestIdAndStatus" resultType="int"> <select id="selectByRequestId" resultMap="AgvTaskResultResultMap">
SELECT COUNT(1) SELECT * FROM agv_task_result WHERE request_id = #{requestId} AND is_delete = '0'
FROM agv_task_result </select>
<select id="countByRequestIdAndStatus" resultType="int">
SELECT COUNT(*) FROM agv_task_result
WHERE request_id = #{requestId} WHERE request_id = #{requestId}
AND status = #{status} AND status = #{status}
AND is_delete = '0' AND is_delete = '0'
</select> </select>
<select id="selectByTaskNo" resultType="com.zg.project.wisdom.domain.AgvTaskResult">
SELECT * FROM agv_task_result WHERE task_no = #{taskNo} AND is_delete = '0'
</select>
<insert id="insertAgvTaskResult" parameterType="AgvTaskResult" useGeneratedKeys="true" keyProperty="id"> <insert id="insertAgvTaskResult" parameterType="AgvTaskResult" useGeneratedKeys="true" keyProperty="id">
INSERT INTO agv_task_result INSERT INTO agv_task_result
<trim prefix="(" suffix=")" suffixOverrides=","> <trim prefix="(" suffix=")" suffixOverrides=",">

View File

@@ -0,0 +1,20 @@
<?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="com.zg.project.wisdom.mapper.AgyWcsMapper">
<resultMap id="AgyWcsResultMap" type="com.zg.project.wisdom.domain.AgyWcs">
<id property="id" column="id"/>
<result property="requestId" column="requestId"/>
<result property="taskId" column="TaskID"/>
</resultMap>
<!-- 插入 AGV-WCS 映射关系 -->
<insert id="insertAgyWcs" parameterType="com.zg.project.wisdom.domain.AgyWcs">
INSERT INTO agy_wcs (requestId, TaskID)
VALUES (#{requestId}, #{taskId})
</insert>
</mapper>

View File

@@ -91,16 +91,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
AND is_delete = '0' AND is_delete = '0'
</select> </select>
<select id="selectPhotoUrlByBillNo" <select id="selectPhotoUrlByRkId" resultMap="AuditSignatureResult" parameterType="java.lang.Long">
resultMap="AuditSignatureResult"
parameterType="java.lang.String">
SELECT sign_url, audit_result SELECT sign_url, audit_result
FROM audit_signature FROM audit_signature
WHERE is_delete = '0' WHERE is_delete = '0'
AND bill_no = #{billNo} AND rk_id = #{rkId}
AND image_type = '1' AND image_type = '1'
AND audit_result = '1'
AND is_current = '1'
ORDER BY create_time DESC ORDER BY create_time DESC
LIMIT 1 LIMIT 1
</select> </select>
<!-- 查询主记录列表(审批记录) signer_role=1 image_type=0 --> <!-- 查询主记录列表(审批记录) signer_role=1 image_type=0 -->

View File

@@ -50,6 +50,11 @@
SELECT * FROM dd_task WHERE id = #{id} AND is_delete = '0' SELECT * FROM dd_task WHERE id = #{id} AND is_delete = '0'
</select> </select>
<!-- 根据任务编号查询 -->
<select id="selectByTaskNo" resultMap="DdTaskResult" parameterType="String">
SELECT * FROM dd_task WHERE task_no = #{taskNo} AND is_delete = '0' LIMIT 1
</select>
<insert id="insertDdTask" parameterType="DdTask"> <insert id="insertDdTask" parameterType="DdTask">
INSERT INTO dd_task ( INSERT INTO dd_task (
task_no, task_dtl, task_type, task_status, mid_status, mid, num, mid_type, source_name, task_no, task_dtl, task_type, task_status, mid_status, mid, num, mid_type, source_name,
@@ -86,6 +91,14 @@
WHERE id = #{id} WHERE id = #{id}
</update> </update>
<update id="updateTaskStatusByTaskNo">
UPDATE dd_task
SET task_status = #{status},
update_time = NOW()
WHERE task_no = #{taskNo}
AND is_delete = '0'
</update>
<delete id="deleteDdTaskByIds"> <delete id="deleteDdTaskByIds">
DELETE FROM dd_task WHERE id IN DELETE FROM dd_task WHERE id IN
<foreach collection="array" item="id" open="(" separator="," close=")"> <foreach collection="array" item="id" open="(" separator="," close=")">

View File

@@ -57,6 +57,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
AND status = '0' AND status = '0'
</select> </select>
<select id="existsByUniqueKeys" resultType="boolean">
SELECT COUNT(1)
FROM gys_jh
WHERE sap_no = #{sapNo}
AND xm_no = #{xmNo}
AND wl_no = #{wlNo}
AND is_delete = '0'
</select>
<insert id="insertGysJh" parameterType="GysJh" useGeneratedKeys="true" keyProperty="id"> <insert id="insertGysJh" parameterType="GysJh" useGeneratedKeys="true" keyProperty="id">
insert into gys_jh insert into gys_jh
<trim prefix="(" suffix=")" suffixOverrides=","> <trim prefix="(" suffix=")" suffixOverrides=",">
@@ -152,6 +161,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
#{sapNo} #{sapNo}
</foreach> </foreach>
</update> </update>
<update id="batchUpdateStatusByIds">
UPDATE gys_jh
SET status = '1'
WHERE id IN
<foreach collection="idSet" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</update>
<delete id="deleteGysJhById" parameterType="Long"> <delete id="deleteGysJhById" parameterType="Long">
delete from gys_jh where id = #{id} delete from gys_jh where id = #{id}
</delete> </delete>

View File

@@ -157,6 +157,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
update_time = NOW() update_time = NOW()
WHERE bill_no_ck = #{billNoCk} WHERE bill_no_ck = #{billNoCk}
</update> </update>
<delete id="deleteByBillNo"> <delete id="deleteByBillNo">
DELETE FROM rk_info DELETE FROM rk_info
WHERE bill_no = #{billNo} WHERE bill_no = #{billNo}

View File

@@ -0,0 +1,70 @@
<?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="com.zg.project.wisdom.mapper.WcsTaskResultMapper">
<resultMap id="WcsTaskResultResultMap" type="com.zg.project.wisdom.domain.WcsTaskResult">
<result property="id" column="id"/>
<result property="taskId" column="task_id"/>
<result property="taskStatus" column="task_status"/>
<result property="msg" column="msg"/>
<result property="jobId" column="job_id"/>
<result property="owner" column="owner"/>
<result property="type" column="type"/>
<result property="priority" column="priority"/>
<result property="sourceName" column="source_name"/>
<result property="targetName" column="target_name"/>
<result property="createTime" column="create_time"/>
<result property="updateTime" column="update_time"/>
<result property="isDelete" column="is_delete"/>
<result property="createBy" column="create_by"/>
<result property="updateBy" column="update_by"/>
</resultMap>
<insert id="insertWcsTaskResult" parameterType="com.zg.project.wisdom.domain.WcsTaskResult" useGeneratedKeys="true" keyProperty="id">
INSERT INTO wcs_task_result
(
task_id,
task_status,
msg,
job_id,
owner,
type,
priority,
source_name,
target_name,
create_time,
update_time,
is_delete,
create_by,
update_by
)
VALUES
(
#{taskId},
#{TaskStatus},
#{msg},
#{jobId},
#{owner},
#{type},
#{priority},
#{sourceName},
#{targetName},
#{createTime},
#{updateTime},
#{isDelete},
#{createBy},
#{updateBy}
)
</insert>
<select id="countByTaskId" resultType="java.lang.Integer" parameterType="java.lang.String">
SELECT COUNT(*)
FROM wcs_status
WHERE TaskID = #{taskId}
AND TaskStatus = '1'
</select>
</mapper>