rev:项目搭建

This commit is contained in:
2026-08-18 16:25:44 +08:00
parent b0dff536ee
commit a56541a1e9
33 changed files with 1691 additions and 123 deletions

View File

@@ -12,19 +12,19 @@ public class SysParamConstant {
*/
public final static String IS_CONNECT_ACS = "is_connect_acs";
/**
* 是否连接无人车
*/
public final static String IS_NOT_CAR = "is_not_car";
/**
* ACS系统IP
*/
public final static String ACS_URL = "acs_url";
/**
* 无人车系统IP
* 是否连接MES
*/
public final static String CAR_URL = "car_url";
public final static String IS_CONNECT_MES = "is_connect_mes";
/**
* MES系统IP
*/
public final static String MES_URL = "mes_url";
}

View File

@@ -55,4 +55,11 @@ public class AcsToWmsController {
public ResponseEntity<Object> getConfirm(@RequestBody JSONObject whereJson) {
return new ResponseEntity<>(acsToWmsService.getConfirm(whereJson), HttpStatus.OK);
}
@PostMapping("/applyTowDis")
@Log(value = "ACS向WMS申请二次分配")
@SaIgnore
public ResponseEntity<Object> applyTowDis(@RequestBody JSONObject whereJson) {
return new ResponseEntity<>(acsToWmsService.applyTowDis(whereJson), HttpStatus.OK);
}
}

View File

@@ -0,0 +1,46 @@
package org.nl.wms.ext.controller;
import cn.dev33.satoken.annotation.SaIgnore;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.nl.common.logging.annotation.Log;
import org.nl.wms.ext.service.MesToWmsService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* <p>
* MES调用wms 控制层
* </p>
*
* @author Liuxy
* @since 2026-08-14
*/
@RestController
@RequestMapping("/api/toWms")
@Slf4j
public class MesToWmsController {
@Resource
private MesToWmsService mesToWmsService;
@PostMapping("/mouldCallMaterial")
@Log(value = "成型叫料")
@SaIgnore
public ResponseEntity<Object> mouldCallMaterial(@RequestBody JSONObject whereJson) {
return new ResponseEntity<>(mesToWmsService.mouldCallMaterial(whereJson), HttpStatus.OK);
}
@PostMapping("/mouldLowMaterial")
@Log(value = "成型下料")
@SaIgnore
public ResponseEntity<Object> mouldLowMaterial(@RequestBody JSONObject whereJson) {
return new ResponseEntity<>(mesToWmsService.mouldLowMaterial(whereJson), HttpStatus.OK);
}
}

View File

@@ -52,4 +52,17 @@ public interface AcsToWmsService {
*/
BaseResponse getConfirm(JSONObject whereJson);
/**
* ACS向WMS申请二次分配
* @param whereJson {
* task_code: 任务号
* point_code: 任务起点/终点
* }
* @return BaseResponse {
* data: {
* point_code: 二次分配点
* }
* }
*/
BaseResponse applyTowDis(JSONObject whereJson);
}

View File

@@ -0,0 +1,41 @@
package org.nl.wms.ext.service;
import com.alibaba.fastjson.JSONObject;
import org.nl.wms.ext.service.util.MesResponse;
/**
* <p>
* Mes调用Wms 接口
* </p>
*
* @author Liuxy
* @since 2026-08-14
*/
public interface MesToWmsService {
/**
* 成型叫料
* @param whereJson {
* materialCode物料料号
* deviceCode叫料设备
* taskCode任务号
* }
* @return MesResponse
*/
MesResponse<?> mouldCallMaterial(JSONObject whereJson);
/**
* 成型下料
* @param whereJson {
* pkgId PKGID
* pointCode 当前下料设备
* materialCode 物料料号
* pcsn 物料批次
* qty 物料数量
* unitName 计量单位
* }
* @return MesResponse
*/
MesResponse<?> mouldLowMaterial(JSONObject whereJson);
}

View File

@@ -0,0 +1,63 @@
package org.nl.wms.ext.service;
import com.alibaba.fastjson.JSONObject;
import org.nl.wms.ext.service.util.MesResponse;
/**
* <p>
* Wms调用Mes 接口
* </p>
*
* @author Liuxy
* @since 2026-08-13
*/
public interface WmsToMesService {
/**
* 原料组盘查询 接口
*
* @param param {
* materialCode 物料料号
* pcsn 物料批次
* }
* @return data: {
* materialCode: 物料料号
* pcsn: 物料批次
* qty: 组盘数量
* unitName: 计量单位
* }
*/
MesResponse<?> rawMaterialGroupInfo(JSONObject param);
/**
* 申请取放货
*
* @param param {
* deviceCode: 当前设备
* type: 申请类型1-取货2-放货)
* }
* @return data {
* isAgree: 0-不允许1允许
* }
*/
MesResponse<?> applyGetOrPut(JSONObject param);
/**
* 任务回传MES
*
* @param param {
* startPoint 起点
* endPoint 终点
* materialCode 物料料号
* pcsn 批次
* qty 物料数量
* unitName 计量单位
* taskType 任务类型
* taskCode 任务号/PKG_ID
* }
* @return MesResponse<?>
*/
MesResponse<?> returnTaskMes(JSONObject param);
}

View File

@@ -1,5 +1,6 @@
package org.nl.wms.ext.service.impl;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -10,11 +11,16 @@ import org.nl.wms.ext.enums.ResultAcsStatus;
import org.nl.wms.ext.service.AcsToWmsService;
import org.nl.wms.ext.util.BaseResponse;
import org.nl.wms.sch_manage.enums.TaskStatus;
import org.nl.wms.sch_manage.service.ISchBasePointService;
import org.nl.wms.sch_manage.service.ISchBaseTaskService;
import org.nl.wms.sch_manage.service.dao.SchBasePoint;
import org.nl.wms.sch_manage.service.dao.SchBaseTask;
import org.nl.wms.sch_manage.service.dao.mapper.SchBaseTaskMapper;
import org.nl.wms.sch_manage.service.util.AbstractTask;
import org.nl.wms.sch_manage.service.util.TaskFactory;
import org.nl.wms.sch_manage.service.util.tasks.MouldCallMaterialTask;
import org.nl.wms.sch_manage.service.util.tasks.MouldLowMaterialTask;
import org.nl.wms.sch_manage.util.PointDisRuleUtil;
import org.nl.wms.warehouse_management.enums.IOSConstant;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
@@ -22,6 +28,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
@@ -60,6 +68,12 @@ public class AcsToWmsServiceImpl implements AcsToWmsService {
@Autowired
private SchBaseTaskMapper schBaseTaskMapper;
@Resource
private ISchBasePointService iSchBasePointService;
@Resource
private PointDisRuleUtil pointDisRuleUtil;
@Override
@Transactional(rollbackFor = Exception.class)
@SneakyThrows
@@ -198,4 +212,61 @@ public class AcsToWmsServiceImpl implements AcsToWmsService {
log.info("ACS向WMS反馈取货完成返回参数--------------------------------------" + BaseResponse.responseOk().toString());
return BaseResponse.responseOk();
}
@Override
@SneakyThrows
public BaseResponse applyTowDis(JSONObject whereJson) {
log.info("ACS向WMS申请二次分配请求参数--------------------------------------" + whereJson.toString());
JSONObject resultData = new JSONObject();
String task_code = whereJson.getString("task_code");
SchBaseTask schBaseTask = schBaseTaskMapper.selectOne(
new LambdaQueryWrapper<SchBaseTask>()
.eq(SchBaseTask::getTask_code, task_code)
);
RLock lock = redissonClient.getLock(task_code);
boolean tryLock = lock.tryLock(0, TimeUnit.SECONDS);
try {
if (tryLock) {
if (ObjectUtil.isEmpty(schBaseTask)) {
throw new BadRequestException("任务编码为【" + task_code + "】的任务不存在!");
}
SchBasePoint pointDao = iSchBasePointService.getById(whereJson.getString("point_code"));
if (ObjectUtil.isEmpty(pointDao)) {
throw new BadRequestException("点位编码为【" + whereJson.getString("point_code") + "】的点位不存在!");
}
// 调用分配规则进行二次分配
String configCode = schBaseTask.getConfig_code();
SchBasePoint point = new SchBasePoint();
// 点位取货
if (MouldCallMaterialTask.class.getSimpleName().equals(configCode)) {
point = pointDisRuleUtil.disGetRegionRule(pointDao.getRegion_code(), schBaseTask.getMaterial_id(), pointDao.getPoint_code())
.get(0);
schBaseTask.setRemark("二次分配成功,原点位"+schBaseTask.getPoint_code1()+"变更为"+point.getPoint_code());
schBaseTask.setPoint_code1(point.getPoint_code());
}
// 点位放货
if (MouldLowMaterialTask.class.getSimpleName().equals(configCode)) {
point = pointDisRuleUtil.disPutRegionRule(pointDao.getRegion_code(), schBaseTask.getMaterial_id())
.get(0);
schBaseTask.setRemark("二次分配成功,原点位"+schBaseTask.getPoint_code2()+"变更为"+point.getPoint_code());
schBaseTask.setPoint_code2(point.getPoint_code());
}
// 更新任务信息
schBaseTaskMapper.updateById(schBaseTask);
resultData.put("point_code",point.getPoint_code());
} else {
throw new BadRequestException("任务编码:" + schBaseTask.getTask_code() + "正在操作中!");
}
} catch (Exception e) {
log.info("ACS向WMS申请二次分配返回参数--------------------------------------" + BaseResponse.requestError(e.getMessage()).toString());
return BaseResponse.requestError(e.getMessage());
} finally {
if (tryLock) {
lock.unlock();
}
}
log.info("ACS向WMS申请二次分配返回参数--------------------------------------" + BaseResponse.responseOk().toString());
return BaseResponse.responseOk(resultData);
}
}

