no message
parent
981b83aa2d
commit
7d31f04772
|
|
@ -49,25 +49,35 @@ public class DictAspect {
|
|||
|
||||
private static final String JAVA_UTIL_DATE = "java.util.Date";
|
||||
|
||||
/**
|
||||
* 定义切点Pointcut
|
||||
*/
|
||||
/* @Pointcut("(@within(org.springframework.web.bind.annotation.RestController) || " +
|
||||
"@within(org.springframework.stereotype.Controller) || @annotation(org.jeecg.common.aspect.annotation.AutoDict)) " +
|
||||
"&& execution(public org.jeecg.common.api.vo.Result org.jeecg..*.*(..)) || execution(public * org.cpte..*.*Controller.*(..))")
|
||||
public void excudeService() {
|
||||
}*/
|
||||
|
||||
/**
|
||||
* 定义切点Pointcut
|
||||
*/
|
||||
@Pointcut("(@within(org.springframework.web.bind.annotation.RestController) || " +
|
||||
"@within(org.springframework.stereotype.Controller) || @annotation(org.jeecg.common.aspect.annotation.AutoDict)) " +
|
||||
"&& execution(public org.jeecg.common.api.vo.Result org.jeecg..*.*(..))")
|
||||
"&& (execution(public org.jeecg.common.api.vo.Result org.jeecg..*.*(..)) || " +
|
||||
"execution(public org.jeecg.common.api.vo.Result org.cpte..*.*(..)))")
|
||||
public void excudeService() {
|
||||
}
|
||||
|
||||
@Around("excudeService()")
|
||||
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
|
||||
long time1 = System.currentTimeMillis();
|
||||
long time1=System.currentTimeMillis();
|
||||
Object result = pjp.proceed();
|
||||
long time2 = System.currentTimeMillis();
|
||||
log.debug("获取JSON数据 耗时:" + (time2 - time1) + "ms");
|
||||
long start = System.currentTimeMillis();
|
||||
result = this.parseDictText(result);
|
||||
long end = System.currentTimeMillis();
|
||||
log.debug("注入字典到JSON数据 耗时" + (end - start) + "ms");
|
||||
long time2=System.currentTimeMillis();
|
||||
log.debug("获取JSON数据 耗时:"+(time2-time1)+"ms");
|
||||
long start=System.currentTimeMillis();
|
||||
result=this.parseDictText(result);
|
||||
long end=System.currentTimeMillis();
|
||||
log.debug("注入字典到JSON数据 耗时"+(end-start)+"ms");
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -77,21 +87,20 @@ public class DictAspect {
|
|||
* 示例为SysUser 字段为sex 添加了注解@Dict(dicCode = "sex") 会在字典服务立马查出来对应的text 然后在请求list的时候将这个字典text,已字段名称加_dictText形式返回到前端
|
||||
* 例输入当前返回值的就会多出一个sex_dictText字段
|
||||
* {
|
||||
* sex:1,
|
||||
* sex_dictText:"男"
|
||||
* sex:1,
|
||||
* sex_dictText:"男"
|
||||
* }
|
||||
* 前端直接取值sext_dictText在table里面无需再进行前端的字典转换了
|
||||
* customRender:function (text) {
|
||||
* if(text==1){
|
||||
* return "男";
|
||||
* }else if(text==2){
|
||||
* return "女";
|
||||
* }else{
|
||||
* return text;
|
||||
* }
|
||||
* }
|
||||
* 目前vue是这么进行字典渲染到table上的多了就很麻烦了 这个直接在服务端渲染完成前端可以直接用
|
||||
*
|
||||
* customRender:function (text) {
|
||||
* if(text==1){
|
||||
* return "男";
|
||||
* }else if(text==2){
|
||||
* return "女";
|
||||
* }else{
|
||||
* return text;
|
||||
* }
|
||||
* }
|
||||
* 目前vue是这么进行字典渲染到table上的多了就很麻烦了 这个直接在服务端渲染完成前端可以直接用
|
||||
* @param result
|
||||
*/
|
||||
private Object parseDictText(Object result) {
|
||||
|
|
@ -105,24 +114,24 @@ public class DictAspect {
|
|||
// 字典数据列表, key = 字典code,value=数据列表
|
||||
Map<String, List<String>> dataListMap = new HashMap<>(5);
|
||||
//取出结果集
|
||||
List<Object> records = ((IPage) ((Result) result).getResult()).getRecords();
|
||||
List<Object> records=((IPage) ((Result) result).getResult()).getRecords();
|
||||
//update-begin--Author:zyf -- Date:20220606 ----for:【VUEN-1230】 判断是否含有字典注解,没有注解返回-----
|
||||
Boolean hasDict = checkHasDict(records);
|
||||
if (!hasDict) {
|
||||
Boolean hasDict= checkHasDict(records);
|
||||
if(!hasDict){
|
||||
return result;
|
||||
}
|
||||
|
||||
log.debug(" __ 进入字典翻译切面 DictAspect —— ");
|
||||
log.debug(" __ 进入字典翻译切面 DictAspect —— " );
|
||||
//update-end--Author:zyf -- Date:20220606 ----for:【VUEN-1230】 判断是否含有字典注解,没有注解返回-----
|
||||
for (Object record : records) {
|
||||
String json = "{}";
|
||||
String json="{}";
|
||||
try {
|
||||
//update-begin--Author:zyf -- Date:20220531 ----for:【issues/#3629】 DictAspect Jackson序列化报错-----
|
||||
//解决@JsonFormat注解解析不了的问题详见SysAnnouncement类的@JsonFormat
|
||||
json = objectMapper.writeValueAsString(record);
|
||||
json = objectMapper.writeValueAsString(record);
|
||||
//update-end--Author:zyf -- Date:20220531 ----for:【issues/#3629】 DictAspect Jackson序列化报错-----
|
||||
} catch (JsonProcessingException e) {
|
||||
log.error("json解析失败" + e.getMessage(), e);
|
||||
log.error("json解析失败"+e.getMessage(),e);
|
||||
}
|
||||
//update-begin--Author:scott -- Date:20211223 ----for:【issues/3303】restcontroller返回json数据后key顺序错乱 -----
|
||||
JSONObject item = JSONObject.parseObject(json, Feature.OrderedField);
|
||||
|
|
@ -136,7 +145,7 @@ public class DictAspect {
|
|||
if (oConvertUtils.isEmpty(value)) {
|
||||
continue;
|
||||
}
|
||||
//update-end--Author:scott -- Date:20190603 ----for:解决继承实体字段无法翻译问题------
|
||||
//update-end--Author:scott -- Date:20190603 ----for:解决继承实体字段无法翻译问题------
|
||||
if (field.getAnnotation(Dict.class) != null) {
|
||||
if (!dictFieldList.contains(field)) {
|
||||
dictFieldList.add(field);
|
||||
|
|
@ -160,8 +169,8 @@ public class DictAspect {
|
|||
//date类型默认转换string格式化日期
|
||||
//update-begin--Author:zyf -- Date:20220531 ----for:【issues/#3629】 DictAspect Jackson序列化报错-----
|
||||
//if (JAVA_UTIL_DATE.equals(field.getType().getName())&&field.getAnnotation(JsonFormat.class)==null&&item.get(field.getName())!=null){
|
||||
//SimpleDateFormat aDate=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
// item.put(field.getName(), aDate.format(new Date((Long) item.get(field.getName()))));
|
||||
//SimpleDateFormat aDate=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
// item.put(field.getName(), aDate.format(new Date((Long) item.get(field.getName()))));
|
||||
//}
|
||||
//update-end--Author:zyf -- Date:20220531 ----for:【issues/#3629】 DictAspect Jackson序列化报错-----
|
||||
}
|
||||
|
|
@ -191,7 +200,7 @@ public class DictAspect {
|
|||
String value = record.getString(field.getName());
|
||||
if (oConvertUtils.isNotEmpty(value)) {
|
||||
List<DictModel> dictModels = translText.get(fieldDictCode);
|
||||
if (dictModels == null || dictModels.size() == 0) {
|
||||
if(dictModels==null || dictModels.size()==0){
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -230,7 +239,6 @@ public class DictAspect {
|
|||
* 一次性把所有的字典都翻译了
|
||||
* 1. 所有的普通数据字典的所有数据只执行一次SQL
|
||||
* 2. 表字典相同的所有数据只执行一次SQL
|
||||
*
|
||||
* @param dataListMap
|
||||
* @return
|
||||
*/
|
||||
|
|
@ -298,13 +306,13 @@ public class DictAspect {
|
|||
log.debug("translateDictFromTableByKeys.dictCode:" + dictCode);
|
||||
log.debug("translateDictFromTableByKeys.values:" + values);
|
||||
//update-begin---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------
|
||||
|
||||
|
||||
//update-begin---author:wangshuai---date:2024-01-09---for:微服务下为空报错没有参数需要传递空字符串---
|
||||
if (null == dataSource) {
|
||||
if(null == dataSource){
|
||||
dataSource = "";
|
||||
}
|
||||
//update-end---author:wangshuai---date:2024-01-09---for:微服务下为空报错没有参数需要传递空字符串---
|
||||
|
||||
|
||||
List<DictModel> texts = commonApi.translateDictFromTableByKeys(table, text, code, values, dataSource);
|
||||
//update-end---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------
|
||||
log.debug("translateDictFromTableByKeys.result:" + texts);
|
||||
|
|
@ -382,8 +390,7 @@ public class DictAspect {
|
|||
}
|
||||
|
||||
/**
|
||||
* 翻译字典文本
|
||||
*
|
||||
* 翻译字典文本
|
||||
* @param code
|
||||
* @param text
|
||||
* @param table
|
||||
|
|
@ -392,39 +399,39 @@ public class DictAspect {
|
|||
*/
|
||||
@Deprecated
|
||||
private String translateDictValue(String code, String text, String table, String key) {
|
||||
if (oConvertUtils.isEmpty(key)) {
|
||||
return null;
|
||||
}
|
||||
StringBuffer textValue = new StringBuffer();
|
||||
if(oConvertUtils.isEmpty(key)) {
|
||||
return null;
|
||||
}
|
||||
StringBuffer textValue=new StringBuffer();
|
||||
String[] keys = key.split(",");
|
||||
for (String k : keys) {
|
||||
String tmpValue = null;
|
||||
log.debug(" 字典 key : " + k);
|
||||
log.debug(" 字典 key : "+ k);
|
||||
if (k.trim().length() == 0) {
|
||||
continue; //跳过循环
|
||||
}
|
||||
//update-begin--Author:scott -- Date:20210531 ----for: !56 优化微服务应用下存在表字段需要字典翻译时加载缓慢问题-----
|
||||
if (!StringUtils.isEmpty(table)) {
|
||||
log.debug("--DictAspect------dicTable=" + table + " ,dicText= " + text + " ,dicCode=" + code);
|
||||
String keyString = String.format("sys:cache:dictTable::SimpleKey [%s,%s,%s,%s]", table, text, code, k.trim());
|
||||
if (redisTemplate.hasKey(keyString)) {
|
||||
if (!StringUtils.isEmpty(table)){
|
||||
log.debug("--DictAspect------dicTable="+ table+" ,dicText= "+text+" ,dicCode="+code);
|
||||
String keyString = String.format("sys:cache:dictTable::SimpleKey [%s,%s,%s,%s]",table,text,code,k.trim());
|
||||
if (redisTemplate.hasKey(keyString)){
|
||||
try {
|
||||
tmpValue = oConvertUtils.getString(redisTemplate.opsForValue().get(keyString));
|
||||
} catch (Exception e) {
|
||||
log.warn(e.getMessage());
|
||||
}
|
||||
} else {
|
||||
tmpValue = commonApi.translateDictFromTable(table, text, code, k.trim());
|
||||
}else {
|
||||
tmpValue= commonApi.translateDictFromTable(table,text,code,k.trim());
|
||||
}
|
||||
} else {
|
||||
String keyString = String.format("sys:cache:dict::%s:%s", code, k.trim());
|
||||
if (redisTemplate.hasKey(keyString)) {
|
||||
}else {
|
||||
String keyString = String.format("sys:cache:dict::%s:%s",code,k.trim());
|
||||
if (redisTemplate.hasKey(keyString)){
|
||||
try {
|
||||
tmpValue = oConvertUtils.getString(redisTemplate.opsForValue().get(keyString));
|
||||
} catch (Exception e) {
|
||||
log.warn(e.getMessage());
|
||||
log.warn(e.getMessage());
|
||||
}
|
||||
} else {
|
||||
}else {
|
||||
tmpValue = commonApi.translateDict(code, k.trim());
|
||||
}
|
||||
}
|
||||
|
|
@ -443,12 +450,11 @@ public class DictAspect {
|
|||
|
||||
/**
|
||||
* 检测返回结果集中是否包含Dict注解
|
||||
*
|
||||
* @param records
|
||||
* @return
|
||||
*/
|
||||
private Boolean checkHasDict(List<Object> records) {
|
||||
if (oConvertUtils.isNotEmpty(records) && records.size() > 0) {
|
||||
private Boolean checkHasDict(List<Object> records){
|
||||
if(oConvertUtils.isNotEmpty(records) && records.size()>0){
|
||||
for (Field field : oConvertUtils.getAllFields(records.get(0))) {
|
||||
if (oConvertUtils.isNotEmpty(field.getAnnotation(Dict.class))) {
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package org.cpte.modules.agvTask.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.cpte.modules.agvTask.entity.AgvTask;
|
||||
import org.cpte.modules.agvTask.mapper.AgvTaskMapper;
|
||||
|
|
@ -73,6 +74,7 @@ public class AgvTaskServiceImpl extends ServiceImpl<AgvTaskMapper, AgvTask> impl
|
|||
priority = 3;
|
||||
}
|
||||
return AgvTask.builder()
|
||||
.id(IdWorker.getId())
|
||||
.businessDetailId(businessDetailId)
|
||||
.carrierCode(carrierCode)
|
||||
.type(type)
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@ public class ItemController extends JeecgController<Item, IItemService> {
|
|||
if (StringUtils.isNotBlank(keyword)) {
|
||||
queryWrapper.and(wrapper -> wrapper.likeRight("item_code", keyword).or().likeRight("item_name", keyword));
|
||||
}
|
||||
queryWrapper.orderByAsc("item_code");
|
||||
Page<Item> page = new Page<Item>(pageNo, pageSize);
|
||||
IPage<Item> pageList = itemService.page(page, queryWrapper);
|
||||
return Result.OK(pageList);
|
||||
|
|
|
|||
|
|
@ -12,11 +12,11 @@ import java.net.URLDecoder;
|
|||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.cpte.modules.base.entity.Area;
|
||||
import org.cpte.modules.base.service.IAreaService;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.aspect.annotation.AutoDict;
|
||||
import org.jeecg.common.system.query.QueryGenerator;
|
||||
import org.jeecg.common.system.query.QueryRuleEnum;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.cpte.modules.base.entity.Point;
|
||||
import org.cpte.modules.base.service.IPointService;
|
||||
|
||||
|
|
@ -25,18 +25,11 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
|
|||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.jeecgframework.poi.excel.ExcelImportUtil;
|
||||
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
|
||||
import org.jeecgframework.poi.excel.entity.ExportParams;
|
||||
import org.jeecgframework.poi.excel.entity.ImportParams;
|
||||
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
|
||||
import org.jeecg.common.system.base.controller.JeecgController;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.multipart.MultipartHttpServletRequest;
|
||||
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import org.jeecg.common.aspect.annotation.AutoLog;
|
||||
|
|
@ -56,6 +49,9 @@ public class PointController extends JeecgController<Point, IPointService> {
|
|||
@Autowired
|
||||
private IPointService pointService;
|
||||
|
||||
@Autowired
|
||||
private IAreaService areaService;
|
||||
|
||||
/**
|
||||
* 分页列表查询
|
||||
*
|
||||
|
|
@ -71,17 +67,18 @@ public class PointController extends JeecgController<Point, IPointService> {
|
|||
public Result<IPage<Point>> queryPageList(Point point,
|
||||
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
|
||||
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
|
||||
@RequestParam(name = "keyword", required = false) String keyword,
|
||||
@RequestParam(name = "keyword", required = false) String keyword,
|
||||
HttpServletRequest req) {
|
||||
|
||||
// 自定义查询规则
|
||||
// 自定义查询规则
|
||||
Map<String, QueryRuleEnum> customeRuleMap = new HashMap<>();
|
||||
customeRuleMap.put("pointCode", QueryRuleEnum.RIGHT_LIKE);
|
||||
QueryWrapper<Point> queryWrapper = QueryGenerator.initQueryWrapper(point, req.getParameterMap(), customeRuleMap);
|
||||
// 如果提供了 keyword,则同时对 pointCode 模糊搜索
|
||||
if (StringUtils.isNotBlank(keyword)) {
|
||||
queryWrapper.and(wrapper -> wrapper.likeRight("point_code", keyword));
|
||||
}
|
||||
// 如果提供了 keyword,则同时对 pointCode 模糊搜索
|
||||
if (StringUtils.isNotBlank(keyword)) {
|
||||
queryWrapper.and(wrapper -> wrapper.likeRight("point_code", keyword));
|
||||
}
|
||||
queryWrapper.orderByAsc("point_code");
|
||||
Page<Point> page = new Page<Point>(pageNo, pageSize);
|
||||
IPage<Point> pageList = pointService.page(page, queryWrapper);
|
||||
return Result.OK(pageList);
|
||||
|
|
@ -162,6 +159,8 @@ public class PointController extends JeecgController<Point, IPointService> {
|
|||
if (point == null) {
|
||||
return Result.error("未找到对应数据");
|
||||
}
|
||||
Area area = areaService.getById(point.getAreaId());
|
||||
point.setAreaId_dictText(area.getAreaName());
|
||||
return Result.OK(point);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ public class StockController extends JeecgController<Stock, IStockService> {
|
|||
if (StringUtils.isNotBlank(keyword)) {
|
||||
queryWrapper.and(wrapper -> wrapper.likeRight("stock_code", keyword));
|
||||
}
|
||||
queryWrapper.orderByAsc("stock_code");
|
||||
Page<Stock> page = new Page<Stock>(pageNo, pageSize);
|
||||
IPage<Stock> pageList = stockService.page(page, queryWrapper);
|
||||
return Result.OK(pageList);
|
||||
|
|
|
|||
|
|
@ -2,10 +2,7 @@ package org.cpte.modules.base.entity;
|
|||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import lombok.Data;
|
||||
|
|
@ -47,6 +44,9 @@ public class Point implements Serializable {
|
|||
@Dict(dictTable = "base_area", dicCode = "id", dicText = "area_name")
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private java.lang.Long areaId;
|
||||
|
||||
@TableField(exist = false)
|
||||
private String areaId_dictText;
|
||||
/**
|
||||
* 库位编码
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -30,8 +30,6 @@ public interface ItemKeyMapper extends BaseMapper<ItemKey> {
|
|||
@Param("project") String project, @Param("taskNo") String taskNo,
|
||||
@Param("propC1") String propC1, @Param("propC3") String propC3);
|
||||
|
||||
List<ItemKey> queryItemKeyByIds(@Param("itemKeyIds") List<Long> itemKeyIds);
|
||||
|
||||
List<ItemKey> queryItemKeys(@Param("itemIds") List<Long> itemIds, @Param("whCodeList") List<String> whCodeList,
|
||||
@Param("projectList") List<String> projectList, @Param("taskNoList") List<String> taskNoList,
|
||||
@Param("propC1List") List<String> propC1List, @Param("propC3List") List<String> propC3List);
|
||||
|
|
|
|||
|
|
@ -46,14 +46,6 @@
|
|||
</choose>
|
||||
</select>
|
||||
|
||||
<select id="queryItemKeyByIds" resultType="org.cpte.modules.base.entity.ItemKey">
|
||||
SELECT * FROM base_item_key
|
||||
WHERE id IN
|
||||
<foreach collection="itemKeyIds" item="itemKeyId" open="(" separator="," close=")">
|
||||
#{itemKeyId}
|
||||
</foreach>
|
||||
</select>
|
||||
|
||||
<select id="queryItemKeys" resultType="org.cpte.modules.base.entity.ItemKey">
|
||||
SELECT * FROM base_item_key
|
||||
WHERE item_id IN
|
||||
|
|
|
|||
|
|
@ -3,6 +3,9 @@ package org.cpte.modules.base.service;
|
|||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import org.cpte.modules.base.entity.ItemKey;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @Description: 物料属性
|
||||
* @author: cpte
|
||||
|
|
@ -14,13 +17,21 @@ public interface IItemKeyService extends IService<ItemKey> {
|
|||
/**
|
||||
* 构建物料属性
|
||||
*
|
||||
* @param itemId 物料ID
|
||||
* @param whCode 外部仓库
|
||||
* @param itemId 物料ID
|
||||
* @param whCode 外部仓库
|
||||
* @param project 项目号
|
||||
* @param taskNo 任务号
|
||||
* @param propC1 批次号
|
||||
* @param propC3 外部库存状态
|
||||
* @param taskNo 任务号
|
||||
* @param propC1 批次号
|
||||
* @param propC3 外部库存状态
|
||||
* @return ItemKey
|
||||
*/
|
||||
ItemKey createItemKey(Long itemId, String whCode, String project, String taskNo, String propC1, String propC3);
|
||||
|
||||
/**
|
||||
* 查询物料属性
|
||||
*
|
||||
* @param itemKeyIds 物料属性ID
|
||||
* @return Map<Long, ItemKey>
|
||||
*/
|
||||
Map<Long, ItemKey> queryByIdsToMap(List<Long> itemKeyIds);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,10 @@ package org.cpte.modules.base.service.impl;
|
|||
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.google.common.collect.Maps;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.cpte.modules.base.entity.Item;
|
||||
import org.cpte.modules.base.entity.ItemKey;
|
||||
import org.cpte.modules.base.mapper.ItemKeyMapper;
|
||||
import org.cpte.modules.base.service.IItemKeyService;
|
||||
|
|
@ -10,7 +13,10 @@ import org.jeecg.common.system.vo.LoginUser;
|
|||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @Description: 物料属性
|
||||
|
|
@ -48,4 +54,17 @@ public class ItemKeyServiceImpl extends ServiceImpl<ItemKeyMapper, ItemKey> impl
|
|||
.build();
|
||||
return this.save(itemKey) ? itemKey : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Long, ItemKey> queryByIdsToMap(List<Long> itemKeyIds) {
|
||||
if (CollectionUtils.isEmpty(itemKeyIds)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
List<ItemKey> itemKeys = this.baseMapper.selectByIds(itemKeyIds);
|
||||
Map<Long, ItemKey> itemKeyMap = Maps.newHashMap();
|
||||
for(ItemKey itemKey: itemKeys){
|
||||
itemKeyMap.put(itemKey.getId(), itemKey);
|
||||
}
|
||||
return itemKeyMap;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONArray;
|
|||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson2.JSONReader;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
||||
import com.google.common.collect.Maps;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
|
|
@ -127,6 +128,7 @@ public class ItemServiceImpl extends ServiceImpl<ItemMapper, Item> implements II
|
|||
log.error("获取登录用户信息失败");
|
||||
}
|
||||
return Item.builder()
|
||||
.id(IdWorker.getId())
|
||||
.itemCode(itemCode)
|
||||
.itemName(itemName)
|
||||
.unit(unit)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package org.cpte.modules.base.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
||||
import com.google.common.collect.Maps;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
|
|
@ -36,6 +37,7 @@ public class StockServiceImpl extends ServiceImpl<StockMapper, Stock> implements
|
|||
log.error("获取登录用户信息失败");
|
||||
}
|
||||
return Stock.builder()
|
||||
.id(IdWorker.getId())
|
||||
.stockCode(stockDTO.getCode())
|
||||
.stockType(StockTypeEnum.TRAY.getValue())
|
||||
.izActive(stockDTO.getIzActive())
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ public enum AsnStatusEnum {
|
|||
|
||||
CANCELED(5, "已取消"),
|
||||
|
||||
SCAN(6, "已扫描"),
|
||||
|
||||
|
||||
;
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,10 @@ import lombok.Getter;
|
|||
@Getter
|
||||
public enum BusinessTypeEnum {
|
||||
|
||||
TRANSPORT("TRANSPORT", "搬运"),
|
||||
|
||||
MOVE("MOVE", "移位"),
|
||||
|
||||
INBOUND("INBOUND", "入库"),
|
||||
|
||||
OUTBOUND("OUTBOUND", "出库"),
|
||||
|
|
|
|||
|
|
@ -10,6 +10,10 @@ import lombok.Getter;
|
|||
*/
|
||||
@Getter
|
||||
public enum InventoryStatusEnum {
|
||||
/**
|
||||
* 禁用
|
||||
*/
|
||||
UNAVAILABLE(0, "禁用"),
|
||||
/**
|
||||
* 可用
|
||||
*/
|
||||
|
|
@ -28,7 +32,7 @@ public enum InventoryStatusEnum {
|
|||
/**
|
||||
* 移位中
|
||||
*/
|
||||
TRANSFER(4, "移位中"),
|
||||
MOVE(4, "移位中"),
|
||||
|
||||
/**
|
||||
* 盘点中
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import org.cpte.modules.agvTask.mapper.AgvTaskMapper;
|
|||
import org.cpte.modules.constant.enums.*;
|
||||
import org.cpte.modules.conveyorLine.request.ScanTrayRequest;
|
||||
import org.cpte.modules.conveyorLine.service.IConveyorLineService;
|
||||
import org.cpte.modules.conveyorLine.service.ScanTrayProcessor;
|
||||
import org.cpte.modules.conveyorLine.service.processor.ScanTrayProcessor;
|
||||
import org.cpte.modules.shipping.entity.Task;
|
||||
import org.cpte.modules.shipping.mapper.TaskMapper;
|
||||
import org.cpte.modules.utils.RedisDistributedLockUtil;
|
||||
|
|
@ -44,6 +44,9 @@ public class IConveyorLineServiceImpl implements IConveyorLineService {
|
|||
throw new RuntimeException("扫描处理中,请稍后重试");
|
||||
}
|
||||
scanTrayProcessor.scanTray(scanTrayRequest);
|
||||
} catch (Exception e) {
|
||||
log.error("扫描托盘异常", e);
|
||||
throw e;
|
||||
} finally {
|
||||
if (StringUtils.isNotEmpty(lockValue)) {
|
||||
redissonLock.unlock(lockKey, lockValue);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
package org.cpte.modules.conveyorLine.service;
|
||||
package org.cpte.modules.conveyorLine.service.processor;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
|
|
@ -86,7 +86,8 @@ public class ScanTrayProcessor {
|
|||
validateTray(data);
|
||||
|
||||
// 4.智能分配库位
|
||||
Point dstPoint = allocatePoint(data.getAsn().getOrderType(), data.getItemKeys(), data.getStation());
|
||||
String areaCode = getAreaCode(data.getAsn().getOrderType());
|
||||
Point dstPoint = allocatePoint(data.getItemKeys(), data.getStation(), areaCode);
|
||||
|
||||
// 5.生成TES任务
|
||||
processAgvTask(data.getAsn(), data.getStock(), data.getStation(), dstPoint);
|
||||
|
|
@ -167,26 +168,35 @@ public class ScanTrayProcessor {
|
|||
}
|
||||
|
||||
//验证当前托盘是否生成了TES任务
|
||||
if (agvTaskMapper.existsByStockCode(stockCode, AgvVendorEnum.TES.getValue()) > 0) {
|
||||
if (agvTaskMapper.existsByStockCode(stockCode, AgvVendorEnum.TES.getValue()) != null) {
|
||||
throw new RuntimeException("【" + stockCode + "】托盘已扫描,请勿重复扫描");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 智能库位分配库位
|
||||
* 获取库区
|
||||
*
|
||||
* @param orderType 单据类型
|
||||
* @param itemKeys 物料属性
|
||||
* @param station 工作站
|
||||
* @return 目标库位
|
||||
* @param orderType 订单类型
|
||||
* @return 库区
|
||||
*/
|
||||
private Point allocatePoint(Integer orderType, List<ItemKey> itemKeys, Point station) {
|
||||
private String getAreaCode(Integer orderType) {
|
||||
String areaCode = "";
|
||||
if (Set.of(0, 1, 2, 3).contains(orderType)) {
|
||||
areaCode = AreaTypeEnum.CPCCQ.getValue();
|
||||
} else {
|
||||
areaCode = AreaTypeEnum.MJCCQ.getValue();
|
||||
}
|
||||
return areaCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* 智能库位分配库位
|
||||
*
|
||||
* @param itemKeys 物料属性
|
||||
* @param station 工作站
|
||||
* @return 目标库位
|
||||
*/
|
||||
public Point allocatePoint(List<ItemKey> itemKeys, Point station, String areaCode) {
|
||||
//1.优先寻找同物料/同仓库/同项目号/同任务号/同批次/同外部库存状态
|
||||
List<Long> itemKeyIds = itemKeys.stream().map(ItemKey::getId).toList();
|
||||
List<Point> availablePoints = pointService.findClusterPoint(itemKeyIds, areaCode);
|
||||
|
|
@ -318,7 +328,7 @@ public class ScanTrayProcessor {
|
|||
return score;
|
||||
}
|
||||
List<Long> itemKeyIds = neighbors.stream().map(Inventory::getItemKeyId).distinct().toList();
|
||||
List<ItemKey> exitItemKeys = itemKeyMapper.queryItemKeyByIds(itemKeyIds);
|
||||
List<ItemKey> exitItemKeys = itemKeyMapper.selectByIds(itemKeyIds);
|
||||
|
||||
// 为每个ItemKey计算匹配度并累加分数
|
||||
for (ItemKey itemKey : itemKeys) {
|
||||
|
|
@ -388,6 +398,8 @@ public class ScanTrayProcessor {
|
|||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void processAgvTask(Asn asn, Stock stock, Point station, Point dstPoint) {
|
||||
asn.setStatus(AsnStatusEnum.SCAN.getValue());
|
||||
asnMapper.updateById(asn);
|
||||
//锁定目标库位
|
||||
pointService.bindPoint(dstPoint);
|
||||
|
||||
|
|
@ -8,8 +8,11 @@ import java.util.stream.Collectors;
|
|||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.cpte.modules.base.entity.ItemKey;
|
||||
import org.cpte.modules.base.service.IItemKeyService;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.system.query.QueryGenerator;
|
||||
import org.jeecg.common.system.query.QueryRuleEnum;
|
||||
|
|
@ -38,128 +41,149 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
|||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import org.jeecg.common.aspect.annotation.AutoLog;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
/**
|
||||
|
||||
/**
|
||||
* @Description: 库存表
|
||||
* @author: cpte
|
||||
* @Date: 2025-11-08
|
||||
* @Date: 2025-11-08
|
||||
* @Version: V1.0
|
||||
*/
|
||||
@Tag(name="库存表")
|
||||
@Tag(name = "库存表")
|
||||
@RestController
|
||||
@RequestMapping("/inventory")
|
||||
@Slf4j
|
||||
public class InventoryController extends JeecgController<Inventory, IInventoryService> {
|
||||
@Autowired
|
||||
private IInventoryService inventoryService;
|
||||
|
||||
/**
|
||||
* 分页列表查询
|
||||
*
|
||||
* @param inventory
|
||||
* @param pageNo
|
||||
* @param pageSize
|
||||
* @param req
|
||||
* @return
|
||||
*/
|
||||
//@AutoLog(value = "库存表-分页列表查询")
|
||||
@Operation(summary="库存表-分页列表查询")
|
||||
@GetMapping(value = "/list")
|
||||
public Result<IPage<Inventory>> queryPageList(Inventory inventory,
|
||||
@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
|
||||
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
|
||||
HttpServletRequest req) {
|
||||
@Autowired
|
||||
private IInventoryService inventoryService;
|
||||
|
||||
@Autowired
|
||||
private IItemKeyService itemKeyService;
|
||||
|
||||
/**
|
||||
* 分页列表查询
|
||||
*
|
||||
* @param inventory
|
||||
* @param pageNo
|
||||
* @param pageSize
|
||||
* @param req
|
||||
* @return
|
||||
*/
|
||||
//@AutoLog(value = "库存表-分页列表查询")
|
||||
@Operation(summary = "库存表-分页列表查询")
|
||||
@GetMapping(value = "/list")
|
||||
public Result<IPage<Inventory>> queryPageList(Inventory inventory,
|
||||
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
|
||||
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
|
||||
HttpServletRequest req) {
|
||||
|
||||
|
||||
QueryWrapper<Inventory> queryWrapper = QueryGenerator.initQueryWrapper(inventory, req.getParameterMap());
|
||||
Page<Inventory> page = new Page<Inventory>(pageNo, pageSize);
|
||||
IPage<Inventory> pageList = inventoryService.page(page, queryWrapper);
|
||||
return Result.OK(pageList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加
|
||||
*
|
||||
* @param inventory
|
||||
* @return
|
||||
*/
|
||||
@AutoLog(value = "库存表-添加")
|
||||
@Operation(summary="库存表-添加")
|
||||
@RequiresPermissions("inventory:data_inventory:add")
|
||||
@PostMapping(value = "/add")
|
||||
public Result<String> add(@RequestBody Inventory inventory) {
|
||||
inventoryService.save(inventory);
|
||||
|
||||
return Result.OK("添加成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
*
|
||||
* @param inventory
|
||||
* @return
|
||||
*/
|
||||
@AutoLog(value = "库存表-编辑")
|
||||
@Operation(summary="库存表-编辑")
|
||||
@RequiresPermissions("inventory:data_inventory:edit")
|
||||
@RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST})
|
||||
public Result<String> edit(@RequestBody Inventory inventory) {
|
||||
inventoryService.updateById(inventory);
|
||||
return Result.OK("编辑成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过id删除
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@AutoLog(value = "库存表-通过id删除")
|
||||
@Operation(summary="库存表-通过id删除")
|
||||
@RequiresPermissions("inventory:data_inventory:delete")
|
||||
@DeleteMapping(value = "/delete")
|
||||
public Result<String> delete(@RequestParam(name="id",required=true) String id) {
|
||||
inventoryService.removeById(id);
|
||||
return Result.OK("删除成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除
|
||||
*
|
||||
* @param ids
|
||||
* @return
|
||||
*/
|
||||
@AutoLog(value = "库存表-批量删除")
|
||||
@Operation(summary="库存表-批量删除")
|
||||
@RequiresPermissions("inventory:data_inventory:deleteBatch")
|
||||
@DeleteMapping(value = "/deleteBatch")
|
||||
public Result<String> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
|
||||
this.inventoryService.removeByIds(Arrays.asList(ids.split(",")));
|
||||
return Result.OK("批量删除成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过id查询
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
//@AutoLog(value = "库存表-通过id查询")
|
||||
@Operation(summary="库存表-通过id查询")
|
||||
@GetMapping(value = "/queryById")
|
||||
public Result<Inventory> queryById(@RequestParam(name="id",required=true) String id) {
|
||||
Inventory inventory = inventoryService.getById(id);
|
||||
if(inventory==null) {
|
||||
return Result.error("未找到对应数据");
|
||||
Page<Inventory> page = new Page<Inventory>(pageNo, pageSize);
|
||||
IPage<Inventory> pageList = inventoryService.page(page, queryWrapper);
|
||||
//物料属性
|
||||
List<Long> itemKeyIds = pageList.getRecords().stream().map(Inventory::getItemKeyId).toList();
|
||||
Map<Long, ItemKey> itemKeyMap=itemKeyService.queryByIdsToMap(itemKeyIds);
|
||||
for(Inventory inv:pageList.getRecords()){
|
||||
ItemKey itemKey = itemKeyMap.get(inv.getItemKeyId());
|
||||
if (itemKey != null) {
|
||||
inv.setWhCode(itemKey.getWhCode());
|
||||
inv.setProject(itemKey.getProject());
|
||||
inv.setTaskNo(itemKey.getTaskNo());
|
||||
inv.setPropC1(itemKey.getPropC1());
|
||||
inv.setPropC3(itemKey.getPropC3());
|
||||
}
|
||||
}
|
||||
return Result.OK(inventory);
|
||||
}
|
||||
return Result.OK(pageList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出excel
|
||||
*
|
||||
* @param request
|
||||
* @param inventory
|
||||
*/
|
||||
* 添加
|
||||
*
|
||||
* @param inventory
|
||||
* @return
|
||||
*/
|
||||
@AutoLog(value = "库存表-添加")
|
||||
@Operation(summary = "库存表-添加")
|
||||
@RequiresPermissions("inventory:data_inventory:add")
|
||||
@PostMapping(value = "/add")
|
||||
public Result<String> add(@RequestBody Inventory inventory) {
|
||||
ItemKey itemKey = itemKeyService.createItemKey(inventory.getItemId(), inventory.getWhCode(), inventory.getProject(), inventory.getTaskNo(), inventory.getPropC1(), inventory.getPropC3());
|
||||
inventory.setItemKeyId(itemKey.getId());
|
||||
inventoryService.save(inventory);
|
||||
|
||||
return Result.OK("添加成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
*
|
||||
* @param inventory
|
||||
* @return
|
||||
*/
|
||||
@AutoLog(value = "库存表-编辑")
|
||||
@Operation(summary = "库存表-编辑")
|
||||
@RequiresPermissions("inventory:data_inventory:edit")
|
||||
@RequestMapping(value = "/edit", method = {RequestMethod.PUT, RequestMethod.POST})
|
||||
public Result<String> edit(@RequestBody Inventory inventory) {
|
||||
ItemKey itemKey = itemKeyService.createItemKey(inventory.getItemId(), inventory.getWhCode(), inventory.getProject(), inventory.getTaskNo(), inventory.getPropC1(), inventory.getPropC3());
|
||||
inventory.setItemKeyId(itemKey.getId());
|
||||
inventoryService.updateById(inventory);
|
||||
return Result.OK("编辑成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过id删除
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@AutoLog(value = "库存表-通过id删除")
|
||||
@Operation(summary = "库存表-通过id删除")
|
||||
@RequiresPermissions("inventory:data_inventory:delete")
|
||||
@DeleteMapping(value = "/delete")
|
||||
public Result<String> delete(@RequestParam(name = "id", required = true) String id) {
|
||||
inventoryService.removeById(id);
|
||||
return Result.OK("删除成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除
|
||||
*
|
||||
* @param ids
|
||||
* @return
|
||||
*/
|
||||
@AutoLog(value = "库存表-批量删除")
|
||||
@Operation(summary = "库存表-批量删除")
|
||||
@RequiresPermissions("inventory:data_inventory:deleteBatch")
|
||||
@DeleteMapping(value = "/deleteBatch")
|
||||
public Result<String> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
|
||||
this.inventoryService.removeByIds(Arrays.asList(ids.split(",")));
|
||||
return Result.OK("批量删除成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过id查询
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
//@AutoLog(value = "库存表-通过id查询")
|
||||
@Operation(summary = "库存表-通过id查询")
|
||||
@GetMapping(value = "/queryById")
|
||||
public Result<Inventory> queryById(@RequestParam(name = "id", required = true) String id) {
|
||||
Inventory inventory = inventoryService.getById(id);
|
||||
if (inventory == null) {
|
||||
return Result.error("未找到对应数据");
|
||||
}
|
||||
return Result.OK(inventory);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出excel
|
||||
*
|
||||
* @param request
|
||||
* @param inventory
|
||||
*/
|
||||
@RequiresPermissions("inventory:data_inventory:exportXls")
|
||||
@RequestMapping(value = "/exportXls")
|
||||
public ModelAndView exportXls(HttpServletRequest request, Inventory inventory) {
|
||||
|
|
@ -167,12 +191,12 @@ public class InventoryController extends JeecgController<Inventory, IInventorySe
|
|||
}
|
||||
|
||||
/**
|
||||
* 通过excel导入数据
|
||||
*
|
||||
* @param request
|
||||
* @param response
|
||||
* @return
|
||||
*/
|
||||
* 通过excel导入数据
|
||||
*
|
||||
* @param request
|
||||
* @param response
|
||||
* @return
|
||||
*/
|
||||
@RequiresPermissions("inventory:data_inventory:importExcel")
|
||||
@RequestMapping(value = "/importExcel", method = RequestMethod.POST)
|
||||
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
|
||||
|
|
|
|||
|
|
@ -5,10 +5,7 @@ import java.io.UnsupportedEncodingException;
|
|||
import java.util.Date;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import lombok.*;
|
||||
|
|
@ -88,13 +85,6 @@ public class Inventory implements Serializable {
|
|||
@Excel(name = "分配数", width = 15)
|
||||
@Schema(description = "分配数")
|
||||
private java.math.BigDecimal queuedQty;
|
||||
/**
|
||||
* 入库记录ID
|
||||
*/
|
||||
@Excel(name = "入库记录ID", width = 15)
|
||||
@Schema(description = "入库记录ID")
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private java.lang.Long receiveRecordId;
|
||||
|
||||
/**
|
||||
* 库存状态
|
||||
|
|
@ -111,6 +101,45 @@ public class Inventory implements Serializable {
|
|||
@Schema(description = "描述")
|
||||
private java.lang.String description;
|
||||
|
||||
/**
|
||||
* 赛意入库单号
|
||||
*/
|
||||
@Schema(description = "赛意入库单号")
|
||||
private java.lang.String orderNo;
|
||||
|
||||
/**
|
||||
* 外部仓库
|
||||
*/
|
||||
@Schema(description = "外部仓库")
|
||||
@TableField(exist = false)
|
||||
private java.lang.String whCode;
|
||||
|
||||
/**
|
||||
* 项目号
|
||||
*/
|
||||
@Schema(description = "项目号")
|
||||
@TableField(exist = false)
|
||||
private java.lang.String project;
|
||||
/**
|
||||
* 任务号
|
||||
*/
|
||||
@Schema(description = "任务号")
|
||||
@TableField(exist = false)
|
||||
private java.lang.String taskNo;
|
||||
/**
|
||||
* 批次号
|
||||
*/
|
||||
@Schema(description = "批次号")
|
||||
@TableField(exist = false)
|
||||
private java.lang.String propC1;
|
||||
/**
|
||||
* 外部库存状态
|
||||
*/
|
||||
@Schema(description = "外部库存状态")
|
||||
@TableField(exist = false)
|
||||
private java.lang.String propC3;
|
||||
|
||||
|
||||
/**
|
||||
* 所属部门
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -54,4 +54,21 @@ public interface InventoryMapper extends BaseMapper<Inventory> {
|
|||
* @return List<Inventory>
|
||||
*/
|
||||
List<Inventory> queryByPointIds(@Param("pointIds") List<Long> pointIds);
|
||||
|
||||
/**
|
||||
* 根据容器查询库存数据
|
||||
*
|
||||
* @param stockId 容器
|
||||
* @return 库存数据
|
||||
*/
|
||||
@Select("select * from data_inventory where stock_id = #{stockId}")
|
||||
List<Inventory> queryInventoryByStockId(@Param("stockId") Long stockId);
|
||||
|
||||
/**
|
||||
* 根据容器ID集合删除库存数据
|
||||
*
|
||||
* @param stockIds 容器ID集合
|
||||
*/
|
||||
void deleteByStockIds(List<Long> stockIds);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,4 +21,12 @@
|
|||
#{pointId}
|
||||
</foreach>
|
||||
</select>
|
||||
|
||||
<delete id="deleteByStockIds">
|
||||
DELETE FROM data_inventory
|
||||
WHERE stock_id IN
|
||||
<foreach collection="stockIds" item="stockId" open="(" separator="," close=")">
|
||||
#{stockId}
|
||||
</foreach>
|
||||
</delete>
|
||||
</mapper>
|
||||
|
|
@ -46,4 +46,11 @@ public interface IInventoryService extends IService<Inventory> {
|
|||
* @return Map<Long, Inventory>
|
||||
*/
|
||||
Map<Long, Inventory> queryByInventoryIdsToMap(List<Long> inventoryIds);
|
||||
|
||||
/**
|
||||
* 根据容器ID删除库存
|
||||
*
|
||||
* @param stockIds 容器ID
|
||||
*/
|
||||
void deleteByStockIds(List<Long> stockIds);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,8 +33,8 @@ public class InventoryServiceImpl extends ServiceImpl<InventoryMapper, Inventory
|
|||
.stockId(receiveRecord.getStockId())
|
||||
.quantity(receivedQty)
|
||||
.queuedQty(BigDecimal.ZERO)
|
||||
.receiveRecordId(receiveRecord.getId())
|
||||
.status(InventoryStatusEnum.AVAILABLE.getValue())
|
||||
.status(InventoryStatusEnum.UNAVAILABLE.getValue())
|
||||
.orderNo(asn.getThirdOrderNo())
|
||||
.description(receiveRecord.getDescription())
|
||||
.tenantId(receiveRecord.getTenantId())
|
||||
.sysOrgCode(receiveRecord.getSysOrgCode())
|
||||
|
|
@ -53,7 +53,6 @@ public class InventoryServiceImpl extends ServiceImpl<InventoryMapper, Inventory
|
|||
.stockId(receiveRecord.getStockId())
|
||||
.quantity(receivedQty)
|
||||
.queuedQty(BigDecimal.ZERO)
|
||||
.receiveRecordId(receiveRecord.getId())
|
||||
.status(InventoryStatusEnum.AVAILABLE.getValue())
|
||||
.description(receiveRecord.getDescription())
|
||||
.tenantId(receiveRecord.getTenantId())
|
||||
|
|
@ -77,5 +76,11 @@ public class InventoryServiceImpl extends ServiceImpl<InventoryMapper, Inventory
|
|||
return inventoryMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deleteByStockIds(List<Long> stockIds) {
|
||||
this.baseMapper.deleteByStockIds(stockIds);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,7 +46,6 @@ public interface IInventoryLogService extends IService<InventoryLog> {
|
|||
void addInboundInventoryLog(Inventory inventory, Long srcPointId, BigDecimal changeQty, String businessNo, Long businessDetailId, String description);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 添加出库库存日志
|
||||
*
|
||||
|
|
@ -88,12 +87,13 @@ public interface IInventoryLogService extends IService<InventoryLog> {
|
|||
* 添加拣货库存日志
|
||||
*
|
||||
* @param inventory 库存
|
||||
* @param dstPointId 目标库位
|
||||
* @param changeQty 变动数量
|
||||
* @param businessNo 业务单号
|
||||
* @param businessDetailId 业务明细ID
|
||||
* @param description 描述
|
||||
*/
|
||||
void addPickInventoryLog(Inventory inventory, BigDecimal changeQty, String businessNo, Long businessDetailId, String description);
|
||||
void addPickInventoryLog(Inventory inventory, Long dstPointId, BigDecimal changeQty, String businessNo, Long businessDetailId, String description);
|
||||
|
||||
/**
|
||||
* 添加退拣库存日志-拣货后取消,库存回退
|
||||
|
|
|
|||
|
|
@ -93,23 +93,25 @@ public class InventoryLogServiceImpl extends ServiceImpl<InventoryLogMapper, Inv
|
|||
inventoryLog.setLogType(InventoryLogEnum.UNALLOC.getValue());
|
||||
// 实际数量不变
|
||||
inventoryLog.setChangeQty(BigDecimal.ZERO);
|
||||
inventoryLog.setBeforeAllocatedQty(BigDecimalUtil.add(inventory.getQueuedQty(), cancelQuantity, 0));
|
||||
inventoryLog.setAfterAllocatedQty(inventory.getQueuedQty());
|
||||
inventoryLog.setBeforeAllocatedQty(inventory.getQueuedQty());
|
||||
inventoryLog.setAfterAllocatedQty(BigDecimalUtil.subtract(inventory.getQueuedQty(), cancelQuantity, 0));
|
||||
addInventoryLog(inventoryLog);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void addPickInventoryLog(Inventory inventory, BigDecimal changeQty, String businessNo, Long businessDetailId, String description) {
|
||||
public void addPickInventoryLog(Inventory inventory,Long dstPointId, BigDecimal changeQty, String businessNo, Long businessDetailId, String description) {
|
||||
InventoryLog inventoryLog = buildInventoryLog(inventory, BigDecimal.ZERO, businessNo, businessDetailId, description);
|
||||
// 拣货类型
|
||||
inventoryLog.setLogType(InventoryLogEnum.OUTBOUND.getValue());
|
||||
// 出库数量为负数
|
||||
inventoryLog.setBeforeQty(BigDecimalUtil.add(inventory.getQuantity(), changeQty, 0));
|
||||
inventoryLog.setBeforeQty(inventory.getQuantity());
|
||||
inventoryLog.setChangeQty(changeQty.negate());
|
||||
inventoryLog.setAfterQty(inventory.getQuantity());
|
||||
inventoryLog.setAfterQty(BigDecimalUtil.subtract(inventory.getQuantity(), changeQty, 0));
|
||||
inventoryLog.setAfterAllocatedQty(BigDecimal.ZERO);
|
||||
inventoryLog.setBeforeAllocatedQty(BigDecimal.ZERO);
|
||||
inventoryLog.setFromPointId(inventory.getPointId());
|
||||
inventoryLog.setToPointId(dstPointId);
|
||||
addInventoryLog(inventoryLog);
|
||||
}
|
||||
|
||||
|
|
@ -174,6 +176,7 @@ public class InventoryLogServiceImpl extends ServiceImpl<InventoryLogMapper, Inv
|
|||
private InventoryLog buildInventoryLog(Inventory inventory, BigDecimal changeQty, String businessNo, Long businessDetailId, String description) {
|
||||
|
||||
return InventoryLog.builder()
|
||||
.id(IdWorker.getId())
|
||||
.inventoryId(inventory.getId())
|
||||
.itemId(inventory.getItemId())
|
||||
.itemKeyId(inventory.getItemKeyId())
|
||||
|
|
|
|||
|
|
@ -33,6 +33,12 @@ public class ReceiveRecord implements Serializable {
|
|||
@Schema(description = "主键")
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private java.lang.Long id;
|
||||
/**
|
||||
* 入库
|
||||
*/
|
||||
@Schema(description = "入库")
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private java.lang.Long asnId;
|
||||
/**
|
||||
* 入库明细
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -43,6 +43,4 @@ public interface AsnDetailMapper extends BaseMapper<AsnDetail> {
|
|||
@Select("select * from data_asn_detail where stock_id = #{stockId} and status = #{status} ")
|
||||
List<AsnDetail> queryByStockCode(@Param("stockId") Long stockId, @Param("status") Integer status);
|
||||
|
||||
@Select("select MAX(line_no) from data_asn_detail where asn_id = #{asnId} ")
|
||||
Integer queryMaxLineNoByAsnId(@Param("asnId") Long asnId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,4 +4,5 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|||
import org.cpte.modules.receive.entity.ReceiveRecord;
|
||||
|
||||
public interface ReceiveRecordMapper extends BaseMapper<ReceiveRecord> {
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,11 +82,4 @@ public interface IAsnService extends IService<Asn> {
|
|||
*/
|
||||
void receiveAsn(Long asnId, String pointCode);
|
||||
|
||||
/**
|
||||
* 入库任务回传
|
||||
*
|
||||
* @param asn 入库单
|
||||
* @param stock 容器
|
||||
*/
|
||||
void receiveCallback(Asn asn, Stock stock);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@ public class AsnDetailServiceImpl extends ServiceImpl<AsnDetailMapper, AsnDetail
|
|||
public ReceiveRecord buildReceiveRecord(AsnDetail asnDetail, BigDecimal receivedQty, ItemKey itemKey, Long dstPointId) {
|
||||
return ReceiveRecord.builder()
|
||||
.id(IdWorker.getId())
|
||||
.asnId(asnDetail.getAsnId())
|
||||
.asnDetailId(asnDetail.getId())
|
||||
.stockId(asnDetail.getStockId())
|
||||
.fromPointId(asnDetail.getToPointId())
|
||||
|
|
|
|||
|
|
@ -1,43 +1,22 @@
|
|||
package org.cpte.modules.receive.service.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.cpte.modules.base.entity.Item;
|
||||
import org.cpte.modules.base.entity.ItemKey;
|
||||
import org.cpte.modules.base.entity.Point;
|
||||
import org.cpte.modules.base.entity.Stock;
|
||||
import org.cpte.modules.base.mapper.PointMapper;
|
||||
import org.cpte.modules.base.mapper.StockMapper;
|
||||
import org.cpte.modules.base.service.IItemKeyService;
|
||||
import org.cpte.modules.base.service.IPointService;
|
||||
import org.cpte.modules.base.service.IStockService;
|
||||
import org.cpte.modules.constant.GeneralConstant;
|
||||
import org.cpte.modules.constant.enums.AsnStatusEnum;
|
||||
import org.cpte.modules.constant.enums.PickStatusEnum;
|
||||
import org.cpte.modules.inventory.entity.Inventory;
|
||||
import org.cpte.modules.inventory.mapper.InventoryMapper;
|
||||
import org.cpte.modules.inventory.service.IInventoryService;
|
||||
import org.cpte.modules.inventoryLog.entity.InventoryLog;
|
||||
import org.cpte.modules.inventoryLog.service.IInventoryLogService;
|
||||
import org.cpte.modules.receive.entity.Asn;
|
||||
import org.cpte.modules.receive.entity.AsnDetail;
|
||||
import org.cpte.modules.receive.entity.ReceiveRecord;
|
||||
import org.cpte.modules.receive.mapper.AsnDetailMapper;
|
||||
import org.cpte.modules.receive.mapper.AsnMapper;
|
||||
import org.cpte.modules.receive.service.IAsnDetailService;
|
||||
import org.cpte.modules.receive.service.IAsnService;
|
||||
import org.cpte.modules.receive.service.ReceiveProcessor;
|
||||
import org.cpte.modules.receive.service.processor.ReceiveProcessor;
|
||||
import org.cpte.modules.saiWms.request.InboundRequest;
|
||||
import org.cpte.modules.saiWms.request.SMOMRequest;
|
||||
import org.cpte.modules.serialNumber.AsnSerialNumberRule;
|
||||
import org.cpte.modules.utils.BatchUtil;
|
||||
import org.cpte.modules.utils.BigDecimalUtil;
|
||||
import org.cpte.modules.utils.RedisDistributedLockUtil;
|
||||
import org.cpte.modules.utils.SwmsLoginUtil;
|
||||
import org.jeecg.common.system.vo.LoginUser;
|
||||
|
|
@ -50,7 +29,6 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
|
|
@ -89,9 +67,12 @@ public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnS
|
|||
try {
|
||||
lockValue = redissonLock.tryLock(lockKey, 10);
|
||||
if (StringUtils.isEmpty(lockValue)) {
|
||||
throw new RuntimeException("入库处理中,请稍后重试");
|
||||
throw new RuntimeException("入库单创建中,请稍后重试");
|
||||
}
|
||||
processorSaveMain(asn, asnDetailList);
|
||||
} catch (Exception e) {
|
||||
log.error("入库单创建异常", e);
|
||||
throw e;
|
||||
} finally {
|
||||
if (StringUtils.isNotEmpty(lockValue)) {
|
||||
redissonLock.unlock(lockKey, lockValue);
|
||||
|
|
@ -230,7 +211,6 @@ public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnS
|
|||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void receiveAsn(Long asnId, String pointCode) {
|
||||
String lockKey = "asn:" + asnId;
|
||||
|
|
@ -242,121 +222,12 @@ public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnS
|
|||
}
|
||||
receiveProcessor.receiveAsn(asnId, pointCode);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
log.error("收货处理异常", e);
|
||||
throw e;
|
||||
} finally {
|
||||
if (StringUtils.isNotEmpty(lockValue)) {
|
||||
redissonLock.unlock(lockKey, lockValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 入库任务回传JSON
|
||||
*/
|
||||
private String receiveCallbackJson(Asn asn, Stock stock, String ticket) {
|
||||
|
||||
SMOMRequest.Task task = new SMOMRequest.Task();
|
||||
task.setNo(asn.getNo());
|
||||
task.setOrderNo(asn.getThirdOrderNo());
|
||||
task.setState(5);
|
||||
task.setLpn(stock.getStockCode());
|
||||
task.setErpKey(asn.getNo());
|
||||
task.setCode("");
|
||||
task.setName("");
|
||||
task.setInfkey(asn.getNo());
|
||||
task.setIsDelete(false);
|
||||
task.setLastUpdateDate(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
|
||||
|
||||
SMOMRequest.ParameterValue1 parameterValue1 = new SMOMRequest.ParameterValue1();
|
||||
parameterValue1.setValue(List.of(task));
|
||||
|
||||
SMOMRequest.ParameterValue2 parameterValue2 = new SMOMRequest.ParameterValue2();
|
||||
parameterValue2.setValue(1);
|
||||
|
||||
SMOMRequest.Context context = new SMOMRequest.Context();
|
||||
context.setInvOrgId(1);
|
||||
context.setTicket(ticket);
|
||||
|
||||
SMOMRequest saiWmsRequest = new SMOMRequest();
|
||||
saiWmsRequest.setApiType("SmomWebApiController");
|
||||
saiWmsRequest.setParameters(List.of(parameterValue1, parameterValue2));
|
||||
saiWmsRequest.setMethod("AutomatedWarehouseTasks");
|
||||
saiWmsRequest.setContext(context);
|
||||
|
||||
return JSON.toJSONString(saiWmsRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receiveCallback(Asn asn, Stock stock) {
|
||||
|
||||
// 检查接口开关, 未开启则返回
|
||||
if (sysDictMapper.queryByDictCode(GeneralConstant.OPEN_FLAG) == null) {
|
||||
updateAsnDetailResponse(asn, GeneralConstant.SMOM_FAIL_CODE, "接口未开启");
|
||||
return;
|
||||
}
|
||||
|
||||
if (PickStatusEnum.CLOSED.getValue().equals(asn.getStatus())) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Map<String, String> authInfo = swmsLoginUtil.Login();
|
||||
if (authInfo == null || authInfo.isEmpty()) {
|
||||
throw new RuntimeException("登录认证信息为空");
|
||||
}
|
||||
String ticket = authInfo.get("Ticket");
|
||||
String authorization = authInfo.get("authorization");
|
||||
String json = receiveCallbackJson(asn, stock, ticket);
|
||||
String url = openApiMapper.getRequestUrl(GeneralConstant.INBOUND_CALLBACK).getOriginUrl();
|
||||
JSONObject jsonObject = swmsLoginUtil.sendSMOMResponse(json, url, authorization);
|
||||
String code = validateResponse(jsonObject);
|
||||
updateAsnDetailResponse(asn, code, jsonObject.toJSONString());
|
||||
} catch (Exception e) {
|
||||
updateAsnDetailResponse(asn, GeneralConstant.SMOM_FAIL_CODE, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证响应数据
|
||||
*
|
||||
* @param jsonObject 响应数据
|
||||
* @return 状态码
|
||||
*/
|
||||
private String validateResponse(JSONObject jsonObject) {
|
||||
JSONObject data = jsonObject.getJSONObject("data");
|
||||
if (data == null) {
|
||||
throw new RuntimeException("数据格式错误:缺少data字段");
|
||||
}
|
||||
JSONObject Result = data.getJSONObject("Result");
|
||||
if (Result == null) {
|
||||
throw new RuntimeException("数据格式错误:缺少Result字段");
|
||||
}
|
||||
JSONArray jsonArray = Result.getJSONArray("ErpErrorDatas");
|
||||
return jsonArray.isEmpty() ? GeneralConstant.SMOM_SUCCESS_CODE : GeneralConstant.SMOM_FAIL_CODE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新任务状态
|
||||
*
|
||||
* @param asn 入库单
|
||||
* @param code 状态码
|
||||
* @param message 信息
|
||||
*/
|
||||
private void updateAsnDetailResponse(Asn asn, String code, String message) {
|
||||
List<AsnDetail> updateToAsnDetail = new ArrayList<>();
|
||||
if (GeneralConstant.SMOM_SUCCESS_CODE.equals(code)) {
|
||||
asn.setStatus(AsnStatusEnum.CLOSED.getValue());
|
||||
List<AsnDetail> asnDetails = asnDetailMapper.selectByMainId(asn.getId());
|
||||
for (AsnDetail asnDetail : asnDetails) {
|
||||
asnDetail.setStatus(AsnStatusEnum.CLOSED.getValue());
|
||||
updateToAsnDetail.add(asnDetail);
|
||||
}
|
||||
}
|
||||
asn.setResMessage(message);
|
||||
asn.setResTime(new Date());
|
||||
this.baseMapper.updateById(asn);
|
||||
if (CollectionUtils.isNotEmpty(updateToAsnDetail)) {
|
||||
asnDetailMapper.updateById(updateToAsnDetail);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,177 @@
|
|||
package org.cpte.modules.receive.service.processor;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.cpte.modules.base.entity.Stock;
|
||||
import org.cpte.modules.constant.GeneralConstant;
|
||||
import org.cpte.modules.constant.enums.AsnStatusEnum;
|
||||
import org.cpte.modules.constant.enums.InventoryStatusEnum;
|
||||
import org.cpte.modules.constant.enums.PickStatusEnum;
|
||||
import org.cpte.modules.inventory.entity.Inventory;
|
||||
import org.cpte.modules.inventory.mapper.InventoryMapper;
|
||||
import org.cpte.modules.receive.entity.Asn;
|
||||
import org.cpte.modules.receive.entity.AsnDetail;
|
||||
import org.cpte.modules.receive.mapper.AsnDetailMapper;
|
||||
import org.cpte.modules.receive.mapper.AsnMapper;
|
||||
import org.cpte.modules.receive.mapper.ReceiveRecordMapper;
|
||||
import org.cpte.modules.saiWms.request.SMOMRequest;
|
||||
import org.cpte.modules.utils.SwmsLoginUtil;
|
||||
import org.jeecg.modules.openapi.mapper.OpenApiMapper;
|
||||
import org.jeecg.modules.system.mapper.SysDictMapper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 收货回传处理
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class ReceiveBackProcessor {
|
||||
|
||||
@Autowired
|
||||
private AsnMapper asnMapper;
|
||||
|
||||
@Autowired
|
||||
private AsnDetailMapper asnDetailMapper;
|
||||
|
||||
@Autowired
|
||||
private InventoryMapper inventoryMapper;
|
||||
|
||||
@Autowired
|
||||
private OpenApiMapper openApiMapper;
|
||||
|
||||
@Autowired
|
||||
private SysDictMapper sysDictMapper;
|
||||
|
||||
@Autowired
|
||||
private SwmsLoginUtil swmsLoginUtil;
|
||||
|
||||
/**
|
||||
* 入库任务回传JSON
|
||||
*/
|
||||
private String receiveBackJson(Asn asn, Stock stock, String ticket) {
|
||||
|
||||
SMOMRequest.Task task = new SMOMRequest.Task();
|
||||
task.setNo(asn.getNo());
|
||||
task.setOrderNo(asn.getThirdOrderNo());
|
||||
task.setState(5);
|
||||
task.setLpn(stock.getStockCode());
|
||||
task.setErpKey(asn.getNo());
|
||||
task.setCode("");
|
||||
task.setName("");
|
||||
task.setInfkey(asn.getNo());
|
||||
task.setIsDelete(false);
|
||||
task.setLastUpdateDate(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
|
||||
|
||||
SMOMRequest.ParameterValue1 parameterValue1 = new SMOMRequest.ParameterValue1();
|
||||
parameterValue1.setValue(List.of(task));
|
||||
|
||||
SMOMRequest.ParameterValue2 parameterValue2 = new SMOMRequest.ParameterValue2();
|
||||
parameterValue2.setValue(1);
|
||||
|
||||
SMOMRequest.Context context = new SMOMRequest.Context();
|
||||
context.setInvOrgId(1);
|
||||
context.setTicket(ticket);
|
||||
|
||||
SMOMRequest saiWmsRequest = new SMOMRequest();
|
||||
saiWmsRequest.setApiType("SmomWebApiController");
|
||||
saiWmsRequest.setParameters(List.of(parameterValue1, parameterValue2));
|
||||
saiWmsRequest.setMethod("AutomatedWarehouseTasks");
|
||||
saiWmsRequest.setContext(context);
|
||||
|
||||
return JSON.toJSONString(saiWmsRequest);
|
||||
}
|
||||
|
||||
public void receiveBack(Asn asn, Stock stock) {
|
||||
// 检查接口开关, 未开启则返回
|
||||
if (sysDictMapper.queryByDictCode(GeneralConstant.OPEN_FLAG) == null) {
|
||||
updateAsnDetailResponse(asn, stock, GeneralConstant.SMOM_FAIL_CODE, "接口未开启");
|
||||
return;
|
||||
}
|
||||
|
||||
if (PickStatusEnum.CLOSED.getValue().equals(asn.getStatus())) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Map<String, String> authInfo = swmsLoginUtil.Login();
|
||||
if (authInfo == null || authInfo.isEmpty()) {
|
||||
throw new RuntimeException("登录认证信息为空");
|
||||
}
|
||||
String ticket = authInfo.get("Ticket");
|
||||
String authorization = authInfo.get("authorization");
|
||||
String json = receiveBackJson(asn, stock, ticket);
|
||||
String url = openApiMapper.getRequestUrl(GeneralConstant.INBOUND_CALLBACK).getOriginUrl();
|
||||
JSONObject jsonObject = swmsLoginUtil.sendSMOMResponse(json, url, authorization);
|
||||
String code = validateResponse(jsonObject);
|
||||
updateAsnDetailResponse(asn, stock, code, jsonObject.toJSONString());
|
||||
} catch (Exception e) {
|
||||
updateAsnDetailResponse(asn, stock, GeneralConstant.SMOM_FAIL_CODE, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新任务状态
|
||||
*
|
||||
* @param asn 入库单
|
||||
* @param code 状态码
|
||||
* @param message 信息
|
||||
*/
|
||||
private void updateAsnDetailResponse(Asn asn, Stock stock, String code, String message) {
|
||||
List<AsnDetail> updateToAsnDetail = new ArrayList<>();
|
||||
List<Inventory> updateToInventory = new ArrayList<>();
|
||||
if (GeneralConstant.SMOM_SUCCESS_CODE.equals(code)) {
|
||||
asn.setStatus(AsnStatusEnum.CLOSED.getValue());
|
||||
List<AsnDetail> asnDetails = asnDetailMapper.selectByMainId(asn.getId());
|
||||
for (AsnDetail asnDetail : asnDetails) {
|
||||
asnDetail.setStatus(AsnStatusEnum.CLOSED.getValue());
|
||||
updateToAsnDetail.add(asnDetail);
|
||||
}
|
||||
|
||||
//更新库存状态
|
||||
List<Inventory> inventories = inventoryMapper.queryInventoryByStockId(stock.getId());
|
||||
for (Inventory inventory : inventories) {
|
||||
inventory.setStatus(InventoryStatusEnum.AVAILABLE.getValue());
|
||||
updateToInventory.add(inventory);
|
||||
}
|
||||
|
||||
}
|
||||
asn.setResMessage(message);
|
||||
asn.setResTime(new Date());
|
||||
asnMapper.updateById(asn);
|
||||
if (CollectionUtils.isNotEmpty(updateToAsnDetail)) {
|
||||
asnDetailMapper.updateById(updateToAsnDetail);
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(updateToInventory)) {
|
||||
inventoryMapper.updateById(updateToInventory);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证响应数据
|
||||
*
|
||||
* @param jsonObject 响应数据
|
||||
* @return 状态码
|
||||
*/
|
||||
private String validateResponse(JSONObject jsonObject) {
|
||||
JSONObject data = jsonObject.getJSONObject("data");
|
||||
if (data == null) {
|
||||
throw new RuntimeException("数据格式错误:缺少data字段");
|
||||
}
|
||||
JSONObject Result = data.getJSONObject("Result");
|
||||
if (Result == null) {
|
||||
throw new RuntimeException("数据格式错误:缺少Result字段");
|
||||
}
|
||||
JSONArray jsonArray = Result.getJSONArray("ErpErrorDatas");
|
||||
return jsonArray.isEmpty() ? GeneralConstant.SMOM_SUCCESS_CODE : GeneralConstant.SMOM_FAIL_CODE;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package org.cpte.modules.receive.service;
|
||||
package org.cpte.modules.receive.service.processor;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
|
|
@ -12,7 +12,6 @@ import org.cpte.modules.base.service.IPointService;
|
|||
import org.cpte.modules.base.service.IStockService;
|
||||
import org.cpte.modules.constant.enums.AsnStatusEnum;
|
||||
import org.cpte.modules.inventory.entity.Inventory;
|
||||
import org.cpte.modules.inventory.mapper.InventoryMapper;
|
||||
import org.cpte.modules.inventory.service.IInventoryService;
|
||||
import org.cpte.modules.inventoryLog.entity.InventoryLog;
|
||||
import org.cpte.modules.inventoryLog.service.IInventoryLogService;
|
||||
|
|
@ -21,9 +20,8 @@ import org.cpte.modules.receive.entity.AsnDetail;
|
|||
import org.cpte.modules.receive.entity.ReceiveRecord;
|
||||
import org.cpte.modules.receive.mapper.AsnDetailMapper;
|
||||
import org.cpte.modules.receive.mapper.AsnMapper;
|
||||
import org.cpte.modules.receive.service.IAsnDetailService;
|
||||
import org.cpte.modules.receive.vo.ReceiveData;
|
||||
import org.cpte.modules.shipping.entity.Pick;
|
||||
import org.cpte.modules.shipping.vo.AllocationData;
|
||||
import org.cpte.modules.utils.BatchUtil;
|
||||
import org.cpte.modules.utils.BigDecimalUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
|
@ -32,6 +30,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
|
@ -54,9 +53,6 @@ public class ReceiveProcessor {
|
|||
@Autowired
|
||||
private AsnDetailMapper asnDetailMapper;
|
||||
|
||||
@Autowired
|
||||
private InventoryMapper inventoryMapper;
|
||||
|
||||
@Autowired
|
||||
private IStockService stockService;
|
||||
|
||||
|
|
@ -75,6 +71,9 @@ public class ReceiveProcessor {
|
|||
@Autowired
|
||||
private IInventoryLogService inventoryLogService;
|
||||
|
||||
@Autowired
|
||||
private ReceiveBackProcessor receiveBackProcessor;
|
||||
|
||||
@Autowired
|
||||
private BatchUtil batchUtil;
|
||||
|
||||
|
|
@ -88,20 +87,17 @@ public class ReceiveProcessor {
|
|||
// 1.数据准备
|
||||
ReceiveData data = prepareReceiveData(asnId, dstPointCode);
|
||||
|
||||
//2.验证托盘
|
||||
// validateStock(data.getStock());
|
||||
|
||||
//3.创建数据结构
|
||||
List<AsnDetail> updateToAsnDetail = new ArrayList<>();
|
||||
List<ReceiveRecord> createToReceiveRecord = new ArrayList<>();
|
||||
List<Inventory> createToInventory = new ArrayList<>();
|
||||
List<InventoryLog> createToInventoryLog = new ArrayList<>();
|
||||
List<ReceiveRecord> createRecords = new ArrayList<>();
|
||||
Map<Long, Inventory> inventoryMap = new HashMap<>();
|
||||
List<InventoryLog> createInventoryLogs = new ArrayList<>();
|
||||
|
||||
//4.处理数据
|
||||
receive(data, updateToAsnDetail, createToReceiveRecord, createToInventory, createToInventoryLog);
|
||||
receive(data, updateToAsnDetail, createRecords, inventoryMap, createInventoryLogs);
|
||||
|
||||
//5.批量操作
|
||||
batchOperation(updateToAsnDetail, createToReceiveRecord, createToInventory, createToInventoryLog);
|
||||
batchOperation(updateToAsnDetail, createRecords, inventoryMap, createInventoryLogs);
|
||||
|
||||
//6.刷新入库
|
||||
refreshData(data);
|
||||
|
|
@ -110,6 +106,7 @@ public class ReceiveProcessor {
|
|||
updateStockAndPoint(data.getStock(), data.getDstPoint());
|
||||
|
||||
//8.回传
|
||||
receiveBackProcessor.receiveBack(data.getAsn(), data.getStock());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -137,36 +134,29 @@ public class ReceiveProcessor {
|
|||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证托盘
|
||||
*
|
||||
* @param stock 托盘
|
||||
*/
|
||||
private void validateStock(Stock stock) {
|
||||
if (inventoryMapper.exitsStockInventory(stock.getId()) != null) {
|
||||
throw new RuntimeException("【" + stock.getStockCode() + "】托盘已入库");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理数据
|
||||
*
|
||||
* @param data 数据
|
||||
* @param updateToAsnDetail 更新入库单明细
|
||||
* @param createToReceiveRecord 创建收货记录
|
||||
* @param createToInventory 创建库存
|
||||
* @param createToInventoryLog 创建库存日志
|
||||
* @param data 数据
|
||||
* @param updateToAsnDetail 更新入库单明细
|
||||
* @param records 创建收货记录
|
||||
* @param inventoryMap 创建库存
|
||||
* @param inventoryLogs 创建库存日志
|
||||
*/
|
||||
private void receive(ReceiveData data,
|
||||
List<AsnDetail> updateToAsnDetail,
|
||||
List<ReceiveRecord> createToReceiveRecord,
|
||||
List<Inventory> createToInventory,
|
||||
List<InventoryLog> createToInventoryLog) {
|
||||
List<ReceiveRecord> records,
|
||||
Map<Long, Inventory> inventoryMap,
|
||||
List<InventoryLog> inventoryLogs) {
|
||||
Asn asn = data.getAsn();
|
||||
Point dstPoint = data.getDstPoint();
|
||||
Stock stock = data.getStock();
|
||||
for (AsnDetail asnDetail : data.getAsnDetails()) {
|
||||
BigDecimal receivedQty = BigDecimalUtil.add(asnDetail.getReceivedQty(), asnDetail.getOrderQty(), 0);
|
||||
BigDecimal unreceivedQty = BigDecimalUtil.subtract(asnDetail.getOrderQty(), asnDetail.getReceivedQty(), 0);
|
||||
if (unreceivedQty.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
continue;
|
||||
}
|
||||
BigDecimal receivedQty = BigDecimalUtil.add(asnDetail.getReceivedQty(), unreceivedQty, 0);
|
||||
asnDetail.setReceivedQty(receivedQty);
|
||||
//更新明细状态
|
||||
if (receivedQty.compareTo(asnDetail.getOrderQty()) >= 0) {
|
||||
|
|
@ -181,39 +171,62 @@ public class ReceiveProcessor {
|
|||
|
||||
//生成入库记录
|
||||
ReceiveRecord receiveRecord = asnDetailService.buildReceiveRecord(asnDetail, receivedQty, itemKey, dstPoint.getId());
|
||||
createToReceiveRecord.add(receiveRecord);
|
||||
records.add(receiveRecord);
|
||||
|
||||
// 生成库存
|
||||
Inventory inventory = inventoryService.buildInventory(stock.getId(), receivedQty, asn, receiveRecord);
|
||||
createToInventory.add(inventory);
|
||||
Inventory inventory = createInventory(asn, receiveRecord, itemKey, stock, receivedQty, inventoryMap);
|
||||
|
||||
//添加库存日志
|
||||
InventoryLog inventoryLog = inventoryLogService.buildInboundInventoryLog(inventory, asnDetail.getToPointId(), receivedQty, asn.getOrderNo(), asnDetail.getId(), asnDetail.getDescription());
|
||||
createToInventoryLog.add(inventoryLog);
|
||||
InventoryLog inventoryLog = inventoryLogService.buildInboundInventoryLog(inventory, asnDetail.getToPointId(),receivedQty, asn.getThirdOrderNo(), receiveRecord.getId(), receiveRecord.getDescription());
|
||||
inventoryLogs.add(inventoryLog);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建库存
|
||||
*
|
||||
* @param asn 入库单
|
||||
* @param receiveRecord 收货记录
|
||||
* @param itemKey 物料属性
|
||||
* @param stock 容器
|
||||
* @param receivedQty 收货数量
|
||||
* @param inventoryMap 创建库存
|
||||
*/
|
||||
private Inventory createInventory(Asn asn, ReceiveRecord receiveRecord, ItemKey itemKey, Stock stock, BigDecimal receivedQty, Map<Long, Inventory> inventoryMap) {
|
||||
Inventory inventory = inventoryService.buildInventory(stock.getId(), BigDecimal.ZERO, asn, receiveRecord);
|
||||
//根据itemKey更新库存
|
||||
Inventory targetInventory = inventoryMap.getOrDefault(itemKey.getId(), inventory);
|
||||
BigDecimal newReceivedQty = BigDecimalUtil.add(targetInventory.getQuantity(), receivedQty, 0);
|
||||
targetInventory.setQuantity(newReceivedQty);
|
||||
inventoryMap.put(targetInventory.getItemKeyId(), targetInventory);
|
||||
return targetInventory;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 批量操作
|
||||
*
|
||||
* @param updateToAsnDetail 更新入库单明细
|
||||
* @param createToReceiveRecord 创建收货记录
|
||||
* @param createToInventory 创建库存
|
||||
* @param createToInventoryLog 创建库存日志
|
||||
* @param updateToAsnDetail 更新入库单明细
|
||||
* @param records 创建收货记录
|
||||
* @param inventoryMap 创建库存
|
||||
* @param inventoryLogs 创建库存日志
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void batchOperation( List<AsnDetail> updateToAsnDetail,List<ReceiveRecord> createToReceiveRecord , List<Inventory> createToInventory, List<InventoryLog> createToInventoryLog) {
|
||||
public void batchOperation(List<AsnDetail> updateToAsnDetail, List<ReceiveRecord> records,
|
||||
Map<Long, Inventory> inventoryMap, List<InventoryLog> inventoryLogs) {
|
||||
if (CollectionUtils.isNotEmpty(updateToAsnDetail)) {
|
||||
batchUtil.updateBatchAsnDetail(updateToAsnDetail);
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(createToReceiveRecord)) {
|
||||
batchUtil.saveBatchReceiveRecord(createToReceiveRecord);
|
||||
if (CollectionUtils.isNotEmpty(records)) {
|
||||
batchUtil.saveBatchReceiveRecord(records);
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(createToInventory)) {
|
||||
if (inventoryMap != null && !inventoryMap.isEmpty()) {
|
||||
List<Inventory> createToInventory = new ArrayList<>(inventoryMap.values());
|
||||
batchUtil.saveBatchInventory(createToInventory);
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(createToInventoryLog)) {
|
||||
batchUtil.saveBatchInventoryLog(createToInventoryLog);
|
||||
if (CollectionUtils.isNotEmpty(inventoryLogs)) {
|
||||
batchUtil.saveBatchInventoryLog(inventoryLogs);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -229,7 +242,7 @@ public class ReceiveProcessor {
|
|||
/**
|
||||
* 更新容器状态和位置
|
||||
*
|
||||
* @param stock 托盘
|
||||
* @param stock 托盘
|
||||
* @param dstPoint 目标库位
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
|
|
@ -4,6 +4,7 @@ import io.swagger.v3.oas.annotations.Operation;
|
|||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.cpte.modules.saiWms.request.CallAgvRequest;
|
||||
import org.cpte.modules.saiWms.request.InboundRequest;
|
||||
import org.cpte.modules.saiWms.request.OutboundRequest;
|
||||
import org.cpte.modules.saiWms.request.SyncStockRequest;
|
||||
|
|
@ -38,6 +39,14 @@ public class SaiWmsController {
|
|||
return Result.OK("操作成功!");
|
||||
}
|
||||
|
||||
@AutoLog(value = "呼叫AGV")
|
||||
@Operation(summary = "赛意WMS-呼叫AGV")
|
||||
@PostMapping(value = "/callAgv")
|
||||
public Result<String> callAgv(@RequestBody CallAgvRequest callAgvRequest) {
|
||||
iSaiWmsService.callAgv(callAgvRequest);
|
||||
return Result.OK("操作成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 入库任务下发
|
||||
*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
package org.cpte.modules.saiWms.request;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class CallAgvRequest {
|
||||
// 托盘号
|
||||
@JsonProperty("stockCode")
|
||||
private String stockCode;
|
||||
|
||||
// 起点
|
||||
@JsonProperty("fromCode")
|
||||
private String fromCode;
|
||||
|
||||
//终点
|
||||
@JsonProperty("toCode")
|
||||
private String toCode;
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package org.cpte.modules.saiWms.service;
|
||||
|
||||
import org.cpte.modules.saiWms.request.CallAgvRequest;
|
||||
import org.cpte.modules.saiWms.request.InboundRequest;
|
||||
import org.cpte.modules.saiWms.request.OutboundRequest;
|
||||
import org.cpte.modules.saiWms.request.SyncStockRequest;
|
||||
|
|
@ -24,4 +25,9 @@ public interface ISMOMService {
|
|||
* 容器同步
|
||||
*/
|
||||
void syncStock(SyncStockRequest syncStockRequest);
|
||||
|
||||
/**
|
||||
* 呼叫AGV
|
||||
*/
|
||||
void callAgv(CallAgvRequest callAgvRequest);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,22 @@
|
|||
package org.cpte.modules.saiWms.service.impl;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.cpte.modules.saiWms.request.CallAgvRequest;
|
||||
import org.cpte.modules.saiWms.request.InboundRequest;
|
||||
import org.cpte.modules.saiWms.request.OutboundRequest;
|
||||
import org.cpte.modules.saiWms.request.SyncStockRequest;
|
||||
import org.cpte.modules.saiWms.service.ISMOMService;
|
||||
import org.cpte.modules.saiWms.service.InBoundTaskProcessor;
|
||||
import org.cpte.modules.saiWms.service.OutBoundTaskProcessor;
|
||||
import org.cpte.modules.saiWms.service.SyncStockProcessor;
|
||||
import org.cpte.modules.saiWms.service.processor.CallAgvProcessor;
|
||||
import org.cpte.modules.saiWms.service.processor.InBoundTaskProcessor;
|
||||
import org.cpte.modules.saiWms.service.processor.OutBoundTaskProcessor;
|
||||
import org.cpte.modules.saiWms.service.processor.SyncStockProcessor;
|
||||
import org.cpte.modules.utils.RedisDistributedLockUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class ISMOMServiceImpl implements ISMOMService {
|
||||
|
||||
@Autowired
|
||||
|
|
@ -22,6 +28,11 @@ public class ISMOMServiceImpl implements ISMOMService {
|
|||
@Autowired
|
||||
private SyncStockProcessor syncStockProcessor;
|
||||
|
||||
@Autowired
|
||||
private CallAgvProcessor callAgvProcessor;
|
||||
|
||||
@Autowired
|
||||
private RedisDistributedLockUtil redissonLock;
|
||||
|
||||
@Override
|
||||
public void inBoundTask(InboundRequest inboundRequest) {
|
||||
|
|
@ -37,6 +48,26 @@ public class ISMOMServiceImpl implements ISMOMService {
|
|||
public void syncStock(SyncStockRequest syncStockRequest) {
|
||||
syncStockProcessor.syncStock(syncStockRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void callAgv(CallAgvRequest callAgvRequest) {
|
||||
String lockKey = "stock:" + callAgvRequest.getStockCode();
|
||||
String lockValue = null;
|
||||
try {
|
||||
lockValue = redissonLock.tryLock(lockKey, 10);
|
||||
if (StringUtils.isEmpty(lockValue)) {
|
||||
throw new RuntimeException("AGV呼叫中,请稍后重试");
|
||||
}
|
||||
callAgvProcessor.callAgv(callAgvRequest);
|
||||
} catch (Exception e) {
|
||||
log.error("AGV呼叫异常", e);
|
||||
throw e;
|
||||
} finally {
|
||||
if (StringUtils.isNotEmpty(lockValue)) {
|
||||
redissonLock.unlock(lockKey, lockValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,97 @@
|
|||
package org.cpte.modules.saiWms.service.processor;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.cpte.modules.agvTask.mapper.AgvTaskMapper;
|
||||
import org.cpte.modules.agvTask.service.IAgvTaskService;
|
||||
import org.cpte.modules.base.entity.Point;
|
||||
import org.cpte.modules.base.entity.Stock;
|
||||
import org.cpte.modules.base.service.IPointService;
|
||||
import org.cpte.modules.base.service.IStockService;
|
||||
import org.cpte.modules.constant.enums.AgvVendorEnum;
|
||||
import org.cpte.modules.constant.enums.AsnOrderTypeEnum;
|
||||
import org.cpte.modules.constant.enums.BusinessTypeEnum;
|
||||
import org.cpte.modules.saiWms.request.CallAgvRequest;
|
||||
import org.cpte.modules.saiWms.request.InboundRequest;
|
||||
import org.cpte.modules.saiWms.vo.CallData;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 呼叫AGV处理
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class CallAgvProcessor {
|
||||
|
||||
@Autowired
|
||||
private AgvTaskMapper agvTaskMapper;
|
||||
|
||||
@Autowired
|
||||
private IStockService stockService;
|
||||
|
||||
@Autowired
|
||||
private IPointService pointService;
|
||||
|
||||
@Autowired
|
||||
private IAgvTaskService agvTaskService;
|
||||
|
||||
public void callAgv(CallAgvRequest callAgvRequest) {
|
||||
// 1.参数校验
|
||||
validateParams(callAgvRequest);
|
||||
|
||||
//2.数据准备
|
||||
CallData callData = validateData(callAgvRequest);
|
||||
|
||||
//3.生成AGV任务
|
||||
generateAgvTask(callData);
|
||||
}
|
||||
|
||||
/**
|
||||
* 呼叫参数校验
|
||||
*
|
||||
* @param callAgvRequest 呼叫参数
|
||||
*/
|
||||
private void validateParams(CallAgvRequest callAgvRequest) {
|
||||
if (StringUtils.isBlank(callAgvRequest.getStockCode())) {
|
||||
throw new RuntimeException("托盘号(stockCode)必填");
|
||||
}
|
||||
if (StringUtils.isBlank(callAgvRequest.getFromCode())) {
|
||||
throw new RuntimeException("起点(fromCode)必填");
|
||||
}
|
||||
if (StringUtils.isBlank(callAgvRequest.getToCode())) {
|
||||
throw new RuntimeException("终点(toCode)必填");
|
||||
}
|
||||
}
|
||||
|
||||
private CallData validateData(CallAgvRequest callAgvRequest) {
|
||||
CallData callData = new CallData();
|
||||
//1.获取托盘
|
||||
Stock stock = stockService.validateStock(callAgvRequest.getStockCode());
|
||||
callData.setStock(stock);
|
||||
|
||||
//2.获取起点
|
||||
Point fromPoint = pointService.validatePoint(callAgvRequest.getFromCode());
|
||||
callData.setFromPoint(fromPoint);
|
||||
|
||||
callData.setToCode(callAgvRequest.getToCode());
|
||||
return callData;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成AGV任务
|
||||
*
|
||||
* @param callData 呼叫参数
|
||||
*/
|
||||
private void generateAgvTask(CallData callData) {
|
||||
String stockCode = callData.getStock().getStockCode();
|
||||
if (agvTaskMapper.existsByStockCode(stockCode, AgvVendorEnum.HIK.getValue()) != null) {
|
||||
throw new RuntimeException("【" + stockCode + "】容器已生成AGV任务,请勿重复操作! ");
|
||||
}
|
||||
agvTaskService.createAgvTask(null, stockCode, callData.getFromPoint().getPointCode(), callData.getToCode(), null, BusinessTypeEnum.TRANSPORT.getValue(), 0, AgvVendorEnum.HIK.getValue());
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package org.cpte.modules.saiWms.service;
|
||||
package org.cpte.modules.saiWms.service.processor;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package org.cpte.modules.saiWms.service;
|
||||
package org.cpte.modules.saiWms.service.processor;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package org.cpte.modules.saiWms.service;
|
||||
package org.cpte.modules.saiWms.service.processor;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package org.cpte.modules.saiWms.vo;
|
||||
|
||||
import lombok.Data;
|
||||
import org.cpte.modules.base.entity.Point;
|
||||
import org.cpte.modules.base.entity.Stock;
|
||||
|
||||
@Data
|
||||
public class CallData {
|
||||
private Stock stock;
|
||||
private Point fromPoint;
|
||||
private String toCode;
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ import org.cpte.modules.constant.GeneralConstant;
|
|||
import org.cpte.modules.serialNumber.PickSerialNumberRule;
|
||||
import org.cpte.modules.shipping.entity.Task;
|
||||
import org.cpte.modules.shipping.service.ITaskService;
|
||||
import org.jeecg.common.system.query.QueryRuleEnum;
|
||||
import org.jeecgframework.poi.excel.ExcelImportUtil;
|
||||
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
|
||||
import org.jeecgframework.poi.excel.entity.ExportParams;
|
||||
|
|
@ -80,6 +81,8 @@ public class PickController {
|
|||
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
|
||||
HttpServletRequest req) {
|
||||
QueryWrapper<Pick> queryWrapper = QueryGenerator.initQueryWrapper(pick, req.getParameterMap());
|
||||
List<String> status = Arrays.stream(req.getParameterMap().get("status[]")).toList();
|
||||
queryWrapper.in("status", status);
|
||||
Page<Pick> page = new Page<Pick>(pageNo, pageSize);
|
||||
IPage<Pick> pageList = pickService.page(page, queryWrapper);
|
||||
return Result.OK(pageList);
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
|||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import lombok.*;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import org.jeecg.common.aspect.annotation.Dict;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.jeecgframework.poi.excel.annotation.Excel;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
|
|
|||
|
|
@ -30,6 +30,14 @@ public interface IPickDetailService extends IService<PickDetail> {
|
|||
*/
|
||||
Map<Long, Pick> queryByPickIdsToMap(List<Long> pickIds);
|
||||
|
||||
/**
|
||||
* 根据出库单明细ID查询出库单明细Map
|
||||
*
|
||||
* @param pickDetailIds 出库单明细ID集合
|
||||
* @return Map<Long, PickDetail>
|
||||
*/
|
||||
Map<Long, PickDetail> queryByPickDetailIdsToMap(List<Long> pickDetailIds);
|
||||
|
||||
|
||||
/**
|
||||
* 刷新出库单
|
||||
|
|
|
|||
|
|
@ -89,17 +89,6 @@ public interface IPickService extends IService<Pick> {
|
|||
*
|
||||
* @param tasks 任务
|
||||
*/
|
||||
void pickTask(List<Task> tasks, Point endPoint);
|
||||
|
||||
/**
|
||||
* 出库任务回传
|
||||
*
|
||||
* @param pick 出库单
|
||||
* @param pickDetail 出库明细
|
||||
* @param task 出库任务
|
||||
* @param state 回传状态 最后一托任务给完工。5,其余执行中.7
|
||||
*/
|
||||
void pickTaskCallback(Pick pick, PickDetail pickDetail, Task task, Integer state);
|
||||
|
||||
void pickTask(List<Task> tasks);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,12 +58,10 @@ public interface ITaskService extends IService<Task> {
|
|||
void generateAgvTask();
|
||||
|
||||
/**
|
||||
* 根据需要移位的库位生成Task任务
|
||||
* 根据主表ID查询任务
|
||||
*
|
||||
* @param movePointIds 库位
|
||||
* @return Task
|
||||
* @param id 主表ID
|
||||
* @return List<Task>
|
||||
*/
|
||||
List<Task> bulidMoveTask(List<Long> movePointIds);
|
||||
|
||||
List<Task> queryTaskByMainId(Long id);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,7 +49,26 @@ public class PickDetailServiceImpl extends ServiceImpl<PickDetailMapper, PickDet
|
|||
return pickMap;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* 获取出库单明细Map
|
||||
*
|
||||
* @param pickDetailIds 出库单明细id
|
||||
* @return 出库单明细Map
|
||||
*/
|
||||
public Map<Long, PickDetail> queryByPickDetailIdsToMap(List<Long> pickDetailIds) {
|
||||
if (CollectionUtils.isEmpty(pickDetailIds)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
Map<Long, PickDetail> pickDetailMap = new HashMap<>();
|
||||
List<PickDetail> pickDetails = this.baseMapper.selectByIds(pickDetailIds);
|
||||
for (PickDetail pickDetail : pickDetails) {
|
||||
pickDetailMap.put(pickDetail.getId(), pickDetail);
|
||||
}
|
||||
return pickDetailMap;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 刷新出库单状态
|
||||
*
|
||||
* @param pick 出库单
|
||||
|
|
|
|||
|
|
@ -9,13 +9,10 @@ import org.apache.commons.lang3.StringUtils;
|
|||
import org.apache.shiro.SecurityUtils;
|
||||
import org.cpte.modules.constant.GeneralConstant;
|
||||
import org.cpte.modules.base.entity.Item;
|
||||
import org.cpte.modules.base.entity.Point;
|
||||
import org.cpte.modules.constant.enums.*;
|
||||
import org.cpte.modules.inventory.entity.Inventory;
|
||||
import org.cpte.modules.inventory.service.IInventoryService;
|
||||
import org.cpte.modules.inventoryLog.service.IInventoryLogService;
|
||||
import org.cpte.modules.receive.entity.Asn;
|
||||
import org.cpte.modules.receive.entity.AsnDetail;
|
||||
import org.cpte.modules.saiWms.request.OutboundRequest;
|
||||
import org.cpte.modules.saiWms.request.SMOMRequest;
|
||||
import org.cpte.modules.serialNumber.PickSerialNumberRule;
|
||||
|
|
@ -25,10 +22,11 @@ import org.cpte.modules.shipping.entity.Task;
|
|||
import org.cpte.modules.shipping.mapper.PickDetailMapper;
|
||||
import org.cpte.modules.shipping.mapper.PickMapper;
|
||||
import org.cpte.modules.shipping.mapper.TaskMapper;
|
||||
import org.cpte.modules.shipping.service.AllocateProcessor;
|
||||
import org.cpte.modules.shipping.service.CancelAllocateProcessor;
|
||||
import org.cpte.modules.shipping.service.processor.AllocateProcessor;
|
||||
import org.cpte.modules.shipping.service.processor.CancelAllocateProcessor;
|
||||
import org.cpte.modules.shipping.service.IPickDetailService;
|
||||
import org.cpte.modules.shipping.service.IPickService;
|
||||
import org.cpte.modules.shipping.service.processor.PickProcessor;
|
||||
import org.cpte.modules.utils.BatchUtil;
|
||||
import org.cpte.modules.utils.BigDecimalUtil;
|
||||
import org.cpte.modules.utils.RedisDistributedLockUtil;
|
||||
|
|
@ -62,50 +60,20 @@ public class PickServiceImpl extends ServiceImpl<PickMapper, Pick> implements IP
|
|||
@Autowired
|
||||
private PickDetailMapper pickDetailMapper;
|
||||
@Autowired
|
||||
private TaskMapper taskMapper;
|
||||
@Autowired
|
||||
private SysDictMapper sysDictMapper;
|
||||
@Autowired
|
||||
private OpenApiMapper openApiMapper;
|
||||
@Autowired
|
||||
private IPickDetailService pickDetailService;
|
||||
@Autowired
|
||||
private IInventoryService inventoryService;
|
||||
@Autowired
|
||||
private IInventoryLogService inventoryLogService;
|
||||
@Autowired
|
||||
private BaseCommonService baseCommonService;
|
||||
@Autowired
|
||||
private SwmsLoginUtil swmsLoginUtil;
|
||||
@Autowired
|
||||
private BatchUtil batchUtils;
|
||||
@Autowired
|
||||
private PickSerialNumberRule pickSerialNumberRule;
|
||||
@Autowired
|
||||
private AllocateProcessor allocateProcessor;
|
||||
@Autowired
|
||||
private CancelAllocateProcessor cancelAllocateProcessor;
|
||||
@Autowired
|
||||
private PickProcessor pickProcessor;
|
||||
@Autowired
|
||||
private RedisDistributedLockUtil redissonLock;
|
||||
|
||||
/**
|
||||
* 获取出库单明细Map
|
||||
*
|
||||
* @param pickDetailIds 出库单明细id
|
||||
* @return 出库单明细Map
|
||||
*/
|
||||
private Map<Long, PickDetail> queryByPickDetailIdsToMap(List<Long> pickDetailIds) {
|
||||
if (CollectionUtils.isEmpty(pickDetailIds)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
Map<Long, PickDetail> pickDetailMap = new HashMap<>();
|
||||
List<PickDetail> pickDetails = pickDetailMapper.selectByIds(pickDetailIds);
|
||||
for (PickDetail pickDetail : pickDetails) {
|
||||
pickDetailMap.put(pickDetail.getId(), pickDetail);
|
||||
}
|
||||
return pickDetailMap;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void saveMain(Pick pick, List<PickDetail> pickDetailList) {
|
||||
|
|
@ -114,9 +82,12 @@ public class PickServiceImpl extends ServiceImpl<PickMapper, Pick> implements IP
|
|||
try {
|
||||
lockValue = redissonLock.tryLock(lockKey, 10);
|
||||
if (StringUtils.isEmpty(lockValue)) {
|
||||
throw new RuntimeException("出库处理中,请稍后重试");
|
||||
throw new RuntimeException("出库单创建中,请稍后重试");
|
||||
}
|
||||
processorSaveMain(pick, pickDetailList);
|
||||
} catch (Exception e) {
|
||||
log.error("出库单创建异常", e);
|
||||
throw e;
|
||||
} finally {
|
||||
if (StringUtils.isNotEmpty(lockValue)) {
|
||||
redissonLock.unlock(lockKey, lockValue);
|
||||
|
|
@ -281,222 +252,8 @@ public class PickServiceImpl extends ServiceImpl<PickMapper, Pick> implements IP
|
|||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void pickTask(List<Task> tasks, Point endPoint) {
|
||||
|
||||
// ================= 1. 数据准备 (批量查询) =================
|
||||
// 1.1 获取出库单
|
||||
List<Long> pickIds = tasks.stream().map(Task::getPickId).distinct().toList();
|
||||
List<Long> pickDetailIds = tasks.stream().map(Task::getPickDetailId).distinct().toList();
|
||||
List<Long> inventoryIds = tasks.stream().map(Task::getInventoryId).distinct().toList();
|
||||
|
||||
// 1.2 构建映射 Map
|
||||
Map<Long, Pick> pickMap = pickDetailService.queryByPickIdsToMap(pickIds);
|
||||
Map<Long, PickDetail> pickDetailMap = queryByPickDetailIdsToMap(pickDetailIds);
|
||||
Map<Long, Inventory> inventoryMap = inventoryService.queryByInventoryIdsToMap(inventoryIds);
|
||||
|
||||
// -------------------------- 2. 创建更新列表---------------------------
|
||||
List<PickDetail> updateToPickDetail = new ArrayList<>();
|
||||
List<Task> updateToTask = new ArrayList<>();
|
||||
List<Inventory> updateToInventory = new ArrayList<>();
|
||||
List<Long> deleteToInventoryIds = new ArrayList<>();
|
||||
|
||||
// -------------------------- 3. 循环拣货 -------------------
|
||||
for (Task task : tasks) {
|
||||
BigDecimal pickedQty = BigDecimalUtil.subtract(task.getPlanQty(), task.getMoveQty(), 0);
|
||||
if (pickedQty.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
continue;
|
||||
}
|
||||
Pick pick = pickMap.get(task.getPickId());
|
||||
PickDetail pickDetail = pickDetailMap.get(task.getPickDetailId());
|
||||
|
||||
// 更新拣货数量,状态
|
||||
pickDetail.setPickedQty(BigDecimalUtil.add(pickDetail.getPickedQty(), pickedQty, 0));
|
||||
Integer status = pickedQty.compareTo(pickDetail.getOrderQty()) >= 0 ? PickStatusEnum.PICKED.getValue() : PickStatusEnum.PICKING.getValue();
|
||||
pickDetail.setStatus(status);
|
||||
updateToPickDetail.add(pickDetail);
|
||||
|
||||
// 更新任务
|
||||
task.setMoveQty(pickedQty);
|
||||
task.setTaskStatus(TaskStatusEnum.COMPLETED.getValue());
|
||||
updateToTask.add(task);
|
||||
|
||||
//扣减库存
|
||||
Inventory inventory = inventoryMap.get(task.getInventoryId());
|
||||
inventory.setQuantity(BigDecimalUtil.subtract(inventory.getQuantity(), pickedQty, 0));
|
||||
inventory.setQueuedQty(BigDecimalUtil.subtract(inventory.getQueuedQty(), pickedQty, 0));
|
||||
inventory.setPointId(endPoint.getId());
|
||||
updateToInventory.add(inventory);
|
||||
|
||||
//库存为0,删除库存
|
||||
if (inventory.getQuantity().compareTo(BigDecimal.ZERO) <= 0) {
|
||||
deleteToInventoryIds.add(inventory.getId());
|
||||
}
|
||||
|
||||
inventoryLogService.addPickInventoryLog(inventory, pickedQty, pick.getOrderNo(), task.getPickDetailId(), null);
|
||||
}
|
||||
|
||||
// -------------------------- 4. 批量操作 --------------------------
|
||||
if (CollectionUtils.isNotEmpty(updateToPickDetail)) {
|
||||
batchUtils.updateBatchPickDetail(updateToPickDetail);
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(updateToTask)) {
|
||||
batchUtils.updateBatchTask(updateToTask);
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(updateToInventory)) {
|
||||
batchUtils.updateBatchInventory(updateToInventory);
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(deleteToInventoryIds)) {
|
||||
inventoryService.removeByIds(deleteToInventoryIds);
|
||||
}
|
||||
|
||||
// -------------------------- 6. 出库回传 --------------------------
|
||||
Map<Long, List<PickDetail>> pickDetailsCache = new HashMap<>();
|
||||
for (Task task : tasks) {
|
||||
Pick pick = pickMap.get(task.getPickId());
|
||||
PickDetail pickDetail = pickDetailMap.get(task.getPickDetailId());
|
||||
|
||||
// 缓存查询结果,避免重复查询
|
||||
Long pickId = pick.getId();
|
||||
List<PickDetail> pickDetails = pickDetailsCache.computeIfAbsent(pickId,
|
||||
id -> pickDetailMapper.selectByMainId(id));
|
||||
|
||||
List<PickDetail> closedPickDetails = pickDetails.stream()
|
||||
.filter(detail -> PickStatusEnum.CLOSED.getValue().equals(detail.getStatus()))
|
||||
.toList();
|
||||
|
||||
int state = pickDetails.size() - closedPickDetails.size() == 1 ? 5 : 7;
|
||||
|
||||
try {
|
||||
pickTaskCallback(pick, pickDetail, task, state);
|
||||
} catch (Exception e) {
|
||||
log.error("出库任务回传失败,任务ID: {}, 错误信息: {}", task.getId(), e.getMessage(), e);
|
||||
}
|
||||
|
||||
// 刷新时重新查询最新的数据
|
||||
List<PickDetail> latestPickDetails = pickDetailMapper.selectByMainId(pick.getId());
|
||||
pickDetailsCache.put(pickId, latestPickDetails); // 更新缓存
|
||||
pickDetailService.refreshPick(pick, latestPickDetails);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 出库库任务回传JSON
|
||||
*/
|
||||
private String pickTaskCallbackJson(Pick pick, PickDetail pickDetail, Task task, Integer state, String ticket) {
|
||||
SMOMRequest.Task taskReq = new SMOMRequest.Task();
|
||||
taskReq.setNo(pick.getNo());
|
||||
taskReq.setOrderNo(pick.getThirdOrderNo());
|
||||
taskReq.setState(state);
|
||||
|
||||
SMOMRequest.ShipmentFeedbackDetail shipmentFeedbackDetail = new SMOMRequest.ShipmentFeedbackDetail();
|
||||
shipmentFeedbackDetail.setLineNo(String.valueOf(pickDetail.getLineNo()));
|
||||
shipmentFeedbackDetail.setLpn(task.getStockCode());
|
||||
shipmentFeedbackDetail.setQty(task.getPlanQty().intValue());
|
||||
shipmentFeedbackDetail.setIsTakeDown(task.getIzAll() == 0);
|
||||
shipmentFeedbackDetail.setProject(pickDetail.getProject());
|
||||
shipmentFeedbackDetail.setTaskNo(pickDetail.getTaskNo());
|
||||
shipmentFeedbackDetail.setLotAtt04(pickDetail.getPropC1());
|
||||
shipmentFeedbackDetail.setLotAtt010(pickDetail.getPropC3());
|
||||
shipmentFeedbackDetail.setErpKey(pick.getNo());
|
||||
shipmentFeedbackDetail.setIsDelete(false);
|
||||
String lastUpdateDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
|
||||
shipmentFeedbackDetail.setLastUpdateDate(lastUpdateDate);
|
||||
taskReq.setShipmentFeedbackDetails(List.of(shipmentFeedbackDetail));
|
||||
|
||||
taskReq.setErpKey(pick.getNo());
|
||||
taskReq.setInfkey(pick.getNo());
|
||||
taskReq.setIsDelete(false);
|
||||
taskReq.setLastUpdateDate(lastUpdateDate);
|
||||
|
||||
|
||||
SMOMRequest.ParameterValue1 parameterValue1 = new SMOMRequest.ParameterValue1();
|
||||
parameterValue1.setValue(List.of(taskReq));
|
||||
|
||||
SMOMRequest.ParameterValue2 parameterValue2 = new SMOMRequest.ParameterValue2();
|
||||
parameterValue2.setValue(1);
|
||||
|
||||
SMOMRequest.Context context = new SMOMRequest.Context();
|
||||
context.setInvOrgId(1);
|
||||
context.setTicket(ticket);
|
||||
|
||||
SMOMRequest saiWmsRequest = new SMOMRequest();
|
||||
saiWmsRequest.setApiType("SmomWebApiController");
|
||||
saiWmsRequest.setParameters(List.of(parameterValue1, parameterValue2));
|
||||
saiWmsRequest.setMethod("OutboundTaskCallbackInterface");
|
||||
saiWmsRequest.setContext(context);
|
||||
|
||||
return JSON.toJSONString(saiWmsRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pickTaskCallback(Pick pick, PickDetail pickDetail, Task task, Integer state) {
|
||||
// 检查接口开关, 未开启则返回
|
||||
if (sysDictMapper.queryByDictCode(GeneralConstant.OPEN_FLAG) == null) {
|
||||
updatePickDetailResponse(pickDetail, task, GeneralConstant.SMOM_FAIL_CODE, "接口未开启");
|
||||
return;
|
||||
}
|
||||
|
||||
if (TaskStatusEnum.CLOSED.getValue().equals(task.getTaskStatus())) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Map<String, String> authInfo = swmsLoginUtil.Login();
|
||||
if (authInfo == null || authInfo.isEmpty()) {
|
||||
throw new RuntimeException("登录认证信息为空");
|
||||
}
|
||||
|
||||
String ticket = authInfo.get("Ticket");
|
||||
String authorization = authInfo.get("authorization");
|
||||
String json = pickTaskCallbackJson(pick, pickDetail, task, state, ticket);
|
||||
String url = openApiMapper.getRequestUrl(GeneralConstant.OUTBOUND_CALLBACK).getOriginUrl();
|
||||
JSONObject jsonObject = swmsLoginUtil.sendSMOMResponse(json, url, authorization);
|
||||
String code = validateResponse(jsonObject);
|
||||
updatePickDetailResponse(pickDetail, task, code, jsonObject.toJSONString());
|
||||
} catch (Exception e) {
|
||||
updatePickDetailResponse(pickDetail, task, GeneralConstant.SMOM_FAIL_CODE, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证响应数据
|
||||
*
|
||||
* @param jsonObject 响应数据
|
||||
* @return 状态码
|
||||
*/
|
||||
private String validateResponse(JSONObject jsonObject) {
|
||||
JSONObject data = jsonObject.getJSONObject("data");
|
||||
if (data == null) {
|
||||
throw new RuntimeException("数据格式错误:缺少data字段");
|
||||
}
|
||||
JSONObject Result = data.getJSONObject("Result");
|
||||
if (Result == null) {
|
||||
throw new RuntimeException("数据格式错误:缺少Result字段");
|
||||
}
|
||||
JSONArray jsonArray = Result.getJSONArray("ErpErrorDatas");
|
||||
return jsonArray.isEmpty() ? GeneralConstant.SMOM_SUCCESS_CODE : GeneralConstant.SMOM_FAIL_CODE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 更新任务状态
|
||||
*
|
||||
* @param task 出库任务
|
||||
* @param message 信息
|
||||
*/
|
||||
private void updatePickDetailResponse(PickDetail pickDetail, Task task, String code, String message) {
|
||||
if (GeneralConstant.SMOM_SUCCESS_CODE.equals(code)) {
|
||||
if (PickStatusEnum.PICKED.getValue().equals(pickDetail.getStatus())) {
|
||||
pickDetail.setStatus(PickStatusEnum.CLOSED.getValue());
|
||||
pickDetailMapper.updateById(pickDetail);
|
||||
}
|
||||
task.setTaskStatus(TaskStatusEnum.CLOSED.getValue());
|
||||
}
|
||||
task.setResMessage(message);
|
||||
task.setResTime(new Date());
|
||||
taskMapper.updateById(task);
|
||||
public void pickTask(List<Task> tasks) {
|
||||
pickProcessor.pick(tasks);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,22 +1,15 @@
|
|||
package org.cpte.modules.shipping.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.cpte.modules.agvTask.entity.AgvTask;
|
||||
import org.cpte.modules.agvTask.service.IAgvTaskService;
|
||||
import org.cpte.modules.base.entity.Item;
|
||||
import org.cpte.modules.base.entity.Point;
|
||||
import org.cpte.modules.base.entity.Stock;
|
||||
import org.cpte.modules.base.mapper.PointMapper;
|
||||
import org.cpte.modules.base.service.IItemService;
|
||||
import org.cpte.modules.base.service.IPointService;
|
||||
import org.cpte.modules.base.service.IStockService;
|
||||
import org.cpte.modules.constant.GeneralConstant;
|
||||
import org.cpte.modules.base.entity.*;
|
||||
import org.cpte.modules.constant.enums.*;
|
||||
import org.cpte.modules.inventory.entity.Inventory;
|
||||
import org.cpte.modules.inventory.mapper.InventoryMapper;
|
||||
import org.cpte.modules.serialNumber.MoveSerialNumberRule;
|
||||
import org.cpte.modules.inventory.service.IInventoryService;
|
||||
import org.cpte.modules.shipping.entity.Task;
|
||||
import org.cpte.modules.shipping.mapper.TaskMapper;
|
||||
import org.cpte.modules.shipping.service.ITaskService;
|
||||
|
|
@ -30,6 +23,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
|
|
@ -43,19 +37,7 @@ import java.util.stream.Collectors;
|
|||
public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements ITaskService {
|
||||
|
||||
@Autowired
|
||||
private PointMapper pointMapper;
|
||||
|
||||
@Autowired
|
||||
private InventoryMapper inventoryMapper;
|
||||
|
||||
@Autowired
|
||||
private IItemService iItemService;
|
||||
|
||||
@Autowired
|
||||
private IPointService iPointService;
|
||||
|
||||
@Autowired
|
||||
private IStockService iStockService;
|
||||
private IInventoryService iInventoryService;
|
||||
|
||||
@Autowired
|
||||
private IAgvTaskService agvTaskService;
|
||||
|
|
@ -63,8 +45,6 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements IT
|
|||
@Autowired
|
||||
private BatchUtil batchUtils;
|
||||
|
||||
@Autowired
|
||||
private MoveSerialNumberRule moveSerialNumberRule;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
|
|
@ -103,7 +83,7 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements IT
|
|||
}
|
||||
|
||||
@Override
|
||||
public Task bulidTask(String taskNo, Integer taskType, Item item, Point fromPoint, Point toPoint, Stock stock, Long pickId, Long pickDetailId,Long itemKeyId, Long inventoryId, BigDecimal planQty, Integer izAll) {
|
||||
public Task bulidTask(String taskNo, Integer taskType, Item item, Point fromPoint, Point toPoint, Stock stock, Long pickId, Long pickDetailId, Long itemKeyId, Long inventoryId, BigDecimal planQty, Integer izAll) {
|
||||
LoginUser sysUser = null;
|
||||
try {
|
||||
sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
||||
|
|
@ -111,6 +91,7 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements IT
|
|||
log.error("获取登录用户信息失败");
|
||||
}
|
||||
return Task.builder()
|
||||
.id(IdWorker.getId())
|
||||
.taskNo(taskNo)
|
||||
.itemId(item.getId())
|
||||
.itemCode(item.getItemCode())
|
||||
|
|
@ -137,14 +118,17 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements IT
|
|||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void generateAgvTask() {
|
||||
|
||||
List<Task> taskList = this.baseMapper.queryUnallocatedTask();
|
||||
if (CollectionUtils.isEmpty(taskList)) {
|
||||
return;
|
||||
}
|
||||
//根据stockCode、fromPointCode、toPointCode 分组
|
||||
//1.获取库存
|
||||
List<Long> inventoryIds = taskList.stream().map(Task::getInventoryId).distinct().toList();
|
||||
Map<Long, Inventory> inventoryMap = iInventoryService.queryByInventoryIdsToMap(inventoryIds);
|
||||
|
||||
//2.根据stockCode、fromPointCode、toPointCode 分组
|
||||
Map<TaskGroupKey, List<Task>> taskGroupMap = taskList.stream()
|
||||
.sorted(Comparator.comparing(Task::getCreateTime))
|
||||
.collect(Collectors.groupingBy(task -> TaskGroupKey.of(
|
||||
|
|
@ -153,7 +137,7 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements IT
|
|||
task.getToPointCode()
|
||||
)));
|
||||
|
||||
//批量创建AGV任务
|
||||
//3.批量创建AGV任务
|
||||
List<AgvTask> createToAgvTaskList = new ArrayList<>();
|
||||
Map<TaskGroupKey, AgvTask> groupToAgvTaskMap = new HashMap<>();
|
||||
for (Map.Entry<TaskGroupKey, List<Task>> entry : taskGroupMap.entrySet()) {
|
||||
|
|
@ -162,8 +146,10 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements IT
|
|||
boolean allSplit = tasks.stream().allMatch(task -> task != null && task.getIzAll() == 1);
|
||||
Integer izAll = allSplit ? 1 : 0;
|
||||
log.info("任务分组:{}", key);
|
||||
String businessType = tasks.get(0).getTaskType() == 1 ? BusinessTypeEnum.OUTBOUND.getValue() : BusinessTypeEnum.MOVE.getValue();
|
||||
|
||||
if (!groupToAgvTaskMap.containsKey(key)) {
|
||||
AgvTask agvTask = agvTaskService.bulidAgvTask(null, key.getStockCode(), key.getFromPointCode(), key.getToPointCode(), null, BusinessTypeEnum.OUTBOUND.getValue(), izAll, AgvVendorEnum.TES.getValue());
|
||||
AgvTask agvTask = agvTaskService.bulidAgvTask(null, key.getStockCode(), key.getFromPointCode(), key.getToPointCode(), null, businessType, izAll, AgvVendorEnum.TES.getValue());
|
||||
createToAgvTaskList.add(agvTask);
|
||||
groupToAgvTaskMap.put(key, agvTask); // 建立映射
|
||||
log.info("创建AGV任务:{}", agvTask);
|
||||
|
|
@ -175,6 +161,7 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements IT
|
|||
|
||||
//批量更新任务
|
||||
List<Task> updateToTaskList = new ArrayList<>();
|
||||
List<Inventory> inventoryList = new ArrayList<>();
|
||||
for (Map.Entry<TaskGroupKey, List<Task>> entry : taskGroupMap.entrySet()) {
|
||||
TaskGroupKey key = entry.getKey();
|
||||
AgvTask agvTask = groupToAgvTaskMap.get(key); // 通过key获取
|
||||
|
|
@ -182,68 +169,30 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements IT
|
|||
for (Task task : list) {
|
||||
task.setAgvTaskId(agvTask.getId());
|
||||
updateToTaskList.add(task);
|
||||
Inventory inventory = inventoryMap.get(task.getInventoryId());
|
||||
if (inventory != null) {
|
||||
Integer status = TaskTypeEnum.PICK.getValue().equals(task.getTaskType()) ? InventoryStatusEnum.OUTBOUND.getValue() : InventoryStatusEnum.MOVE.getValue();
|
||||
inventory.setStatus(status);
|
||||
inventoryList.add(inventory);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(updateToTaskList)) {
|
||||
batchUtils.updateBatchTask(updateToTaskList);
|
||||
}
|
||||
List<Long> inventoryIdList = taskList.stream().map(Task::getInventoryId).distinct().toList();
|
||||
List<Inventory> inventoryList = inventoryMapper.selectByIds(inventoryIdList);
|
||||
for (Inventory inventory : inventoryList) {
|
||||
inventory.setStatus(InventoryStatusEnum.OUTBOUND.getValue());
|
||||
}
|
||||
|
||||
if (CollectionUtils.isNotEmpty(inventoryList)) {
|
||||
batchUtils.updateBatchInventory(inventoryList);
|
||||
Map<Long, Inventory> distinctInventoryMap = inventoryList.stream()
|
||||
.collect(Collectors.toMap(Inventory::getId,
|
||||
Function.identity(), (existing, replacement) -> existing));
|
||||
batchUtils.updateBatchInventory(new ArrayList<>(distinctInventoryMap.values()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Task> bulidMoveTask(List<Long> movePointIds) {
|
||||
List<Task> moveList = new ArrayList<>();
|
||||
List<Inventory> moveInventoryList = inventoryMapper.queryByPointIds(movePointIds);
|
||||
|
||||
//移位物料
|
||||
List<Long> moveItemIds = moveInventoryList.stream().map(Inventory::getItemId).distinct().toList();
|
||||
Map<Long, Item> moveItemMap = iItemService.queryByItemIdsToMap(moveItemIds);
|
||||
|
||||
//移位库位
|
||||
List<Long> fromPointIds = moveInventoryList.stream().map(Inventory::getPointId).distinct().toList();
|
||||
Map<Long, Point> fromPointMap = iPointService.queryByPointIdsToMap(fromPointIds);
|
||||
|
||||
//移位容器
|
||||
List<Long> stockIds = moveInventoryList.stream().map(Inventory::getStockId).distinct().toList();
|
||||
Map<Long, Stock> stockMap = iStockService.queryByStockIdsToMap(stockIds);
|
||||
|
||||
for (Inventory inv : moveInventoryList) {
|
||||
|
||||
//判读改点位是否有出库任务
|
||||
Item moveItem = moveItemMap.get(inv.getItemId());
|
||||
Point fromPoint = fromPointMap.get(inv.getPointId());
|
||||
Stock stock = stockMap.get(inv.getStockId());
|
||||
String taskNo = moveSerialNumberRule.generateSerialNumber(GeneralConstant.MOVE_ORDER_NO);
|
||||
//根据算法找到最优的目标库位
|
||||
Point toPoint=null;
|
||||
Task moveTask = this.bulidTask(taskNo, TaskTypeEnum.MOVE.getValue(), moveItem, fromPoint, toPoint, stock, null, null,inv.getItemKeyId(), inv.getId(), inv.getQuantity(), 0);
|
||||
moveList.add(moveTask);
|
||||
log.info("生成移位任务:{}- 容器:{} - 库位:{} - 库存数量:{}", taskNo, stock.getStockCode(), fromPoint.getPointCode(), inv.getQuantity());
|
||||
inv.setStatus(InventoryStatusEnum.TRANSFER.getValue());
|
||||
inventoryMapper.updateById(inv);
|
||||
}
|
||||
return moveList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Task> queryTaskByMainId(Long id) {
|
||||
return this.baseMapper.queryTaskByMainId(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 选择最优移位目标
|
||||
*/
|
||||
private Point findBestMovePoint(){
|
||||
// 1. 获取所有可用库位
|
||||
//List<Point> availablePoints = pointMapper.queryPoints(null, CommonStatusEnum.FREE.getValue(), areaCode);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,24 +1,28 @@
|
|||
package org.cpte.modules.shipping.service;
|
||||
package org.cpte.modules.shipping.service.processor;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.cpte.modules.base.entity.Item;
|
||||
import org.cpte.modules.base.entity.ItemKey;
|
||||
import org.cpte.modules.base.entity.Point;
|
||||
import org.cpte.modules.base.entity.Stock;
|
||||
import org.cpte.modules.base.entity.*;
|
||||
import org.cpte.modules.base.mapper.AreaMapper;
|
||||
import org.cpte.modules.base.mapper.ItemKeyMapper;
|
||||
import org.cpte.modules.base.service.IItemKeyService;
|
||||
import org.cpte.modules.base.service.IItemService;
|
||||
import org.cpte.modules.base.service.IPointService;
|
||||
import org.cpte.modules.base.service.IStockService;
|
||||
import org.cpte.modules.constant.GeneralConstant;
|
||||
import org.cpte.modules.constant.enums.*;
|
||||
import org.cpte.modules.conveyorLine.service.processor.ScanTrayProcessor;
|
||||
import org.cpte.modules.inventory.entity.Inventory;
|
||||
import org.cpte.modules.inventory.mapper.InventoryMapper;
|
||||
import org.cpte.modules.inventoryLog.service.IInventoryLogService;
|
||||
import org.cpte.modules.serialNumber.MoveSerialNumberRule;
|
||||
import org.cpte.modules.shipping.entity.Pick;
|
||||
import org.cpte.modules.shipping.entity.PickDetail;
|
||||
import org.cpte.modules.shipping.entity.Task;
|
||||
import org.cpte.modules.shipping.mapper.PickDetailMapper;
|
||||
import org.cpte.modules.shipping.service.IPickDetailService;
|
||||
import org.cpte.modules.shipping.service.ITaskService;
|
||||
import org.cpte.modules.shipping.vo.AllocationData;
|
||||
import org.cpte.modules.shipping.vo.InventoryScore;
|
||||
import org.cpte.modules.shipping.vo.ItemGroupKey;
|
||||
|
|
@ -28,6 +32,7 @@ import org.cpte.modules.utils.RedisDistributedLockUtil;
|
|||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
|
@ -39,6 +44,9 @@ import java.util.stream.Collectors;
|
|||
@Slf4j
|
||||
public class AllocateProcessor {
|
||||
|
||||
@Autowired
|
||||
private AreaMapper areaMapper;
|
||||
|
||||
@Autowired
|
||||
private PickDetailMapper pickDetailMapper;
|
||||
|
||||
|
|
@ -57,6 +65,9 @@ public class AllocateProcessor {
|
|||
@Autowired
|
||||
private IPointService pointService;
|
||||
|
||||
@Autowired
|
||||
private IItemKeyService itemKeyService;
|
||||
|
||||
@Autowired
|
||||
private IPickDetailService pickDetailService;
|
||||
|
||||
|
|
@ -66,12 +77,19 @@ public class AllocateProcessor {
|
|||
@Autowired
|
||||
private IInventoryLogService inventoryLogService;
|
||||
|
||||
@Autowired
|
||||
private ScanTrayProcessor scanTrayProcessor;
|
||||
|
||||
@Autowired
|
||||
private MoveSerialNumberRule moveSerialNumberRule;
|
||||
|
||||
@Autowired
|
||||
private BatchUtil batchUtil;
|
||||
|
||||
@Autowired
|
||||
private RedisDistributedLockUtil redissonLock;
|
||||
|
||||
|
||||
/**
|
||||
* 分配出库单
|
||||
*
|
||||
|
|
@ -94,14 +112,18 @@ public class AllocateProcessor {
|
|||
Map<Long, Inventory> inventoryUpdateMap = new HashMap<>();
|
||||
Map<Long, PickDetail> pickDetailUpdateMap = new HashMap<>();
|
||||
List<Task> createToTask = new ArrayList<>();
|
||||
List<Point> movePoints = new ArrayList<>();
|
||||
|
||||
//4.分配
|
||||
allocate(data, inventoryUpdateMap, pickDetailUpdateMap, createToTask, errorMsgSet);
|
||||
allocate(data, inventoryUpdateMap, pickDetailUpdateMap, createToTask, movePoints, errorMsgSet);
|
||||
|
||||
//5.批量操作
|
||||
//5.生成移位任务
|
||||
moveTask(createToTask, movePoints);
|
||||
|
||||
//6.批量操作
|
||||
batchOperation(inventoryUpdateMap, pickDetailUpdateMap, createToTask);
|
||||
|
||||
//6.刷新出库单
|
||||
//7.刷新出库单
|
||||
refreshData(data);
|
||||
|
||||
return new ArrayList<>(errorMsgSet);
|
||||
|
|
@ -199,13 +221,12 @@ public class AllocateProcessor {
|
|||
/**
|
||||
* 分配
|
||||
*/
|
||||
private void allocate(AllocationData data, Map<Long, Inventory> inventoryUpdateMap, Map<Long, PickDetail> pickDetailUpdateMap, List<Task> createToTask, Set<String> errorMsgSet) {
|
||||
private void allocate(AllocationData data, Map<Long, Inventory> inventoryUpdateMap, Map<Long, PickDetail> pickDetailUpdateMap, List<Task> createToTask, List<Point> movePoints, Set<String> errorMsgSet) {
|
||||
for (PickDetail pickDetail : data.getPickDetails()) {
|
||||
try {
|
||||
allocatePickDetail(pickDetail, data, errorMsgSet, inventoryUpdateMap, pickDetailUpdateMap, createToTask);
|
||||
allocatePickDetail(pickDetail, data, errorMsgSet, inventoryUpdateMap, pickDetailUpdateMap, createToTask, movePoints);
|
||||
} catch (Exception e) {
|
||||
log.error("分配明细失败,明细ID: {}", pickDetail.getId(), e);
|
||||
errorMsgSet.add(String.format("分配明细失败,明细ID:%s,原因:%s",
|
||||
errorMsgSet.add(String.format("分配异常,明细ID:%s,原因:%s",
|
||||
pickDetail.getId(), e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
|
@ -223,7 +244,7 @@ public class AllocateProcessor {
|
|||
*/
|
||||
private void allocatePickDetail(PickDetail pickDetail, AllocationData data,
|
||||
Set<String> errorMsgSet, Map<Long, Inventory> inventoryUpdateMap,
|
||||
Map<Long, PickDetail> pickDetailUpdateMap, List<Task> createToTask) {
|
||||
Map<Long, PickDetail> pickDetailUpdateMap, List<Task> createToTask, List<Point> movePoints) {
|
||||
|
||||
Pick pick = data.getPickMap().get(pickDetail.getPickId());
|
||||
Item item = data.getItemMap().get(pickDetail.getItemId());
|
||||
|
|
@ -239,21 +260,23 @@ public class AllocateProcessor {
|
|||
return;
|
||||
}
|
||||
|
||||
String lockKey = String.valueOf(pickDetail.getId());
|
||||
// 分配库存
|
||||
String lockKey = "allocate:" + pickDetail.getId();
|
||||
String lockValue = null;
|
||||
try {
|
||||
lockValue = redissonLock.tryLock(lockKey, 10);
|
||||
if (StringUtils.isEmpty(lockValue)) {
|
||||
return;
|
||||
throw new RuntimeException("分配处理中,请稍后重试");
|
||||
}
|
||||
// 分配库存
|
||||
allocateInventory(pickDetail, item, pick, matchedInventories, inventoryUpdateMap, pickDetailUpdateMap,
|
||||
createToTask, data, unAllocatedQty, errorMsgSet);
|
||||
createToTask, movePoints, data, unAllocatedQty, errorMsgSet);
|
||||
} catch (Exception e) {
|
||||
log.error("分配异常,明细ID: {}", pickDetail.getId(), e);
|
||||
throw e;
|
||||
} finally {
|
||||
if (StringUtils.isNotEmpty(lockValue)) {
|
||||
redissonLock.unlock(lockKey, lockValue);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -314,13 +337,12 @@ public class AllocateProcessor {
|
|||
*/
|
||||
private void allocateInventory(PickDetail pickDetail, Item item, Pick pick,
|
||||
List<Inventory> matchedInventories, Map<Long, Inventory> inventoryUpdateMap,
|
||||
Map<Long, PickDetail> pickDetailUpdateMap, List<Task> createToTask,
|
||||
Map<Long, PickDetail> pickDetailUpdateMap, List<Task> createToTask, List<Point> movePoints,
|
||||
AllocationData data, BigDecimal totalUnAllocatedQty, Set<String> errorMsgSet) {
|
||||
// 智能排序库存
|
||||
List<InventoryScore> scoredInventories = scoreInventories(matchedInventories);
|
||||
//未分配数量
|
||||
BigDecimal remainingQty = totalUnAllocatedQty;
|
||||
String requestId = UUID.randomUUID().toString();
|
||||
for (InventoryScore inventoryScore : scoredInventories) {
|
||||
if (remainingQty.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
break;
|
||||
|
|
@ -342,6 +364,9 @@ public class AllocateProcessor {
|
|||
// 创建任务
|
||||
createPickTask(pickDetail, pick, item, inventory, inventoryScore, allocateQty, createToTask, data);
|
||||
|
||||
// 获取需要移位的库位
|
||||
getMovePoints(inventoryScore, movePoints);
|
||||
|
||||
// 记录分配日志
|
||||
inventoryLogService.addAllocInventoryLog(inventory, inventoryScore.getOutPoint().getId(), allocateQty, pick.getOrderNo(), pickDetail.getId(), pickDetail.getDescription());
|
||||
|
||||
|
|
@ -500,31 +525,11 @@ public class AllocateProcessor {
|
|||
*/
|
||||
private void updateInventoryAllocation(Inventory inventory, BigDecimal allocateQty,
|
||||
Map<Long, Inventory> inventoryUpdateMap) {
|
||||
|
||||
Inventory inventoryToUpdate = inventoryUpdateMap.computeIfAbsent(
|
||||
inventory.getId(), id -> {
|
||||
// 2. 用Builder实现拷贝
|
||||
return Inventory.builder()
|
||||
.id(inventory.getId())
|
||||
.itemId(inventory.getItemId())
|
||||
.itemKeyId(inventory.getItemKeyId())
|
||||
.pointId(inventory.getPointId())
|
||||
.stockId(inventory.getStockId())
|
||||
.quantity(inventory.getQuantity())
|
||||
.queuedQty(BigDecimal.ZERO)
|
||||
.receiveRecordId(inventory.getReceiveRecordId())
|
||||
.status(inventory.getStatus())
|
||||
.description(inventory.getDescription())
|
||||
.sysOrgCode(inventory.getSysOrgCode())
|
||||
.tenantId(inventory.getTenantId())
|
||||
.createBy(inventory.getCreateBy())
|
||||
.createTime(inventory.getCreateTime())
|
||||
.build();
|
||||
});
|
||||
|
||||
BigDecimal newQueuedQty = BigDecimalUtil.add(inventoryToUpdate.getQueuedQty(), allocateQty, 0);
|
||||
inventoryToUpdate.setQueuedQty(newQueuedQty);
|
||||
inventoryToUpdate.setStatus(InventoryStatusEnum.ALLOCATED.getValue());
|
||||
Inventory targetInventory = inventoryUpdateMap.getOrDefault(inventory.getId(), inventory);
|
||||
BigDecimal newQueuedQty = BigDecimalUtil.add(targetInventory.getQueuedQty(), allocateQty, 0);
|
||||
targetInventory.setQueuedQty(newQueuedQty);
|
||||
targetInventory.setStatus(InventoryStatusEnum.ALLOCATED.getValue());
|
||||
inventoryUpdateMap.put(targetInventory.getId(), targetInventory);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -536,8 +541,15 @@ public class AllocateProcessor {
|
|||
*/
|
||||
private void updatePickDetailAllocation(PickDetail pickDetail, BigDecimal allocateQty,
|
||||
Map<Long, PickDetail> pickDetailUpdateMap) {
|
||||
PickDetail targetPickDetail = pickDetailUpdateMap.getOrDefault(pickDetail.getId(), pickDetail);
|
||||
BigDecimal newAllocatedQty = BigDecimalUtil.add(targetPickDetail.getAllocatedQty(), allocateQty, 0);
|
||||
Integer status = newAllocatedQty.compareTo(targetPickDetail.getOrderQty()) >= 0 ?
|
||||
PickStatusEnum.ASSIGNED.getValue() : PickStatusEnum.PARTIAL.getValue();
|
||||
targetPickDetail.setAllocatedQty(newAllocatedQty);
|
||||
targetPickDetail.setStatus(status);
|
||||
pickDetailUpdateMap.put(targetPickDetail.getId(), targetPickDetail);
|
||||
|
||||
PickDetail detailToUpdate = pickDetailUpdateMap.computeIfAbsent(
|
||||
/* PickDetail detailToUpdate = pickDetailUpdateMap.computeIfAbsent(
|
||||
pickDetail.getId(), id -> {
|
||||
// 2. 用Builder实现拷贝
|
||||
return PickDetail.builder()
|
||||
|
|
@ -568,7 +580,7 @@ public class AllocateProcessor {
|
|||
// 更新状态
|
||||
Integer status = newAllocatedQty.compareTo(detailToUpdate.getOrderQty()) >= 0 ?
|
||||
PickStatusEnum.ASSIGNED.getValue() : PickStatusEnum.PARTIAL.getValue();
|
||||
detailToUpdate.setStatus(status);
|
||||
detailToUpdate.setStatus(status);*/
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -611,6 +623,7 @@ public class AllocateProcessor {
|
|||
task.getTaskNo(), stock.getStockCode(),
|
||||
fromPoint.getPointCode(), izAll, allocateQty);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -637,6 +650,105 @@ public class AllocateProcessor {
|
|||
errorMsgSet.add(failInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取移位库位
|
||||
*
|
||||
* @param inventoryScore 库位评分
|
||||
* @param movePoints 移位库位
|
||||
*/
|
||||
private void getMovePoints(InventoryScore inventoryScore, List<Point> movePoints) {
|
||||
if (CollectionUtils.isNotEmpty(inventoryScore.getMovePoints())) {
|
||||
for (Point movePoint : inventoryScore.getMovePoints()) {
|
||||
if (!movePoints.contains(movePoint)) {
|
||||
movePoints.add(movePoint);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.info("无移位库位");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 移位任务
|
||||
*
|
||||
* @param createToTask 创建的出库任务
|
||||
* @param movePoints 移位库位
|
||||
*/
|
||||
void moveTask(List<Task> createToTask, List<Point> movePoints) {
|
||||
|
||||
if (CollectionUtils.isNotEmpty(movePoints)) {
|
||||
Set<Long> createTaskIds = createToTask.stream()
|
||||
.map(Task::getFromPointId)
|
||||
.collect(Collectors.toSet());
|
||||
List<Point> pointsToMove = movePoints.stream()
|
||||
.filter(point -> !createTaskIds.contains(point.getId()))
|
||||
.toList();
|
||||
if (CollectionUtils.isNotEmpty(pointsToMove)) {
|
||||
List<Task> moveToTask = bulidMoveTask(pointsToMove);
|
||||
if (CollectionUtils.isNotEmpty(moveToTask)) {
|
||||
createToTask.addAll(moveToTask);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建移位任务
|
||||
*
|
||||
* @param movePoints 移位库位
|
||||
* @return 移位任务
|
||||
*/
|
||||
public List<Task> bulidMoveTask(List<Point> movePoints) {
|
||||
List<Task> moveList = new ArrayList<>();
|
||||
|
||||
//库存
|
||||
List<Long> pointIds = movePoints.stream().map(Point::getId).toList();
|
||||
List<Inventory> moveInventoryList = inventoryMapper.queryByPointIds(pointIds);
|
||||
|
||||
//物料
|
||||
List<Long> itemIds = moveInventoryList.stream().map(Inventory::getItemId).distinct().toList();
|
||||
Map<Long, Item> moveItemMap = itemService.queryByItemIdsToMap(itemIds);
|
||||
|
||||
//物料属性
|
||||
List<Long> itemKeyIds = moveInventoryList.stream().map(Inventory::getItemKeyId).distinct().toList();
|
||||
Map<Long, ItemKey> itemKeyMap = itemKeyService.queryByIdsToMap(itemKeyIds);
|
||||
|
||||
//库位
|
||||
Map<Long, Point> fromPointMap = movePoints.stream().collect(Collectors.toMap(Point::getId, point -> point));
|
||||
|
||||
//容器
|
||||
List<Long> stockIds = moveInventoryList.stream().map(Inventory::getStockId).distinct().toList();
|
||||
Map<Long, Stock> stockMap = stockService.queryByStockIdsToMap(stockIds);
|
||||
|
||||
for (Inventory inv : moveInventoryList) {
|
||||
Item moveItem = moveItemMap.get(inv.getItemId());
|
||||
Point fromPoint = fromPointMap.get(inv.getPointId());
|
||||
Stock stock = stockMap.get(inv.getStockId());
|
||||
String taskNo = moveSerialNumberRule.generateSerialNumber(GeneralConstant.MOVE_ORDER_NO);
|
||||
//根据算法找到最优的目标库位
|
||||
Point toPoint = allocatePoint(fromPoint, itemKeyMap.get(inv.getItemKeyId()));
|
||||
Task moveTask = taskService.bulidTask(taskNo, TaskTypeEnum.MOVE.getValue(), moveItem, fromPoint, toPoint, stock, null, null, inv.getItemKeyId(), inv.getId(), inv.getQuantity(), 0);
|
||||
moveList.add(moveTask);
|
||||
log.info("生成移位任务:{}- 容器:{} - 库位:{} - 库存数量:{}", taskNo, stock.getStockCode(), fromPoint.getPointCode(), inv.getQuantity());
|
||||
}
|
||||
return moveList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 智能分配移位库位
|
||||
*
|
||||
* @param currentPoint 当前库位
|
||||
* @return 目标库位
|
||||
*/
|
||||
private Point allocatePoint(Point currentPoint, ItemKey itemKey) {
|
||||
Area area = areaMapper.selectById(currentPoint.getAreaId());
|
||||
String areaCode = area.getAreaCode();
|
||||
List<ItemKey> itemKeyIds = Collections.singletonList(itemKey);
|
||||
return scanTrayProcessor.allocatePoint(itemKeyIds, currentPoint, areaCode);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 批量操作
|
||||
*
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package org.cpte.modules.shipping.service;
|
||||
package org.cpte.modules.shipping.service.processor;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
|
|
@ -12,6 +12,7 @@ import org.cpte.modules.shipping.entity.PickDetail;
|
|||
import org.cpte.modules.shipping.entity.Task;
|
||||
import org.cpte.modules.shipping.mapper.PickDetailMapper;
|
||||
import org.cpte.modules.shipping.mapper.TaskMapper;
|
||||
import org.cpte.modules.shipping.service.IPickDetailService;
|
||||
import org.cpte.modules.shipping.vo.CancelAllocateData;
|
||||
import org.cpte.modules.utils.BatchUtil;
|
||||
import org.cpte.modules.utils.BigDecimalUtil;
|
||||
|
|
@ -196,7 +197,6 @@ public class CancelAllocateProcessor {
|
|||
.stockId(inventory.getStockId())
|
||||
.quantity(inventory.getQuantity())
|
||||
.queuedQty(inventory.getQueuedQty())
|
||||
.receiveRecordId(inventory.getReceiveRecordId())
|
||||
.status(inventory.getStatus())
|
||||
.description(inventory.getDescription())
|
||||
.sysOrgCode(inventory.getSysOrgCode())
|
||||
|
|
@ -0,0 +1,197 @@
|
|||
package org.cpte.modules.shipping.service.processor;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.cpte.modules.constant.GeneralConstant;
|
||||
import org.cpte.modules.constant.enums.PickStatusEnum;
|
||||
import org.cpte.modules.constant.enums.TaskStatusEnum;
|
||||
import org.cpte.modules.saiWms.request.SMOMRequest;
|
||||
import org.cpte.modules.shipping.entity.Pick;
|
||||
import org.cpte.modules.shipping.entity.PickDetail;
|
||||
import org.cpte.modules.shipping.entity.Task;
|
||||
import org.cpte.modules.shipping.mapper.PickDetailMapper;
|
||||
import org.cpte.modules.shipping.mapper.TaskMapper;
|
||||
import org.cpte.modules.shipping.vo.PickData;
|
||||
import org.cpte.modules.utils.SwmsLoginUtil;
|
||||
import org.jeecg.modules.openapi.mapper.OpenApiMapper;
|
||||
import org.jeecg.modules.system.mapper.SysDictMapper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 出库回传
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class PickBackProcessor {
|
||||
|
||||
@Autowired
|
||||
private PickDetailMapper pickDetailMapper;
|
||||
|
||||
@Autowired
|
||||
private TaskMapper taskMapper;
|
||||
|
||||
@Autowired
|
||||
private OpenApiMapper openApiMapper;
|
||||
|
||||
@Autowired
|
||||
private SysDictMapper sysDictMapper;
|
||||
|
||||
@Autowired
|
||||
private SwmsLoginUtil swmsLoginUtil;
|
||||
|
||||
|
||||
/**
|
||||
* 出库库任务回传JSON
|
||||
*/
|
||||
private String pickTaskCallbackJson(Pick pick, PickDetail pickDetail, Task task, Integer state, String ticket) {
|
||||
SMOMRequest.Task taskReq = new SMOMRequest.Task();
|
||||
taskReq.setNo(pick.getNo());
|
||||
taskReq.setOrderNo(pick.getThirdOrderNo());
|
||||
taskReq.setState(state);
|
||||
|
||||
SMOMRequest.ShipmentFeedbackDetail shipmentFeedbackDetail = new SMOMRequest.ShipmentFeedbackDetail();
|
||||
shipmentFeedbackDetail.setLineNo(String.valueOf(pickDetail.getLineNo()));
|
||||
shipmentFeedbackDetail.setLpn(task.getStockCode());
|
||||
shipmentFeedbackDetail.setQty(task.getPlanQty().intValue());
|
||||
shipmentFeedbackDetail.setIsTakeDown(task.getIzAll() == 0);
|
||||
shipmentFeedbackDetail.setProject(pickDetail.getProject());
|
||||
shipmentFeedbackDetail.setTaskNo(pickDetail.getTaskNo());
|
||||
shipmentFeedbackDetail.setLotAtt04(pickDetail.getPropC1());
|
||||
shipmentFeedbackDetail.setLotAtt010(pickDetail.getPropC3());
|
||||
shipmentFeedbackDetail.setErpKey(pick.getNo());
|
||||
shipmentFeedbackDetail.setIsDelete(false);
|
||||
String lastUpdateDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
|
||||
shipmentFeedbackDetail.setLastUpdateDate(lastUpdateDate);
|
||||
taskReq.setShipmentFeedbackDetails(List.of(shipmentFeedbackDetail));
|
||||
|
||||
taskReq.setErpKey(pick.getNo());
|
||||
taskReq.setInfkey(pick.getNo());
|
||||
taskReq.setIsDelete(false);
|
||||
taskReq.setLastUpdateDate(lastUpdateDate);
|
||||
|
||||
|
||||
SMOMRequest.ParameterValue1 parameterValue1 = new SMOMRequest.ParameterValue1();
|
||||
parameterValue1.setValue(List.of(taskReq));
|
||||
|
||||
SMOMRequest.ParameterValue2 parameterValue2 = new SMOMRequest.ParameterValue2();
|
||||
parameterValue2.setValue(1);
|
||||
|
||||
SMOMRequest.Context context = new SMOMRequest.Context();
|
||||
context.setInvOrgId(1);
|
||||
context.setTicket(ticket);
|
||||
|
||||
SMOMRequest saiWmsRequest = new SMOMRequest();
|
||||
saiWmsRequest.setApiType("SmomWebApiController");
|
||||
saiWmsRequest.setParameters(List.of(parameterValue1, parameterValue2));
|
||||
saiWmsRequest.setMethod("OutboundTaskCallbackInterface");
|
||||
saiWmsRequest.setContext(context);
|
||||
|
||||
return JSON.toJSONString(saiWmsRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* 出库任务回传
|
||||
*
|
||||
* @param data 数据
|
||||
* @param tasks 任务
|
||||
*/
|
||||
public void pickBack(PickData data, List<Task> tasks) {
|
||||
Map<Long, List<PickDetail>> pickDetailsCache = new HashMap<>();
|
||||
for (Task task : tasks) {
|
||||
Pick pick = data.getPickMap().get(task.getPickId());
|
||||
PickDetail pickDetail = data.getPickDetailMap().get(task.getPickDetailId());
|
||||
Long pickId = pick.getId();
|
||||
try {
|
||||
// 缓存查询结果,避免重复查询
|
||||
List<PickDetail> pickDetails = pickDetailsCache.computeIfAbsent(pickId, id -> pickDetailMapper.selectByMainId(id));
|
||||
|
||||
//已关闭的出库单
|
||||
List<PickDetail> closedPickDetails = pickDetails.stream().filter(detail -> PickStatusEnum.CLOSED.getValue().equals(detail.getStatus())).toList();
|
||||
|
||||
int state = pickDetails.size() - closedPickDetails.size() == 1 ? 5 : 7;
|
||||
|
||||
pickBackProcessor(pick, pickDetail, task, state);
|
||||
} catch (Exception e) {
|
||||
log.error("出库任务回传失败,任务ID: {}, 错误信息: {}", task.getId(), e.getMessage(), e);
|
||||
}
|
||||
List<PickDetail> latestPickDetails = pickDetailMapper.selectByMainId(pickId);
|
||||
pickDetailsCache.put(pickId, latestPickDetails); // 更新缓存
|
||||
}
|
||||
}
|
||||
|
||||
private void pickBackProcessor(Pick pick, PickDetail pickDetail, Task task, Integer state) {
|
||||
// 检查接口开关, 未开启则返回
|
||||
if (sysDictMapper.queryByDictCode(GeneralConstant.OPEN_FLAG) == null) {
|
||||
updatePickDetailResponse(pickDetail, task, GeneralConstant.SMOM_FAIL_CODE, "接口未开启");
|
||||
return;
|
||||
}
|
||||
|
||||
if (TaskStatusEnum.CLOSED.getValue().equals(task.getTaskStatus())) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Map<String, String> authInfo = swmsLoginUtil.Login();
|
||||
if (authInfo == null || authInfo.isEmpty()) {
|
||||
throw new RuntimeException("登录认证信息为空");
|
||||
}
|
||||
|
||||
String ticket = authInfo.get("Ticket");
|
||||
String authorization = authInfo.get("authorization");
|
||||
String json = pickTaskCallbackJson(pick, pickDetail, task, state, ticket);
|
||||
String url = openApiMapper.getRequestUrl(GeneralConstant.OUTBOUND_CALLBACK).getOriginUrl();
|
||||
JSONObject jsonObject = swmsLoginUtil.sendSMOMResponse(json, url, authorization);
|
||||
String code = validateResponse(jsonObject);
|
||||
updatePickDetailResponse(pickDetail, task, code, jsonObject.toJSONString());
|
||||
} catch (Exception e) {
|
||||
updatePickDetailResponse(pickDetail, task, GeneralConstant.SMOM_FAIL_CODE, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证响应数据
|
||||
*
|
||||
* @param jsonObject 响应数据
|
||||
* @return 状态码
|
||||
*/
|
||||
private String validateResponse(JSONObject jsonObject) {
|
||||
JSONObject data = jsonObject.getJSONObject("data");
|
||||
if (data == null) {
|
||||
throw new RuntimeException("数据格式错误:缺少data字段");
|
||||
}
|
||||
JSONObject Result = data.getJSONObject("Result");
|
||||
if (Result == null) {
|
||||
throw new RuntimeException("数据格式错误:缺少Result字段");
|
||||
}
|
||||
JSONArray jsonArray = Result.getJSONArray("ErpErrorDatas");
|
||||
return jsonArray.isEmpty() ? GeneralConstant.SMOM_SUCCESS_CODE : GeneralConstant.SMOM_FAIL_CODE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新任务状态
|
||||
*
|
||||
* @param task 出库任务
|
||||
* @param message 信息
|
||||
*/
|
||||
private void updatePickDetailResponse(PickDetail pickDetail, Task task, String code, String message) {
|
||||
if (GeneralConstant.SMOM_SUCCESS_CODE.equals(code)) {
|
||||
if (PickStatusEnum.PICKED.getValue().equals(pickDetail.getStatus())) {
|
||||
pickDetail.setStatus(PickStatusEnum.CLOSED.getValue());
|
||||
pickDetailMapper.updateById(pickDetail);
|
||||
}
|
||||
task.setTaskStatus(TaskStatusEnum.CLOSED.getValue());
|
||||
}
|
||||
task.setResMessage(message);
|
||||
task.setResTime(new Date());
|
||||
taskMapper.updateById(task);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,345 @@
|
|||
package org.cpte.modules.shipping.service.processor;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.cpte.modules.base.entity.Stock;
|
||||
import org.cpte.modules.base.service.IStockService;
|
||||
import org.cpte.modules.constant.enums.CommonStatusEnum;
|
||||
import org.cpte.modules.constant.enums.PickStatusEnum;
|
||||
import org.cpte.modules.constant.enums.TaskStatusEnum;
|
||||
import org.cpte.modules.inventory.entity.Inventory;
|
||||
import org.cpte.modules.inventory.service.IInventoryService;
|
||||
import org.cpte.modules.inventoryLog.service.IInventoryLogService;
|
||||
import org.cpte.modules.shipping.entity.Pick;
|
||||
import org.cpte.modules.shipping.entity.PickDetail;
|
||||
import org.cpte.modules.shipping.entity.Task;
|
||||
import org.cpte.modules.shipping.mapper.PickDetailMapper;
|
||||
import org.cpte.modules.shipping.service.IPickDetailService;
|
||||
import org.cpte.modules.shipping.vo.PickData;
|
||||
import org.cpte.modules.utils.BatchUtil;
|
||||
import org.cpte.modules.utils.BigDecimalUtil;
|
||||
import org.cpte.modules.utils.RedisDistributedLockUtil;
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.modules.base.service.BaseCommonService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 拣货处理
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class PickProcessor {
|
||||
|
||||
@Autowired
|
||||
private PickDetailMapper pickDetailMapper;
|
||||
|
||||
@Autowired
|
||||
private IStockService stockService;
|
||||
|
||||
@Autowired
|
||||
private IPickDetailService pickDetailService;
|
||||
|
||||
@Autowired
|
||||
private IInventoryService inventoryService;
|
||||
|
||||
@Autowired
|
||||
private IInventoryLogService inventoryLogService;
|
||||
|
||||
@Autowired
|
||||
private BaseCommonService baseCommonService;
|
||||
|
||||
@Autowired
|
||||
private BatchUtil batchUtil;
|
||||
|
||||
@Autowired
|
||||
private PickBackProcessor pickBackProcessor;
|
||||
|
||||
@Autowired
|
||||
private RedisDistributedLockUtil redissonLock;
|
||||
|
||||
/**
|
||||
* 拣货
|
||||
*
|
||||
* @param tasks 任务
|
||||
*/
|
||||
public void pick(List<Task> tasks) {
|
||||
// 1.数据准备
|
||||
PickData data = preparePickData(tasks);
|
||||
|
||||
//2.创建数据结构
|
||||
List<Inventory> deleteToInventory = new ArrayList<>();
|
||||
Map<Long, PickDetail> pickDetailUpdateMap = new HashMap<>();
|
||||
List<Task> updateToTask = new ArrayList<>();
|
||||
List<Stock> updateToStock = new ArrayList<>();
|
||||
|
||||
//3.拣货
|
||||
pickTask(data, pickDetailUpdateMap, updateToTask, deleteToInventory, updateToStock);
|
||||
|
||||
//4.批量操作
|
||||
batchOperation(deleteToInventory, pickDetailUpdateMap, updateToTask, updateToStock);
|
||||
|
||||
//5.刷新出库单
|
||||
refreshData(data);
|
||||
|
||||
//6.回传
|
||||
pickBackProcessor.pickBack(data, updateToTask);
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据准备
|
||||
*
|
||||
* @param tasks 任务
|
||||
* @return PickData
|
||||
*/
|
||||
private PickData preparePickData(List<Task> tasks) {
|
||||
PickData data = new PickData();
|
||||
data.setTasks(tasks);
|
||||
|
||||
//查询出库单
|
||||
List<Long> pickIds = tasks.stream().map(Task::getPickId).distinct().toList();
|
||||
Map<Long, Pick> pickMap = pickDetailService.queryByPickIdsToMap(pickIds);
|
||||
data.setPickMap(pickMap);
|
||||
|
||||
//查询出库单明细
|
||||
List<Long> pickDetailIds = tasks.stream().map(Task::getPickDetailId).distinct().toList();
|
||||
Map<Long, PickDetail> pickDetailMap = pickDetailService.queryByPickDetailIdsToMap(pickDetailIds);
|
||||
data.setPickDetailMap(pickDetailMap);
|
||||
|
||||
//查询库存
|
||||
List<Long> inventoryIds = tasks.stream().map(Task::getInventoryId).distinct().toList();
|
||||
Map<Long, Inventory> inventoryMap = inventoryService.queryByInventoryIdsToMap(inventoryIds);
|
||||
data.setInventoryMap(inventoryMap);
|
||||
|
||||
//库存容器
|
||||
List<Long> stockIds = inventoryMap.values().stream().map(Inventory::getStockId).distinct().toList();
|
||||
Map<Long, Stock> stockMap = stockService.queryByStockIdsToMap(stockIds);
|
||||
data.setStockMap(stockMap);
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 拣货
|
||||
*
|
||||
* @param data 数据
|
||||
*/
|
||||
private void pickTask(PickData data, Map<Long, PickDetail> pickDetailUpdateMap, List<Task> updateToTask, List<Inventory> deleteToInventory, List<Stock> updateToStock) {
|
||||
for (Task task : data.getTasks()) {
|
||||
try {
|
||||
processorTaskLock(data, task, pickDetailUpdateMap, updateToTask, deleteToInventory, updateToStock);
|
||||
} catch (Exception e) {
|
||||
log.error("拣货异常", e);
|
||||
//记录拣货异常日志
|
||||
baseCommonService.addLog("出库任务拣货:" + "\n" + task.getTaskNo() + e, CommonConstant.LOG_TYPE_4, CommonConstant.OPERATE_TYPE_4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理任务
|
||||
*
|
||||
* @param data 数据
|
||||
* @param task 任务
|
||||
* @param pickDetailUpdateMap 拣货明细更新集合
|
||||
* @param updateToTask 更新任务集合
|
||||
* @param deleteToInventory 删除库存集合
|
||||
* @param updateToStock 更新容器状态集合
|
||||
*/
|
||||
private void processorTaskLock(PickData data, Task task, Map<Long, PickDetail> pickDetailUpdateMap, List<Task> updateToTask, List<Inventory> deleteToInventory, List<Stock> updateToStock) {
|
||||
// 拣货处理
|
||||
String lockKey = "task:" + task.getId();
|
||||
String lockValue = null;
|
||||
try {
|
||||
lockValue = redissonLock.tryLock(lockKey, 10);
|
||||
if (StringUtils.isEmpty(lockValue)) {
|
||||
throw new RuntimeException("拣货处理中,请稍后重试");
|
||||
}
|
||||
processorTask(data, task, pickDetailUpdateMap, updateToTask, deleteToInventory, updateToStock);
|
||||
} catch (Exception e) {
|
||||
log.error("拣货异常", e);
|
||||
throw e;
|
||||
} finally {
|
||||
if (StringUtils.isNotEmpty(lockValue)) {
|
||||
redissonLock.unlock(lockKey, lockValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 处理任务
|
||||
*
|
||||
* @param data 数据
|
||||
* @param task 任务
|
||||
* @param pickDetailUpdateMap 拣货明细更新集合
|
||||
* @param updateToTask 更新任务集合
|
||||
* @param deleteToInventory 删除库存集合
|
||||
* @param updateToStock 更新容器状态集合
|
||||
*/
|
||||
private void processorTask(PickData data, Task task, Map<Long, PickDetail> pickDetailUpdateMap, List<Task> updateToTask, List<Inventory> deleteToInventory, List<Stock> updateToStock) {
|
||||
|
||||
BigDecimal pickedQty = BigDecimalUtil.subtract(task.getPlanQty(), task.getMoveQty(), 0);
|
||||
if (pickedQty.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
//扣减库存
|
||||
/*Inventory inventory = data.getInventoryMap().get(task.getInventoryId());
|
||||
updateInventory(inventory, pickedQty,inventoryUpdateMap);*/
|
||||
|
||||
// 更新拣货数量,状态
|
||||
updatePickDetail(data, task, pickedQty, pickDetailUpdateMap);
|
||||
|
||||
//更新task
|
||||
updateTask(task, pickedQty, updateToTask);
|
||||
|
||||
//删除库存
|
||||
deleteInventory(data, task, deleteToInventory);
|
||||
|
||||
//更新容器状态
|
||||
updateToStock(data, task, updateToStock);
|
||||
|
||||
//添加库存日志
|
||||
addInventoryLog(data, task, pickedQty);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新库存
|
||||
*
|
||||
* @param inventory 库存
|
||||
* @param pickedQty 拣货数量
|
||||
* @param inventoryUpdateMap 库更新集合
|
||||
*/
|
||||
private void updateInventory(Inventory inventory, BigDecimal pickedQty,
|
||||
Map<Long, Inventory> inventoryUpdateMap) {
|
||||
Inventory targetInventory = inventoryUpdateMap.getOrDefault(inventory.getId(), inventory);
|
||||
BigDecimal quantity = BigDecimalUtil.subtract(targetInventory.getQuantity(), pickedQty, 0);
|
||||
BigDecimal queuedQty = BigDecimalUtil.subtract(targetInventory.getQueuedQty(), pickedQty, 0);
|
||||
targetInventory.setQuantity(quantity);
|
||||
targetInventory.setQueuedQty(queuedQty);
|
||||
inventoryUpdateMap.put(targetInventory.getId(), targetInventory);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除库存
|
||||
*
|
||||
* @param data 数据
|
||||
* @param deleteToInventory 删除集合
|
||||
*/
|
||||
private void deleteInventory(PickData data, Task task, List<Inventory> deleteToInventory) {
|
||||
Inventory inventory = data.getInventoryMap().get(task.getInventoryId());
|
||||
if (!deleteToInventory.contains(inventory)) {
|
||||
deleteToInventory.add(inventory);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新出库明细
|
||||
*
|
||||
* @param data 数据
|
||||
* @param pickedQty 拣货数量
|
||||
* @param pickDetailUpdateMap 拣货明细更新集合
|
||||
*/
|
||||
private void updatePickDetail(PickData data, Task task, BigDecimal pickedQty,
|
||||
Map<Long, PickDetail> pickDetailUpdateMap) {
|
||||
//出库明细
|
||||
PickDetail pickDetail = data.getPickDetailMap().get(task.getPickDetailId());
|
||||
//获取map最新的出库明细
|
||||
PickDetail targetPickDetail = pickDetailUpdateMap.getOrDefault(pickDetail.getId(), pickDetail);
|
||||
//拣货数量
|
||||
BigDecimal newPickedQty = BigDecimalUtil.add(targetPickDetail.getPickedQty(), pickedQty, 0);
|
||||
//状态
|
||||
Integer status = newPickedQty.compareTo(targetPickDetail.getOrderQty()) >= 0 ? PickStatusEnum.PICKED.getValue() : PickStatusEnum.PICKING.getValue();
|
||||
targetPickDetail.setPickedQty(newPickedQty);
|
||||
targetPickDetail.setStatus(status);
|
||||
pickDetailUpdateMap.put(targetPickDetail.getId(), targetPickDetail);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新出库明细
|
||||
*
|
||||
* @param task 出库任务
|
||||
* @param pickedQty 拣货数量
|
||||
* @param updateToTask 拣货明细更新集合
|
||||
*/
|
||||
private void updateTask(Task task, BigDecimal pickedQty, List<Task> updateToTask) {
|
||||
// 更新任务
|
||||
task.setMoveQty(pickedQty);
|
||||
task.setTaskStatus(TaskStatusEnum.COMPLETED.getValue());
|
||||
updateToTask.add(task);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新容器状态
|
||||
*
|
||||
* @param data 数据
|
||||
* @param updateToStock 容器更新集合
|
||||
*/
|
||||
private void updateToStock(PickData data, Task task, List<Stock> updateToStock) {
|
||||
Stock stock = data.getStockMap().get(task.getStockId());
|
||||
if (!updateToStock.contains(stock)) {
|
||||
stock.setPointId(null);
|
||||
stock.setStatus(CommonStatusEnum.FREE.getValue());
|
||||
updateToStock.add(stock);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加库存日志
|
||||
*
|
||||
* @param data 数据
|
||||
* @param task 任务
|
||||
* @param pickedQty 拣货数量
|
||||
*/
|
||||
private void addInventoryLog(PickData data, Task task, BigDecimal pickedQty) {
|
||||
Inventory inventory = data.getInventoryMap().get(task.getInventoryId());
|
||||
Pick pick = data.getPickMap().get(task.getPickId());
|
||||
inventoryLogService.addPickInventoryLog(inventory, task.getToPointId(), pickedQty, pick.getOrderNo(), task.getId(), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量操作
|
||||
*
|
||||
* @param deleteToInventory 删除库存
|
||||
* @param pickDetailUpdateMap 更新出库明细
|
||||
* @param updateToTask 创建出库任务
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void batchOperation(List<Inventory> deleteToInventory, Map<Long, PickDetail> pickDetailUpdateMap, List<Task> updateToTask, List<Stock> updateToStock) {
|
||||
if (CollectionUtils.isNotEmpty(deleteToInventory)) {
|
||||
List<Long> deleteToInventoryIds = deleteToInventory.stream().map(Inventory::getId).toList();
|
||||
inventoryService.removeByIds(deleteToInventoryIds);
|
||||
}
|
||||
List<PickDetail> updateToPickDetail = new ArrayList<>(pickDetailUpdateMap.values());
|
||||
if (CollectionUtils.isNotEmpty(updateToPickDetail)) {
|
||||
batchUtil.updateBatchPickDetail(updateToPickDetail);
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(updateToTask)) {
|
||||
batchUtil.updateBatchTask(updateToTask);
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(updateToStock)) {
|
||||
stockService.updateBatchById(updateToStock);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新出库单
|
||||
*
|
||||
* @param data 数据
|
||||
*/
|
||||
private void refreshData(PickData data) {
|
||||
for (Map.Entry<Long, Pick> entry : data.getPickMap().entrySet()) {
|
||||
pickDetailService.refreshPick(entry.getValue(), pickDetailMapper.selectByMainId(entry.getKey()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package org.cpte.modules.shipping.vo;
|
||||
|
||||
import lombok.Data;
|
||||
import org.cpte.modules.base.entity.Stock;
|
||||
import org.cpte.modules.inventory.entity.Inventory;
|
||||
import org.cpte.modules.shipping.entity.Pick;
|
||||
import org.cpte.modules.shipping.entity.PickDetail;
|
||||
import org.cpte.modules.shipping.entity.Task;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
public class PickData {
|
||||
private List<Task> tasks;
|
||||
private Map<Long, Stock> stockMap;
|
||||
private Map<Long, Pick> pickMap;
|
||||
private Map<Long, PickDetail> pickDetailMap;
|
||||
private Map<Long, Inventory> inventoryMap;
|
||||
}
|
||||
|
|
@ -48,12 +48,6 @@ public class ITesAgvServiceImpl implements ITesAgvService {
|
|||
@Autowired
|
||||
private OpenApiMapper openApiMapper;
|
||||
|
||||
@Autowired
|
||||
private IPointService pointService;
|
||||
|
||||
@Autowired
|
||||
private IStockService stockService;
|
||||
|
||||
@Autowired
|
||||
private IAsnService asnService;
|
||||
|
||||
|
|
@ -232,10 +226,9 @@ public class ITesAgvServiceImpl implements ITesAgvService {
|
|||
asnService.receiveAsn(asnId, agvTask.getEndCode());
|
||||
} else if (BusinessTypeEnum.OUTBOUND.getValue().equals(agvTask.getType())) {
|
||||
//拣货
|
||||
Point endPoint = pointService.validatePoint(agvTask.getEndCode());
|
||||
List<Task> tasks = taskMapper.queryByAgvTask(agvTask.getId());
|
||||
pickService.pickTask(tasks, endPoint);
|
||||
Point startPoint = pointService.validatePoint(agvTask.getStartCode());
|
||||
pickService.pickTask(tasks);
|
||||
/* Point startPoint = pointService.validatePoint(agvTask.getStartCode());
|
||||
|
||||
Stock stock = stockService.validateStock(agvTask.getCarrierCode());
|
||||
pointService.unbindPoint(startPoint);
|
||||
|
|
@ -246,7 +239,7 @@ public class ITesAgvServiceImpl implements ITesAgvService {
|
|||
//查询电梯口点位作为目标点位
|
||||
String endCode = pointService.getElevatorPoint(agvTask.getEndCode(), GeneralConstant.CK_ELEVATOR_TASK_INDEX);
|
||||
agvTaskService.createAgvTask(null, agvTask.getCarrierCode(), agvTask.getEndCode(), endCode, null, BusinessTypeEnum.OUTBOUND.getValue(), 0, AgvVendorEnum.HIK.getValue());
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
agvTask.setStatus(AgvStatusEnum.COMPLETED.getValue());
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package org.cpte.modules.utils;
|
||||
|
||||
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
||||
import org.cpte.modules.agvTask.entity.AgvTask;
|
||||
import org.cpte.modules.base.entity.Item;
|
||||
import org.cpte.modules.base.entity.Point;
|
||||
|
|
@ -15,7 +14,6 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.sql.Date;
|
||||
|
|
@ -86,7 +84,7 @@ public class BatchUtil {
|
|||
String sql = "INSERT INTO base_item (id,item_code,item_name,unit,iz_active, del_flag,sys_org_code,tenant_id,create_by,create_time) VALUES (?,?,?,?,?,?,?,?,?,?)";
|
||||
batchInsert(sql, items, (ps, item) -> {
|
||||
try {
|
||||
ps.setLong(1, IdWorker.getId());
|
||||
ps.setLong(1, item.getId());
|
||||
ps.setString(2, item.getItemCode());
|
||||
ps.setString(3, item.getItemName());
|
||||
ps.setString(4, item.getUnit());
|
||||
|
|
@ -130,7 +128,7 @@ public class BatchUtil {
|
|||
String sql = "INSERT INTO base_point (id,area_id, point_code,status,row_num,col_num,layer_num,description,iz_active,del_flag,sys_org_code,tenant_id,create_by,create_time) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
|
||||
batchInsert(sql, points, (ps, point) -> {
|
||||
try {
|
||||
ps.setLong(1, IdWorker.getId());
|
||||
ps.setLong(1, point.getId());
|
||||
ps.setLong(2, point.getAreaId());
|
||||
ps.setString(3, point.getPointCode());
|
||||
ps.setInt(4, point.getStatus());
|
||||
|
|
@ -183,7 +181,7 @@ public class BatchUtil {
|
|||
String sql = "INSERT INTO base_stock (id,stock_code, stock_type, status, del_flag, iz_active,sys_org_code,tenant_id,create_by,create_time) VALUES (?,?,?,?,?,?,?,?,?,?)";
|
||||
batchInsert(sql, stocks, (ps, stock) -> {
|
||||
try {
|
||||
ps.setLong(1, IdWorker.getId());
|
||||
ps.setLong(1, stock.getId());
|
||||
ps.setString(2, stock.getStockCode());
|
||||
ps.setString(3, stock.getStockType());
|
||||
ps.setInt(4, stock.getStatus());
|
||||
|
|
@ -259,23 +257,24 @@ public class BatchUtil {
|
|||
*/
|
||||
@Transactional
|
||||
public void saveBatchReceiveRecord(List<ReceiveRecord> receiveRecords) {
|
||||
String sql = "INSERT INTO data_receive_record (id,asn_detail_id,stock_id,from_point_id,to_point_id, item_id,item_key_id,received_qty,description,sys_org_code,tenant_id,create_by,create_time) " +
|
||||
"VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)";
|
||||
String sql = "INSERT INTO data_receive_record (id,asn_id,asn_detail_id,stock_id,from_point_id,to_point_id, item_id,item_key_id,received_qty,description,sys_org_code,tenant_id,create_by,create_time) " +
|
||||
"VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
|
||||
batchInsert(sql, receiveRecords, (ps, record) -> {
|
||||
try {
|
||||
ps.setLong(1, record.getId());
|
||||
ps.setLong(2, record.getAsnDetailId());
|
||||
ps.setLong(3, record.getStockId());
|
||||
ps.setLong(4, record.getFromPointId());
|
||||
ps.setLong(5, record.getToPointId());
|
||||
ps.setLong(6, record.getItemId());
|
||||
ps.setLong(7, record.getItemKeyId());
|
||||
ps.setBigDecimal(8, record.getReceivedQty());
|
||||
ps.setString(9, record.getDescription());
|
||||
ps.setString(10, record.getSysOrgCode());
|
||||
ps.setLong(11, record.getTenantId());
|
||||
ps.setString(12, record.getCreateBy());
|
||||
ps.setDate(13, new Date(record.getCreateTime().getTime()));
|
||||
ps.setLong(2, record.getAsnId());
|
||||
ps.setLong(3, record.getAsnDetailId());
|
||||
ps.setLong(4, record.getStockId());
|
||||
ps.setLong(5, record.getFromPointId());
|
||||
ps.setLong(6, record.getToPointId());
|
||||
ps.setLong(7, record.getItemId());
|
||||
ps.setLong(8, record.getItemKeyId());
|
||||
ps.setBigDecimal(9, record.getReceivedQty());
|
||||
ps.setString(10, record.getDescription());
|
||||
ps.setString(11, record.getSysOrgCode());
|
||||
ps.setLong(12, record.getTenantId());
|
||||
ps.setString(13, record.getCreateBy());
|
||||
ps.setDate(14, new Date(record.getCreateTime().getTime()));
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
|
@ -291,7 +290,7 @@ public class BatchUtil {
|
|||
"VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
|
||||
batchInsert(sql, tasks, (ps, task) -> {
|
||||
try {
|
||||
ps.setLong(1, IdWorker.getId());
|
||||
ps.setLong(1, task.getId());
|
||||
ps.setString(2, task.getTaskNo());
|
||||
ps.setLong(3, task.getItemId());
|
||||
ps.setString(4, task.getItemCode());
|
||||
|
|
@ -348,9 +347,7 @@ public class BatchUtil {
|
|||
"VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
|
||||
batchInsert(sql, agvTasks, (ps, agvTask) -> {
|
||||
try {
|
||||
long id = IdWorker.getId();
|
||||
agvTask.setId(IdWorker.getId()); // 关键:将生成的ID赋值给对象,解决null问题
|
||||
ps.setLong(1, id);
|
||||
ps.setLong(1, agvTask.getId());
|
||||
ps.setObject(2, agvTask.getBusinessDetailId());
|
||||
ps.setString(3, agvTask.getCarrierCode());
|
||||
ps.setString(4, agvTask.getCarrierType());
|
||||
|
|
@ -377,7 +374,7 @@ public class BatchUtil {
|
|||
*/
|
||||
@Transactional
|
||||
public void saveBatchInventory(List<Inventory> inventories) {
|
||||
String sql = "INSERT INTO data_inventory (id,item_key_id,item_id,point_id,stock_id,receive_record_id,quantity,queued_qty,status,description,sys_org_code,tenant_id,create_by,create_time) " +
|
||||
String sql = "INSERT INTO data_inventory (id,item_key_id,item_id,point_id,stock_id,quantity,queued_qty,status,order_no,description,sys_org_code,tenant_id,create_by,create_time) " +
|
||||
"VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
|
||||
batchInsert(sql, inventories, (ps, inventory) -> {
|
||||
try {
|
||||
|
|
@ -386,10 +383,10 @@ public class BatchUtil {
|
|||
ps.setLong(3, inventory.getItemId());
|
||||
ps.setLong(4, inventory.getPointId());
|
||||
ps.setLong(5, inventory.getStockId());
|
||||
ps.setObject(6, inventory.getReceiveRecordId());
|
||||
ps.setBigDecimal(7, inventory.getQuantity());
|
||||
ps.setBigDecimal(8, inventory.getQueuedQty());
|
||||
ps.setInt(9, inventory.getStatus());
|
||||
ps.setBigDecimal(6, inventory.getQuantity());
|
||||
ps.setBigDecimal(7, inventory.getQueuedQty());
|
||||
ps.setInt(8, inventory.getStatus());
|
||||
ps.setString(9, inventory.getOrderNo());
|
||||
ps.setString(10, inventory.getDescription());
|
||||
ps.setString(11, inventory.getSysOrgCode());
|
||||
ps.setLong(12, inventory.getTenantId());
|
||||
|
|
@ -429,7 +426,7 @@ public class BatchUtil {
|
|||
"VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
|
||||
batchInsert(sql, inventoryLogs, (ps, inventoryLog) -> {
|
||||
try {
|
||||
ps.setLong(1, IdWorker.getId());
|
||||
ps.setLong(1, inventoryLog.getId());
|
||||
ps.setInt(2, inventoryLog.getLogType());
|
||||
ps.setString(3, inventoryLog.getBusinessNo());
|
||||
ps.setObject(4, inventoryLog.getBusinessDetailId());
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ import java.nio.charset.StandardCharsets;
|
|||
import java.security.MessageDigest;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class test {
|
||||
public static void main(String[] args) {
|
||||
|
|
@ -29,8 +31,10 @@ public class test {
|
|||
System.out.println("=======================================================================================");
|
||||
System.out.println("agv-timestamp:" + timestamp);
|
||||
System.out.println("agv-signature:" + md5(agvMap.get("ak")+ agvMap.get("sk") + timestamp));
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static String md5(String sourceStr) {
|
||||
String result = "";
|
||||
try {
|
||||
|
|
|
|||
Loading…
Reference in New Issue