no message

main
HUOJIN\92525 2025-12-19 18:06:14 +08:00
parent 981b83aa2d
commit 7d31f04772
58 changed files with 1657 additions and 880 deletions

View File

@ -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 listtext_dictText
* sex_dictText
* {
* sex:1,
* sex_dictText:"男"
* sex:1,
* sex_dictText:"男"
* }
* sext_dictTexttable
* customRender:function (text) {
* if(text==1){
* return "男";
* }else if(text==2){
* return "女";
* }else{
* return text;
* }
* }
* vuetable
*
* customRender:function (text) {
* if(text==1){
* return "男";
* }else if(text==2){
* return "女";
* }else{
* return text;
* }
* }
* vuetable
* @param result
*/
private Object parseDictText(Object result) {
@ -105,24 +114,24 @@ public class DictAspect {
// 字典数据列表, key = 字典codevalue=数据列表
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
*/
@ -300,7 +308,7 @@ public class DictAspect {
//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:微服务下为空报错没有参数需要传递空字符串---
@ -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;

View File

@ -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)

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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;
/**
*
*/

View File

@ -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);

View File

@ -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

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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)

View File

@ -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())

View File

@ -20,6 +20,8 @@ public enum AsnStatusEnum {
CANCELED(5, "已取消"),
SCAN(6, "已扫描"),
;

View File

@ -10,6 +10,10 @@ import lombok.Getter;
@Getter
public enum BusinessTypeEnum {
TRANSPORT("TRANSPORT", "搬运"),
MOVE("MOVE", "移位"),
INBOUND("INBOUND", "入库"),
OUTBOUND("OUTBOUND", "出库"),

View File

@ -10,6 +10,10 @@ import lombok.Getter;
*/
@Getter
public enum InventoryStatusEnum {
/**
*
*/
UNAVAILABLE(0, "禁用"),
/**
*
*/
@ -28,7 +32,7 @@ public enum InventoryStatusEnum {
/**
*
*/
TRANSFER(4, "移位中"),
MOVE(4, "移位中"),
/**
*

View File

@ -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);

View File

@ -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);

View File

@ -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;
@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 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) {

View File

@ -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;
/**
*
*/

View File

@ -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);
}

View File

@ -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>

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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);
/**
* 退-退

View File

@ -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())

View File

@ -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;
/**
*
*/

View File

@ -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);
}

View File

@ -4,4 +4,5 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.cpte.modules.receive.entity.ReceiveRecord;
public interface ReceiveRecordMapper extends BaseMapper<ReceiveRecord> {
}

View File

@ -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);
}

View File

@ -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())

View File

@ -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);
}
}
}

View File

@ -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;
}
}

View File

@ -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)

View File

@ -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("操作成功!");
}
/**
*
*

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);
}
}
}
}

View File

@ -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());
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -30,6 +30,14 @@ public interface IPickDetailService extends IService<PickDetail> {
*/
Map<Long, Pick> queryByPickIdsToMap(List<Long> pickIds);
/**
* IDMap
*
* @param pickDetailIds ID
* @return Map<Long, PickDetail>
*/
Map<Long, PickDetail> queryByPickDetailIdsToMap(List<Long> pickDetailIds);
/**
*

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
/**
*
*

View File

@ -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())

View File

@ -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);
}
}

View File

@ -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()));
}
}
}

View File

@ -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;
}

View File

@ -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());

View File

@ -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());

View File

@ -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 {