View File

@@ -0,0 +1,138 @@
package org.nl.wms.ext.service.impl;
import cn.hutool.core.lang.Assert;
import com.alibaba.fastjson.JSONObject;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.nl.common.exception.BadRequestException;
import org.nl.wms.ext.service.MesToWmsService;
import org.nl.wms.ext.service.util.MesResponse;
import org.nl.wms.sch_manage.enums.RegionEnum;
import org.nl.wms.sch_manage.service.ISchBasePointService;
import org.nl.wms.sch_manage.service.ISchBaseTaskService;
import org.nl.wms.sch_manage.service.dao.SchBasePoint;
import org.nl.wms.sch_manage.service.util.tasks.MouldCallMaterialTask;
import org.nl.wms.sch_manage.service.util.tasks.MouldLowMaterialTask;
import org.nl.wms.sch_manage.util.PointDisRuleUtil;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
/**
* <p>
* Mes调用Wms 实现类
* </p>
*
* @author Liuxy
* @since 2026-08-14
*/
@Service
@Slf4j
public class MesToWmsServiceImpl implements MesToWmsService {
@Resource
private ISchBasePointService iSchBasePointService;
@Resource
private RedissonClient redissonClient;
@Resource
private PointDisRuleUtil pointDisRuleUtil;
@Resource
private ISchBaseTaskService iSchBaseTaskService;
@Override
@SneakyThrows
public MesResponse<?> mouldCallMaterial(JSONObject whereJson) {
log.info("MES下发成型叫料任务输入参数为-------------------" + whereJson.toString());
String taskCode = whereJson.getString("taskCode");
RLock lock = redissonClient.getLock(taskCode);
boolean tryLock = lock.tryLock(0, TimeUnit.SECONDS);
try {
if (tryLock) {
// 基础校验
Assert.notEmpty(whereJson, "输入参数为空!");
String materialCode = whereJson.getString("materialCode");
Assert.notEmpty(materialCode, "物料料号为空!");
String deviceCode = whereJson.getString("deviceCode");
SchBasePoint endPointDao = iSchBasePointService.getById(deviceCode);
Assert.notNull(endPointDao, "叫料设备不存在!");
// 调用点位取货分配规则
Optional<SchBasePoint> firstNoBlockPoint = pointDisRuleUtil.disGetRegionRule(RegionEnum.RAW_REGION.getCode(), materialCode,null)
.stream().findFirst();
SchBasePoint point = firstNoBlockPoint.orElseThrow(() ->
new BadRequestException("当前原料区可分配物料全部被阻挡,请检查点位库存!")
);
// 调用生成任务
iSchBaseTaskService.createBussTask(point, point.getPoint_code(), endPointDao.getPoint_code(),
MouldCallMaterialTask.class.getSimpleName(), taskCode);
} else {
throw new BadRequestException("任务号为:" + taskCode + "的任务正在操作中!");
}
} catch (Exception e) {
log.info("MES下发成型叫料任务输出参数为-------------------" + MesResponse.requestErp("下发成型叫料失败:" + e.getMessage()));
return MesResponse.requestErp("下发成型叫料失败:" + e.getMessage());
} finally {
if (tryLock) {
lock.unlock();
}
}
log.info("MES下发成型叫料任务输出参数为-------------------" + MesResponse.requestOk("下发成型叫料任务成功!"));
return MesResponse.requestOk("下发成型叫料任务成功!");
}
@Override
@SneakyThrows
public MesResponse<?> mouldLowMaterial(JSONObject whereJson) {
log.info("MES下发成型下料任务输入参数为-------------------" + whereJson.toString());
String pkgId = whereJson.getString("pkgId");
RLock lock = redissonClient.getLock(pkgId);
boolean tryLock = lock.tryLock(0, TimeUnit.SECONDS);
try {
if (tryLock) {
// 基础校验
Assert.notEmpty(whereJson, "输入参数为空!");
String materialCode = whereJson.getString("materialCode");
Assert.notEmpty(materialCode, "物料料号为空!");
Assert.notEmpty(whereJson.getString("pcsn"), "物料批次为空!");
Assert.notEmpty(whereJson.getString("qty"), "物料数量为空!");
Assert.notEmpty(whereJson.getString("unitName"), "计量单位为空!");
String pointCode = whereJson.getString("pointCode");
SchBasePoint startPointDao = iSchBasePointService.getById(pointCode);
Assert.notNull(startPointDao, "下料设备不存在!");
// 调用点位放货分配规则
Optional<SchBasePoint> firstNoBlockPoint = pointDisRuleUtil.disPutRegionRule(RegionEnum.QUALITY_REGION.getCode(), materialCode)
.stream().findFirst();
SchBasePoint point = firstNoBlockPoint.orElseThrow(() ->
new BadRequestException("当前质检区域没有可分配的点位,可用排已全部使用!")
);
// 调用生成任务
point.setMaterial_id(materialCode);
point.setMaterial_pcsn(whereJson.getString("pcsn"));
point.setMaterial_qty(whereJson.getString("qty"));
point.setUnit_name(whereJson.getString("unitName"));
iSchBaseTaskService.createBussTask(point, startPointDao.getPoint_code(), point.getPoint_code(),
MouldLowMaterialTask.class.getSimpleName(), pkgId);
} else {
throw new BadRequestException("PKG_ID" + pkgId + "的任务正在操作中!");
}
} catch (Exception e) {
log.info("MES下发成型下料任务输出参数为-------------------" + MesResponse.requestErp("下发成型下料失败:" + e.getMessage()));
return MesResponse.requestErp("下发成型下料失败:" + e.getMessage());
} finally {
if (tryLock) {
lock.unlock();
}
}
log.info("MES下发成型下料任务输出参数为-------------------" + MesResponse.requestOk("下发成型下料任务成功!"));
return MesResponse.requestOk("下发成型下料任务成功!");
}
}

View File

