From b6ac89fffc946ca33c4a6234290581c2256a1d77 Mon Sep 17 00:00:00 2001 From: wenshijun Date: Thu, 24 Jul 2025 14:19:42 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=89=E6=96=B9=E8=B0=83=E5=BA=A6=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E6=8E=A5=E5=8F=A3=E5=BC=80=E5=8F=910724?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../zg/framework/config/SecurityConfig.java | 1 + .../information/controller/MtdController.java | 54 ++++ .../controller/PcdeDetailController.java | 2 +- .../zg/project/information/domain/Mtd.java | 141 ++++++++++ .../information/domain/PcdeDetail.java | 95 +++---- .../project/information/mapper/MtdMapper.java | 20 ++ .../information/mapper/PcdeDetailMapper.java | 7 +- .../information/service/IMtdService.java | 13 + .../service/impl/MtdServiceImpl.java | 44 +++ .../service/impl/PcdeDetailServiceImpl.java | 70 +++-- .../controller/AgvTaskResultController.java | 107 ++++++-- .../wisdom/controller/DdTaskController.java | 64 ++--- .../wisdom/controller/GysJhController.java | 2 +- .../controller/MockRemoteController.java | 119 ++++++++ .../project/wisdom/domain/AgvTaskResult.java | 107 ++++++-- .../com/zg/project/wisdom/domain/AgyWcs.java | 26 ++ .../project/wisdom/domain/WcsTaskResult.java | 187 +++++++++++++ .../zg/project/wisdom/domain/dto/AgvDTO.java | 1 + .../wisdom/domain/dto/OutGoodsDTO.java | 9 + .../wisdom/domain/dto/PcRkInfoBatchDTO.java | 3 - .../wisdom/domain/dto/TaskExecuteDTO.java | 14 + .../wisdom/mapper/AgvTaskResultMapper.java | 17 +- .../project/wisdom/mapper/AgyWcsMapper.java | 7 + .../wisdom/mapper/AuditSignatureMapper.java | 2 +- .../project/wisdom/mapper/DdTaskMapper.java | 14 + .../zg/project/wisdom/mapper/GysJhMapper.java | 21 ++ .../wisdom/mapper/WcsTaskResultMapper.java | 11 + .../wisdom/service/IAgvTaskResultService.java | 15 +- .../wisdom/service/IDdTaskService.java | 4 +- .../wisdom/service/IWcsTaskResultService.java | 10 + .../impl/AgvTaskResultServiceImpl.java | 253 +++++++++++++++++- .../service/impl/DdTaskServiceImpl.java | 177 +++++++++--- .../wisdom/service/impl/GysJhServiceImpl.java | 15 +- .../service/impl/RkInfoServiceImpl.java | 37 +-- .../impl/WcsTaskResultServiceImpl.java | 44 +++ src/main/resources/application.yml | 10 +- .../mybatis/information/MtdMapper.xml | 66 +++++ .../mybatis/information/PcdeDetailMapper.xml | 32 ++- .../mybatis/wisdom/AgvTaskResultMapper.xml | 13 +- .../resources/mybatis/wisdom/AgyWcsMapper.xml | 20 ++ .../mybatis/wisdom/AuditSignatureMapper.xml | 12 +- .../resources/mybatis/wisdom/DdTaskMapper.xml | 13 + .../resources/mybatis/wisdom/GysJhMapper.xml | 19 ++ .../resources/mybatis/wisdom/RkInfoMapper.xml | 1 + .../mybatis/wisdom/WcsTaskResultMapper.xml | 70 +++++ 45 files changed, 1717 insertions(+), 252 deletions(-) create mode 100644 src/main/java/com/zg/project/information/controller/MtdController.java create mode 100644 src/main/java/com/zg/project/information/domain/Mtd.java create mode 100644 src/main/java/com/zg/project/information/mapper/MtdMapper.java create mode 100644 src/main/java/com/zg/project/information/service/IMtdService.java create mode 100644 src/main/java/com/zg/project/information/service/impl/MtdServiceImpl.java create mode 100644 src/main/java/com/zg/project/wisdom/controller/MockRemoteController.java create mode 100644 src/main/java/com/zg/project/wisdom/domain/AgyWcs.java create mode 100644 src/main/java/com/zg/project/wisdom/domain/WcsTaskResult.java create mode 100644 src/main/java/com/zg/project/wisdom/domain/dto/OutGoodsDTO.java create mode 100644 src/main/java/com/zg/project/wisdom/domain/dto/TaskExecuteDTO.java create mode 100644 src/main/java/com/zg/project/wisdom/mapper/AgyWcsMapper.java create mode 100644 src/main/java/com/zg/project/wisdom/mapper/WcsTaskResultMapper.java create mode 100644 src/main/java/com/zg/project/wisdom/service/IWcsTaskResultService.java create mode 100644 src/main/java/com/zg/project/wisdom/service/impl/WcsTaskResultServiceImpl.java create mode 100644 src/main/resources/mybatis/information/MtdMapper.xml create mode 100644 src/main/resources/mybatis/wisdom/AgyWcsMapper.xml create mode 100644 src/main/resources/mybatis/wisdom/WcsTaskResultMapper.xml diff --git a/src/main/java/com/zg/framework/config/SecurityConfig.java b/src/main/java/com/zg/framework/config/SecurityConfig.java index 7f46219..8d21f87 100644 --- a/src/main/java/com/zg/framework/config/SecurityConfig.java +++ b/src/main/java/com/zg/framework/config/SecurityConfig.java @@ -120,6 +120,7 @@ public class SecurityConfig "/system/config/**", "/AutoInventory/**", "/ws/**", + "/mock/**", "/information/device/**", "/MatchScan/**", "/wisdom/task/**", diff --git a/src/main/java/com/zg/project/information/controller/MtdController.java b/src/main/java/com/zg/project/information/controller/MtdController.java new file mode 100644 index 0000000..b263933 --- /dev/null +++ b/src/main/java/com/zg/project/information/controller/MtdController.java @@ -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 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 list = mtdService.selectMtdList(mtd); + ExcelUtil util = new ExcelUtil<>(Mtd.class); + return util.exportExcel(list, "物料信息"); + } + + @GetMapping("/{id}") + public AjaxResult getInfo(@PathVariable Long id) { + return AjaxResult.success(mtdService.selectMtdById(id)); + } +} diff --git a/src/main/java/com/zg/project/information/controller/PcdeDetailController.java b/src/main/java/com/zg/project/information/controller/PcdeDetailController.java index 4db4863..1d87e84 100644 --- a/src/main/java/com/zg/project/information/controller/PcdeDetailController.java +++ b/src/main/java/com/zg/project/information/controller/PcdeDetailController.java @@ -67,7 +67,7 @@ public class PcdeDetailController extends BaseController } /** - * 导入供应计划数据(全部新增,不校验重复) + * 导入库位明细数据 */ @PreAuthorize("@ss.hasPermi('information:pcdedetail:import')") @Log(title = "库位明细", businessType = BusinessType.IMPORT) diff --git a/src/main/java/com/zg/project/information/domain/Mtd.java b/src/main/java/com/zg/project/information/domain/Mtd.java new file mode 100644 index 0000000..cbbec16 --- /dev/null +++ b/src/main/java/com/zg/project/information/domain/Mtd.java @@ -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(); + } +} diff --git a/src/main/java/com/zg/project/information/domain/PcdeDetail.java b/src/main/java/com/zg/project/information/domain/PcdeDetail.java index e207d93..cc6a463 100644 --- a/src/main/java/com/zg/project/information/domain/PcdeDetail.java +++ b/src/main/java/com/zg/project/information/domain/PcdeDetail.java @@ -13,8 +13,7 @@ import com.zg.framework.web.domain.BaseEntity; * @author zg * @date 2025-05-29 */ -public class PcdeDetail extends BaseEntity -{ +public class PcdeDetail extends BaseEntity { private static final long serialVersionUID = 1L; /** 主键ID */ @@ -25,16 +24,20 @@ public class PcdeDetail extends BaseEntity private String pcode; /** 所属场景 */ + @Excel(name = "所属场景名称") private String scene; /** 所属场景名称 */ - @Excel(name = "所属场景名称") private String sceneName; /** 所属仓库 */ @Excel(name = "所属仓库") private String warehouse; + /** 所属仓库名称 */ + @Excel(name = "所属仓库名称") + private String warehouseName; + /** 编码后ID */ @Excel(name = "编码后ID") private String encodedId; @@ -64,141 +67,129 @@ public class PcdeDetail extends BaseEntity @JsonFormat(pattern = "yyyy-MM-dd") private Date updatedAt; - public void setId(Long id) - { + // Getter & Setter + + public void setId(Long id) { this.id = id; } - public Long getId() - { + public Long getId() { return id; } public String getPcode() { return pcode; } + public void setPcode(String pcode) { this.pcode = pcode; } - public void setScene(String scene) - { + public void setScene(String scene) { this.scene = scene; } - public String getScene() - { + public String getScene() { return scene; } - public void setSceneName(String sceneName) - { + public void setSceneName(String sceneName) { this.sceneName = sceneName; } - public String getSceneName() - { + public String getSceneName() { return sceneName; } - public void setWarehouse(String warehouse) - { + public void setWarehouse(String warehouse) { this.warehouse = warehouse; } - public String getWarehouse() - { + public String getWarehouse() { 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; } - public String getEncodedId() - { + public String getEncodedId() { return encodedId; } - public void setTag(String tag) - { + public void setTag(String tag) { this.tag = tag; } - public String getTag() - { + public String getTag() { return tag; } - public void setRemark(String remark) - { + public void setRemark(String remark) { this.remark = remark; } - public String getRemark() - { + public String getRemark() { return remark; } - public void setIsDelete(String isDelete) - { + public void setIsDelete(String isDelete) { this.isDelete = isDelete; } - public String getIsDelete() - { + public String getIsDelete() { return isDelete; } - public void setCreatedBy(String createdBy) - { + public void setCreatedBy(String createdBy) { this.createdBy = createdBy; } - public String getCreatedBy() - { + public String getCreatedBy() { return createdBy; } - public void setCreatedAt(Date createdAt) - { + public void setCreatedAt(Date createdAt) { this.createdAt = createdAt; } - public Date getCreatedAt() - { + public Date getCreatedAt() { return createdAt; } - public void setUpdatedBy(String updatedBy) - { + public void setUpdatedBy(String updatedBy) { this.updatedBy = updatedBy; } - public String getUpdatedBy() - { + public String getUpdatedBy() { return updatedBy; } - public void setUpdatedAt(Date updatedAt) - { + public void setUpdatedAt(Date updatedAt) { this.updatedAt = updatedAt; } - public Date getUpdatedAt() - { + public Date getUpdatedAt() { return updatedAt; } @Override public String toString() { - return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) .append("id", getId()) .append("pcode", getPcode()) .append("scene", getScene()) .append("sceneName", getSceneName()) .append("warehouse", getWarehouse()) + .append("warehouseName", getWarehouseName()) .append("encodedId", getEncodedId()) .append("tag", getTag()) .append("remark", getRemark()) diff --git a/src/main/java/com/zg/project/information/mapper/MtdMapper.java b/src/main/java/com/zg/project/information/mapper/MtdMapper.java new file mode 100644 index 0000000..fa76bac --- /dev/null +++ b/src/main/java/com/zg/project/information/mapper/MtdMapper.java @@ -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 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); +} diff --git a/src/main/java/com/zg/project/information/mapper/PcdeDetailMapper.java b/src/main/java/com/zg/project/information/mapper/PcdeDetailMapper.java index 243abb9..11ce27b 100644 --- a/src/main/java/com/zg/project/information/mapper/PcdeDetailMapper.java +++ b/src/main/java/com/zg/project/information/mapper/PcdeDetailMapper.java @@ -60,10 +60,9 @@ public interface PcdeDetailMapper public int deletePcdeDetailByIds(Long[] ids); /** - * 根据库位编码查询库位信息 - * @param locationCode + * 根据仓库编码查询库位信息 + * @param pcode * @return */ - PcdeDetail selectByLocationCode(String locationCode); - + PcdeDetail selectByPcode(String pcode); } diff --git a/src/main/java/com/zg/project/information/service/IMtdService.java b/src/main/java/com/zg/project/information/service/IMtdService.java new file mode 100644 index 0000000..40c5b8f --- /dev/null +++ b/src/main/java/com/zg/project/information/service/IMtdService.java @@ -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 selectMtdList(Mtd mtd); + int insertMtd(Mtd mtd); + int updateMtd(Mtd mtd); + int deleteMtdById(Long id); + int deleteMtdByIds(Long[] ids); +} diff --git a/src/main/java/com/zg/project/information/service/impl/MtdServiceImpl.java b/src/main/java/com/zg/project/information/service/impl/MtdServiceImpl.java new file mode 100644 index 0000000..cb6564f --- /dev/null +++ b/src/main/java/com/zg/project/information/service/impl/MtdServiceImpl.java @@ -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 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); + } +} diff --git a/src/main/java/com/zg/project/information/service/impl/PcdeDetailServiceImpl.java b/src/main/java/com/zg/project/information/service/impl/PcdeDetailServiceImpl.java index 2209d25..13794ce 100644 --- a/src/main/java/com/zg/project/information/service/impl/PcdeDetailServiceImpl.java +++ b/src/main/java/com/zg/project/information/service/impl/PcdeDetailServiceImpl.java @@ -1,15 +1,17 @@ package com.zg.project.information.service.impl; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.TimerTask; +import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.zg.common.exception.ServiceException; import com.zg.common.utils.DateUtils; -import com.zg.project.wisdom.domain.GysJh; -import com.zg.project.wisdom.domain.RkInfo; +import com.zg.framework.manager.AsyncManager; import com.zg.project.wisdom.mapper.RkInfoMapper; -import com.zg.project.wisdom.service.IRkInfoService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.zg.project.information.mapper.PcdeDetailMapper; @@ -155,36 +157,56 @@ public class PcdeDetailServiceImpl implements IPcdeDetailService throw new ServiceException("导入数据不能为空!"); } - int successNum = 0; - int failureNum = 0; - StringBuilder failureMsg = new StringBuilder(); + AtomicInteger successNum = new AtomicInteger(0); + AtomicInteger failureNum = new AtomicInteger(0); + List failureMsgs = Collections.synchronizedList(new ArrayList<>()); for (PcdeDetail detail : pcdeList) { - try { - PcdeDetail exist = pcdeDetailMapper.selectByLocationCode(detail.getPcode()); - if (exist == null) { - detail.setCreateBy(operName); - detail.setCreateTime(DateUtils.getNowDate()); - pcdeDetailMapper.insertPcdeDetail(detail); - successNum++; - } else { - failureNum++; - failureMsg.append("
库位编号 ").append(detail.getPcode()).append(" 已存在"); + TimerTask task = new TimerTask() { + @Override + public void run() { + try { + PcdeDetail exist = pcdeDetailMapper.selectByPcode(detail.getPcode()); + if (exist == null) { + detail.setCreateBy(operName); + detail.setCreateTime(DateUtils.getNowDate()); + pcdeDetailMapper.insertPcdeDetail(detail); + 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("
库位编号 ").append(detail.getPcode()).append(" 导入失败:").append(e.getMessage()); - } + }; + + // ✅ 使用自定义线程池工具类提交任务 + AsyncManager.me().execute(task); } - if (failureNum > 0) { - failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据有误,错误如下:"); - throw new ServiceException(failureMsg.toString()); + // ❗此处无法精确等待全部线程完成,只做简单延时(如需精确等待建议用 CountDownLatch) + try { + 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("
").append(fail); + } + throw new ServiceException(msg.toString()); } else { - return "恭喜您,数据已全部导入成功!共 " + successNum + " 条。"; + return "恭喜您,数据已全部导入成功!共 " + successNum.get() + " 条。"; } } + /** * 获取未被入库单据使用的库位列表 */ diff --git a/src/main/java/com/zg/project/wisdom/controller/AgvTaskResultController.java b/src/main/java/com/zg/project/wisdom/controller/AgvTaskResultController.java index 2b805dc..504fe84 100644 --- a/src/main/java/com/zg/project/wisdom/controller/AgvTaskResultController.java +++ b/src/main/java/com/zg/project/wisdom/controller/AgvTaskResultController.java @@ -1,24 +1,107 @@ 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.domain.AjaxResult; import com.zg.framework.web.page.TableDataInfo; 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.OutGoodsDTO; import com.zg.project.wisdom.service.IAgvTaskResultService; +import com.zg.project.wisdom.service.IWcsTaskResultService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; +import java.util.Date; import java.util.List; @RestController -@RequestMapping("/wisdom/agv") +@RequestMapping("/wisdom") public class AgvTaskResultController extends BaseController { @Autowired 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任务结果列表(分页) */ @@ -60,26 +143,4 @@ public class AgvTaskResultController extends BaseController { public AjaxResult remove(@PathVariable Long[] 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()); - } - } } diff --git a/src/main/java/com/zg/project/wisdom/controller/DdTaskController.java b/src/main/java/com/zg/project/wisdom/controller/DdTaskController.java index 263787d..10af7bc 100644 --- a/src/main/java/com/zg/project/wisdom/controller/DdTaskController.java +++ b/src/main/java/com/zg/project/wisdom/controller/DdTaskController.java @@ -9,6 +9,7 @@ import com.zg.framework.web.controller.BaseController; import com.zg.framework.web.domain.AjaxResult; import com.zg.framework.web.page.TableDataInfo; 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.service.IDdTaskService; import org.springframework.beans.factory.annotation.Autowired; @@ -27,10 +28,28 @@ public class DdTaskController extends BaseController { @Autowired 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") public TableDataInfo list(DdTask ddTask) { startPage(); @@ -38,10 +57,18 @@ public class DdTaskController extends BaseController { 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) @PostMapping("/export") public AjaxResult export(DdTask ddTask) { @@ -50,29 +77,9 @@ public class DdTaskController extends BaseController { 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) @PutMapping 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) @DeleteMapping("/{ids}") public AjaxResult remove(@PathVariable Long[] 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); - } - } diff --git a/src/main/java/com/zg/project/wisdom/controller/GysJhController.java b/src/main/java/com/zg/project/wisdom/controller/GysJhController.java index aae1f43..f3e1939 100644 --- a/src/main/java/com/zg/project/wisdom/controller/GysJhController.java +++ b/src/main/java/com/zg/project/wisdom/controller/GysJhController.java @@ -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) @PostMapping("/importData") public AjaxResult importData(@RequestParam("file") MultipartFile file) throws Exception { diff --git a/src/main/java/com/zg/project/wisdom/controller/MockRemoteController.java b/src/main/java/com/zg/project/wisdom/controller/MockRemoteController.java new file mode 100644 index 0000000..070e77e --- /dev/null +++ b/src/main/java/com/zg/project/wisdom/controller/MockRemoteController.java @@ -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 mockWcs(@RequestBody Map param) { + System.out.println("【MOCK-WCS】接收到下架或上架任务:" + param); + Map result = new HashMap<>(); + result.put("code", 0); + result.put("msg", "WCS任务已接收"); + return result; + } + + + /** + * 模拟 WCS 状态回调接口(发送 taskId 和状态数字 1~4) + */ + @PostMapping("/wcs/task/callback") + public Map mockWcsCallback(@RequestBody Map param) { + System.out.println("【MOCK-WCS】模拟立库回调任务:" + param); + + String taskId = String.valueOf(param.get("taskId")); + String callbackUrl = "http://localhost:8080/wisdom/wcs/callback"; // 改成你项目实际地址 + + // 状态顺序:接收成功 → 开始执行 → 执行成功 → 执行失败 + List statusList = Arrays.asList("1", "2", "3", "4"); + + new Thread(() -> { + ObjectMapper mapper = new ObjectMapper(); + for (String status : statusList) { + Map 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 result = new HashMap<>(); + result.put("code", 0); + result.put("msg", "WCS模拟状态已开始逐步回调"); + return result; + } + + /** + * 模拟 AGV 状态回调接口(发送 requestId 和多个执行阶段状态) + */ + @PostMapping("/agv/task/create") + public Map mockAgv(@RequestBody Map param) { + System.out.println("【MOCK-AGV】接收到搬运任务:" + param); + + String requestId = String.valueOf(param.get("requestId")); + String callbackUrl = "http://localhost:8080/wisdom/agv/callback"; // 改成你实际项目地址 + + // AGV 的标准执行流程状态 + List 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 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 result = new HashMap<>(); + result.put("code", 0); + result.put("msg", "AGV模拟状态已开始逐步回调"); + return result; + } +} diff --git a/src/main/java/com/zg/project/wisdom/domain/AgvTaskResult.java b/src/main/java/com/zg/project/wisdom/domain/AgvTaskResult.java index 37ea049..262ad1a 100644 --- a/src/main/java/com/zg/project/wisdom/domain/AgvTaskResult.java +++ b/src/main/java/com/zg/project/wisdom/domain/AgvTaskResult.java @@ -60,20 +60,7 @@ public class AgvTaskResult extends BaseEntity { @Excel(name = "AGV更新时间") 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 = "执行状态") private String status; @@ -84,6 +71,33 @@ public class AgvTaskResult extends BaseEntity { /** 是否删除(0正常 1删除) */ 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 public Long getId() { @@ -198,6 +212,62 @@ public class AgvTaskResult extends BaseEntity { 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 public String toString() { return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) @@ -214,6 +284,13 @@ public class AgvTaskResult extends BaseEntity { .append("updatedAt", getUpdatedAt()) .append("status", getStatus()) .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("createTime", getCreateTime()) .append("updateBy", getUpdateBy()) @@ -221,4 +298,4 @@ public class AgvTaskResult extends BaseEntity { .append("isDelete", getIsDelete()) .toString(); } -} \ No newline at end of file +} diff --git a/src/main/java/com/zg/project/wisdom/domain/AgyWcs.java b/src/main/java/com/zg/project/wisdom/domain/AgyWcs.java new file mode 100644 index 0000000..256bd33 --- /dev/null +++ b/src/main/java/com/zg/project/wisdom/domain/AgyWcs.java @@ -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 + '\'' + + '}'; + } +} diff --git a/src/main/java/com/zg/project/wisdom/domain/WcsTaskResult.java b/src/main/java/com/zg/project/wisdom/domain/WcsTaskResult.java new file mode 100644 index 0000000..f666ccb --- /dev/null +++ b/src/main/java/com/zg/project/wisdom/domain/WcsTaskResult.java @@ -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(); + } +} diff --git a/src/main/java/com/zg/project/wisdom/domain/dto/AgvDTO.java b/src/main/java/com/zg/project/wisdom/domain/dto/AgvDTO.java index 79f5c33..a30ef7a 100644 --- a/src/main/java/com/zg/project/wisdom/domain/dto/AgvDTO.java +++ b/src/main/java/com/zg/project/wisdom/domain/dto/AgvDTO.java @@ -5,6 +5,7 @@ import lombok.Data; @Data public class AgvDTO { private String requestId; + private String taskId; private String jobId; private String owner; private String type; diff --git a/src/main/java/com/zg/project/wisdom/domain/dto/OutGoodsDTO.java b/src/main/java/com/zg/project/wisdom/domain/dto/OutGoodsDTO.java new file mode 100644 index 0000000..a1dd79f --- /dev/null +++ b/src/main/java/com/zg/project/wisdom/domain/dto/OutGoodsDTO.java @@ -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=有货(影响是否传物料信息) +} \ No newline at end of file diff --git a/src/main/java/com/zg/project/wisdom/domain/dto/PcRkInfoBatchDTO.java b/src/main/java/com/zg/project/wisdom/domain/dto/PcRkInfoBatchDTO.java index 396f21c..8976cfc 100644 --- a/src/main/java/com/zg/project/wisdom/domain/dto/PcRkInfoBatchDTO.java +++ b/src/main/java/com/zg/project/wisdom/domain/dto/PcRkInfoBatchDTO.java @@ -10,9 +10,6 @@ import java.util.List; @Data public class PcRkInfoBatchDTO { - /** 供应计划主键ID */ - private Long gysJhId; - /** 审核人用户ID */ private String approverId; diff --git a/src/main/java/com/zg/project/wisdom/domain/dto/TaskExecuteDTO.java b/src/main/java/com/zg/project/wisdom/domain/dto/TaskExecuteDTO.java new file mode 100644 index 0000000..c523f30 --- /dev/null +++ b/src/main/java/com/zg/project/wisdom/domain/dto/TaskExecuteDTO.java @@ -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=有货 + +} diff --git a/src/main/java/com/zg/project/wisdom/mapper/AgvTaskResultMapper.java b/src/main/java/com/zg/project/wisdom/mapper/AgvTaskResultMapper.java index e59c749..cb1e841 100644 --- a/src/main/java/com/zg/project/wisdom/mapper/AgvTaskResultMapper.java +++ b/src/main/java/com/zg/project/wisdom/mapper/AgvTaskResultMapper.java @@ -1,6 +1,7 @@ package com.zg.project.wisdom.mapper; import com.zg.project.wisdom.domain.AgvTaskResult; +import org.apache.ibatis.annotations.Param; import java.util.List; @@ -18,5 +19,19 @@ public interface AgvTaskResultMapper { 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); } diff --git a/src/main/java/com/zg/project/wisdom/mapper/AgyWcsMapper.java b/src/main/java/com/zg/project/wisdom/mapper/AgyWcsMapper.java new file mode 100644 index 0000000..4876183 --- /dev/null +++ b/src/main/java/com/zg/project/wisdom/mapper/AgyWcsMapper.java @@ -0,0 +1,7 @@ +package com.zg.project.wisdom.mapper; + +import com.zg.project.wisdom.domain.AgyWcs; + +public interface AgyWcsMapper { + int insertAgyWcs(AgyWcs aw); +} \ No newline at end of file diff --git a/src/main/java/com/zg/project/wisdom/mapper/AuditSignatureMapper.java b/src/main/java/com/zg/project/wisdom/mapper/AuditSignatureMapper.java index 6d074bb..a47ccb9 100644 --- a/src/main/java/com/zg/project/wisdom/mapper/AuditSignatureMapper.java +++ b/src/main/java/com/zg/project/wisdom/mapper/AuditSignatureMapper.java @@ -85,7 +85,7 @@ public interface AuditSignatureMapper /** * 查询现场图片URL(按入库ID) */ - AuditSignature selectPhotoUrlByBillNo(@Param("billNo") String billNo); + AuditSignature selectPhotoUrlByRkId(@Param("rkId") Long rkId); /** * 查询审批记录列表(按主表ID) diff --git a/src/main/java/com/zg/project/wisdom/mapper/DdTaskMapper.java b/src/main/java/com/zg/project/wisdom/mapper/DdTaskMapper.java index e51ce41..d3f73ee 100644 --- a/src/main/java/com/zg/project/wisdom/mapper/DdTaskMapper.java +++ b/src/main/java/com/zg/project/wisdom/mapper/DdTaskMapper.java @@ -1,6 +1,8 @@ package com.zg.project.wisdom.mapper; import com.zg.project.wisdom.domain.DdTask; +import org.apache.ibatis.annotations.Param; + import java.util.List; /** @@ -39,4 +41,16 @@ public interface DdTaskMapper { * 删除单个调度任务 */ int deleteDdTaskById(Long id); + + /** + * 根据任务编号更新任务状态 + */ + void updateTaskStatusByTaskNo(String taskNo, int i); + + /** + * 根据任务编号查询调度任务 + * @param taskNo 任务编号 + * @return DdTask 对象 + */ + DdTask selectByTaskNo(@Param("taskNo") String taskNo); } diff --git a/src/main/java/com/zg/project/wisdom/mapper/GysJhMapper.java b/src/main/java/com/zg/project/wisdom/mapper/GysJhMapper.java index b2327f5..568aec5 100644 --- a/src/main/java/com/zg/project/wisdom/mapper/GysJhMapper.java +++ b/src/main/java/com/zg/project/wisdom/mapper/GysJhMapper.java @@ -1,7 +1,10 @@ package com.zg.project.wisdom.mapper; import java.util.List; +import java.util.Set; + import com.zg.project.wisdom.domain.GysJh; +import org.apache.ibatis.annotations.Param; /** * 供应计划Mapper接口 @@ -77,4 +80,22 @@ public interface GysJhMapper * @param sapNos */ void resetGysJhStatusBySapNos(List 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 idSet); + } diff --git a/src/main/java/com/zg/project/wisdom/mapper/WcsTaskResultMapper.java b/src/main/java/com/zg/project/wisdom/mapper/WcsTaskResultMapper.java new file mode 100644 index 0000000..b702755 --- /dev/null +++ b/src/main/java/com/zg/project/wisdom/mapper/WcsTaskResultMapper.java @@ -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); +} diff --git a/src/main/java/com/zg/project/wisdom/service/IAgvTaskResultService.java b/src/main/java/com/zg/project/wisdom/service/IAgvTaskResultService.java index 1194dd6..e04d7ad 100644 --- a/src/main/java/com/zg/project/wisdom/service/IAgvTaskResultService.java +++ b/src/main/java/com/zg/project/wisdom/service/IAgvTaskResultService.java @@ -2,6 +2,7 @@ package com.zg.project.wisdom.service; import com.zg.project.wisdom.domain.AgvTaskResult; import com.zg.project.wisdom.domain.dto.AgvDTO; +import com.zg.project.wisdom.domain.dto.OutGoodsDTO; import java.util.List; @@ -27,6 +28,18 @@ public interface IAgvTaskResultService { /** 处理AGV回调 */ 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); } diff --git a/src/main/java/com/zg/project/wisdom/service/IDdTaskService.java b/src/main/java/com/zg/project/wisdom/service/IDdTaskService.java index 963014c..56e429f 100644 --- a/src/main/java/com/zg/project/wisdom/service/IDdTaskService.java +++ b/src/main/java/com/zg/project/wisdom/service/IDdTaskService.java @@ -2,6 +2,7 @@ package com.zg.project.wisdom.service; import com.zg.framework.web.domain.AjaxResult; import com.zg.project.wisdom.domain.DdTask; +import com.zg.project.wisdom.domain.dto.TaskExecuteDTO; import com.zg.project.wisdom.domain.vo.TaskExecuteResultVO; import java.util.List; @@ -42,9 +43,8 @@ public interface IDdTaskService { * 删除单个调度任务 */ int deleteDdTaskById(Long id); - /** * 执行任务 */ - TaskExecuteResultVO executeTask(Long id); + TaskExecuteResultVO executeTask(TaskExecuteDTO dto); } diff --git a/src/main/java/com/zg/project/wisdom/service/IWcsTaskResultService.java b/src/main/java/com/zg/project/wisdom/service/IWcsTaskResultService.java new file mode 100644 index 0000000..4975866 --- /dev/null +++ b/src/main/java/com/zg/project/wisdom/service/IWcsTaskResultService.java @@ -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); +} diff --git a/src/main/java/com/zg/project/wisdom/service/impl/AgvTaskResultServiceImpl.java b/src/main/java/com/zg/project/wisdom/service/impl/AgvTaskResultServiceImpl.java index f022689..61d7928 100644 --- a/src/main/java/com/zg/project/wisdom/service/impl/AgvTaskResultServiceImpl.java +++ b/src/main/java/com/zg/project/wisdom/service/impl/AgvTaskResultServiceImpl.java @@ -1,15 +1,34 @@ 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.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.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.OutGoodsDTO; 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 org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import java.util.Date; import java.util.List; +import java.util.Objects; + +import static com.zg.framework.datasource.DynamicDataSourceContextHolder.log; @Service public class AgvTaskResultServiceImpl implements IAgvTaskResultService { @@ -17,6 +36,31 @@ public class AgvTaskResultServiceImpl implements IAgvTaskResultService { @Autowired 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 public AgvTaskResult selectAgvTaskResultById(Long id) { return agvTaskResultMapper.selectAgvTaskResultById(id); @@ -50,12 +94,17 @@ public class AgvTaskResultServiceImpl implements IAgvTaskResultService { } @Override + @Transactional(rollbackFor = Exception.class) public void handleAgvCallback(AgvDTO dto) { String requestId = dto.getRequestId(); - String taskNo = requestId != null && requestId.length() > 2 - ? requestId.substring(0, requestId.length() - 2) - : requestId; + if (StringUtils.isBlank(requestId)) { + throw new ServiceException("requestId不能为空"); + } + // 截取 taskNo(去除 -AGV 等后缀) + String taskNo = requestId.substring(0, requestId.length() - 2); + + // 写入 AGV 回调状态记录(每个状态都一条,不覆盖) AgvTaskResult result = new AgvTaskResult(); result.setRequestId(requestId); result.setTaskNo(taskNo); @@ -65,19 +114,211 @@ public class AgvTaskResultServiceImpl implements IAgvTaskResultService { result.setPriority(dto.getPriority()); result.setSourceName(dto.getSourceName()); result.setTargetName(dto.getTargetName()); - result.setCreatedAt(dto.getCreatedAt()); - result.setUpdatedAt(dto.getUpdatedAt()); result.setStatus(dto.getStatus()); result.setMsg(dto.getMsg()); result.setCreateBy("agv"); result.setCreateTime(DateUtils.getNowDate()); + result.setUpdateTime(DateUtils.getNowDate()); result.setIsDelete("0"); 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 public boolean existsByRequestIdAndStatus(String requestId, String status) { - return agvTaskResultMapper.selectCountByRequestIdAndStatus(requestId, status) > 0; + return agvTaskResultMapper.countByRequestIdAndStatus(requestId, status) > 0; } + } diff --git a/src/main/java/com/zg/project/wisdom/service/impl/DdTaskServiceImpl.java b/src/main/java/com/zg/project/wisdom/service/impl/DdTaskServiceImpl.java index d99515c..4a82dad 100644 --- a/src/main/java/com/zg/project/wisdom/service/impl/DdTaskServiceImpl.java +++ b/src/main/java/com/zg/project/wisdom/service/impl/DdTaskServiceImpl.java @@ -8,9 +8,15 @@ import com.zg.common.utils.SecurityUtils; import com.zg.common.utils.StringUtils; import com.zg.common.utils.http.HttpUtils; 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.WcsTaskResult; +import com.zg.project.wisdom.domain.dto.TaskExecuteDTO; 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.WcsTaskResultMapper; import com.zg.project.wisdom.service.IDdTaskService; import org.apache.commons.lang3.RandomUtils; import org.apache.commons.lang3.math.NumberUtils; @@ -25,6 +31,8 @@ import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.*; +import static com.zg.framework.datasource.DynamicDataSourceContextHolder.log; + /** * 调度任务 Service 实现类 * @@ -36,9 +44,27 @@ public class DdTaskServiceImpl implements IDdTaskService { @Autowired 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; + @Value("${mock.wcs-job-create-url}") + private String wcsJobCreateUrl; + @Override public List selectDdTaskList(DdTask ddTask) { return ddTaskMapper.selectDdTaskList(ddTask); @@ -102,74 +128,141 @@ public class DdTaskServiceImpl implements IDdTaskService { @Override @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. 查询任务 DdTask task = ddTaskMapper.selectDdTaskById(id); if (task == null) { throw new ServiceException("任务不存在,ID = " + id); } - if (task.getTaskStatus() == null || task.getTaskStatus() != 0) { + if (!Objects.equals(task.getTaskStatus(), 0)) { throw new ServiceException("任务状态不是待执行,当前状态为:" + task.getTaskStatus()); } - // 2. 构造 requestId - String requestId; - if (StringUtils.isBlank(task.getTaskNo())) { - String timeStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("MMddHHmmss")); - int rand = new Random().nextInt(900) + 100; - requestId = timeStr + rand; - int num = Optional.ofNullable(task.getNum()).orElse(0); - 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移库 + String taskNo = task.getTaskNo(); + String taskType = task.getTaskType(); // 0入库,1出库,2移库 + String requestId = null; // ✅ AGV 使用 + String taskIdParam = null; // ✅ WCS 使用,提前声明防作用域错误 + String response; + int code; + String msg; - // 3. 构造 AGV 参数 + // 2. 构造参数 JSONObject param = new JSONObject(); - param.put("requestId", requestId); - param.put("taskNo", task.getTaskNo()); param.put("owner", "wms"); - param.put("type", type); + param.put("type", taskType); param.put("priority", 1); param.put("sourceName", task.getSourceName()); - param.put("targetName", task.getTargetName()); + param.put("targetName", targetName); - // 4. 调用 AGV 接口 - String result = HttpUtils.sendPost(agvJobCreateUrl, param.toJSONString()); - if (StringUtils.isBlank(result)) { - throw new ServiceException("AGV接口无响应"); + if ("0".equals(taskType) || "2".equals(taskType)) { + // ✅ 入库/移库 → AGV + requestId = taskNo + ("0".equals(taskType) ? "11" : "12"); // 拼接规则:11 入库,12 移库 + param.put("taskNo", taskNo); + param.put("requestId", requestId); + log.info("[任务执行] 类型={}(AGV),requestId={}, 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; - String msg; + // 3. 解析响应 + JSONObject respJson; try { - JSONObject json = JSON.parseObject(result); - code = json.getInteger("code"); - msg = json.getString("msg"); + respJson = JSON.parseObject(response); + code = respJson.getInteger("code"); + msg = respJson.getString("msg"); } catch (Exception e) { - throw new ServiceException("AGV响应解析失败:" + result); + throw new ServiceException("响应解析失败: " + response); } - if (!Objects.equals(code, 0)) { - throw new ServiceException("AGV调用失败:" + msg); + if (code != 200) { + throw new ServiceException("任务执行失败: " + msg); } - // 5. 更新任务状态 + // 4. 更新任务状态为已提交 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.setUpdateTime(DateUtils.getNowDate()); ddTaskMapper.updateDdTask(task); - // 6. 返回结果 - TaskExecuteResultVO resultVO = new TaskExecuteResultVO(); - resultVO.setRequestId(requestId); - resultVO.setCode(code); - resultVO.setMsg(msg); - return resultVO; + // 5. 写入执行记录 + String userId = SecurityUtils.getUserId().toString(); + Date now = DateUtils.getNowDate(); + + if ("0".equals(taskType) || "2".equals(taskType)) { + 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; } } diff --git a/src/main/java/com/zg/project/wisdom/service/impl/GysJhServiceImpl.java b/src/main/java/com/zg/project/wisdom/service/impl/GysJhServiceImpl.java index f94aeca..e15ad81 100644 --- a/src/main/java/com/zg/project/wisdom/service/impl/GysJhServiceImpl.java +++ b/src/main/java/com/zg/project/wisdom/service/impl/GysJhServiceImpl.java @@ -114,6 +114,17 @@ public class GysJhServiceImpl implements IGysJhService for (GysJh jh : jhList) { try { + // 唯一性校验:订单号 + 项目号 + 物料号 + boolean exists = gysJhMapper.existsByUniqueKeys(jh.getSapNo(), jh.getXmNo(), jh.getWlNo()); + if (exists) { + failureNum++; + failureMsg.append("
订单号:").append(jh.getSapNo()) + .append(",项目号:").append(jh.getXmNo()) + .append(",物料号:").append(jh.getWlNo()) + .append(" 已存在,跳过导入。"); + continue; + } + jh.setCreateBy(operName); jh.setStatus("0"); jh.setIsDelete("0"); @@ -121,7 +132,8 @@ public class GysJhServiceImpl implements IGysJhService successNum++; } catch (Exception e) { failureNum++; - failureMsg.append("
项目号:").append(jh.getXmNo()) + failureMsg.append("
订单号:").append(jh.getSapNo()) + .append(",项目号:").append(jh.getXmNo()) .append(",物料号:").append(jh.getWlNo()) .append(" 导入失败:").append(e.getMessage()); } @@ -135,6 +147,7 @@ public class GysJhServiceImpl implements IGysJhService return "导入成功,共 " + successNum + " 条数据"; } + /** * 根据SAP编号查询 * @param sapNo diff --git a/src/main/java/com/zg/project/wisdom/service/impl/RkInfoServiceImpl.java b/src/main/java/com/zg/project/wisdom/service/impl/RkInfoServiceImpl.java index 21e4993..02bcbad 100644 --- a/src/main/java/com/zg/project/wisdom/service/impl/RkInfoServiceImpl.java +++ b/src/main/java/com/zg/project/wisdom/service/impl/RkInfoServiceImpl.java @@ -96,7 +96,7 @@ public class RkInfoServiceImpl implements IRkInfoService } // 查询现场图片 + 审核结果(image_type = '1') - AuditSignature signature = auditSignatureMapper.selectPhotoUrlByBillNo(info.getBillNo()); + AuditSignature signature = auditSignatureMapper.selectPhotoUrlByRkId(info.getId()); if (signature != null) { info.setScenePhotoUrl(signature.getSignUrl()); info.setAuditResult(signature.getAuditResult()); @@ -171,24 +171,24 @@ public class RkInfoServiceImpl implements IRkInfoService List records = new ArrayList<>(); - // ✅ 第一步:先构造 RkInfo 列表(不保存照片) + // ✅ 第一步:构造 RkInfo 列表(包含 gysJhId) for (PcRkInfoItemDTO item : list) { RkInfo rk = new RkInfo(); BeanUtils.copyProperties(item, rk); rk.setBillNo(billNo); - rk.setGysJhId(dto.getGysJhId()); rk.setRkType(dto.getRkType()); rk.setWlType(dto.getWlType()); rk.setLihuoY(dto.getLihuoY()); - rk.setGysJhId(dto.getGysJhId()); rk.setRkTime(now); rk.setCangku(dto.getCangku()); rk.setCreateBy(userId); rk.setCreateTime(now); rk.setIsDelete("0"); + rk.setGysJhId(item.getGysJhId()); // ✅ 正确设置 gysJhId + if (needAudit) { - rk.setStatus("0"); // 入库待审核 + rk.setStatus("0"); // 待审核 rk.setIsChuku("2"); // 待入库(审核中) } else { rk.setStatus("1"); // 审核通过 @@ -198,23 +198,23 @@ public class RkInfoServiceImpl implements IRkInfoService rkInfos.add(rk); } - // ✅ 第二步:批量保存入库记录,回填主键 ID + // ✅ 第二步:批量保存入库记录 rkInfoMapper.batchInsertRkInfo(rkInfos); - // ✅ 第三步:根据主键构造照片记录 + // ✅ 第三步:构造照片记录(审核开启时) for (int i = 0; i < rkInfos.size(); i++) { RkInfo rk = rkInfos.get(i); PcRkInfoItemDTO item = list.get(i); if (needAudit && StringUtils.isNotBlank(item.getPhotoUrl())) { AuditSignature photo = new AuditSignature(); - photo.setRkId(rk.getId()); // ✅ 此时已填充 ID + photo.setRkId(rk.getId()); photo.setBillNo(billNo); photo.setBillType("0"); photo.setAuditResult("2"); photo.setSignerId(userId); - photo.setSignerRole("2"); // 拍照人 - photo.setImageType("1"); // 现场图 + photo.setSignerRole("2"); + photo.setImageType("1"); // 现场图 photo.setSignUrl(item.getPhotoUrl()); photo.setSignTime(now); photo.setPcode(item.getPcode()); @@ -228,9 +228,8 @@ public class RkInfoServiceImpl implements IRkInfoService } } - // ✅ 第四步:如果启用审核,添加发起人签字记录 + // ✅ 第四步:审核开启时添加发起人签字记录 if (needAudit) { - // === 检查是否已有发起人签字记录 === boolean hasOldSign = auditSignatureMapper.existsCurrentSigner(billNo, "0"); if (hasOldSign) { auditSignatureMapper.updateIsCurrentToZero(billNo, "0"); @@ -252,15 +251,21 @@ public class RkInfoServiceImpl implements IRkInfoService mainSign.setCreateTime(now); records.add(mainSign); - // ✅ 写入照片 + 签字图 if (!records.isEmpty()) { auditSignatureMapper.batchInsert(records); } } - // ✅ 更新供应计划状态-》修改逻辑,审核通过后再修改供应计划状态 - if (!needAudit && dto.getGysJhId() != null) { - gysJhMapper.updateStatusById(dto.getGysJhId()); + // ✅ 第五步:如果审核关闭,立即批量更新供应计划状态 + if (!needAudit) { + Set jhIdSet = list.stream() + .map(PcRkInfoItemDTO::getGysJhId) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + + if (!jhIdSet.isEmpty()) { + gysJhMapper.batchUpdateStatusByIds(jhIdSet); + } } } diff --git a/src/main/java/com/zg/project/wisdom/service/impl/WcsTaskResultServiceImpl.java b/src/main/java/com/zg/project/wisdom/service/impl/WcsTaskResultServiceImpl.java new file mode 100644 index 0000000..8baff53 --- /dev/null +++ b/src/main/java/com/zg/project/wisdom/service/impl/WcsTaskResultServiceImpl.java @@ -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; + } +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 8e856b6..b7b0706 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -145,7 +145,11 @@ gen: agv: 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: # device: @@ -156,3 +160,7 @@ minio: accessKey: admin secretKey: admin123 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 \ No newline at end of file diff --git a/src/main/resources/mybatis/information/MtdMapper.xml b/src/main/resources/mybatis/information/MtdMapper.xml new file mode 100644 index 0000000..53e4ed5 --- /dev/null +++ b/src/main/resources/mybatis/information/MtdMapper.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + INSERT INTO mtd (mid, des_mat, grp, unt, uprc, btpe, mtpe, stpe) + VALUES (#{mid}, #{desMat}, #{grp}, #{unt}, #{uprc}, #{btpe}, #{mtpe}, #{stpe}) + + + + UPDATE mtd + SET mid = #{mid}, + des_mat = #{desMat}, + grp = #{grp}, + unt = #{unt}, + uprc = #{uprc}, + btpe = #{btpe}, + mtpe = #{mtpe}, + stpe = #{stpe} + WHERE id = #{id} + + + + DELETE FROM mtd WHERE id = #{id} + + + + DELETE FROM mtd WHERE id IN + + #{id} + + + + diff --git a/src/main/resources/mybatis/information/PcdeDetailMapper.xml b/src/main/resources/mybatis/information/PcdeDetailMapper.xml index 6339fe7..51e1865 100644 --- a/src/main/resources/mybatis/information/PcdeDetailMapper.xml +++ b/src/main/resources/mybatis/information/PcdeDetailMapper.xml @@ -4,28 +4,31 @@ "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + - - - - - - - - - - - - - + + + + + + + + + + + + + + - 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.created_by, d.created_at, d.updated_by, d.updated_at from pcde_detail d left join scene_mapping m on d.scene = m.scene_code + left join warehouse_info w on d.warehouse = w.warehouse_code diff --git a/src/main/resources/mybatis/wisdom/AgvTaskResultMapper.xml b/src/main/resources/mybatis/wisdom/AgvTaskResultMapper.xml index b7f02b4..5d6993b 100644 --- a/src/main/resources/mybatis/wisdom/AgvTaskResultMapper.xml +++ b/src/main/resources/mybatis/wisdom/AgvTaskResultMapper.xml @@ -35,14 +35,21 @@ - + SELECT * FROM agv_task_result WHERE request_id = #{requestId} AND is_delete = '0' + + + + + INSERT INTO agv_task_result diff --git a/src/main/resources/mybatis/wisdom/AgyWcsMapper.xml b/src/main/resources/mybatis/wisdom/AgyWcsMapper.xml new file mode 100644 index 0000000..9b560dd --- /dev/null +++ b/src/main/resources/mybatis/wisdom/AgyWcsMapper.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + INSERT INTO agy_wcs (requestId, TaskID) + VALUES (#{requestId}, #{taskId}) + + + diff --git a/src/main/resources/mybatis/wisdom/AuditSignatureMapper.xml b/src/main/resources/mybatis/wisdom/AuditSignatureMapper.xml index d24f290..60d8e3d 100644 --- a/src/main/resources/mybatis/wisdom/AuditSignatureMapper.xml +++ b/src/main/resources/mybatis/wisdom/AuditSignatureMapper.xml @@ -91,16 +91,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" AND is_delete = '0' - SELECT sign_url, audit_result FROM audit_signature WHERE is_delete = '0' - AND bill_no = #{billNo} - AND image_type = '1' + AND rk_id = #{rkId} + AND image_type = '1' + AND audit_result = '1' + AND is_current = '1' ORDER BY create_time DESC - LIMIT 1 + LIMIT 1 diff --git a/src/main/resources/mybatis/wisdom/DdTaskMapper.xml b/src/main/resources/mybatis/wisdom/DdTaskMapper.xml index 365e381..09476c9 100644 --- a/src/main/resources/mybatis/wisdom/DdTaskMapper.xml +++ b/src/main/resources/mybatis/wisdom/DdTaskMapper.xml @@ -50,6 +50,11 @@ SELECT * FROM dd_task WHERE id = #{id} AND is_delete = '0' + + + INSERT INTO dd_task ( task_no, task_dtl, task_type, task_status, mid_status, mid, num, mid_type, source_name, @@ -86,6 +91,14 @@ WHERE id = #{id} + + UPDATE dd_task + SET task_status = #{status}, + update_time = NOW() + WHERE task_no = #{taskNo} + AND is_delete = '0' + + DELETE FROM dd_task WHERE id IN diff --git a/src/main/resources/mybatis/wisdom/GysJhMapper.xml b/src/main/resources/mybatis/wisdom/GysJhMapper.xml index 3236184..a999c6f 100644 --- a/src/main/resources/mybatis/wisdom/GysJhMapper.xml +++ b/src/main/resources/mybatis/wisdom/GysJhMapper.xml @@ -57,6 +57,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" AND status = '0' + + insert into gys_jh @@ -152,6 +161,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" #{sapNo} + + + UPDATE gys_jh + SET status = '1' + WHERE id IN + + #{id} + + + delete from gys_jh where id = #{id} diff --git a/src/main/resources/mybatis/wisdom/RkInfoMapper.xml b/src/main/resources/mybatis/wisdom/RkInfoMapper.xml index 4da991c..c0654d4 100644 --- a/src/main/resources/mybatis/wisdom/RkInfoMapper.xml +++ b/src/main/resources/mybatis/wisdom/RkInfoMapper.xml @@ -157,6 +157,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" update_time = NOW() WHERE bill_no_ck = #{billNoCk} + DELETE FROM rk_info WHERE bill_no = #{billNo} diff --git a/src/main/resources/mybatis/wisdom/WcsTaskResultMapper.xml b/src/main/resources/mybatis/wisdom/WcsTaskResultMapper.xml new file mode 100644 index 0000000..7862fd7 --- /dev/null +++ b/src/main/resources/mybatis/wisdom/WcsTaskResultMapper.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + 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} + ) + + + + +