三方调度相关接口开发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,130 +67,117 @@ 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;
} }
@@ -199,6 +189,7 @@ public class PcdeDetail extends BaseEntity
.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,35 +157,55 @@ 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) {
TimerTask task = new TimerTask() {
@Override
public void run() {
try { try {
PcdeDetail exist = pcdeDetailMapper.selectByLocationCode(detail.getPcode()); PcdeDetail exist = pcdeDetailMapper.selectByPcode(detail.getPcode());
if (exist == null) { if (exist == null) {
detail.setCreateBy(operName); detail.setCreateBy(operName);
detail.setCreateTime(DateUtils.getNowDate()); detail.setCreateTime(DateUtils.getNowDate());
pcdeDetailMapper.insertPcdeDetail(detail); pcdeDetailMapper.insertPcdeDetail(detail);
successNum++; successNum.incrementAndGet();
} else { } else {
failureNum++; failureNum.incrementAndGet();
failureMsg.append("<br/>库位编号 ").append(detail.getPcode()).append(" 已存在"); failureMsgs.add("库位编号 = " + detail.getPcode() + " 已存在");
} }
} catch (Exception e) { } catch (Exception e) {
failureNum++; failureNum.incrementAndGet();
failureMsg.append("<br/>库位编号 ").append(detail.getPcode()).append(" 导入失败:").append(e.getMessage()); failureMsgs.add("库位编号 = " + detail.getPcode() + " 导入失败:" + e.getMessage());
}
}
};
// ✅ 使用自定义线程池工具类提交任务
AsyncManager.me().execute(task);
}
// ❗此处无法精确等待全部线程完成,只做简单延时(如需精确等待建议用 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("<br/>").append(fail);
}
throw new ServiceException(msg.toString());
} else {
return "恭喜您,数据已全部导入成功!共 " + successNum.get() + " 条。";
} }
} }
if (failureNum > 0) {
failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据有误,错误如下:");
throw new ServiceException(failureMsg.toString());
} else {
return "恭喜您,数据已全部导入成功!共 " + successNum + " 条。";
}
}
/** /**
* 获取未被入库单据使用的库位列表 * 获取未被入库单据使用的库位列表

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);
} }
Integer code; log.info("[任务执行] 类型=出库WCS下架TaskID={}, param={}", taskIdParam, param);
String msg; response = HttpUtils.sendPost(wcsJobCreateUrl, param.toJSONString());
} else {
throw new ServiceException("未知任务类型: " + taskType);
}
// 3. 解析响应
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,22 +198,22 @@ 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);
@@ -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,12 +4,14 @@
"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="warehouseName" column="warehouse_name"/>
<result property="encodedId" column="encoded_id"/> <result property="encodedId" column="encoded_id"/>
<result property="tag" column="tag"/> <result property="tag" column="tag"/>
<result property="remark" column="remark"/> <result property="remark" column="remark"/>
@@ -21,11 +23,12 @@
</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,14 +91,14 @@ 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>

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>