@@ -0,0 +1,65 @@
package org.nl.wms.ext.service.impl;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.nl.wms.ext.service.WmsToMesService;
import org.nl.wms.ext.service.util.MesResponse;
import org.nl.wms.ext.util.MesUtil;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
* <p>
* Wms调用Mes 实现类
* </p>
*
* @author Liuxy
* @since 2026-08-13
*/
@Service
@Slf4j
public class WmsToMesServiceImpl implements WmsToMesService {
@Resource
private MesUtil mesUtil;
/**
* 原料组盘查询API
*/
private final String RAW_MATERIAL_GROUP = "/api";
/**
* 申请取放货API
*/
private final String APPLY_GET_PUT = "/api";
/**
* 回传任务信息API
*/
private final String RETURN_TASK = "/api";
@Override
public MesResponse<?> rawMaterialGroupInfo(JSONObject param) {
log.info("下发MES接口查询原料组盘信息的输入参数为-------------------" + param.toString());
MesResponse<?> mesResponse = mesUtil.sendMes(param, RAW_MATERIAL_GROUP);
log.info("下发MES接口查询原料组盘信息的输出参数为-------------------" + mesResponse.toString());
return mesResponse;
}
@Override
public MesResponse<?> applyGetOrPut(JSONObject param) {
log.info("向MES申请是否取放货的输入参数为-------------------" + param.toString());
MesResponse<?> mesResponse = mesUtil.sendMes(param, APPLY_GET_PUT);
log.info("向MES申请是否取放货的输出参数为-------------------" + mesResponse.toString());
return mesResponse;
}
@Override
public MesResponse<?> returnTaskMes(JSONObject param) {
log.info("向MES回传任务信息的输入参数为-------------------" + param.toString());
MesResponse<?> mesResponse = mesUtil.sendMes(param, RETURN_TASK);
log.info("向MES回传任务信息的输出参数为-------------------" + mesResponse.toString());
return mesResponse;
}
}

View File

@@ -0,0 +1,79 @@
package org.nl.wms.ext.service.util;
import com.alibaba.fastjson.JSONObject;
import lombok.Builder;
import lombok.Data;
/**
* <p>
* MES 返回结果
* </p>
*
* @author Liuxy
* @since 2026-08-13
*/
@Data
@Builder
public class MesResponse<T> {
/**
* 信息
*/
private String message;
/**
* 返回数据
*/
private T data;
/**
* 返回状态码
*/
private int status;
/**
* 不带数据反馈
* @return ErpResponse
*/
public static MesResponse requestOk() {
return MesResponse.builder()
.status(200)
.message("请求成功!")
.build();
}
/**
* 带信息反馈
* @return ErpResponse
*/
public static MesResponse requestOk(String message) {
return MesResponse.builder()
.status(200)
.message(message)
.build();
}
/**
* 带信息反馈报错
* @return ErpResponse
*/
public static MesResponse requestErp(String message) {
return MesResponse.builder()
.status(400)
.message(message)
.build();
}
/**
* 带数据反馈
* @return ErpResponse
*/
public static <T> MesResponse requestParamOk(T data) {
return MesResponse.builder()
.status(200)
.message("操作成功!")
.data(data)
.build();
}
}

View File

@@ -0,0 +1,68 @@
package org.nl.wms.ext.util;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.nl.system.enums.SysParamConstant;
import org.nl.system.service.param.ISysParamService;
import org.nl.system.service.param.dao.Param;
import org.nl.wms.ext.service.util.MesResponse;
import org.nl.wms.warehouse_management.enums.IOSConstant;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* <p>
* MES工具类
* </p>
*
* @author Liuxy
* @since 2026-08-13
*/
@Component
@Slf4j
public class MesUtil {
@Resource
private ISysParamService iSysParamService;
public MesResponse<?> sendMes(JSONObject param, String api) {
log.info("下发MES接口" + api + "的输入参数为:-------------------" + param.toString());
MesResponse<?> resultMes;
//判断是否连接ACS系统
Param isConnectMes = iSysParamService.findByCode(SysParamConstant.IS_CONNECT_MES);
if (ObjectUtil.isEmpty(isConnectMes)) {
return MesResponse.requestErp("系统参数表中:" + SysParamConstant.IS_CONNECT_MES + "不存在");
}
if (isConnectMes.getValue().equals(IOSConstant.IS_DELETE_NO)) {
return MesResponse.requestOk("下发成功未连接MES系统!");
}
// mes地址
Param mesUrlParam = iSysParamService.findByCode(SysParamConstant.MES_URL);
if (ObjectUtil.isEmpty(mesUrlParam)) {
return MesResponse.requestErp("系统参数表中:" + SysParamConstant.MES_URL + "不存在");
}
String url = mesUrlParam.getValue() + api;
try {
String resultMsg = HttpRequest.post(url)
.body(String.valueOf(param))
.execute().body();
// 格式转换
JSONObject result = JSONObject.parseObject(resultMsg);
resultMes = JSONObject.toJavaObject(result, MesResponse.class);
log.info("下发MES接口的输出参数为-------------------" + resultMsg);
} catch (Exception e) {
//网络不通
String msg = e.getMessage();
log.error("下发MES接口连接失败{}", msg);
return MesResponse.requestErp("网络不通,请求失败!" + msg);
}
return resultMes;
}
}

View File

@@ -0,0 +1,64 @@
package org.nl.wms.pda.buss_management.controller;
import cn.dev33.satoken.annotation.SaIgnore;
import com.alibaba.fastjson.JSONObject;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.nl.common.logging.annotation.Log;
import org.nl.wms.pda.buss_management.service.ManMadeService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* <p>
* PDA人工管理控制层
* </p>
*
* @author Liuxy
* @since 2026-08-13
*/
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/pda/manMade")
@Slf4j
public class ManMadeController {
@Resource
private ManMadeService manMadeService;
@PostMapping("/parseCode")
@Log("人工放货-扫码解析")
@SaIgnore
public ResponseEntity<Object> parseCode(@RequestBody JSONObject whereJson) {
return new ResponseEntity<>(manMadeService.parseCode(whereJson), HttpStatus.OK);
}
@PostMapping("/bindPoint")
@Log("人工放货-绑定点位")
@SaIgnore
public ResponseEntity<Object> bindPoint(@RequestBody JSONObject whereJson) {
return new ResponseEntity<>(manMadeService.bindPoint(whereJson), HttpStatus.OK);
}
@PostMapping("/queryPointInfo")
@Log("人工取货-根据点位编码查询点位物料信息")
@SaIgnore
public ResponseEntity<Object> queryPointInfo(@RequestBody JSONObject whereJson) {
return new ResponseEntity<>(manMadeService.queryPointInfo(whereJson), HttpStatus.OK);
}
@PostMapping("/unBindPoint")
@Log("人工取货-解绑点位")
@SaIgnore
public ResponseEntity<Object> unBindPoint(@RequestBody JSONObject whereJson) {
return new ResponseEntity<>(manMadeService.unBindPoint(whereJson), HttpStatus.OK);
}
}

View File

@@ -0,0 +1,59 @@
package org.nl.wms.pda.buss_management.service;
import com.alibaba.fastjson.JSONObject;
import org.nl.wms.pda.util.PdaResponse;
/**
* <p>
* PDA人工管理控制层接口
* </p>
*
* @author Liuxy
* @since 2026-08-13
*/
public interface ManMadeService {
/**
* 人工放货 - 扫码解析
*
* @param whereJson {
* code
* }
* @return PdaResponse
*/
PdaResponse<?> parseCode(JSONObject whereJson);
/**
* 人工放货 - 绑定点位
*
* @param whereJson {
* pointCode: 点位编码
* materialCode: 物料料号
* pcsn: 物料批次
* qty: 物料数量
* unitName: 计量单位
* }
* @return PdaResponse
*/
PdaResponse<?> bindPoint(JSONObject whereJson);
/**
* 人工取货 - 根据点位编码查询点位物料信息
*
* @param whereJson {
* pointCode: 点位编码
* }
* @return PdaResponse
*/
PdaResponse<?> queryPointInfo(JSONObject whereJson);
/**
* 人工取货 - 解绑点位
*
* @param whereJson {
* pointCode: 点位编码
* }
* @return PdaResponse
*/
PdaResponse<?> unBindPoint(JSONObject whereJson);
}

View File

@@ -0,0 +1,87 @@
package org.nl.wms.pda.buss_management.service.impl;
import cn.hutool.core.lang.Assert;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.nl.wms.ext.service.WmsToMesService;
import org.nl.wms.ext.service.util.MesResponse;
import org.nl.wms.pda.buss_management.service.ManMadeService;
import org.nl.wms.pda.util.PdaResponse;
import org.nl.wms.sch_manage.enums.PointStatusEnum;
import org.nl.wms.sch_manage.service.ISchBasePointService;
import org.nl.wms.sch_manage.service.dao.SchBasePoint;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
/**
* <p>
* PDA人工管理控制层 实现类
* </p>
*
* @author Liuxy
* @since 2026-08-13
*/
@Service
@Slf4j
public class ManMadeServiceImpl implements ManMadeService {
@Resource
private WmsToMesService wmsToMesService;
@Resource
private ISchBasePointService iSchBasePointService;
@Override
public PdaResponse<?> parseCode(JSONObject whereJson) {
String code = whereJson.getString("code");
Assert.notNull(code, "扫码内容为空!");
String[] arrCode = code.split(",");
JSONObject paramJson = new JSONObject()
.fluentPut("materialCode", arrCode[0])
.fluentPut("pcsn", arrCode[1]);
MesResponse<?> mesResponse = wmsToMesService.rawMaterialGroupInfo(paramJson);
Assert.equals(HttpStatus.OK.value(), mesResponse.getStatus(), mesResponse.getMessage());
return PdaResponse.requestParamOk(mesResponse.getData());
}
@Override
@Transactional
public PdaResponse<?> bindPoint(JSONObject whereJson) {
Assert.notEmpty(whereJson, "输入参数为空!");
boolean isUpdate = iSchBasePointService.lambdaUpdate()
.eq(SchBasePoint::getPoint_code, whereJson.getString("pointCode"))
.set(SchBasePoint::getMaterial_id, whereJson.getString("materialCode"))
.set(SchBasePoint::getMaterial_pcsn, whereJson.getString("pcsn"))
.set(SchBasePoint::getMaterial_qty, whereJson.getString("qty"))
.set(SchBasePoint::getUnit_name, whereJson.getString("unitName"))
.set(SchBasePoint::getPoint_status, PointStatusEnum.FULL_POINT.getCode())
.update();
Assert.isTrue(isUpdate, "点位不存在【{}】", whereJson.getString("pointCode"));
return PdaResponse.requestOk();
}
@Override
public PdaResponse<?> queryPointInfo(JSONObject whereJson) {
return PdaResponse.requestParamOk(iSchBasePointService.getById(whereJson.getString("pointCode")));
}
@Override
public PdaResponse<?> unBindPoint(JSONObject whereJson) {
Assert.notEmpty(whereJson, "输入参数为空!");
boolean isUpdate = iSchBasePointService.lambdaUpdate()
.eq(SchBasePoint::getPoint_code, whereJson.getString("pointCode"))
.set(SchBasePoint::getMaterial_id, "")
.set(SchBasePoint::getMaterial_pcsn, "")
.set(SchBasePoint::getMaterial_qty, "")
.set(SchBasePoint::getUnit_name, "")
.set(SchBasePoint::getPoint_status, PointStatusEnum.EMPTY_POINT.getCode())
.update();
Assert.isTrue(isUpdate, "点位不存在【{}】", whereJson.getString("pointCode"));
return PdaResponse.requestOk();
}
}

View File

@@ -73,6 +73,13 @@ public class SchBaseTaskController {
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
@PostMapping("/returnTaskMes")
@Log("回传MES")
public ResponseEntity<Object> returnTaskMes(@RequestBody SchBaseTask entity) {
schBaseTaskService.returnTaskMes(entity);
return new ResponseEntity<>(HttpStatus.OK);
}
@Log("导出数据")
@GetMapping(value = "/download")
public void download(@RequestParam Map map, HttpServletResponse response, String[] product_area) throws IOException {

View File

@@ -3,26 +3,30 @@ package org.nl.wms.sch_manage.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @Author: Liuxy
* @Description:
* @Date: 2025/5/20
* <p>
* 点位状态枚举类
* </p>
*
* @author Liuxy
* @since 2026-08-14
*/
@Getter
@AllArgsConstructor
public enum PointStatusEnum {
/**
* 空位/无货
* 空位
*/
EMPTY_POINT("1", "空位/无货"),
/**
* 有
* 有
*/
FULL_POINT("3", ""),
FULL_POINT("2", ""),
/**
* 空载具/有货
* 空载具
*/
EMPTY_VEHICLE("2", "空载具/有货");
EMPTY_VEHICLE("3", "空载具");
private final String code;
private final String label;

View File

@@ -0,0 +1,29 @@
package org.nl.wms.sch_manage.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* <p>
* 区域枚举类
* </p>
*
* @author Liuxy
* @since 2026-08-14
*/
@Getter
@AllArgsConstructor
public enum RegionEnum {
/**
* 原材料区域
*/
RAW_REGION("TEST01", "原材料区域"),
/**
* 质量区域
*/
QUALITY_REGION("TEST01", "原材料区域");
private final String code;
private final String name;
}

View File

@@ -1,10 +1,12 @@
package org.nl.wms.sch_manage.service;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import org.nl.common.domain.query.PageQuery;
import org.nl.wms.sch_manage.service.dao.SchBasePoint;
import org.nl.wms.sch_manage.service.dao.SchBaseTask;
import org.nl.wms.sch_manage.service.dto.SchBaseTaskQuery;
@@ -74,15 +76,27 @@ public interface ISchBaseTaskService extends IService<SchBaseTask> {
SchBaseTask getByCode(String taskCode);
/**
* 根据配置编码货位未完成的任务
* @param config_code 配置编码
* @return List<SchBaseTask>
* 业务创建任务(统一入口)
* @param pointDao 点位实体类(物料信息)
* @param startPoint 起点
* @param endPoint 终点
* @param configCode 任务配置编码
* @param taskCode 外部系统任务号
*/
List<SchBaseTask> getTaskConfigList(String config_code);
List<SchBaseTask> getTaskByQuery(LambdaQueryWrapper<SchBaseTask> lam);
Integer haveTaskAll(String deviceCode);
void createBussTask(SchBasePoint pointDao, String startPoint, String endPoint, String configCode,String taskCode);
/**
* 导出
* @param map map
* @param response response
* @param product_area product_area
* @throws IOException IOException
*/
void download(Map map, HttpServletResponse response, String[] product_area) throws IOException;
/**
* 任务回传mes
* @param entity 任务实体类
*/
void returnTaskMes(SchBaseTask entity);
}

View File

@@ -134,8 +134,13 @@ public class SchBasePoint implements Serializable {
private String material_id;
private String material_qty;
private String material_pcsn;
private String unit_name;
private String is_lock;
@TableField(exist = false)
private List<String> can_vehicle_types;

View File

@@ -37,10 +37,10 @@ public class SchBaseRegion implements Serializable {
private String workshop_code;
private String belong_floor;
private String remark;
private String create_id;

View File

@@ -126,6 +126,10 @@ public class SchBaseTask implements Serializable {
private String contact_task;
private String material_pcsn;
private String unit_name;
/**
* 是否需要等待
*/

View File

@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.nl.wms.sch_manage.service.dao.SchBasePoint;
import org.nl.wms.sch_manage.service.dto.SchBasePointQuery;
@@ -19,7 +20,7 @@ public interface SchBasePointMapper extends BaseMapper<SchBasePoint> {
* 批量禁用启用
*
* @param pointCodes 参数
* @param used 参数
* @param used 参数
*/
void batchChangeUsed(List<String> pointCodes, Boolean used);
@@ -49,10 +50,11 @@ public interface SchBasePointMapper extends BaseMapper<SchBasePoint> {
/**
* 查询点位物料明细
*
* @param whereJson {
* point_code点位编码
* storagevehicle_code载具编码
* }
* }
* @return List<JSONObject>
*/
List<JSONObject> getPointDtl(@Param("param") JSONObject whereJson);
@@ -63,6 +65,7 @@ public interface SchBasePointMapper extends BaseMapper<SchBasePoint> {
/**
* 无人车卸货 - 查询无人车点位信息
*
* @return PdaResponse
*/
List<JSONObject> queryNotCarPoint();
@@ -70,10 +73,11 @@ public interface SchBasePointMapper extends BaseMapper<SchBasePoint> {
/**
* 手持功能
* 点位更新 - 根据载具/点位查询明细
*
* @param whereJson {
* point_code: 点位编码
* vehicle_code: 载具编码
* }
* }
* @return PdaResponse
*/
List<JSONObject> pdaQueryPointDtl(@Param("param") JSONObject whereJson);
@@ -85,20 +89,67 @@ public interface SchBasePointMapper extends BaseMapper<SchBasePoint> {
List<SchBasePoint> getCRUsedDevice();
/**
* 手持:卸货库存查询 - 查询库存
* 手持:卸货库存查询 - 查询库存
*
* @param whereJson {
* region_code: 区域编码
* }
* }
* @return List<JSONObject>
*/
List<JSONObject> getUnLoadIvt(@Param("param") JSONObject whereJson);
/**
* 手持:卸货库存查询 - 查询库存
* 手持:卸货库存查询 - 查询库存
*
* @param whereJson {
* region_code: 区域编码
* }
* }
* @return List<JSONObject>
*/
List<JSONObject> getUnLoadIvtWbc(@Param("param") JSONObject whereJson);
/**
* 根据区域编码、物料料号查询点位库存信息(有任务的不查询)
*
* @param material_id 物料料号
* @param region_code 区域编码
* @return List<SchBasePoint>
*/
List<SchBasePoint> getRegionMaterialPoint(@Param("material_id") String material_id, @Param("region_code") String region_code);
/**
* 根据区域编码、物料料号查询点位库存信息
*
* @param material_id 物料料号
* @param region_code 区域编码
* @return List<SchBasePoint>
*/
@Select("select * from sch_base_point" +
" where material_id = #{material_id} and region_code = #{region_code} and is_used = '1' and point_status = '2'"
)
List<SchBasePoint> getUnRegionMaterialPoint(@Param("material_id") String material_id, @Param("region_code") String region_code);
/**
* 根据区域编码查询所有点位
*
* @param region_code 区域编码
* @return List<SchBasePoint>
*/
@Select("select * from sch_base_point" +
" where region_code = #{region_code} and is_used = '1'"
)
List<SchBasePoint> getRegionAllPoint(@Param("region_code") String region_code);
/**
* 根据区域编码查询空的一排
*
* @param region_code 区域编码
* @return String
*/
@Select("SELECT row_num FROM sch_base_point " +
"WHERE region_code = #{region_code} " +
"GROUP BY row_num " +
"HAVING MAX(point_status) = '1' AND MIN(point_status) = '1'" +
"ORDER BY row_num LIMIT 1")
String getEmpRowNum(@Param("region_code") String region_code);
}

View File

@@ -339,4 +339,25 @@
</if>
</where>
</select>
<select id="getRegionMaterialPoint" resultType="org.nl.wms.sch_manage.service.dao.SchBasePoint">
SELECT
p.*
FROM
sch_base_point p
<where>
p.material_id = #{material_id}
AND p.region_code = #{region_code}
AND p.is_used = '1'
AND p.point_status = '2'
AND NOT EXISTS (
SELECT 1
FROM sch_base_task t
WHERE
t.is_delete = FALSE
AND '5' > t.task_status
AND ( t.point_code1 = p.point_code OR t.point_code2 = p.point_code )
)
</where>
</select>
</mapper>

View File

@@ -16,10 +16,12 @@ import org.nl.common.domain.query.PageQuery;
import org.nl.common.exception.BadRequestException;
import org.nl.common.utils.FileUtil;
import org.nl.common.utils.SecurityUtils;
import org.nl.system.service.logging.dao.SysLog;
import org.nl.wms.basedata_manage.enums.BaseDataEnum;
import org.nl.wms.ext.service.WmsToMesService;
import org.nl.wms.ext.service.util.MesResponse;
import org.nl.wms.sch_manage.enums.TaskStatus;
import org.nl.wms.sch_manage.service.ISchBaseTaskService;
import org.nl.wms.sch_manage.service.dao.SchBasePoint;
import org.nl.wms.sch_manage.service.dao.SchBaseTask;
import org.nl.wms.sch_manage.service.dao.mapper.SchBaseTaskMapper;
import org.nl.wms.sch_manage.service.dto.SchBaseTaskQuery;
@@ -29,10 +31,11 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.function.Consumer;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
/**
@@ -50,6 +53,9 @@ public class SchBaseTaskServiceImpl extends ServiceImpl<SchBaseTaskMapper, SchBa
@Autowired
private TaskFactory taskFactory;
@Resource
private WmsToMesService wmsToMesService;
@Override
public IPage<SchBaseTask> queryAll(SchBaseTaskQuery whereJson, PageQuery page) {
List<String> collect = ObjectUtil.isNotEmpty(whereJson.getMore_task_status())
@@ -163,32 +169,16 @@ public class SchBaseTaskServiceImpl extends ServiceImpl<SchBaseTaskMapper, SchBa
}
@Override
public List<SchBaseTask> getTaskConfigList(String config_code) {
return this.list(
new QueryWrapper<SchBaseTask>().lambda()
.eq(SchBaseTask::getConfig_code, config_code)
.lt(SchBaseTask::getTask_status, TaskStatus.FINISHED.getCode())
.eq(SchBaseTask::getIs_delete, BaseDataEnum.IS_YES_NOT.code(""))
);
}
@Override
public List<SchBaseTask> getTaskByQuery(LambdaQueryWrapper<SchBaseTask> lam) {
lam.eq(SchBaseTask::getIs_delete, "0")
.le(SchBaseTask::getTask_status, TaskStatus.EXECUTING.getCode());
return list(lam);
}
@Override
public Integer haveTaskAll(String deviceCode) {
LambdaQueryWrapper<SchBaseTask> lam = new LambdaQueryWrapper<>();
lam.eq(SchBaseTask::getIs_delete, false)
.and(ll -> ll.eq(SchBaseTask::getPoint_code1, deviceCode).or()
.eq(SchBaseTask::getPoint_code2, deviceCode).or()
.eq(SchBaseTask::getPoint_code3, deviceCode).or()
.eq(SchBaseTask::getPoint_code4, deviceCode))
.lt(SchBaseTask::getTask_status, TaskStatus.FINISHED.getCode());
return this.count(lam);
public void createBussTask(SchBasePoint pointDao, String startPoint, String endPoint, String configCode, String taskCode) {
AbstractTask task = taskFactory.getTask(configCode);
JSONObject param = new JSONObject().fluentPut("point_code1", startPoint)
.fluentPut("point_code2", endPoint)
.fluentPut("material_id", pointDao.getMaterial_id())
.fluentPut("material_qty", pointDao.getMaterial_qty())
.fluentPut("material_pcsn", pointDao.getMaterial_pcsn())
.fluentPut("unit_name", pointDao.getUnit_name())
.fluentPut("contact_task", taskCode);
task.create(param);
}
@Override
@@ -198,7 +188,7 @@ public class SchBaseTaskServiceImpl extends ServiceImpl<SchBaseTaskMapper, SchBa
if (collect != null) {
if (collect.contains(TaskStatus.UNFINISHED.getCode())) {
collect = null;
map.put("unFinished",TaskStatus.EXECUTING.getCode());
map.put("unFinished", TaskStatus.EXECUTING.getCode());
}
}
List<SchBaseTask> dataList = schBaseTaskMapper.downloadTask(map, collect);
@@ -221,4 +211,25 @@ public class SchBaseTaskServiceImpl extends ServiceImpl<SchBaseTaskMapper, SchBa
FileUtil.downloadExcel(list, response);
}
@Override
public void returnTaskMes(SchBaseTask taskObj) {
// TODO 任务类型待定
JSONObject param = new JSONObject()
.fluentPut("startPoint", taskObj.getPoint_code1())
.fluentPut("endPoint", taskObj.getPoint_code2())
.fluentPut("materialCode", taskObj.getMaterial_id())
.fluentPut("pcsn", taskObj.getMaterial_pcsn())
.fluentPut("qty", taskObj.getMaterial_qty())
.fluentPut("unitName", taskObj.getUnit_name())
.fluentPut("taskCode", taskObj.getContact_task())
.fluentPut("taskType", "1");
CompletableFuture<? extends MesResponse<?>> future = CompletableFuture.supplyAsync(() -> {
return wmsToMesService.returnTaskMes(param);
});
future.whenComplete((result, throwable) -> {
taskObj.setRemark(result.getStatus() != 200 ? "任务完成回传MES失败" + result.getMessage() : "任务完成回传MES成功!");
this.updateById(taskObj);
});
}
}

View File

@@ -0,0 +1,210 @@
package org.nl.wms.sch_manage.service.util.tasks;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import org.nl.common.exception.BadRequestException;
import org.nl.common.utils.CodeUtil;
import org.nl.common.utils.SecurityUtils;
import org.nl.config.IdUtil;
import org.nl.wms.sch_manage.enums.PointStatusEnum;
import org.nl.wms.sch_manage.enums.TaskStatus;
import org.nl.wms.sch_manage.service.ISchBasePointService;
import org.nl.wms.sch_manage.service.ISchBaseTaskService;
import org.nl.wms.sch_manage.service.dao.SchBasePoint;
import org.nl.wms.sch_manage.service.dao.SchBaseTask;
import org.nl.wms.sch_manage.service.util.ACSTaskTypeEnum;
import org.nl.wms.sch_manage.service.util.AbstractTask;
import org.nl.wms.sch_manage.service.util.AcsTaskDto;
import org.nl.wms.sch_manage.service.util.TaskType;
import org.nl.wms.warehouse_management.enums.IOSConstant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
/**
* <p>
* 成型叫料任务类
* </p>
*
* @author Liuxy
* @since 2026-08-14
*/
@Component(value = "MouldCallMaterialTask")
@TaskType("MouldCallMaterialTask")
public class MouldCallMaterialTask extends AbstractTask {
/**
* 任务服务类
*/
@Autowired
private ISchBaseTaskService taskService;
/**
* 点位服务
*/
@Resource
private ISchBasePointService iSchBasePointService;
@Override
public String create(JSONObject json) {
SchBaseTask task = new SchBaseTask();
task.setTask_id(IdUtil.getStringId());
task.setTask_code(CodeUtil.getNewCode("TASK_CODE"));
task.setTask_status(TaskStatus.CREATE.getCode());
task.setConfig_code(MouldCallMaterialTask.class.getSimpleName());
task.setPoint_code1(json.getString("point_code1"));
task.setPoint_code2(json.getString("point_code2"));
task.setVehicle_code(json.getString("vehicle_code"));
task.setMaterial_id(json.getString("material_id"));
task.setMaterial_qty(json.getBigDecimal("material_qty"));
task.setMaterial_pcsn(json.getString("material_pcsn"));
task.setUnit_name(json.getString("unit_name"));
task.setRequest_param(json.toString());
task.setPriority(json.getString("Priority"));
task.setContact_task(json.getString("contact_task"));
task.setRemark(json.getString("remark"));
task.setCreate_id(SecurityUtils.getCurrentUserId());
task.setCreate_name(SecurityUtils.getCurrentNickName());
task.setCreate_time(DateUtil.now());
taskService.save(task);
// 更新起点
iSchBasePointService.update(
new UpdateWrapper<SchBasePoint>().lambda()
.eq(SchBasePoint::getPoint_code, task.getPoint_code1())
.set(SchBasePoint::getIs_lock, IOSConstant.ONE)
);
// 下发任务
this.sendTaskOne(task.getTask_id());
return task.getTask_id();
}
@Override
public AcsTaskDto sendAcsParam(String taskId) {
SchBaseTask taskDao = taskService.getById(taskId);
// 组织下发给acs的数据
AcsTaskDto acsTaskDto = new AcsTaskDto();
acsTaskDto.setExt_task_id(taskDao.getTask_id());
acsTaskDto.setTask_code(taskDao.getTask_code());
acsTaskDto.setStart_device_code(taskDao.getPoint_code1());
acsTaskDto.setNext_device_code(taskDao.getPoint_code2());
acsTaskDto.setPriority(taskDao.getPriority());
acsTaskDto.setVehicle_code(taskDao.getVehicle_code());
acsTaskDto.setVehicle_type(IOSConstant.ONE);
acsTaskDto.setTask_type(ACSTaskTypeEnum.AGV_TASK.getCode());
acsTaskDto.setPriority(IOSConstant.ONE);
acsTaskDto.setAgv_system_type(IOSConstant.TWO);
return acsTaskDto;
}
@Override
@Transactional
protected void updateStatus(String task_code, TaskStatus status) {
// 校验任务
SchBaseTask taskObj = taskService.getByCode(task_code);
if (taskObj.getTask_status().equals(TaskStatus.FINISHED.getCode())) {
throw new BadRequestException("该任务已完成!");
}
if (taskObj.getTask_status().equals(TaskStatus.CANCELED.getCode())) {
throw new BadRequestException("该任务已取消!");
}
// 根据传来的类型去对任务进行操作
if (status.equals(TaskStatus.EXECUTING)) {
// 更新明细状态
taskObj.setTask_status(TaskStatus.EXECUTING.getCode());
taskObj.setRemark("执行中");
taskObj.setUpdate_time(DateUtil.now());
taskService.updateById(taskObj);
}
if (status.equals(TaskStatus.FINISHED)) {
this.finishTask(taskObj);
}
if (status.equals(TaskStatus.CANCELED)) {
this.cancelTask(taskObj);
}
}
@Override
@Transactional
public void forceFinish(String task_code) {
SchBaseTask taskObj = taskService.getByCode(task_code);
if (ObjectUtil.isEmpty(taskObj)) {
throw new BadRequestException("该任务不存在");
}
this.finishTask(taskObj);
}
@Override
@Transactional
public void cancel(String task_code) {
SchBaseTask taskObj = taskService.getByCode(task_code);
if (ObjectUtil.isEmpty(taskObj)) {
throw new BadRequestException("该任务不存在");
}
if (Integer.parseInt(taskObj.getTask_status()) > Integer.parseInt(TaskStatus.EXECUTING.getCode())) {
throw new BadRequestException("只能取消生成中的任务!");
}
this.cancelTask(taskObj);
}
@Override
public void taskConfirm(String task_code) {
}
@Transactional
public void finishTask(SchBaseTask taskObj) {
// 更新起点
iSchBasePointService.update(
new UpdateWrapper<SchBasePoint>().lambda()
.eq(SchBasePoint::getPoint_code, taskObj.getPoint_code1())
.set(SchBasePoint::getVehicle_code, "")
.set(SchBasePoint::getMaterial_id, "")
.set(SchBasePoint::getMaterial_qty, "")
.set(SchBasePoint::getMaterial_pcsn, "")
.set(SchBasePoint::getUnit_name, "")
.set(SchBasePoint::getIs_lock, IOSConstant.ZERO)
.set(SchBasePoint::getPoint_status, PointStatusEnum.EMPTY_POINT.getCode())
);
// 更新终点
iSchBasePointService.update(
new UpdateWrapper<SchBasePoint>().lambda()
.eq(SchBasePoint::getPoint_code, taskObj.getPoint_code2())
.set(SchBasePoint::getVehicle_code, taskObj.getVehicle_code())
.set(SchBasePoint::getMaterial_id, taskObj.getMaterial_id())
.set(SchBasePoint::getMaterial_qty, taskObj.getMaterial_qty())
.set(SchBasePoint::getMaterial_pcsn, taskObj.getMaterial_pcsn())
.set(SchBasePoint::getUnit_name, taskObj.getUnit_name())
.set(SchBasePoint::getIs_lock, IOSConstant.ZERO)
.set(SchBasePoint::getPoint_status, PointStatusEnum.FULL_POINT.getCode())
);
// 更新任务
taskObj.setRemark("已完成");
taskObj.setTask_status(TaskStatus.FINISHED.getCode());
taskObj.setUpdate_time(DateUtil.now());
taskService.updateById(taskObj);
// 回传mes
taskService.returnTaskMes(taskObj);
}
@Transactional
public void cancelTask(SchBaseTask taskObj) {
// 更新任务
taskObj.setRemark("已取消");
taskObj.setTask_status(TaskStatus.CANCELED.getCode());
taskObj.setUpdate_time(DateUtil.now());
taskService.updateById(taskObj);
// 更新起点
iSchBasePointService.update(
new UpdateWrapper<SchBasePoint>().lambda()
.eq(SchBasePoint::getPoint_code, taskObj.getPoint_code1())
.set(SchBasePoint::getIs_lock, IOSConstant.ZERO)
);
}
}

View File

@@ -0,0 +1,195 @@
package org.nl.wms.sch_manage.service.util.tasks;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import org.nl.common.exception.BadRequestException;
import org.nl.common.utils.CodeUtil;
import org.nl.common.utils.SecurityUtils;
import org.nl.config.IdUtil;
import org.nl.wms.sch_manage.enums.PointStatusEnum;
import org.nl.wms.sch_manage.enums.TaskStatus;
import org.nl.wms.sch_manage.service.ISchBasePointService;
import org.nl.wms.sch_manage.service.ISchBaseTaskService;
import org.nl.wms.sch_manage.service.dao.SchBasePoint;
import org.nl.wms.sch_manage.service.dao.SchBaseTask;
import org.nl.wms.sch_manage.service.util.ACSTaskTypeEnum;
import org.nl.wms.sch_manage.service.util.AbstractTask;
import org.nl.wms.sch_manage.service.util.AcsTaskDto;
import org.nl.wms.sch_manage.service.util.TaskType;
import org.nl.wms.warehouse_management.enums.IOSConstant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
/**
* <p>
* 成型下料任务类
* </p>
*
* @author Liuxy
* @since 2026-08-14
*/
@Component(value = "MouldLowMaterialTask")
@TaskType("MouldLowMaterialTask")
public class MouldLowMaterialTask extends AbstractTask {
/**
* 任务服务类
*/
@Autowired
private ISchBaseTaskService taskService;
/**
* 点位服务
*/
@Resource
private ISchBasePointService iSchBasePointService;
@Override
public String create(JSONObject json) {
SchBaseTask task = new SchBaseTask();
task.setTask_id(IdUtil.getStringId());
task.setTask_code(CodeUtil.getNewCode("TASK_CODE"));
task.setTask_status(TaskStatus.CREATE.getCode());
task.setConfig_code(MouldLowMaterialTask.class.getSimpleName());
task.setPoint_code1(json.getString("point_code1"));
task.setPoint_code2(json.getString("point_code2"));
task.setVehicle_code(json.getString("vehicle_code"));
task.setMaterial_id(json.getString("material_id"));
task.setMaterial_qty(json.getBigDecimal("material_qty"));
task.setMaterial_pcsn(json.getString("material_pcsn"));
task.setUnit_name(json.getString("unit_name"));
task.setRequest_param(json.toString());
task.setPriority(json.getString("Priority"));
task.setContact_task(json.getString("contact_task"));
task.setRemark(json.getString("remark"));
task.setCreate_id(SecurityUtils.getCurrentUserId());
task.setCreate_name(SecurityUtils.getCurrentNickName());
task.setCreate_time(DateUtil.now());
taskService.save(task);
// 下发任务
this.sendTaskOne(task.getTask_id());
return task.getTask_id();
}
@Override
public AcsTaskDto sendAcsParam(String taskId) {
SchBaseTask taskDao = taskService.getById(taskId);
// 组织下发给acs的数据
AcsTaskDto acsTaskDto = new AcsTaskDto();
acsTaskDto.setExt_task_id(taskDao.getTask_id());
acsTaskDto.setTask_code(taskDao.getTask_code());
acsTaskDto.setStart_device_code(taskDao.getPoint_code1());
acsTaskDto.setNext_device_code(taskDao.getPoint_code2());
acsTaskDto.setPriority(taskDao.getPriority());
acsTaskDto.setVehicle_code(taskDao.getVehicle_code());
acsTaskDto.setVehicle_type(IOSConstant.ONE);
acsTaskDto.setTask_type(ACSTaskTypeEnum.AGV_TASK.getCode());
acsTaskDto.setPriority(IOSConstant.ONE);
acsTaskDto.setAgv_system_type(IOSConstant.TWO);
return acsTaskDto;
}
@Override
@Transactional
protected void updateStatus(String task_code, TaskStatus status) {
// 校验任务
SchBaseTask taskObj = taskService.getByCode(task_code);
if (taskObj.getTask_status().equals(TaskStatus.FINISHED.getCode())) {
throw new BadRequestException("该任务已完成!");
}
if (taskObj.getTask_status().equals(TaskStatus.CANCELED.getCode())) {
throw new BadRequestException("该任务已取消!");
}
// 根据传来的类型去对任务进行操作
if (status.equals(TaskStatus.EXECUTING)) {
// 更新明细状态
taskObj.setTask_status(TaskStatus.EXECUTING.getCode());
taskObj.setRemark("执行中");
taskObj.setUpdate_time(DateUtil.now());
taskService.updateById(taskObj);
}
if (status.equals(TaskStatus.FINISHED)) {
this.finishTask(taskObj);
}
if (status.equals(TaskStatus.CANCELED)) {
this.cancelTask(taskObj);
}
}
@Override
@Transactional
public void forceFinish(String task_code) {
SchBaseTask taskObj = taskService.getByCode(task_code);
if (ObjectUtil.isEmpty(taskObj)) {
throw new BadRequestException("该任务不存在");
}
this.finishTask(taskObj);
}
@Override
@Transactional
public void cancel(String task_code) {
SchBaseTask taskObj = taskService.getByCode(task_code);
if (ObjectUtil.isEmpty(taskObj)) {
throw new BadRequestException("该任务不存在");
}
if (Integer.parseInt(taskObj.getTask_status()) > Integer.parseInt(TaskStatus.CREATE.getCode())) {
throw new BadRequestException("只能取消生成中的任务!");
}
this.cancelTask(taskObj);
}
@Override
public void taskConfirm(String task_code) {
}
@Transactional
public void finishTask(SchBaseTask taskObj) {
// 更新起点
iSchBasePointService.update(
new UpdateWrapper<SchBasePoint>().lambda()
.eq(SchBasePoint::getPoint_code, taskObj.getPoint_code1())
.set(SchBasePoint::getVehicle_code, "")
.set(SchBasePoint::getMaterial_id, "")
.set(SchBasePoint::getMaterial_qty, "")
.set(SchBasePoint::getMaterial_pcsn, "")
.set(SchBasePoint::getUnit_name, "")
.set(SchBasePoint::getPoint_status, PointStatusEnum.EMPTY_POINT.getCode())
);
// 更新终点
iSchBasePointService.update(
new UpdateWrapper<SchBasePoint>().lambda()
.eq(SchBasePoint::getPoint_code, taskObj.getPoint_code2())
.set(SchBasePoint::getVehicle_code, taskObj.getVehicle_code())
.set(SchBasePoint::getMaterial_id, taskObj.getMaterial_id())
.set(SchBasePoint::getMaterial_qty, taskObj.getMaterial_qty())
.set(SchBasePoint::getMaterial_pcsn, taskObj.getMaterial_pcsn())
.set(SchBasePoint::getUnit_name, taskObj.getUnit_name())
.set(SchBasePoint::getPoint_status, PointStatusEnum.FULL_POINT.getCode())
);
// 更新任务
taskObj.setRemark("已完成");
taskObj.setTask_status(TaskStatus.FINISHED.getCode());
taskObj.setUpdate_time(DateUtil.now());
taskService.updateById(taskObj);
}
@Transactional
public void cancelTask(SchBaseTask taskObj) {
// 更新任务
taskObj.setRemark("已取消");
taskObj.setTask_status(TaskStatus.CANCELED.getCode());
taskObj.setUpdate_time(DateUtil.now());
taskService.updateById(taskObj);
}
}

View File

@@ -61,6 +61,8 @@ public class PdaPointTask extends AbstractTask {
task.setVehicle_code(json.getString("vehicle_code"));
task.setMaterial_id(json.getString("material_id"));
task.setMaterial_qty(json.getBigDecimal("material_qty"));
task.setMaterial_pcsn(json.getString("material_pcsn"));
task.setUnit_name(json.getString("unit_name"));
task.setRequest_param(json.toString());
task.setPriority(json.getString("Priority"));
task.setContact_task(json.getString("contact_task"));

View File

@@ -0,0 +1,186 @@
package org.nl.wms.sch_manage.util;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.nl.wms.sch_manage.enums.PointStatusEnum;
import org.nl.wms.sch_manage.service.dao.SchBasePoint;
import org.nl.wms.sch_manage.service.dao.mapper.SchBasePointMapper;
import org.nl.wms.warehouse_management.enums.IOSConstant;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;
/**
* <p>
* 点位分配规则工具类
* </p>
*
* @author Liuxy
* @since 2026-08-13
*/
@Component
public class PointDisRuleUtil {
@Resource
private SchBasePointMapper schBasePointMapper;
/**
* 点位取货区域分配规则
* 二次分配可公用
* ps: pointCode则带任务查询 判断是否有在进行的取货任务(适用与下发任务)
* 否则只查询库存(适用与二次分配)
*
* @param regionCode 区域编码
* @param materialCode 物料料号
* @return List<SchBasePoint>
*/
public List<SchBasePoint> disGetRegionRule(String regionCode, String materialCode, String pointCode) {
Assert.notEmpty(regionCode, "区域编码为空!");
Assert.notEmpty(materialCode, "物料料号为空!");
// 查询所有此区域物料的货位
List<SchBasePoint> pointAllList = ObjectUtil.isEmpty(pointCode)
? schBasePointMapper.getRegionMaterialPoint(materialCode, regionCode)
: schBasePointMapper.getUnRegionMaterialPoint(materialCode, regionCode);
Assert.notEmpty(pointAllList, "区域【" + regionCode + "】中没有物料【" + materialCode + "】的点位库存信息!");
return checPointGetList(pointAllList, regionCode);
}
/**
* 点位放货区域分配规则
* 二次分配可公用
*
* @param regionCode 区域编码
* @param materialCode 物料料号
* @return List<SchBasePoint>
*/
public List<SchBasePoint> disPutRegionRule(String regionCode, String materialCode) {
Assert.notEmpty(regionCode, "区域编码为空!");
Assert.notEmpty(materialCode, "物料料号为空!");
// 调用分配放货分配规则
return checPointPutList(regionCode, materialCode);
}
/**
* 点位取货阻挡校验
* 1.根据排分组,根据出库顺序排序(升序)
* 2.校验是否阻挡
* 3.返回最终可出库点位库存信息
*
* @param pointList 点位库存信息
* @param regionCode 区域编码
* @return List<SchBasePoint>
*/
private List<SchBasePoint> checPointGetList(List<SchBasePoint> pointList, String regionCode) {
// 查询此区域所有点位
List<SchBasePoint> regionAllList = schBasePointMapper.getRegionAllPoint(regionCode);
LinkedHashMap<Integer, List<SchBasePoint>> collect = pointList.stream()
.sorted(Comparator.comparing(SchBasePoint::getRow_num,
Comparator.nullsLast(Comparator.naturalOrder()))
.thenComparing(SchBasePoint::getOut_order_seq,
Comparator.nullsLast(Comparator.naturalOrder())))
.collect(Collectors.groupingBy(SchBasePoint::getRow_num,
LinkedHashMap::new, Collectors.toList()));
for (Map.Entry<Integer, List<SchBasePoint>> entry : collect.entrySet()) {
Integer rowNum = entry.getKey();
List<SchBasePoint> currentPointList = entry.getValue();
// 当前排全部点位
List<SchBasePoint> rowAllPoints = regionAllList.stream()
.filter(row -> Objects.equals(row.getRow_num(), rowNum))
.collect(Collectors.toList());
// 找到本行第一个没有阻挡的点位
Optional<SchBasePoint> firstNoBlockPoint = currentPointList.stream()
.filter(point -> rowAllPoints.stream()
.noneMatch(p -> p.getOut_order_seq() < point.getOut_order_seq()
&& PointStatusEnum.FULL_POINT.getCode().equals(p.getPoint_status())))
.findFirst();
// 如果本行存在无阻挡点位,直接返回这一整行
if (firstNoBlockPoint.isPresent() || rowAllPoints.stream()
.filter(r -> r.getOut_order_seq() < currentPointList.get(0).getOut_order_seq()
&& PointStatusEnum.FULL_POINT.getCode().equals(r.getPoint_status()))
.allMatch(p -> IOSConstant.ONE.equals(p.getIs_lock()))) {
return currentPointList;
}
}
return Collections.emptyList();
}
/**
* 点位放货分配规则
* 当前只允许相同物料存放在一排当中
* 1.根据物料料号找相同物料的一排
* 2.如果没有空位找空的一排
*
* @param regionCode 区域编码
* @param materialCode 物料料号
* @return List<SchBasePoint>
*/
private List<SchBasePoint> checPointPutList(String regionCode, String materialCode) {
// 相同物料的排
List<SchBasePoint> pointLikeAllList = schBasePointMapper.getUnRegionMaterialPoint(materialCode, regionCode);
// 为空找新的一排
if (ObjectUtil.isEmpty(pointLikeAllList)) {
return this.getEmpRowNum(regionCode);
}
// 根据物料排 进行分组
LinkedHashMap<Integer, List<SchBasePoint>> collect = pointLikeAllList.stream()
.sorted(Comparator.comparing(SchBasePoint::getRow_num,
Comparator.nullsLast(Comparator.naturalOrder()))
.thenComparing(SchBasePoint::getIn_order_seq,
Comparator.nullsLast(Comparator.naturalOrder())))
.collect(Collectors.groupingBy(SchBasePoint::getRow_num,
LinkedHashMap::new, Collectors.toList()));
// 查询此区域所有点位
List<SchBasePoint> regionAllList = schBasePointMapper.getRegionAllPoint(regionCode);
for (Map.Entry<Integer, List<SchBasePoint>> entry : collect.entrySet()) {
Integer rowNum = entry.getKey();
// 当前排全部点位
List<SchBasePoint> rowAllPoints = regionAllList.stream()
.filter(row -> Objects.equals(row.getRow_num(), rowNum))
.collect(Collectors.toList());
// 查找当前排空位并升序排序
List<SchBasePoint> empPointList = rowAllPoints.stream()
.filter(row -> row.getPoint_status().equals(IOSConstant.ONE))
.sorted(Comparator.comparing(SchBasePoint::getIn_order_seq))
.collect(Collectors.toList());
if (ObjectUtil.isEmpty(empPointList)) {
continue;
}
// 校验是否有空位并且没有空洞的一排
for (SchBasePoint pointDao : empPointList) {
// 查找当前编码的前面是否货
SchBasePoint point = rowAllPoints.stream()
.filter(row -> row.getIn_order_seq() >= pointDao.getIn_order_seq()
&& row.getPoint_status().equals(PointStatusEnum.FULL_POINT.getCode())
).findFirst().orElse(null);
if (ObjectUtil.isEmpty(point)) {
// 返回大于当前点位的空位
return empPointList.stream()
.filter(row -> row.getIn_order_seq() >= pointDao.getIn_order_seq())
.collect(Collectors.toList());
}
// 继续遍历
}
}
return getEmpRowNum(regionCode);
}
/**
* 找空的一排
*
* @param regionCode 区域编码
* @return private List<SchBasePoint>
*/
private List<SchBasePoint> getEmpRowNum(String regionCode) {
return schBasePointMapper.selectList(
new QueryWrapper<SchBasePoint>().lambda()
.eq(SchBasePoint::getRow_num, schBasePointMapper.getEmpRowNum(regionCode))
.eq(SchBasePoint::getIs_used, IOSConstant.ONE)
.orderByAsc(SchBasePoint::getIn_order_seq)
);
}
}