no message
parent
7d31f04772
commit
32f9edffc3
|
|
@ -2,6 +2,10 @@ package org.cpte.modules.agvTask.service;
|
||||||
|
|
||||||
import org.cpte.modules.agvTask.entity.AgvTask;
|
import org.cpte.modules.agvTask.entity.AgvTask;
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import org.cpte.modules.base.entity.Point;
|
||||||
|
import org.cpte.modules.base.entity.Stock;
|
||||||
|
import org.cpte.modules.conveyorLine.vo.ScanTrayData;
|
||||||
|
import org.cpte.modules.receive.entity.Asn;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
@ -40,4 +44,11 @@ public interface IAgvTaskService extends IService<AgvTask> {
|
||||||
*/
|
*/
|
||||||
AgvTask bulidAgvTask(Long businessDetailId, String carrierCode, String startCode, String endCode, String taskType, String type, Integer izAll, String agvVendor);
|
AgvTask bulidAgvTask(Long businessDetailId, String carrierCode, String startCode, String endCode, String taskType, String type, Integer izAll, String agvVendor);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理AGV任务
|
||||||
|
* @param data 扫描数据
|
||||||
|
* @param dstPoint 目标库位
|
||||||
|
*/
|
||||||
|
void processAgvTask(ScanTrayData data, Point dstPoint);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,22 @@ package org.cpte.modules.agvTask.service.impl;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
||||||
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.apache.shiro.SecurityUtils;
|
import org.apache.shiro.SecurityUtils;
|
||||||
import org.cpte.modules.agvTask.entity.AgvTask;
|
import org.cpte.modules.agvTask.entity.AgvTask;
|
||||||
import org.cpte.modules.agvTask.mapper.AgvTaskMapper;
|
import org.cpte.modules.agvTask.mapper.AgvTaskMapper;
|
||||||
import org.cpte.modules.agvTask.service.IAgvTaskService;
|
import org.cpte.modules.agvTask.service.IAgvTaskService;
|
||||||
import org.cpte.modules.constant.enums.AgvStatusEnum;
|
import org.cpte.modules.base.entity.Point;
|
||||||
import org.cpte.modules.constant.enums.AgvVendorEnum;
|
import org.cpte.modules.base.entity.Stock;
|
||||||
import org.cpte.modules.constant.enums.StockTypeEnum;
|
import org.cpte.modules.base.service.IPointService;
|
||||||
|
import org.cpte.modules.base.service.IStockService;
|
||||||
|
import org.cpte.modules.constant.enums.*;
|
||||||
|
import org.cpte.modules.conveyorLine.vo.ScanTrayData;
|
||||||
|
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.shipping.mapper.PickMapper;
|
||||||
import org.jeecg.common.system.vo.LoginUser;
|
import org.jeecg.common.system.vo.LoginUser;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
@ -28,9 +37,18 @@ import java.util.List;
|
||||||
@Service
|
@Service
|
||||||
public class AgvTaskServiceImpl extends ServiceImpl<AgvTaskMapper, AgvTask> implements IAgvTaskService {
|
public class AgvTaskServiceImpl extends ServiceImpl<AgvTaskMapper, AgvTask> implements IAgvTaskService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AsnMapper asnMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AsnDetailMapper asnDetailMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IPointService pointService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public AgvTask createAgvTask(Long businessDetailId, String carrierCode, String startCode, String endCode, String taskType, String type,Integer izAll, String agvVendor) {
|
public AgvTask createAgvTask(Long businessDetailId, String carrierCode, String startCode, String endCode, String taskType, String type, Integer izAll, String agvVendor) {
|
||||||
LoginUser sysUser = null;
|
LoginUser sysUser = null;
|
||||||
try {
|
try {
|
||||||
sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
||||||
|
|
@ -62,7 +80,7 @@ public class AgvTaskServiceImpl extends ServiceImpl<AgvTaskMapper, AgvTask> impl
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AgvTask bulidAgvTask(Long businessDetailId, String carrierCode, String startCode, String endCode, String taskType, String type,Integer izAll, String agvVendor) {
|
public AgvTask bulidAgvTask(Long businessDetailId, String carrierCode, String startCode, String endCode, String taskType, String type, Integer izAll, String agvVendor) {
|
||||||
LoginUser sysUser = null;
|
LoginUser sysUser = null;
|
||||||
try {
|
try {
|
||||||
sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
||||||
|
|
@ -92,4 +110,30 @@ public class AgvTaskServiceImpl extends ServiceImpl<AgvTaskMapper, AgvTask> impl
|
||||||
.createTime(new Date())
|
.createTime(new Date())
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void processAgvTask(ScanTrayData data, Point dstPoint) {
|
||||||
|
Asn asn = data.getAsn();
|
||||||
|
asn.setStatus(AsnStatusEnum.SCAN.getValue());
|
||||||
|
asnMapper.updateById(asn);
|
||||||
|
|
||||||
|
//写入工作站和终点库位
|
||||||
|
Point station = data.getStation();
|
||||||
|
List<AsnDetail> asnDetails = data.getAsnDetails();
|
||||||
|
for (AsnDetail asnDetail : data.getAsnDetails()) {
|
||||||
|
asnDetail.setStationId(station.getId());
|
||||||
|
asnDetail.setToPointId(dstPoint.getId());
|
||||||
|
}
|
||||||
|
if (CollectionUtils.isNotEmpty(asnDetails)) {
|
||||||
|
asnDetailMapper.updateById(asnDetails);
|
||||||
|
}
|
||||||
|
|
||||||
|
//锁定目标库位
|
||||||
|
pointService.bindPoint(dstPoint);
|
||||||
|
|
||||||
|
//验证通过,生成Tes任务
|
||||||
|
Stock stock = data.getStock();
|
||||||
|
createAgvTask(asn.getId(), stock.getStockCode(), station.getPointCode(), dstPoint.getPointCode(), null, BusinessTypeEnum.INBOUND.getValue(), 0, AgvVendorEnum.TES.getValue());
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,11 +55,7 @@ public class AreaController extends JeecgController<Area, IAreaService> {
|
||||||
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
|
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
|
||||||
@RequestParam(name = "keyword", required = false) String keyword,
|
@RequestParam(name = "keyword", required = false) String keyword,
|
||||||
HttpServletRequest req) {
|
HttpServletRequest req) {
|
||||||
// 自定义查询规则
|
QueryWrapper<Area> queryWrapper = QueryGenerator.initQueryWrapper(area, req.getParameterMap());
|
||||||
Map<String, QueryRuleEnum> customeRuleMap = new HashMap<>();
|
|
||||||
customeRuleMap.put("areaCode", QueryRuleEnum.RIGHT_LIKE);
|
|
||||||
customeRuleMap.put("areaName", QueryRuleEnum.RIGHT_LIKE);
|
|
||||||
QueryWrapper<Area> queryWrapper = QueryGenerator.initQueryWrapper(area, req.getParameterMap(), customeRuleMap);
|
|
||||||
// 如果提供了 keyword,则同时对 areaCode 和 areaName 进行模糊搜索
|
// 如果提供了 keyword,则同时对 areaCode 和 areaName 进行模糊搜索
|
||||||
if (StringUtils.isNotBlank(keyword)) {
|
if (StringUtils.isNotBlank(keyword)) {
|
||||||
queryWrapper.and(wrapper -> wrapper.likeRight("area_code", keyword).or().likeRight("area_name", keyword));
|
queryWrapper.and(wrapper -> wrapper.likeRight("area_code", keyword).or().likeRight("area_name", keyword));
|
||||||
|
|
|
||||||
|
|
@ -72,11 +72,8 @@ public class ItemController extends JeecgController<Item, IItemService> {
|
||||||
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
|
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
|
||||||
@RequestParam(name = "keyword", required = false) String keyword,
|
@RequestParam(name = "keyword", required = false) String keyword,
|
||||||
HttpServletRequest req) {
|
HttpServletRequest req) {
|
||||||
// 自定义查询规则
|
|
||||||
Map<String, QueryRuleEnum> customeRuleMap = new HashMap<>();
|
QueryWrapper<Item> queryWrapper = QueryGenerator.initQueryWrapper(item, req.getParameterMap());
|
||||||
customeRuleMap.put("itemCode", QueryRuleEnum.RIGHT_LIKE);
|
|
||||||
customeRuleMap.put("itemName", QueryRuleEnum.RIGHT_LIKE);
|
|
||||||
QueryWrapper<Item> queryWrapper = QueryGenerator.initQueryWrapper(item, req.getParameterMap(),customeRuleMap);
|
|
||||||
// 如果提供了 keyword,则同时对 areaCode 和 areaName 进行模糊搜索
|
// 如果提供了 keyword,则同时对 areaCode 和 areaName 进行模糊搜索
|
||||||
if (StringUtils.isNotBlank(keyword)) {
|
if (StringUtils.isNotBlank(keyword)) {
|
||||||
queryWrapper.and(wrapper -> wrapper.likeRight("item_code", keyword).or().likeRight("item_name", keyword));
|
queryWrapper.and(wrapper -> wrapper.likeRight("item_code", keyword).or().likeRight("item_name", keyword));
|
||||||
|
|
|
||||||
|
|
@ -70,10 +70,7 @@ public class PointController extends JeecgController<Point, IPointService> {
|
||||||
@RequestParam(name = "keyword", required = false) String keyword,
|
@RequestParam(name = "keyword", required = false) String keyword,
|
||||||
HttpServletRequest req) {
|
HttpServletRequest req) {
|
||||||
|
|
||||||
// 自定义查询规则
|
QueryWrapper<Point> queryWrapper = QueryGenerator.initQueryWrapper(point, req.getParameterMap());
|
||||||
Map<String, QueryRuleEnum> customeRuleMap = new HashMap<>();
|
|
||||||
customeRuleMap.put("pointCode", QueryRuleEnum.RIGHT_LIKE);
|
|
||||||
QueryWrapper<Point> queryWrapper = QueryGenerator.initQueryWrapper(point, req.getParameterMap(), customeRuleMap);
|
|
||||||
// 如果提供了 keyword,则同时对 pointCode 模糊搜索
|
// 如果提供了 keyword,则同时对 pointCode 模糊搜索
|
||||||
if (StringUtils.isNotBlank(keyword)) {
|
if (StringUtils.isNotBlank(keyword)) {
|
||||||
queryWrapper.and(wrapper -> wrapper.likeRight("point_code", keyword));
|
queryWrapper.and(wrapper -> wrapper.likeRight("point_code", keyword));
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,12 @@ import java.io.IOException;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.URLDecoder;
|
import java.net.URLDecoder;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.cpte.modules.inventory.entity.Inventory;
|
||||||
|
import org.cpte.modules.inventory.mapper.InventoryMapper;
|
||||||
import org.jeecg.common.api.vo.Result;
|
import org.jeecg.common.api.vo.Result;
|
||||||
import org.jeecg.common.system.query.QueryGenerator;
|
import org.jeecg.common.system.query.QueryGenerator;
|
||||||
import org.jeecg.common.system.query.QueryRuleEnum;
|
import org.jeecg.common.system.query.QueryRuleEnum;
|
||||||
|
|
@ -55,6 +58,9 @@ public class StockController extends JeecgController<Stock, IStockService> {
|
||||||
@Autowired
|
@Autowired
|
||||||
private IStockService stockService;
|
private IStockService stockService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private InventoryMapper inventoryMapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分页列表查询
|
* 分页列表查询
|
||||||
*
|
*
|
||||||
|
|
@ -71,15 +77,22 @@ public class StockController extends JeecgController<Stock, IStockService> {
|
||||||
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
|
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
|
||||||
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
|
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
|
||||||
@RequestParam(name = "keyword", required = false) String keyword,
|
@RequestParam(name = "keyword", required = false) String keyword,
|
||||||
|
@RequestParam(name = "izScan", required = false) boolean izScan,
|
||||||
HttpServletRequest req) {
|
HttpServletRequest req) {
|
||||||
// 自定义查询规则
|
QueryWrapper<Stock> queryWrapper = QueryGenerator.initQueryWrapper(stock, req.getParameterMap());
|
||||||
Map<String, QueryRuleEnum> customeRuleMap = new HashMap<>();
|
|
||||||
customeRuleMap.put("stockCode", QueryRuleEnum.RIGHT_LIKE);
|
|
||||||
QueryWrapper<Stock> queryWrapper = QueryGenerator.initQueryWrapper(stock, req.getParameterMap(), customeRuleMap);
|
|
||||||
// 如果提供了 keyword,则同时对 pointCode 模糊搜索
|
// 如果提供了 keyword,则同时对 pointCode 模糊搜索
|
||||||
if (StringUtils.isNotBlank(keyword)) {
|
if (StringUtils.isNotBlank(keyword)) {
|
||||||
queryWrapper.and(wrapper -> wrapper.likeRight("stock_code", keyword));
|
queryWrapper.and(wrapper -> wrapper.likeRight("stock_code", keyword));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//是否扫描
|
||||||
|
if (izScan) {
|
||||||
|
/*List<Inventory> inventories = inventoryMapper.selectList(null);
|
||||||
|
List<Long> stockIds = inventories.stream().map(Inventory::getStockId).distinct().toList();
|
||||||
|
queryWrapper.notIn("id", stockIds);*/
|
||||||
|
queryWrapper.notExists("SELECT 1 FROM data_inventory WHERE stock_id = base_stock.id");
|
||||||
|
}
|
||||||
|
|
||||||
queryWrapper.orderByAsc("stock_code");
|
queryWrapper.orderByAsc("stock_code");
|
||||||
Page<Stock> page = new Page<Stock>(pageNo, pageSize);
|
Page<Stock> page = new Page<Stock>(pageNo, pageSize);
|
||||||
IPage<Stock> pageList = stockService.page(page, queryWrapper);
|
IPage<Stock> pageList = stockService.page(page, queryWrapper);
|
||||||
|
|
|
||||||
|
|
@ -40,15 +40,7 @@ public class Stock implements Serializable {
|
||||||
@Schema(description = "主键")
|
@Schema(description = "主键")
|
||||||
@JsonSerialize(using = ToStringSerializer.class)
|
@JsonSerialize(using = ToStringSerializer.class)
|
||||||
private java.lang.Long id;
|
private java.lang.Long id;
|
||||||
/**
|
|
||||||
* 库位ID
|
|
||||||
*/
|
|
||||||
@Excel(name = "库位ID", width = 15)
|
|
||||||
@Schema(description = "库位ID")
|
|
||||||
@Dict(dictTable = "base_point", dicCode = "id", dicText = "point_code")
|
|
||||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
|
||||||
@JsonSerialize(using = ToStringSerializer.class)
|
|
||||||
private java.lang.Long pointId;
|
|
||||||
/**
|
/**
|
||||||
* 容器编码
|
* 容器编码
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -42,9 +42,8 @@ public interface IStockService extends IService<Stock> {
|
||||||
* 绑定容器
|
* 绑定容器
|
||||||
*
|
*
|
||||||
* @param stock 容器
|
* @param stock 容器
|
||||||
* @param point 容器位置
|
|
||||||
*/
|
*/
|
||||||
void bindStock(Stock stock, Point point);
|
void bindStock(Stock stock);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据容器编码集合查询容器信息
|
* 根据容器编码集合查询容器信息
|
||||||
|
|
@ -70,5 +69,11 @@ public interface IStockService extends IService<Stock> {
|
||||||
*/
|
*/
|
||||||
Map<Long, Stock> queryByStockIdsToMap(List<Long> stockIds);
|
Map<Long, Stock> queryByStockIdsToMap(List<Long> stockIds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量操作
|
||||||
|
*
|
||||||
|
* @param insertToStock 创建的容器
|
||||||
|
* @param updateToStock 更新的容器
|
||||||
|
*/
|
||||||
|
void batchOperation(List<Stock> insertToStock, List<Stock> updateToStock);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ import com.google.common.collect.Maps;
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.cpte.modules.base.entity.Point;
|
import org.cpte.modules.base.entity.Point;
|
||||||
import org.cpte.modules.base.mapper.PointMapper;
|
import org.cpte.modules.base.mapper.PointMapper;
|
||||||
import org.cpte.modules.base.service.IAreaService;
|
|
||||||
import org.cpte.modules.base.service.IPointService;
|
import org.cpte.modules.base.service.IPointService;
|
||||||
import org.cpte.modules.constant.enums.AreaTypeEnum;
|
import org.cpte.modules.constant.enums.AreaTypeEnum;
|
||||||
import org.cpte.modules.constant.enums.CommonStatusEnum;
|
import org.cpte.modules.constant.enums.CommonStatusEnum;
|
||||||
|
|
@ -29,9 +28,6 @@ import java.util.Map;
|
||||||
@Service
|
@Service
|
||||||
public class PointServiceImpl extends ServiceImpl<PointMapper, Point> implements IPointService {
|
public class PointServiceImpl extends ServiceImpl<PointMapper, Point> implements IPointService {
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IAreaService iAreaService;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private RedisUtil redisUtil;
|
private RedisUtil redisUtil;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,13 @@ import org.cpte.modules.base.service.IStockService;
|
||||||
import org.cpte.modules.constant.enums.CommonStatusEnum;
|
import org.cpte.modules.constant.enums.CommonStatusEnum;
|
||||||
import org.cpte.modules.constant.enums.StockTypeEnum;
|
import org.cpte.modules.constant.enums.StockTypeEnum;
|
||||||
import org.cpte.modules.saiWms.request.SyncStockRequest;
|
import org.cpte.modules.saiWms.request.SyncStockRequest;
|
||||||
|
import org.cpte.modules.utils.BatchUtil;
|
||||||
import org.jeecg.common.system.vo.LoginUser;
|
import org.jeecg.common.system.vo.LoginUser;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
|
@ -28,6 +31,9 @@ import java.util.*;
|
||||||
@Service
|
@Service
|
||||||
public class StockServiceImpl extends ServiceImpl<StockMapper, Stock> implements IStockService {
|
public class StockServiceImpl extends ServiceImpl<StockMapper, Stock> implements IStockService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private BatchUtil batchUtil;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Stock buildStocK(SyncStockRequest.StockDTO stockDTO) {
|
public Stock buildStocK(SyncStockRequest.StockDTO stockDTO) {
|
||||||
LoginUser sysUser = null;
|
LoginUser sysUser = null;
|
||||||
|
|
@ -79,8 +85,7 @@ public class StockServiceImpl extends ServiceImpl<StockMapper, Stock> implements
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void bindStock(Stock stock, Point point) {
|
public void bindStock(Stock stock) {
|
||||||
stock.setPointId(point == null ? null : point.getId());
|
|
||||||
stock.setStatus(CommonStatusEnum.USED.getValue());
|
stock.setStatus(CommonStatusEnum.USED.getValue());
|
||||||
this.baseMapper.updateById(stock);
|
this.baseMapper.updateById(stock);
|
||||||
}
|
}
|
||||||
|
|
@ -134,4 +139,15 @@ public class StockServiceImpl extends ServiceImpl<StockMapper, Stock> implements
|
||||||
}
|
}
|
||||||
return stockMap;
|
return stockMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void batchOperation(List<Stock> insertToStock, List<Stock> updateToStock) {
|
||||||
|
if (CollectionUtils.isNotEmpty(insertToStock)) {
|
||||||
|
batchUtil.saveBatchStock(insertToStock);
|
||||||
|
}
|
||||||
|
if (CollectionUtils.isNotEmpty(updateToStock)) {
|
||||||
|
batchUtil.batchUpdateStocks(updateToStock);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
package org.cpte.modules.conveyorLine.service;
|
package org.cpte.modules.conveyorLine.service;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import org.cpte.modules.base.entity.Point;
|
||||||
|
import org.cpte.modules.base.entity.Stock;
|
||||||
import org.cpte.modules.conveyorLine.request.ScanTrayRequest;
|
import org.cpte.modules.conveyorLine.request.ScanTrayRequest;
|
||||||
|
import org.cpte.modules.receive.entity.Asn;
|
||||||
|
|
||||||
public interface IConveyorLineService {
|
public interface IConveyorLineService {
|
||||||
|
|
||||||
|
|
@ -12,5 +15,11 @@ public interface IConveyorLineService {
|
||||||
*/
|
*/
|
||||||
void scanTray(ScanTrayRequest scanTrayRequest);
|
void scanTray(ScanTrayRequest scanTrayRequest);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示 输送线大屏显示
|
||||||
|
*
|
||||||
|
* @param conveyorLine conveyorLine
|
||||||
|
*/
|
||||||
JSONObject showConveyorLine(String conveyorLine);
|
JSONObject showConveyorLine(String conveyorLine);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ package org.cpte.modules.conveyorLine.service.processor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.cpte.modules.agvTask.mapper.AgvTaskMapper;
|
|
||||||
import org.cpte.modules.agvTask.service.IAgvTaskService;
|
import org.cpte.modules.agvTask.service.IAgvTaskService;
|
||||||
import org.cpte.modules.base.entity.Item;
|
import org.cpte.modules.base.entity.Item;
|
||||||
import org.cpte.modules.base.entity.ItemKey;
|
import org.cpte.modules.base.entity.ItemKey;
|
||||||
|
|
@ -26,7 +25,6 @@ import org.cpte.modules.receive.mapper.AsnDetailMapper;
|
||||||
import org.cpte.modules.receive.mapper.AsnMapper;
|
import org.cpte.modules.receive.mapper.AsnMapper;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
|
@ -61,9 +59,6 @@ public class ScanTrayProcessor {
|
||||||
@Autowired
|
@Autowired
|
||||||
private InventoryMapper inventoryMapper;
|
private InventoryMapper inventoryMapper;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private AgvTaskMapper agvTaskMapper;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private IPointService pointService;
|
private IPointService pointService;
|
||||||
|
|
||||||
|
|
@ -90,7 +85,7 @@ public class ScanTrayProcessor {
|
||||||
Point dstPoint = allocatePoint(data.getItemKeys(), data.getStation(), areaCode);
|
Point dstPoint = allocatePoint(data.getItemKeys(), data.getStation(), areaCode);
|
||||||
|
|
||||||
// 5.生成TES任务
|
// 5.生成TES任务
|
||||||
processAgvTask(data.getAsn(), data.getStock(), data.getStation(), dstPoint);
|
agvTaskService.processAgvTask(data, dstPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -157,6 +152,12 @@ public class ScanTrayProcessor {
|
||||||
private void validateTray(ScanTrayData data) {
|
private void validateTray(ScanTrayData data) {
|
||||||
Long stockId = data.getStock().getId();
|
Long stockId = data.getStock().getId();
|
||||||
String stockCode = data.getStock().getStockCode();
|
String stockCode = data.getStock().getStockCode();
|
||||||
|
Asn asn = data.getAsn();
|
||||||
|
//验证当前托盘是否生成了TES任务
|
||||||
|
if (AsnStatusEnum.SCAN.getValue().equals(asn.getStatus())) {
|
||||||
|
throw new RuntimeException("【" + stockCode + "】托盘已扫描,请勿重复扫描");
|
||||||
|
}
|
||||||
|
|
||||||
List<AsnDetail> asnDetails = asnDetailMapper.queryByStockCode(stockId, AsnStatusEnum.CREATED.getValue());
|
List<AsnDetail> asnDetails = asnDetailMapper.queryByStockCode(stockId, AsnStatusEnum.CREATED.getValue());
|
||||||
if (CollectionUtils.isEmpty(asnDetails)) {
|
if (CollectionUtils.isEmpty(asnDetails)) {
|
||||||
throw new RuntimeException("【" + stockCode + "】托盘,无入库任务");
|
throw new RuntimeException("【" + stockCode + "】托盘,无入库任务");
|
||||||
|
|
@ -167,10 +168,7 @@ public class ScanTrayProcessor {
|
||||||
throw new RuntimeException("【" + stockCode + "】托盘已入库");
|
throw new RuntimeException("【" + stockCode + "】托盘已入库");
|
||||||
}
|
}
|
||||||
|
|
||||||
//验证当前托盘是否生成了TES任务
|
|
||||||
if (agvTaskMapper.existsByStockCode(stockCode, AgvVendorEnum.TES.getValue()) != null) {
|
|
||||||
throw new RuntimeException("【" + stockCode + "】托盘已扫描,请勿重复扫描");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -395,16 +393,4 @@ public class ScanTrayProcessor {
|
||||||
// 距离越小分数越高
|
// 距离越小分数越高
|
||||||
return Math.max(0, 100 - (distance / 100.0));
|
return Math.max(0, 100 - (distance / 100.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@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);
|
|
||||||
|
|
||||||
//验证通过,生成Tes任务
|
|
||||||
agvTaskService.createAgvTask(asn.getId(), stock.getStockCode(), station.getPointCode(), dstPoint.getPointCode(), null, BusinessTypeEnum.INBOUND.getValue(), 0, AgvVendorEnum.TES.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -132,12 +132,6 @@ public class IHikAgvServiceImpl implements IHikAgvService {
|
||||||
if (agvTask == null) {
|
if (agvTask == null) {
|
||||||
throw new RuntimeException("【" + taskReporterRequest.getRobotTaskCode() + "】任务不存在");
|
throw new RuntimeException("【" + taskReporterRequest.getRobotTaskCode() + "】任务不存在");
|
||||||
}
|
}
|
||||||
Point point = null;
|
|
||||||
Stock stock = stock = iStockService.validateStock(agvTask.getCarrierCode());
|
|
||||||
if (BusinessTypeEnum.INBOUND.getValue().equals(agvTask.getType())) {
|
|
||||||
point = iPointService.validatePoint(agvTask.getEndCode());
|
|
||||||
}
|
|
||||||
|
|
||||||
String status = taskReporterRequest.getExtra().getValues().getMethod();
|
String status = taskReporterRequest.getExtra().getValues().getMethod();
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case "outbin":
|
case "outbin":
|
||||||
|
|
@ -146,7 +140,7 @@ public class IHikAgvServiceImpl implements IHikAgvService {
|
||||||
break;
|
break;
|
||||||
case "end":
|
case "end":
|
||||||
//任务完成
|
//任务完成
|
||||||
handleEnd(agvTask, stock, point);
|
handleEnd(agvTask);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -223,11 +217,7 @@ public class IHikAgvServiceImpl implements IHikAgvService {
|
||||||
*
|
*
|
||||||
* @param agvTask 任务
|
* @param agvTask 任务
|
||||||
*/
|
*/
|
||||||
private void handleEnd(AgvTask agvTask, Stock stock, Point point) {
|
private void handleEnd(AgvTask agvTask) {
|
||||||
if (BusinessTypeEnum.INBOUND.getValue().equals(agvTask.getType())) {
|
|
||||||
//绑定容器和点位
|
|
||||||
iStockService.bindStock(stock, point);
|
|
||||||
}
|
|
||||||
//更新任务状态
|
//更新任务状态
|
||||||
agvTask.setStatus(AgvStatusEnum.COMPLETED.getValue());
|
agvTask.setStatus(AgvStatusEnum.COMPLETED.getValue());
|
||||||
agvTask.setEndTime(new Date());
|
agvTask.setEndTime(new Date());
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,6 @@ public class InventoryLogServiceImpl extends ServiceImpl<InventoryLogMapper, Inv
|
||||||
inventoryLog.setChangeQty(BigDecimal.ZERO);
|
inventoryLog.setChangeQty(BigDecimal.ZERO);
|
||||||
inventoryLog.setBeforeAllocatedQty(BigDecimalUtil.subtract(inventory.getQueuedQty(), AllocatedQty, 0));
|
inventoryLog.setBeforeAllocatedQty(BigDecimalUtil.subtract(inventory.getQueuedQty(), AllocatedQty, 0));
|
||||||
inventoryLog.setAfterAllocatedQty(inventory.getQueuedQty());
|
inventoryLog.setAfterAllocatedQty(inventory.getQueuedQty());
|
||||||
log.debug("库存分配日志记录成功,变动前分配数量: {}, 变动后分配数量: {}", inventoryLog.getBeforeAllocatedQty(), inventoryLog.getAfterAllocatedQty());
|
|
||||||
addInventoryLog(inventoryLog);
|
addInventoryLog(inventoryLog);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -93,8 +92,8 @@ public class InventoryLogServiceImpl extends ServiceImpl<InventoryLogMapper, Inv
|
||||||
inventoryLog.setLogType(InventoryLogEnum.UNALLOC.getValue());
|
inventoryLog.setLogType(InventoryLogEnum.UNALLOC.getValue());
|
||||||
// 实际数量不变
|
// 实际数量不变
|
||||||
inventoryLog.setChangeQty(BigDecimal.ZERO);
|
inventoryLog.setChangeQty(BigDecimal.ZERO);
|
||||||
inventoryLog.setBeforeAllocatedQty(inventory.getQueuedQty());
|
inventoryLog.setBeforeAllocatedQty(BigDecimalUtil.add(inventory.getQueuedQty(), cancelQuantity, 0));
|
||||||
inventoryLog.setAfterAllocatedQty(BigDecimalUtil.subtract(inventory.getQueuedQty(), cancelQuantity, 0));
|
inventoryLog.setAfterAllocatedQty(inventory.getQueuedQty());
|
||||||
addInventoryLog(inventoryLog);
|
addInventoryLog(inventoryLog);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -105,9 +104,10 @@ public class InventoryLogServiceImpl extends ServiceImpl<InventoryLogMapper, Inv
|
||||||
// 拣货类型
|
// 拣货类型
|
||||||
inventoryLog.setLogType(InventoryLogEnum.OUTBOUND.getValue());
|
inventoryLog.setLogType(InventoryLogEnum.OUTBOUND.getValue());
|
||||||
// 出库数量为负数
|
// 出库数量为负数
|
||||||
inventoryLog.setBeforeQty(inventory.getQuantity());
|
|
||||||
inventoryLog.setChangeQty(changeQty.negate());
|
inventoryLog.setChangeQty(changeQty.negate());
|
||||||
inventoryLog.setAfterQty(BigDecimalUtil.subtract(inventory.getQuantity(), changeQty, 0));
|
log.info("库存变动日志记录成功,库存数量: {}, 拣货数量: {}", inventory.getQuantity(), changeQty);
|
||||||
|
inventoryLog.setBeforeQty(BigDecimalUtil.add(inventory.getQuantity(), changeQty, 0));
|
||||||
|
inventoryLog.setAfterQty(inventory.getQuantity());
|
||||||
inventoryLog.setAfterAllocatedQty(BigDecimal.ZERO);
|
inventoryLog.setAfterAllocatedQty(BigDecimal.ZERO);
|
||||||
inventoryLog.setBeforeAllocatedQty(BigDecimal.ZERO);
|
inventoryLog.setBeforeAllocatedQty(BigDecimal.ZERO);
|
||||||
inventoryLog.setFromPointId(inventory.getPointId());
|
inventoryLog.setFromPointId(inventory.getPointId());
|
||||||
|
|
|
||||||
|
|
@ -265,4 +265,6 @@ public class AsnController {
|
||||||
return Result.OK("文件导入失败!");
|
return Result.OK("文件导入失败!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,16 @@ public class AsnDetail implements Serializable {
|
||||||
@Schema(description = "起点库位")
|
@Schema(description = "起点库位")
|
||||||
@JsonSerialize(using = ToStringSerializer.class)
|
@JsonSerialize(using = ToStringSerializer.class)
|
||||||
private java.lang.Long fromPointId;
|
private java.lang.Long fromPointId;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工作站库位
|
||||||
|
*/
|
||||||
|
@Schema(description = "工作站")
|
||||||
|
@JsonSerialize(using = ToStringSerializer.class)
|
||||||
|
private java.lang.Long stationId;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 终点库位
|
* 终点库位
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ import org.cpte.modules.base.entity.Item;
|
||||||
import org.cpte.modules.base.entity.ItemKey;
|
import org.cpte.modules.base.entity.ItemKey;
|
||||||
import org.cpte.modules.base.entity.Point;
|
import org.cpte.modules.base.entity.Point;
|
||||||
import org.cpte.modules.base.entity.Stock;
|
import org.cpte.modules.base.entity.Stock;
|
||||||
|
import org.cpte.modules.inventory.entity.Inventory;
|
||||||
|
import org.cpte.modules.inventoryLog.entity.InventoryLog;
|
||||||
import org.cpte.modules.receive.entity.Asn;
|
import org.cpte.modules.receive.entity.Asn;
|
||||||
import org.cpte.modules.receive.entity.AsnDetail;
|
import org.cpte.modules.receive.entity.AsnDetail;
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
|
@ -30,6 +32,24 @@ public interface IAsnDetailService extends IService<AsnDetail> {
|
||||||
*/
|
*/
|
||||||
public List<AsnDetail> selectByMainId(Long mainId);
|
public List<AsnDetail> selectByMainId(Long mainId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存主表信息
|
||||||
|
*
|
||||||
|
* @param asn 入库单
|
||||||
|
* @param asnDetailList 入库明细
|
||||||
|
*/
|
||||||
|
void processorSaveMain(Asn asn, List<AsnDetail> asnDetailList);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 入库处理
|
||||||
|
*
|
||||||
|
* @param inboundRequest 入库参数
|
||||||
|
* @param itemMap 物料
|
||||||
|
* @param srcPoint 起点
|
||||||
|
* @param stock 容器
|
||||||
|
*/
|
||||||
|
void processInboundTask(InboundRequest inboundRequest, Map<String, Item> itemMap, Point srcPoint, Stock stock);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 刷新入库单
|
* 刷新入库单
|
||||||
*
|
*
|
||||||
|
|
@ -38,6 +58,27 @@ public interface IAsnDetailService extends IService<AsnDetail> {
|
||||||
*/
|
*/
|
||||||
void refreshAsn(Asn asn, List<AsnDetail> asnDetails);
|
void refreshAsn(Asn asn, List<AsnDetail> asnDetails);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建入库单
|
||||||
|
*
|
||||||
|
* @param inboundRequest 入库请求
|
||||||
|
* @return Asn
|
||||||
|
*/
|
||||||
|
Asn buildAsn(InboundRequest inboundRequest);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建入库单明细
|
||||||
|
*
|
||||||
|
* @param inboundDetails 入库单明细
|
||||||
|
* @param itemMap 物料信息
|
||||||
|
* @param stock 容器
|
||||||
|
* @param srcPoint 源库位
|
||||||
|
* @param station 工作站
|
||||||
|
* @return AsnDetail
|
||||||
|
*/
|
||||||
|
List<AsnDetail> buildAsnDetail(List<InboundRequest.InboundDetail> inboundDetails, Map<String, Item> itemMap, Stock stock, Point srcPoint, Point station);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构建入库记录
|
* 构建入库记录
|
||||||
*
|
*
|
||||||
|
|
@ -49,5 +90,14 @@ public interface IAsnDetailService extends IService<AsnDetail> {
|
||||||
*/
|
*/
|
||||||
ReceiveRecord buildReceiveRecord(AsnDetail asnDetail, BigDecimal receivedQty, ItemKey itemKey, Long dstPointId);
|
ReceiveRecord buildReceiveRecord(AsnDetail asnDetail, BigDecimal receivedQty, ItemKey itemKey, Long dstPointId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量操作
|
||||||
|
*
|
||||||
|
* @param updateToAsnDetail 更新入库单明细
|
||||||
|
* @param records 创建收货记录
|
||||||
|
* @param inventoryMap 创建库存
|
||||||
|
* @param inventoryLogs 创建库存日志
|
||||||
|
*/
|
||||||
|
void batchOperation(List<AsnDetail> updateToAsnDetail, List<ReceiveRecord> records, Map<Long, Inventory> inventoryMap, List<InventoryLog> inventoryLogs);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,12 @@
|
||||||
package org.cpte.modules.receive.service;
|
package org.cpte.modules.receive.service;
|
||||||
|
|
||||||
|
import org.cpte.modules.agvTask.entity.AgvTask;
|
||||||
import org.cpte.modules.base.entity.Item;
|
import org.cpte.modules.base.entity.Item;
|
||||||
import org.cpte.modules.base.entity.ItemKey;
|
import org.cpte.modules.base.entity.ItemKey;
|
||||||
import org.cpte.modules.base.entity.Point;
|
import org.cpte.modules.base.entity.Point;
|
||||||
import org.cpte.modules.base.entity.Stock;
|
import org.cpte.modules.base.entity.Stock;
|
||||||
|
import org.cpte.modules.inventory.entity.Inventory;
|
||||||
|
import org.cpte.modules.inventoryLog.entity.InventoryLog;
|
||||||
import org.cpte.modules.receive.entity.AsnDetail;
|
import org.cpte.modules.receive.entity.AsnDetail;
|
||||||
import org.cpte.modules.receive.entity.Asn;
|
import org.cpte.modules.receive.entity.Asn;
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
|
@ -54,32 +57,13 @@ public interface IAsnService extends IService<Asn> {
|
||||||
*/
|
*/
|
||||||
public void delBatchMain(Collection<? extends Serializable> idList);
|
public void delBatchMain(Collection<? extends Serializable> idList);
|
||||||
|
|
||||||
/**
|
|
||||||
* 构建入库单
|
|
||||||
*
|
|
||||||
* @param inboundRequest 入库请求
|
|
||||||
* @return Asn
|
|
||||||
*/
|
|
||||||
Asn buildAsn(InboundRequest inboundRequest);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构建入库单明细
|
|
||||||
*
|
|
||||||
* @param inboundDetails 入库单明细
|
|
||||||
* @param itemMap 物料信息
|
|
||||||
* @param stock 容器
|
|
||||||
* @param srcPoint 源库位
|
|
||||||
* @param dstPoint 目标库位
|
|
||||||
* @return AsnDetail
|
|
||||||
*/
|
|
||||||
List<AsnDetail> buildAsnDetail(List<InboundRequest.InboundDetail> inboundDetails, Map<String, Item> itemMap, Stock stock, Point srcPoint, Point dstPoint);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 收货操作
|
* 收货操作
|
||||||
*
|
*
|
||||||
* @param asnId 入库单ID
|
* @param asnId 入库单ID
|
||||||
* @param pointCode 目标库位
|
|
||||||
*/
|
*/
|
||||||
void receiveAsn(Long asnId, String pointCode);
|
void receiveAsn(Long asnId);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,19 @@
|
||||||
package org.cpte.modules.receive.service.impl;
|
package org.cpte.modules.receive.service.impl;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
||||||
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
|
import org.apache.shiro.SecurityUtils;
|
||||||
|
import org.cpte.modules.agvTask.service.IAgvTaskService;
|
||||||
import org.cpte.modules.base.entity.Item;
|
import org.cpte.modules.base.entity.Item;
|
||||||
import org.cpte.modules.base.entity.ItemKey;
|
import org.cpte.modules.base.entity.ItemKey;
|
||||||
import org.cpte.modules.base.entity.Point;
|
import org.cpte.modules.base.entity.Point;
|
||||||
import org.cpte.modules.base.entity.Stock;
|
import org.cpte.modules.base.entity.Stock;
|
||||||
import org.cpte.modules.constant.enums.AsnStatusEnum;
|
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.inventory.entity.Inventory;
|
||||||
|
import org.cpte.modules.inventoryLog.entity.InventoryLog;
|
||||||
import org.cpte.modules.receive.entity.Asn;
|
import org.cpte.modules.receive.entity.Asn;
|
||||||
import org.cpte.modules.receive.entity.AsnDetail;
|
import org.cpte.modules.receive.entity.AsnDetail;
|
||||||
import org.cpte.modules.receive.entity.ReceiveRecord;
|
import org.cpte.modules.receive.entity.ReceiveRecord;
|
||||||
|
|
@ -13,7 +21,9 @@ import org.cpte.modules.receive.mapper.AsnDetailMapper;
|
||||||
import org.cpte.modules.receive.mapper.AsnMapper;
|
import org.cpte.modules.receive.mapper.AsnMapper;
|
||||||
import org.cpte.modules.receive.service.IAsnDetailService;
|
import org.cpte.modules.receive.service.IAsnDetailService;
|
||||||
import org.cpte.modules.saiWms.request.InboundRequest;
|
import org.cpte.modules.saiWms.request.InboundRequest;
|
||||||
import org.cpte.modules.shipping.mapper.PickMapper;
|
import org.cpte.modules.serialNumber.AsnSerialNumberRule;
|
||||||
|
import org.cpte.modules.utils.BatchUtil;
|
||||||
|
import org.jeecg.common.system.vo.LoginUser;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
|
@ -21,9 +31,11 @@ import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description: 入库明细
|
* @Description: 入库明细
|
||||||
|
|
@ -37,11 +49,93 @@ public class AsnDetailServiceImpl extends ServiceImpl<AsnDetailMapper, AsnDetail
|
||||||
@Autowired
|
@Autowired
|
||||||
private AsnMapper asnMapper;
|
private AsnMapper asnMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IPointService pointService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IStockService stockService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IAgvTaskService agvTaskService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private BatchUtil batchUtil;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AsnSerialNumberRule asnSerialNumberRule;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<AsnDetail> selectByMainId(Long mainId) {
|
public List<AsnDetail> selectByMainId(Long mainId) {
|
||||||
return this.baseMapper.selectByMainId(mainId);
|
return this.baseMapper.selectByMainId(mainId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void processorSaveMain(Asn asn, List<AsnDetail> asnDetailList) {
|
||||||
|
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
||||||
|
asn.setTenantId(Long.parseLong(sysUser.getRelTenantIds()));
|
||||||
|
asn.setSysOrgCode(sysUser.getOrgCode());
|
||||||
|
String orderNo = asnSerialNumberRule.generateSerialNumber(GeneralConstant.ASN_ORDER_NO);
|
||||||
|
asn.setOrderNo(orderNo);
|
||||||
|
asnMapper.insert(asn);
|
||||||
|
|
||||||
|
if (asnDetailList == null || asnDetailList.isEmpty()) {
|
||||||
|
throw new RuntimeException("请新增入库明细");
|
||||||
|
}
|
||||||
|
|
||||||
|
AtomicInteger lineNoCounter = new AtomicInteger(1);
|
||||||
|
for (AsnDetail entity : asnDetailList) {
|
||||||
|
if (entity.getLineNo() == null || entity.getLineNo() == 0) {
|
||||||
|
entity.setLineNo(lineNoCounter.getAndIncrement());
|
||||||
|
}
|
||||||
|
entity.setAsnId(asn.getId());
|
||||||
|
entity.setTenantId(Long.parseLong(sysUser.getRelTenantIds()));
|
||||||
|
entity.setSysOrgCode(sysUser.getOrgCode());
|
||||||
|
this.baseMapper.insert(entity);
|
||||||
|
}
|
||||||
|
//刷新入库单
|
||||||
|
refreshAsn(asn, asnDetailList);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void processInboundTask(InboundRequest inboundRequest, Map<String, Item> itemMap, Point srcPoint, Stock stock) {
|
||||||
|
//1.获取工作站
|
||||||
|
Point station = null;
|
||||||
|
if (AsnOrderTypeEnum.PRODUCT.getValue().equals(inboundRequest.getType())) {
|
||||||
|
station = getStationPoint(inboundRequest.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
//2.构建入库单和入库明细
|
||||||
|
Asn asn = buildAsn(inboundRequest);
|
||||||
|
List<AsnDetail> asnDetails = buildAsnDetail(inboundRequest.getDetails(), itemMap, stock, srcPoint, station);
|
||||||
|
processorSaveMain(asn, asnDetails);
|
||||||
|
|
||||||
|
//3.绑定容器
|
||||||
|
stockService.bindStock(stock);
|
||||||
|
|
||||||
|
//4.成品入库,生成AGV任务
|
||||||
|
if (AsnOrderTypeEnum.PRODUCT.getValue().equals(inboundRequest.getType()) && station != null) {
|
||||||
|
agvTaskService.createAgvTask(asn.getId(), stock.getStockCode(), srcPoint.getPointCode(), station.getPointCode(), null, BusinessTypeEnum.INBOUND.getValue(), 0, AgvVendorEnum.HIK.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取工作站
|
||||||
|
*
|
||||||
|
* @param orderType 任务类型
|
||||||
|
* @return Point
|
||||||
|
*/
|
||||||
|
private Point getStationPoint(Integer orderType) {
|
||||||
|
Point dstPoint = null;
|
||||||
|
if (AsnOrderTypeEnum.PRODUCT.getValue().equals(orderType)) {
|
||||||
|
//1.获取入库输送线工作台点位为终点,均衡分配点位-轮询方式
|
||||||
|
dstPoint = pointService.getWorkStationPoint(null, AreaTypeEnum.RK_DOCK.getValue(), GeneralConstant.RK_DOCK_TASK_INDEX);
|
||||||
|
}
|
||||||
|
return dstPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void refreshAsn(Asn asn, List<AsnDetail> asnDetails) {
|
public void refreshAsn(Asn asn, List<AsnDetail> asnDetails) {
|
||||||
|
|
||||||
if (asnDetails == null) {
|
if (asnDetails == null) {
|
||||||
|
|
@ -77,6 +171,45 @@ public class AsnDetailServiceImpl extends ServiceImpl<AsnDetailMapper, AsnDetail
|
||||||
asnMapper.updateById(asn);
|
asnMapper.updateById(asn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Asn buildAsn(InboundRequest inboundRequest) {
|
||||||
|
return Asn.builder()
|
||||||
|
.thirdOrderNo(inboundRequest.getOrderNo())
|
||||||
|
.no(inboundRequest.getNo())
|
||||||
|
.whCode(inboundRequest.getWhCode())
|
||||||
|
.supplierCode(inboundRequest.getSupplierCode())
|
||||||
|
.orderType(inboundRequest.getType())
|
||||||
|
.status(AsnStatusEnum.CREATED.getValue())
|
||||||
|
.orderDate(new Date())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<AsnDetail> buildAsnDetail(List<InboundRequest.InboundDetail> inboundDetails, Map<String, Item> itemMap, Stock stock, Point srcPoint, Point station) {
|
||||||
|
List<AsnDetail> newDetailList = new ArrayList<>();
|
||||||
|
for (InboundRequest.InboundDetail detail : inboundDetails) {
|
||||||
|
AsnDetail asnDetail = AsnDetail.builder()
|
||||||
|
.lineNo(Integer.parseInt(detail.getLineNo()))
|
||||||
|
.itemId(itemMap.get(detail.getItem()).getId())
|
||||||
|
.unit(detail.getUnit())
|
||||||
|
.orderQty(BigDecimal.valueOf(detail.getQty()))
|
||||||
|
.receivedQty(BigDecimal.ZERO)
|
||||||
|
.stockId(stock.getId())
|
||||||
|
.fromPointId(srcPoint == null ? null : srcPoint.getId())
|
||||||
|
.stationId(station== null ? null : station.getId())
|
||||||
|
.status(AsnStatusEnum.CREATED.getValue())
|
||||||
|
.project(detail.getProject())
|
||||||
|
.taskNo(detail.getTaskNo())
|
||||||
|
.propC1(detail.getLotAtt04())
|
||||||
|
.propC3(detail.getLotAtt010())
|
||||||
|
.build();
|
||||||
|
newDetailList.add(asnDetail);
|
||||||
|
}
|
||||||
|
return newDetailList;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ReceiveRecord buildReceiveRecord(AsnDetail asnDetail, BigDecimal receivedQty, ItemKey itemKey, Long dstPointId) {
|
public ReceiveRecord buildReceiveRecord(AsnDetail asnDetail, BigDecimal receivedQty, ItemKey itemKey, Long dstPointId) {
|
||||||
return ReceiveRecord.builder()
|
return ReceiveRecord.builder()
|
||||||
|
|
@ -96,4 +229,23 @@ public class AsnDetailServiceImpl extends ServiceImpl<AsnDetailMapper, AsnDetail
|
||||||
.createTime(new Date())
|
.createTime(new Date())
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
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(records)) {
|
||||||
|
batchUtil.saveBatchReceiveRecord(records);
|
||||||
|
}
|
||||||
|
if (inventoryMap != null && !inventoryMap.isEmpty()) {
|
||||||
|
List<Inventory> createToInventory = new ArrayList<>(inventoryMap.values());
|
||||||
|
batchUtil.saveBatchInventory(createToInventory);
|
||||||
|
}
|
||||||
|
if (CollectionUtils.isNotEmpty(inventoryLogs)) {
|
||||||
|
batchUtil.saveBatchInventoryLog(inventoryLogs);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,10 @@ package org.cpte.modules.receive.service.impl;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.shiro.SecurityUtils;
|
import org.cpte.modules.agvTask.entity.AgvTask;
|
||||||
import org.cpte.modules.base.entity.Item;
|
import org.cpte.modules.base.entity.Item;
|
||||||
import org.cpte.modules.base.entity.Point;
|
import org.cpte.modules.base.entity.Point;
|
||||||
import org.cpte.modules.base.entity.Stock;
|
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.AsnStatusEnum;
|
||||||
import org.cpte.modules.receive.entity.Asn;
|
import org.cpte.modules.receive.entity.Asn;
|
||||||
import org.cpte.modules.receive.entity.AsnDetail;
|
import org.cpte.modules.receive.entity.AsnDetail;
|
||||||
|
|
@ -16,12 +15,7 @@ import org.cpte.modules.receive.service.IAsnDetailService;
|
||||||
import org.cpte.modules.receive.service.IAsnService;
|
import org.cpte.modules.receive.service.IAsnService;
|
||||||
import org.cpte.modules.receive.service.processor.ReceiveProcessor;
|
import org.cpte.modules.receive.service.processor.ReceiveProcessor;
|
||||||
import org.cpte.modules.saiWms.request.InboundRequest;
|
import org.cpte.modules.saiWms.request.InboundRequest;
|
||||||
import org.cpte.modules.serialNumber.AsnSerialNumberRule;
|
|
||||||
import org.cpte.modules.utils.RedisDistributedLockUtil;
|
import org.cpte.modules.utils.RedisDistributedLockUtil;
|
||||||
import org.cpte.modules.utils.SwmsLoginUtil;
|
|
||||||
import org.jeecg.common.system.vo.LoginUser;
|
|
||||||
import org.jeecg.modules.openapi.mapper.OpenApiMapper;
|
|
||||||
import org.jeecg.modules.system.mapper.SysDictMapper;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
@ -42,22 +36,13 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnService {
|
public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnService {
|
||||||
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private AsnDetailMapper asnDetailMapper;
|
private AsnDetailMapper asnDetailMapper;
|
||||||
@Autowired
|
@Autowired
|
||||||
private OpenApiMapper openApiMapper;
|
|
||||||
@Autowired
|
|
||||||
private SysDictMapper sysDictMapper;
|
|
||||||
@Autowired
|
|
||||||
private IAsnDetailService asnDetailService;
|
private IAsnDetailService asnDetailService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private ReceiveProcessor receiveProcessor;
|
private ReceiveProcessor receiveProcessor;
|
||||||
@Autowired
|
@Autowired
|
||||||
private SwmsLoginUtil swmsLoginUtil;
|
|
||||||
@Autowired
|
|
||||||
private AsnSerialNumberRule asnSerialNumberRule;
|
|
||||||
@Autowired
|
|
||||||
private RedisDistributedLockUtil redissonLock;
|
private RedisDistributedLockUtil redissonLock;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -69,7 +54,7 @@ public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnS
|
||||||
if (StringUtils.isEmpty(lockValue)) {
|
if (StringUtils.isEmpty(lockValue)) {
|
||||||
throw new RuntimeException("入库单创建中,请稍后重试");
|
throw new RuntimeException("入库单创建中,请稍后重试");
|
||||||
}
|
}
|
||||||
processorSaveMain(asn, asnDetailList);
|
asnDetailService.processorSaveMain(asn, asnDetailList);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("入库单创建异常", e);
|
log.error("入库单创建异常", e);
|
||||||
throw e;
|
throw e;
|
||||||
|
|
@ -80,40 +65,6 @@ public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 保存主表信息
|
|
||||||
*
|
|
||||||
* @param asn 入库单
|
|
||||||
* @param asnDetailList 入库明细
|
|
||||||
*/
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
|
||||||
public void processorSaveMain(Asn asn, List<AsnDetail> asnDetailList) {
|
|
||||||
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
|
||||||
asn.setTenantId(Long.parseLong(sysUser.getRelTenantIds()));
|
|
||||||
asn.setSysOrgCode(sysUser.getOrgCode());
|
|
||||||
String orderNo = asnSerialNumberRule.generateSerialNumber(GeneralConstant.ASN_ORDER_NO);
|
|
||||||
asn.setOrderNo(orderNo);
|
|
||||||
this.baseMapper.insert(asn);
|
|
||||||
|
|
||||||
if (asnDetailList == null || asnDetailList.isEmpty()) {
|
|
||||||
throw new RuntimeException("请新增入库明细");
|
|
||||||
}
|
|
||||||
|
|
||||||
AtomicInteger lineNoCounter = new AtomicInteger(1);
|
|
||||||
for (AsnDetail entity : asnDetailList) {
|
|
||||||
if (entity.getLineNo() == null || entity.getLineNo() == 0) {
|
|
||||||
entity.setLineNo(lineNoCounter.getAndIncrement());
|
|
||||||
}
|
|
||||||
entity.setAsnId(asn.getId());
|
|
||||||
entity.setTenantId(Long.parseLong(sysUser.getRelTenantIds()));
|
|
||||||
entity.setSysOrgCode(sysUser.getOrgCode());
|
|
||||||
asnDetailMapper.insert(entity);
|
|
||||||
}
|
|
||||||
//刷新入库单
|
|
||||||
asnDetailService.refreshAsn(asn, asnDetailList);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void updateMain(Asn asn, List<AsnDetail> asnDetailList) {
|
public void updateMain(Asn asn, List<AsnDetail> asnDetailList) {
|
||||||
|
|
@ -123,10 +74,6 @@ public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnS
|
||||||
throw new RuntimeException("请新增入库明细");
|
throw new RuntimeException("请新增入库明细");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (asnDetailList.size() > 1) {
|
|
||||||
throw new RuntimeException("入库明细只允许新增一条");
|
|
||||||
}
|
|
||||||
|
|
||||||
AtomicInteger lineNoCounter = new AtomicInteger(1);
|
AtomicInteger lineNoCounter = new AtomicInteger(1);
|
||||||
for (AsnDetail entity : asnDetailList) {
|
for (AsnDetail entity : asnDetailList) {
|
||||||
if (entity.getLineNo() == null || entity.getLineNo() == 0) {
|
if (entity.getLineNo() == null || entity.getLineNo() == 0) {
|
||||||
|
|
@ -172,47 +119,8 @@ public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnS
|
||||||
throw new RuntimeException("操作失败:【" + orderNoList + "】入库单,非创建状态不允许删除");
|
throw new RuntimeException("操作失败:【" + orderNoList + "】入库单,非创建状态不允许删除");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Asn buildAsn(InboundRequest inboundRequest) {
|
public void receiveAsn(Long asnId) {
|
||||||
return Asn.builder()
|
|
||||||
.thirdOrderNo(inboundRequest.getOrderNo())
|
|
||||||
.no(inboundRequest.getNo())
|
|
||||||
.whCode(inboundRequest.getWhCode())
|
|
||||||
.supplierCode(inboundRequest.getSupplierCode())
|
|
||||||
.orderType(inboundRequest.getType())
|
|
||||||
.status(AsnStatusEnum.CREATED.getValue())
|
|
||||||
.orderDate(new Date())
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<AsnDetail> buildAsnDetail(List<InboundRequest.InboundDetail> inboundDetails, Map<String, Item> itemMap, Stock stock, Point srcPoint, Point dstPoint) {
|
|
||||||
List<AsnDetail> newDetailList = new ArrayList<>();
|
|
||||||
for (InboundRequest.InboundDetail detail : inboundDetails) {
|
|
||||||
AsnDetail asnDetail = AsnDetail.builder()
|
|
||||||
.lineNo(Integer.parseInt(detail.getLineNo()))
|
|
||||||
.itemId(itemMap.get(detail.getItem()).getId())
|
|
||||||
.unit(detail.getUnit())
|
|
||||||
.orderQty(BigDecimal.valueOf(detail.getQty()))
|
|
||||||
.receivedQty(BigDecimal.ZERO)
|
|
||||||
.stockId(stock.getId())
|
|
||||||
.fromPointId(srcPoint == null ? null : srcPoint.getId())
|
|
||||||
.toPointId(dstPoint == null ? null : dstPoint.getId())
|
|
||||||
.status(AsnStatusEnum.CREATED.getValue())
|
|
||||||
.project(detail.getProject())
|
|
||||||
.taskNo(detail.getTaskNo())
|
|
||||||
.propC1(detail.getLotAtt04())
|
|
||||||
.propC3(detail.getLotAtt010())
|
|
||||||
.build();
|
|
||||||
newDetailList.add(asnDetail);
|
|
||||||
}
|
|
||||||
return newDetailList;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void receiveAsn(Long asnId, String pointCode) {
|
|
||||||
String lockKey = "asn:" + asnId;
|
String lockKey = "asn:" + asnId;
|
||||||
String lockValue = null;
|
String lockValue = null;
|
||||||
try {
|
try {
|
||||||
|
|
@ -220,7 +128,7 @@ public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnS
|
||||||
if (StringUtils.isEmpty(lockValue)) {
|
if (StringUtils.isEmpty(lockValue)) {
|
||||||
throw new RuntimeException("收货处理中,请稍后重试");
|
throw new RuntimeException("收货处理中,请稍后重试");
|
||||||
}
|
}
|
||||||
receiveProcessor.receiveAsn(asnId, pointCode);
|
receiveProcessor.receiveAsn(asnId);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("收货处理异常", e);
|
log.error("收货处理异常", e);
|
||||||
throw e;
|
throw e;
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,6 @@ import org.cpte.modules.base.entity.Stock;
|
||||||
import org.cpte.modules.base.mapper.PointMapper;
|
import org.cpte.modules.base.mapper.PointMapper;
|
||||||
import org.cpte.modules.base.mapper.StockMapper;
|
import org.cpte.modules.base.mapper.StockMapper;
|
||||||
import org.cpte.modules.base.service.IItemKeyService;
|
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.enums.AsnStatusEnum;
|
import org.cpte.modules.constant.enums.AsnStatusEnum;
|
||||||
import org.cpte.modules.inventory.entity.Inventory;
|
import org.cpte.modules.inventory.entity.Inventory;
|
||||||
import org.cpte.modules.inventory.service.IInventoryService;
|
import org.cpte.modules.inventory.service.IInventoryService;
|
||||||
|
|
@ -22,11 +20,9 @@ import org.cpte.modules.receive.mapper.AsnDetailMapper;
|
||||||
import org.cpte.modules.receive.mapper.AsnMapper;
|
import org.cpte.modules.receive.mapper.AsnMapper;
|
||||||
import org.cpte.modules.receive.service.IAsnDetailService;
|
import org.cpte.modules.receive.service.IAsnDetailService;
|
||||||
import org.cpte.modules.receive.vo.ReceiveData;
|
import org.cpte.modules.receive.vo.ReceiveData;
|
||||||
import org.cpte.modules.utils.BatchUtil;
|
|
||||||
import org.cpte.modules.utils.BigDecimalUtil;
|
import org.cpte.modules.utils.BigDecimalUtil;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
@ -42,10 +38,10 @@ import java.util.Map;
|
||||||
public class ReceiveProcessor {
|
public class ReceiveProcessor {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private StockMapper stockMapper;
|
private PointMapper pointMapper;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private PointMapper pointMapper;
|
private StockMapper stockMapper;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private AsnMapper asnMapper;
|
private AsnMapper asnMapper;
|
||||||
|
|
@ -53,12 +49,6 @@ public class ReceiveProcessor {
|
||||||
@Autowired
|
@Autowired
|
||||||
private AsnDetailMapper asnDetailMapper;
|
private AsnDetailMapper asnDetailMapper;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IStockService stockService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IPointService pointService;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private IAsnDetailService asnDetailService;
|
private IAsnDetailService asnDetailService;
|
||||||
|
|
||||||
|
|
@ -74,18 +64,15 @@ public class ReceiveProcessor {
|
||||||
@Autowired
|
@Autowired
|
||||||
private ReceiveBackProcessor receiveBackProcessor;
|
private ReceiveBackProcessor receiveBackProcessor;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private BatchUtil batchUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 收货
|
* 收货
|
||||||
*
|
*
|
||||||
* @param asnId 入库单
|
* @param asnId 入库单
|
||||||
* @param dstPointCode 目标库位
|
|
||||||
*/
|
*/
|
||||||
public void receiveAsn(Long asnId, String dstPointCode) {
|
public void receiveAsn(Long asnId) {
|
||||||
// 1.数据准备
|
// 1.数据准备
|
||||||
ReceiveData data = prepareReceiveData(asnId, dstPointCode);
|
ReceiveData data = prepareReceiveData(asnId);
|
||||||
|
|
||||||
//3.创建数据结构
|
//3.创建数据结构
|
||||||
List<AsnDetail> updateToAsnDetail = new ArrayList<>();
|
List<AsnDetail> updateToAsnDetail = new ArrayList<>();
|
||||||
|
|
@ -97,14 +84,11 @@ public class ReceiveProcessor {
|
||||||
receive(data, updateToAsnDetail, createRecords, inventoryMap, createInventoryLogs);
|
receive(data, updateToAsnDetail, createRecords, inventoryMap, createInventoryLogs);
|
||||||
|
|
||||||
//5.批量操作
|
//5.批量操作
|
||||||
batchOperation(updateToAsnDetail, createRecords, inventoryMap, createInventoryLogs);
|
asnDetailService.batchOperation(updateToAsnDetail, createRecords, inventoryMap, createInventoryLogs);
|
||||||
|
|
||||||
//6.刷新入库
|
//6.刷新入库
|
||||||
refreshData(data);
|
refreshData(data);
|
||||||
|
|
||||||
//7.更新容器状态和位置
|
|
||||||
updateStockAndPoint(data.getStock(), data.getDstPoint());
|
|
||||||
|
|
||||||
//8.回传
|
//8.回传
|
||||||
receiveBackProcessor.receiveBack(data.getAsn(), data.getStock());
|
receiveBackProcessor.receiveBack(data.getAsn(), data.getStock());
|
||||||
}
|
}
|
||||||
|
|
@ -112,11 +96,10 @@ public class ReceiveProcessor {
|
||||||
/**
|
/**
|
||||||
* 数据准备
|
* 数据准备
|
||||||
*
|
*
|
||||||
* @param asnId 入库单
|
* @param asnId 入库单
|
||||||
* @param dstPointCode 目标库位
|
|
||||||
* @return ReceiveData
|
* @return ReceiveData
|
||||||
*/
|
*/
|
||||||
private ReceiveData prepareReceiveData(Long asnId, String dstPointCode) {
|
private ReceiveData prepareReceiveData(Long asnId) {
|
||||||
ReceiveData data = new ReceiveData();
|
ReceiveData data = new ReceiveData();
|
||||||
Asn asn = asnMapper.selectById(asnId);
|
Asn asn = asnMapper.selectById(asnId);
|
||||||
data.setAsn(asn);
|
data.setAsn(asn);
|
||||||
|
|
@ -124,13 +107,13 @@ public class ReceiveProcessor {
|
||||||
List<AsnDetail> asnDetails = asnDetailMapper.selectByMainId(asnId);
|
List<AsnDetail> asnDetails = asnDetailMapper.selectByMainId(asnId);
|
||||||
if (CollectionUtils.isNotEmpty(asnDetails)) {
|
if (CollectionUtils.isNotEmpty(asnDetails)) {
|
||||||
data.setAsnDetails(asnDetails);
|
data.setAsnDetails(asnDetails);
|
||||||
|
|
||||||
Stock stock = stockMapper.selectById(asnDetails.get(0).getStockId());
|
Stock stock = stockMapper.selectById(asnDetails.get(0).getStockId());
|
||||||
data.setStock(stock);
|
data.setStock(stock);
|
||||||
|
|
||||||
|
Point point = pointMapper.selectById(asnDetails.get(0).getToPointId());
|
||||||
|
data.setPoint(point);
|
||||||
}
|
}
|
||||||
|
|
||||||
Point dstPoint = pointMapper.queryByPointCode(dstPointCode);
|
|
||||||
data.setDstPoint(dstPoint);
|
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -149,8 +132,7 @@ public class ReceiveProcessor {
|
||||||
Map<Long, Inventory> inventoryMap,
|
Map<Long, Inventory> inventoryMap,
|
||||||
List<InventoryLog> inventoryLogs) {
|
List<InventoryLog> inventoryLogs) {
|
||||||
Asn asn = data.getAsn();
|
Asn asn = data.getAsn();
|
||||||
Point dstPoint = data.getDstPoint();
|
|
||||||
Stock stock = data.getStock();
|
|
||||||
for (AsnDetail asnDetail : data.getAsnDetails()) {
|
for (AsnDetail asnDetail : data.getAsnDetails()) {
|
||||||
BigDecimal unreceivedQty = BigDecimalUtil.subtract(asnDetail.getOrderQty(), asnDetail.getReceivedQty(), 0);
|
BigDecimal unreceivedQty = BigDecimalUtil.subtract(asnDetail.getOrderQty(), asnDetail.getReceivedQty(), 0);
|
||||||
if (unreceivedQty.compareTo(BigDecimal.ZERO) <= 0) {
|
if (unreceivedQty.compareTo(BigDecimal.ZERO) <= 0) {
|
||||||
|
|
@ -170,14 +152,14 @@ public class ReceiveProcessor {
|
||||||
ItemKey itemKey = itemKeyService.createItemKey(asnDetail.getItemId(), asn.getWhCode(), asnDetail.getProject(), asnDetail.getTaskNo(), asnDetail.getPropC1(), asnDetail.getPropC3());
|
ItemKey itemKey = itemKeyService.createItemKey(asnDetail.getItemId(), asn.getWhCode(), asnDetail.getProject(), asnDetail.getTaskNo(), asnDetail.getPropC1(), asnDetail.getPropC3());
|
||||||
|
|
||||||
//生成入库记录
|
//生成入库记录
|
||||||
ReceiveRecord receiveRecord = asnDetailService.buildReceiveRecord(asnDetail, receivedQty, itemKey, dstPoint.getId());
|
ReceiveRecord receiveRecord = asnDetailService.buildReceiveRecord(asnDetail, receivedQty, itemKey, asnDetail.getToPointId());
|
||||||
records.add(receiveRecord);
|
records.add(receiveRecord);
|
||||||
|
|
||||||
// 生成库存
|
// 生成库存
|
||||||
Inventory inventory = createInventory(asn, receiveRecord, itemKey, stock, receivedQty, inventoryMap);
|
Inventory inventory = createInventory(asn, receiveRecord, itemKey, asnDetail.getStockId(), receivedQty, inventoryMap);
|
||||||
|
|
||||||
//添加库存日志
|
//添加库存日志
|
||||||
InventoryLog inventoryLog = inventoryLogService.buildInboundInventoryLog(inventory, asnDetail.getToPointId(),receivedQty, asn.getThirdOrderNo(), receiveRecord.getId(), receiveRecord.getDescription());
|
InventoryLog inventoryLog = inventoryLogService.buildInboundInventoryLog(inventory, asnDetail.getFromPointId() == null ? asnDetail.getStationId() : asnDetail.getFromPointId(), receivedQty, asn.getThirdOrderNo(), receiveRecord.getId(), receiveRecord.getDescription());
|
||||||
inventoryLogs.add(inventoryLog);
|
inventoryLogs.add(inventoryLog);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -189,12 +171,12 @@ public class ReceiveProcessor {
|
||||||
* @param asn 入库单
|
* @param asn 入库单
|
||||||
* @param receiveRecord 收货记录
|
* @param receiveRecord 收货记录
|
||||||
* @param itemKey 物料属性
|
* @param itemKey 物料属性
|
||||||
* @param stock 容器
|
* @param stockId 容器
|
||||||
* @param receivedQty 收货数量
|
* @param receivedQty 收货数量
|
||||||
* @param inventoryMap 创建库存
|
* @param inventoryMap 创建库存
|
||||||
*/
|
*/
|
||||||
private Inventory createInventory(Asn asn, ReceiveRecord receiveRecord, ItemKey itemKey, Stock stock, BigDecimal receivedQty, Map<Long, Inventory> inventoryMap) {
|
private Inventory createInventory(Asn asn, ReceiveRecord receiveRecord, ItemKey itemKey, Long stockId, BigDecimal receivedQty, Map<Long, Inventory> inventoryMap) {
|
||||||
Inventory inventory = inventoryService.buildInventory(stock.getId(), BigDecimal.ZERO, asn, receiveRecord);
|
Inventory inventory = inventoryService.buildInventory(stockId, BigDecimal.ZERO, asn, receiveRecord);
|
||||||
//根据itemKey更新库存
|
//根据itemKey更新库存
|
||||||
Inventory targetInventory = inventoryMap.getOrDefault(itemKey.getId(), inventory);
|
Inventory targetInventory = inventoryMap.getOrDefault(itemKey.getId(), inventory);
|
||||||
BigDecimal newReceivedQty = BigDecimalUtil.add(targetInventory.getQuantity(), receivedQty, 0);
|
BigDecimal newReceivedQty = BigDecimalUtil.add(targetInventory.getQuantity(), receivedQty, 0);
|
||||||
|
|
@ -203,33 +185,6 @@ public class ReceiveProcessor {
|
||||||
return targetInventory;
|
return targetInventory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 批量操作
|
|
||||||
*
|
|
||||||
* @param updateToAsnDetail 更新入库单明细
|
|
||||||
* @param records 创建收货记录
|
|
||||||
* @param inventoryMap 创建库存
|
|
||||||
* @param inventoryLogs 创建库存日志
|
|
||||||
*/
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
|
||||||
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(records)) {
|
|
||||||
batchUtil.saveBatchReceiveRecord(records);
|
|
||||||
}
|
|
||||||
if (inventoryMap != null && !inventoryMap.isEmpty()) {
|
|
||||||
List<Inventory> createToInventory = new ArrayList<>(inventoryMap.values());
|
|
||||||
batchUtil.saveBatchInventory(createToInventory);
|
|
||||||
}
|
|
||||||
if (CollectionUtils.isNotEmpty(inventoryLogs)) {
|
|
||||||
batchUtil.saveBatchInventoryLog(inventoryLogs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 刷新出库单
|
* 刷新出库单
|
||||||
*
|
*
|
||||||
|
|
@ -239,16 +194,4 @@ public class ReceiveProcessor {
|
||||||
asnDetailService.refreshAsn(data.getAsn(), data.getAsnDetails());
|
asnDetailService.refreshAsn(data.getAsn(), data.getAsnDetails());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新容器状态和位置
|
|
||||||
*
|
|
||||||
* @param stock 托盘
|
|
||||||
* @param dstPoint 目标库位
|
|
||||||
*/
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
|
||||||
public void updateStockAndPoint(Stock stock, Point dstPoint) {
|
|
||||||
//更新容器状态和位置
|
|
||||||
stockService.bindStock(stock, dstPoint);
|
|
||||||
pointService.bindPoint(dstPoint);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,5 +13,5 @@ public class ReceiveData {
|
||||||
private Asn asn ;
|
private Asn asn ;
|
||||||
private List<AsnDetail> asnDetails;
|
private List<AsnDetail> asnDetails;
|
||||||
private Stock stock;
|
private Stock stock;
|
||||||
private Point dstPoint;
|
private Point point;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.cpte.modules.receive.service.IAsnService;
|
||||||
import org.cpte.modules.saiWms.request.CallAgvRequest;
|
import org.cpte.modules.saiWms.request.CallAgvRequest;
|
||||||
import org.cpte.modules.saiWms.request.InboundRequest;
|
import org.cpte.modules.saiWms.request.InboundRequest;
|
||||||
import org.cpte.modules.saiWms.request.OutboundRequest;
|
import org.cpte.modules.saiWms.request.OutboundRequest;
|
||||||
|
|
@ -11,6 +12,7 @@ import org.cpte.modules.saiWms.request.SyncStockRequest;
|
||||||
import org.cpte.modules.saiWms.service.ISMOMService;
|
import org.cpte.modules.saiWms.service.ISMOMService;
|
||||||
import org.jeecg.common.api.vo.Result;
|
import org.jeecg.common.api.vo.Result;
|
||||||
import org.jeecg.common.aspect.annotation.AutoLog;
|
import org.jeecg.common.aspect.annotation.AutoLog;
|
||||||
|
import org.jeecg.config.shiro.IgnoreAuth;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
|
@ -26,6 +28,9 @@ public class SaiWmsController {
|
||||||
@Autowired
|
@Autowired
|
||||||
private ISMOMService iSaiWmsService;
|
private ISMOMService iSaiWmsService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IAsnService asnService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 容器同步
|
* 容器同步
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -36,12 +36,44 @@ public class ISMOMServiceImpl implements ISMOMService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void inBoundTask(InboundRequest inboundRequest) {
|
public void inBoundTask(InboundRequest inboundRequest) {
|
||||||
inBoundTaskProcessor.inBoundTask(inboundRequest);
|
//5.入库处理
|
||||||
|
String lockKey = "inbound:" + inboundRequest.getNo();
|
||||||
|
String lockValue = null;
|
||||||
|
try {
|
||||||
|
lockValue = redissonLock.tryLock(lockKey, 10);
|
||||||
|
if (StringUtils.isEmpty(lockValue)) {
|
||||||
|
throw new RuntimeException("入库单接收中,请稍后重试");
|
||||||
|
}
|
||||||
|
inBoundTaskProcessor.inBoundTask(inboundRequest);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("入库单接收异常", e);
|
||||||
|
throw e;
|
||||||
|
} finally {
|
||||||
|
if (StringUtils.isNotEmpty(lockValue)) {
|
||||||
|
redissonLock.unlock(lockKey, lockValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void outBoundTask(OutboundRequest outboundRequest) {
|
public void outBoundTask(OutboundRequest outboundRequest) {
|
||||||
outBoundTaskProcessor.outBoundTask(outboundRequest);
|
String lockKey = "outbound:" + outboundRequest.getNo();
|
||||||
|
String lockValue = null;
|
||||||
|
try {
|
||||||
|
lockValue = redissonLock.tryLock(lockKey, 10);
|
||||||
|
if (StringUtils.isEmpty(lockValue)) {
|
||||||
|
throw new RuntimeException("出库单接收中,请稍后重试");
|
||||||
|
}
|
||||||
|
outBoundTaskProcessor.outBoundTask(outboundRequest);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("出库单接收异常", e);
|
||||||
|
throw e;
|
||||||
|
} finally {
|
||||||
|
if (StringUtils.isNotEmpty(lockValue)) {
|
||||||
|
redissonLock.unlock(lockKey, lockValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,10 @@ import org.cpte.modules.inventory.mapper.InventoryMapper;
|
||||||
import org.cpte.modules.receive.entity.Asn;
|
import org.cpte.modules.receive.entity.Asn;
|
||||||
import org.cpte.modules.receive.entity.AsnDetail;
|
import org.cpte.modules.receive.entity.AsnDetail;
|
||||||
import org.cpte.modules.receive.mapper.AsnMapper;
|
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.IAsnService;
|
||||||
import org.cpte.modules.saiWms.request.InboundRequest;
|
import org.cpte.modules.saiWms.request.InboundRequest;
|
||||||
|
import org.cpte.modules.utils.RedisDistributedLockUtil;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
@ -53,10 +55,7 @@ public class InBoundTaskProcessor {
|
||||||
private IPointService pointService;
|
private IPointService pointService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private IAsnService asnService;
|
private IAsnDetailService asnDetailService;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IAgvTaskService agvTaskService;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 接收入库任务
|
* 接收入库任务
|
||||||
|
|
@ -77,34 +76,7 @@ public class InBoundTaskProcessor {
|
||||||
Point srcPoint = validateSrcPoint(inboundRequest.getType(), inboundRequest.getLocationFrom());
|
Point srcPoint = validateSrcPoint(inboundRequest.getType(), inboundRequest.getLocationFrom());
|
||||||
|
|
||||||
//5.入库处理
|
//5.入库处理
|
||||||
processInboundTask(inboundRequest, itemMap, srcPoint, stock);
|
asnDetailService.processInboundTask(inboundRequest, itemMap, srcPoint, stock);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 入库处理
|
|
||||||
*
|
|
||||||
* @param inboundRequest 入库参数
|
|
||||||
* @param itemMap 物料
|
|
||||||
* @param srcPoint 起点
|
|
||||||
* @param stock 容器
|
|
||||||
*/
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
|
||||||
private void processInboundTask(InboundRequest inboundRequest, Map<String, Item> itemMap, Point srcPoint, Stock stock) {
|
|
||||||
//1.获取终点
|
|
||||||
Point dstPoint = getDstPoint(inboundRequest.getType());
|
|
||||||
|
|
||||||
//2.构建入库单和入库明细
|
|
||||||
Asn createAsn = asnService.buildAsn(inboundRequest);
|
|
||||||
List<AsnDetail> asnDetails = asnService.buildAsnDetail(inboundRequest.getDetails(), itemMap, stock, srcPoint, dstPoint);
|
|
||||||
asnService.saveMain(createAsn, asnDetails);
|
|
||||||
|
|
||||||
//3.绑定容器和起点
|
|
||||||
stockService.bindStock(stock, srcPoint);
|
|
||||||
|
|
||||||
//4.成品入库,生成AGV任务
|
|
||||||
if (AsnOrderTypeEnum.PRODUCT.getValue().equals(inboundRequest.getType())) {
|
|
||||||
agvTaskService.createAgvTask(createAsn.getId(), stock.getStockCode(), srcPoint.getPointCode(), dstPoint.getPointCode(), null, BusinessTypeEnum.INBOUND.getValue(), 0, AgvVendorEnum.HIK.getValue());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -229,19 +201,4 @@ public class InBoundTaskProcessor {
|
||||||
return srcPoint;
|
return srcPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取终点
|
|
||||||
*
|
|
||||||
* @param orderType 任务类型
|
|
||||||
* @return Point
|
|
||||||
*/
|
|
||||||
private Point getDstPoint(Integer orderType) {
|
|
||||||
Point dstPoint = null;
|
|
||||||
if (AsnOrderTypeEnum.PRODUCT.getValue().equals(orderType)) {
|
|
||||||
//1.获取入库输送线工作台点位为终点,均衡分配点位-轮询方式
|
|
||||||
dstPoint = pointService.getWorkStationPoint(null, AreaTypeEnum.RK_DOCK.getValue(), GeneralConstant.RK_DOCK_TASK_INDEX);
|
|
||||||
}
|
|
||||||
return dstPoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import org.cpte.modules.saiWms.request.OutboundRequest;
|
||||||
import org.cpte.modules.shipping.entity.Pick;
|
import org.cpte.modules.shipping.entity.Pick;
|
||||||
import org.cpte.modules.shipping.entity.PickDetail;
|
import org.cpte.modules.shipping.entity.PickDetail;
|
||||||
import org.cpte.modules.shipping.mapper.PickMapper;
|
import org.cpte.modules.shipping.mapper.PickMapper;
|
||||||
|
import org.cpte.modules.shipping.service.IPickDetailService;
|
||||||
import org.cpte.modules.shipping.service.IPickService;
|
import org.cpte.modules.shipping.service.IPickService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
@ -39,7 +40,7 @@ public class OutBoundTaskProcessor {
|
||||||
private IPointService pointService;
|
private IPointService pointService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private IPickService pickService;
|
private IPickDetailService pickDetailService;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -58,24 +59,9 @@ public class OutBoundTaskProcessor {
|
||||||
Map<String, Item> itemMap = validateItem(outboundRequest.getDetails());
|
Map<String, Item> itemMap = validateItem(outboundRequest.getDetails());
|
||||||
|
|
||||||
//5.出库处理
|
//5.出库处理
|
||||||
processOutBoundTask(outboundRequest, itemMap);
|
pickDetailService.processOutBoundTask(outboundRequest, itemMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 出库处理
|
|
||||||
*
|
|
||||||
* @param outboundRequest 出库参数
|
|
||||||
* @param itemMap 物料
|
|
||||||
*/
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
|
||||||
private void processOutBoundTask(OutboundRequest outboundRequest, Map<String, Item> itemMap) {
|
|
||||||
// 创建出库单和明细
|
|
||||||
Pick createPick = pickService.buildPick(outboundRequest);
|
|
||||||
List<PickDetail> pickDetails = pickService.buildPickDetail(outboundRequest.getDetails(), itemMap);
|
|
||||||
pickService.saveMain(createPick, pickDetails);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 出库参数校验
|
* 出库参数校验
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,7 @@ public class SyncStockProcessor {
|
||||||
@Autowired
|
@Autowired
|
||||||
private IStockService stockService;
|
private IStockService stockService;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private BatchUtil batchUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 接收容器同步信息
|
* 接收容器同步信息
|
||||||
|
|
@ -46,7 +45,7 @@ public class SyncStockProcessor {
|
||||||
processStock(syncStockRequest.getStocks(), stockMap, insertToStock, updateToStock);
|
processStock(syncStockRequest.getStocks(), stockMap, insertToStock, updateToStock);
|
||||||
|
|
||||||
//5.批量操作
|
//5.批量操作
|
||||||
batchOperation(insertToStock, updateToStock);
|
stockService.batchOperation(insertToStock, updateToStock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -125,21 +124,4 @@ public class SyncStockProcessor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 批量操作
|
|
||||||
*
|
|
||||||
* @param insertToStock 创建的容器
|
|
||||||
* @param updateToStock 更新的容器
|
|
||||||
*/
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
|
||||||
public void batchOperation(List<Stock> insertToStock, List<Stock> updateToStock) {
|
|
||||||
if (CollectionUtils.isNotEmpty(insertToStock)) {
|
|
||||||
batchUtil.saveBatchStock(insertToStock);
|
|
||||||
}
|
|
||||||
if (CollectionUtils.isNotEmpty(updateToStock)) {
|
|
||||||
batchUtil.batchUpdateStocks(updateToStock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import org.apache.commons.lang3.StringUtils;
|
||||||
import org.cpte.modules.constant.GeneralConstant;
|
import org.cpte.modules.constant.GeneralConstant;
|
||||||
import org.cpte.modules.serialNumber.PickSerialNumberRule;
|
import org.cpte.modules.serialNumber.PickSerialNumberRule;
|
||||||
import org.cpte.modules.shipping.entity.Task;
|
import org.cpte.modules.shipping.entity.Task;
|
||||||
|
import org.cpte.modules.shipping.mapper.TaskMapper;
|
||||||
import org.cpte.modules.shipping.service.ITaskService;
|
import org.cpte.modules.shipping.service.ITaskService;
|
||||||
import org.jeecg.common.system.query.QueryRuleEnum;
|
import org.jeecg.common.system.query.QueryRuleEnum;
|
||||||
import org.jeecgframework.poi.excel.ExcelImportUtil;
|
import org.jeecgframework.poi.excel.ExcelImportUtil;
|
||||||
|
|
@ -55,6 +56,8 @@ import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||||
@RequestMapping("/shipping/pick")
|
@RequestMapping("/shipping/pick")
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class PickController {
|
public class PickController {
|
||||||
|
@Autowired
|
||||||
|
private TaskMapper taskMapper;
|
||||||
@Autowired
|
@Autowired
|
||||||
private IPickService pickService;
|
private IPickService pickService;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
|
@ -81,9 +84,7 @@ public class PickController {
|
||||||
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
|
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
|
||||||
HttpServletRequest req) {
|
HttpServletRequest req) {
|
||||||
QueryWrapper<Pick> queryWrapper = QueryGenerator.initQueryWrapper(pick, req.getParameterMap());
|
QueryWrapper<Pick> queryWrapper = QueryGenerator.initQueryWrapper(pick, req.getParameterMap());
|
||||||
List<String> status = Arrays.stream(req.getParameterMap().get("status[]")).toList();
|
Page<Pick> page = new Page<>(pageNo, pageSize);
|
||||||
queryWrapper.in("status", status);
|
|
||||||
Page<Pick> page = new Page<Pick>(pageNo, pageSize);
|
|
||||||
IPage<Pick> pageList = pickService.page(page, queryWrapper);
|
IPage<Pick> pageList = pickService.page(page, queryWrapper);
|
||||||
return Result.OK(pageList);
|
return Result.OK(pageList);
|
||||||
}
|
}
|
||||||
|
|
@ -280,8 +281,8 @@ public class PickController {
|
||||||
return Result.OK("文件导入失败!");
|
return Result.OK("文件导入失败!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@AutoLog(value = "出库分配")
|
@AutoLog(value = "批量分配")
|
||||||
@Operation(summary = "出库分配")
|
@Operation(summary = "批量分配")
|
||||||
@RequiresPermissions("shipping:data_pick:allocatePick")
|
@RequiresPermissions("shipping:data_pick:allocatePick")
|
||||||
@GetMapping(value = "/allocatePick")
|
@GetMapping(value = "/allocatePick")
|
||||||
public Result<String> allocatePick(@RequestParam(name = "ids", required = true) String ids) {
|
public Result<String> allocatePick(@RequestParam(name = "ids", required = true) String ids) {
|
||||||
|
|
@ -304,13 +305,13 @@ public class PickController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@AutoLog(value = "取消分配")
|
@AutoLog(value = "批量取消分配")
|
||||||
@Operation(summary = "取消分配")
|
@Operation(summary = "批量取消分配")
|
||||||
@RequiresPermissions("shipping:data_pick:cancelAllocate")
|
@RequiresPermissions("shipping:data_pick:cancelAllocate")
|
||||||
@GetMapping(value = "/cancelAllocate")
|
@GetMapping(value = "/cancelAllocate")
|
||||||
public Result<String> cancelAllocate(@RequestParam(name = "ids", required = true) String ids) {
|
public Result<String> cancelAllocate(@RequestParam(name = "ids", required = true) String ids) {
|
||||||
if (StringUtils.isEmpty(ids)) {
|
if (StringUtils.isEmpty(ids)) {
|
||||||
return Result.error("请选择需要取消的出库单");
|
return Result.error("请选择需取消的出库单");
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
List<String> idsList = Arrays.asList(ids.split(","));
|
List<String> idsList = Arrays.asList(ids.split(","));
|
||||||
|
|
@ -327,4 +328,23 @@ public class PickController {
|
||||||
return Result.error("取消异常:" + e.getMessage());
|
return Result.error("取消异常:" + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AutoLog(value = "批量拣货")
|
||||||
|
@Operation(summary = "批量拣货")
|
||||||
|
@RequiresPermissions("shipping:data_pick:pickTask")
|
||||||
|
@GetMapping(value = "/pickTask")
|
||||||
|
public Result<String> pickTask(@RequestParam(name = "ids", required = true) String ids) {
|
||||||
|
if (StringUtils.isEmpty(ids)) {
|
||||||
|
return Result.error("请选择需要拣货的出库单");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
List<String> idsList = Arrays.asList(ids.split(","));
|
||||||
|
List<Long> pickIds = idsList.stream().map(Long::parseLong).toList();
|
||||||
|
List<Task> tasks = taskMapper.queryByPickIds(pickIds);
|
||||||
|
pickService.pickTask(tasks);
|
||||||
|
return Result.OK("拣货成功");
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Result.error("拣货异常:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,50 +1,119 @@
|
||||||
package org.cpte.modules.shipping.service;
|
package org.cpte.modules.shipping.service;
|
||||||
|
|
||||||
|
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.inventory.entity.Inventory;
|
||||||
|
import org.cpte.modules.saiWms.request.OutboundRequest;
|
||||||
import org.cpte.modules.shipping.entity.Pick;
|
import org.cpte.modules.shipping.entity.Pick;
|
||||||
import org.cpte.modules.shipping.entity.PickDetail;
|
import org.cpte.modules.shipping.entity.PickDetail;
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import org.cpte.modules.shipping.entity.Task;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description: 出库明细
|
* @Description: 出库明细
|
||||||
* @author: cpte
|
* @author: cpte
|
||||||
* @Date: 2025-11-14
|
* @Date: 2025-11-14
|
||||||
* @Version: V1.0
|
* @Version: V1.0
|
||||||
*/
|
*/
|
||||||
public interface IPickDetailService extends IService<PickDetail> {
|
public interface IPickDetailService extends IService<PickDetail> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通过主表id查询子表数据
|
* 构建出库单
|
||||||
*
|
*
|
||||||
* @param mainId 主表id
|
* @param outboundRequest 出库单请求
|
||||||
* @return List<PickDetail>
|
* @return 出库单
|
||||||
*/
|
*/
|
||||||
public List<PickDetail> selectByMainId(Long mainId);
|
Pick buildPick(OutboundRequest outboundRequest);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据出库单ID查询出库单Map
|
* 构建出库单明细
|
||||||
*
|
*
|
||||||
* @param pickIds 出库单ID集合
|
* @param details 出库单明细
|
||||||
* @return Map<Long, Pick>
|
* @param exitItemMap 物料
|
||||||
*/
|
* @return 出库单明细
|
||||||
Map<Long, Pick> queryByPickIdsToMap(List<Long> pickIds);
|
*/
|
||||||
|
List<PickDetail> buildPickDetail(List<OutboundRequest.OutboundDetail> details, Map<String, Item> exitItemMap);
|
||||||
/**
|
|
||||||
* 根据出库单明细ID查询出库单明细Map
|
|
||||||
*
|
|
||||||
* @param pickDetailIds 出库单明细ID集合
|
|
||||||
* @return Map<Long, PickDetail>
|
|
||||||
*/
|
|
||||||
Map<Long, PickDetail> queryByPickDetailIdsToMap(List<Long> pickDetailIds);
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过主表id查询子表数据
|
||||||
|
*
|
||||||
|
* @param mainId 主表id
|
||||||
|
* @return List<PickDetail>
|
||||||
|
*/
|
||||||
|
public List<PickDetail> selectByMainId(Long mainId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据出库单ID查询出库单Map
|
||||||
|
*
|
||||||
|
* @param pickIds 出库单ID集合
|
||||||
|
* @return Map<Long, Pick>
|
||||||
|
*/
|
||||||
|
Map<Long, Pick> queryByPickIdsToMap(List<Long> pickIds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据出库单明细ID查询出库单明细Map
|
||||||
|
*
|
||||||
|
* @param pickDetailIds 出库单明细ID集合
|
||||||
|
* @return Map<Long, PickDetail>
|
||||||
|
*/
|
||||||
|
Map<Long, PickDetail> queryByPickDetailIdsToMap(List<Long> pickDetailIds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存主表及从表
|
||||||
|
*
|
||||||
|
* @param pick 出库单
|
||||||
|
* @param pickDetailList 出库单明细
|
||||||
|
*/
|
||||||
|
void processorSaveMain(Pick pick, List<PickDetail> pickDetailList);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理出库任务
|
||||||
|
*
|
||||||
|
* @param outboundRequest 出库参数
|
||||||
|
* @param itemMap 物料
|
||||||
|
*/
|
||||||
|
void processOutBoundTask(OutboundRequest outboundRequest, Map<String, Item> itemMap);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量操作
|
||||||
|
*
|
||||||
|
* @param inventoryUpdateMap 库存更新
|
||||||
|
* @param pickDetailUpdateMap 出库单明细更新
|
||||||
|
* @param createToTask 创建任务
|
||||||
|
*/
|
||||||
|
void batchOperationAllocate(Map<Long, Inventory> inventoryUpdateMap, Map<Long, PickDetail> pickDetailUpdateMap, List<Task> createToTask);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量操作
|
||||||
|
*
|
||||||
|
* @param inventoryUpdateMap 库存更新
|
||||||
|
* @param pickDetailUpdateMap 出库单明细更新
|
||||||
|
* @param deleteToTask 删除任务
|
||||||
|
*/
|
||||||
|
void batchOperationCancel(Map<Long, Inventory> inventoryUpdateMap, Map<Long, PickDetail> pickDetailUpdateMap, List<Task> deleteToTask);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 刷新出库单
|
* 批量操作
|
||||||
*
|
*
|
||||||
* @param pick 出库单
|
* @param deleteToInventory 删除库存
|
||||||
* @param pickDetails 出库单明细
|
* @param pickDetailUpdateMap 出库单明细更新
|
||||||
*/
|
* @param updateToTask 更新任务
|
||||||
void refreshPick(Pick pick, List<PickDetail> pickDetails);
|
* @param updateToStock 更新库存
|
||||||
|
* @param updateToPoint 更新点位
|
||||||
|
*/
|
||||||
|
void batchOperationPick(List<Inventory> deleteToInventory, Map<Long, PickDetail> pickDetailUpdateMap, List<Task> updateToTask, List<Stock> updateToStock, List<Point> updateToPoint);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 刷新出库单
|
||||||
|
*
|
||||||
|
* @param pick 出库单
|
||||||
|
* @param pickDetails 出库单明细
|
||||||
|
*/
|
||||||
|
void refreshPick(Pick pick, List<PickDetail> pickDetails);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
package org.cpte.modules.shipping.service;
|
package org.cpte.modules.shipping.service;
|
||||||
|
|
||||||
import org.cpte.modules.base.entity.Item;
|
|
||||||
import org.cpte.modules.base.entity.Point;
|
|
||||||
import org.cpte.modules.saiWms.request.OutboundRequest;
|
|
||||||
import org.cpte.modules.shipping.entity.PickDetail;
|
import org.cpte.modules.shipping.entity.PickDetail;
|
||||||
import org.cpte.modules.shipping.entity.Pick;
|
import org.cpte.modules.shipping.entity.Pick;
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
|
@ -11,7 +8,6 @@ import org.cpte.modules.shipping.entity.Task;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description: 出库单
|
* @Description: 出库单
|
||||||
|
|
@ -51,24 +47,6 @@ public interface IPickService extends IService<Pick> {
|
||||||
*/
|
*/
|
||||||
public void delBatchMain(Collection<? extends Serializable> idList);
|
public void delBatchMain(Collection<? extends Serializable> idList);
|
||||||
|
|
||||||
/**
|
|
||||||
* 构建出库单
|
|
||||||
*
|
|
||||||
* @param outboundRequest 出库单请求
|
|
||||||
* @return 出库单
|
|
||||||
*/
|
|
||||||
Pick buildPick(OutboundRequest outboundRequest);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构建出库单明细
|
|
||||||
*
|
|
||||||
* @param details 出库单明细
|
|
||||||
* @param exitItemMap 物料
|
|
||||||
* @return 出库单明细
|
|
||||||
*/
|
|
||||||
List<PickDetail> buildPickDetail(List<OutboundRequest.OutboundDetail> details, Map<String, Item> exitItemMap);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分配出库单
|
* 分配出库单
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,37 @@
|
||||||
package org.cpte.modules.shipping.service.impl;
|
package org.cpte.modules.shipping.service.impl;
|
||||||
|
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
|
import org.apache.shiro.SecurityUtils;
|
||||||
|
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.service.IPointService;
|
||||||
|
import org.cpte.modules.base.service.IStockService;
|
||||||
|
import org.cpte.modules.constant.GeneralConstant;
|
||||||
import org.cpte.modules.constant.enums.PickStatusEnum;
|
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.saiWms.request.OutboundRequest;
|
||||||
|
import org.cpte.modules.serialNumber.PickSerialNumberRule;
|
||||||
import org.cpte.modules.shipping.entity.Pick;
|
import org.cpte.modules.shipping.entity.Pick;
|
||||||
import org.cpte.modules.shipping.entity.PickDetail;
|
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.PickDetailMapper;
|
||||||
import org.cpte.modules.shipping.mapper.PickMapper;
|
import org.cpte.modules.shipping.mapper.PickMapper;
|
||||||
|
import org.cpte.modules.shipping.mapper.TaskMapper;
|
||||||
import org.cpte.modules.shipping.service.IPickDetailService;
|
import org.cpte.modules.shipping.service.IPickDetailService;
|
||||||
|
import org.cpte.modules.utils.BatchUtil;
|
||||||
|
import org.jeecg.common.system.vo.LoginUser;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description: 出库明细
|
* @Description: 出库明细
|
||||||
|
|
@ -26,11 +44,66 @@ public class PickDetailServiceImpl extends ServiceImpl<PickDetailMapper, PickDet
|
||||||
@Autowired
|
@Autowired
|
||||||
private PickMapper pickMapper;
|
private PickMapper pickMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private TaskMapper taskMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private InventoryMapper inventoryMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IStockService stockService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IPointService pointService;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private BatchUtil batchUtil;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PickSerialNumberRule pickSerialNumberRule;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<PickDetail> selectByMainId(Long mainId) {
|
public List<PickDetail> selectByMainId(Long mainId) {
|
||||||
return this.baseMapper.selectByMainId(mainId);
|
return this.baseMapper.selectByMainId(mainId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Pick buildPick(OutboundRequest outboundRequest) {
|
||||||
|
return Pick.builder()
|
||||||
|
.thirdOrderNo(outboundRequest.getOrderNo())
|
||||||
|
.no(outboundRequest.getNo())
|
||||||
|
.whCode(outboundRequest.getWhCode())
|
||||||
|
.customerCode(outboundRequest.getCustomerCode())
|
||||||
|
.orderType(outboundRequest.getType())
|
||||||
|
.status(PickStatusEnum.CREATED.getValue())
|
||||||
|
.orderDate(new Date())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<PickDetail> buildPickDetail(List<OutboundRequest.OutboundDetail> details, Map<String, Item> exitItemMap) {
|
||||||
|
List<PickDetail> newDetailList = new ArrayList<>();
|
||||||
|
for (OutboundRequest.OutboundDetail detail : details) {
|
||||||
|
PickDetail pickDetail = PickDetail.builder()
|
||||||
|
.lineNo(Integer.parseInt(detail.getLineNo()))
|
||||||
|
.itemId(exitItemMap.get(detail.getItem()).getId())
|
||||||
|
.unit(detail.getUnit())
|
||||||
|
.orderQty(BigDecimal.valueOf(detail.getQty()))
|
||||||
|
.allocatedQty(BigDecimal.ZERO)
|
||||||
|
.pickedQty(BigDecimal.ZERO)
|
||||||
|
.status(PickStatusEnum.CREATED.getValue())
|
||||||
|
.project(detail.getProject())
|
||||||
|
.taskNo(detail.getTaskNo())
|
||||||
|
.propC1(detail.getLotAtt04())
|
||||||
|
.propC3(detail.getLotAtt010())
|
||||||
|
.build();
|
||||||
|
newDetailList.add(pickDetail);
|
||||||
|
}
|
||||||
|
return newDetailList;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取出库单Map
|
* 获取出库单Map
|
||||||
*
|
*
|
||||||
|
|
@ -67,6 +140,101 @@ public class PickDetailServiceImpl extends ServiceImpl<PickDetailMapper, PickDet
|
||||||
return pickDetailMap;
|
return pickDetailMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void processorSaveMain(Pick pick, List<PickDetail> pickDetailList) {
|
||||||
|
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
||||||
|
pick.setTenantId(Long.parseLong(sysUser.getRelTenantIds()));
|
||||||
|
pick.setSysOrgCode(sysUser.getOrgCode());
|
||||||
|
String orderNo = pickSerialNumberRule.generateSerialNumber(GeneralConstant.PICK_ORDER_NO);
|
||||||
|
pick.setOrderNo(orderNo);
|
||||||
|
pickMapper.insert(pick);
|
||||||
|
|
||||||
|
if (pickDetailList == null || pickDetailList.isEmpty()) {
|
||||||
|
throw new RuntimeException("请新增出库明细");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前出库单下已存在的最大序号
|
||||||
|
Integer maxLineNo = this.baseMapper.queryMaxLineNoByPickId(pick.getId());
|
||||||
|
AtomicInteger lineNoCounter = new AtomicInteger((maxLineNo != null) ? maxLineNo + 1 : 1);
|
||||||
|
|
||||||
|
for (PickDetail entity : pickDetailList) {
|
||||||
|
if (entity.getLineNo() == null || entity.getLineNo() == 0) {
|
||||||
|
entity.setLineNo(lineNoCounter.getAndIncrement());
|
||||||
|
}
|
||||||
|
entity.setPickId(pick.getId());
|
||||||
|
entity.setTenantId(Long.parseLong(sysUser.getRelTenantIds()));
|
||||||
|
entity.setSysOrgCode(sysUser.getOrgCode());
|
||||||
|
this.baseMapper.insert(entity);
|
||||||
|
}
|
||||||
|
//刷新出库单
|
||||||
|
refreshPick(pick, pickDetailList);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void processOutBoundTask(OutboundRequest outboundRequest, Map<String, Item> itemMap) {
|
||||||
|
// 创建出库单和明细
|
||||||
|
Pick createPick = buildPick(outboundRequest);
|
||||||
|
List<PickDetail> pickDetails = buildPickDetail(outboundRequest.getDetails(), itemMap);
|
||||||
|
processorSaveMain(createPick, pickDetails);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void batchOperationAllocate(Map<Long, Inventory> inventoryUpdateMap, Map<Long, PickDetail> pickDetailUpdateMap, List<Task> createToTask) {
|
||||||
|
|
||||||
|
List<Inventory> updateToInventory = new ArrayList<>(inventoryUpdateMap.values());
|
||||||
|
List<PickDetail> updateToPickDetail = new ArrayList<>(pickDetailUpdateMap.values());
|
||||||
|
if (CollectionUtils.isNotEmpty(updateToInventory)) {
|
||||||
|
batchUtil.updateBatchInventory(updateToInventory);
|
||||||
|
}
|
||||||
|
if (CollectionUtils.isNotEmpty(updateToPickDetail)) {
|
||||||
|
batchUtil.updateBatchPickDetail(updateToPickDetail);
|
||||||
|
}
|
||||||
|
if (CollectionUtils.isNotEmpty(createToTask)) {
|
||||||
|
batchUtil.saveBatchTask(createToTask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void batchOperationCancel(Map<Long, Inventory> inventoryUpdateMap, Map<Long, PickDetail> pickDetailUpdateMap, List<Task> deleteToTask) {
|
||||||
|
List<Inventory> updateToInventory = new ArrayList<>(inventoryUpdateMap.values());
|
||||||
|
List<PickDetail> updateToPickDetail = new ArrayList<>(pickDetailUpdateMap.values());
|
||||||
|
if (CollectionUtils.isNotEmpty(updateToInventory)) {
|
||||||
|
batchUtil.updateBatchInventory(updateToInventory);
|
||||||
|
}
|
||||||
|
if (CollectionUtils.isNotEmpty(updateToPickDetail)) {
|
||||||
|
batchUtil.updateBatchPickDetail(updateToPickDetail);
|
||||||
|
}
|
||||||
|
if (CollectionUtils.isNotEmpty(deleteToTask)) {
|
||||||
|
taskMapper.deleteByIds(deleteToTask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void batchOperationPick(List<Inventory> deleteToInventory, Map<Long, PickDetail> pickDetailUpdateMap, List<Task> updateToTask, List<Stock> updateToStock, List<Point> updateToPoint) {
|
||||||
|
if (CollectionUtils.isNotEmpty(deleteToInventory)) {
|
||||||
|
List<Long> deleteToInventoryIds = deleteToInventory.stream().map(Inventory::getId).toList();
|
||||||
|
inventoryMapper.deleteByIds(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);
|
||||||
|
}
|
||||||
|
if (CollectionUtils.isNotEmpty(updateToPoint)) {
|
||||||
|
pointService.updateBatchById(updateToPoint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 刷新出库单状态
|
* 刷新出库单状态
|
||||||
|
|
|
||||||
|
|
@ -1,49 +1,27 @@
|
||||||
package org.cpte.modules.shipping.service.impl;
|
package org.cpte.modules.shipping.service.impl;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
|
||||||
import com.alibaba.fastjson.JSONArray;
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
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.constant.enums.*;
|
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.saiWms.request.OutboundRequest;
|
|
||||||
import org.cpte.modules.saiWms.request.SMOMRequest;
|
|
||||||
import org.cpte.modules.serialNumber.PickSerialNumberRule;
|
|
||||||
import org.cpte.modules.shipping.entity.Pick;
|
import org.cpte.modules.shipping.entity.Pick;
|
||||||
import org.cpte.modules.shipping.entity.PickDetail;
|
import org.cpte.modules.shipping.entity.PickDetail;
|
||||||
import org.cpte.modules.shipping.entity.Task;
|
import org.cpte.modules.shipping.entity.Task;
|
||||||
import org.cpte.modules.shipping.mapper.PickDetailMapper;
|
import org.cpte.modules.shipping.mapper.PickDetailMapper;
|
||||||
import org.cpte.modules.shipping.mapper.PickMapper;
|
import org.cpte.modules.shipping.mapper.PickMapper;
|
||||||
import org.cpte.modules.shipping.mapper.TaskMapper;
|
|
||||||
import org.cpte.modules.shipping.service.processor.AllocateProcessor;
|
import org.cpte.modules.shipping.service.processor.AllocateProcessor;
|
||||||
import org.cpte.modules.shipping.service.processor.CancelAllocateProcessor;
|
import org.cpte.modules.shipping.service.processor.CancelAllocateProcessor;
|
||||||
import org.cpte.modules.shipping.service.IPickDetailService;
|
import org.cpte.modules.shipping.service.IPickDetailService;
|
||||||
import org.cpte.modules.shipping.service.IPickService;
|
import org.cpte.modules.shipping.service.IPickService;
|
||||||
import org.cpte.modules.shipping.service.processor.PickProcessor;
|
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;
|
import org.cpte.modules.utils.RedisDistributedLockUtil;
|
||||||
import org.cpte.modules.utils.SwmsLoginUtil;
|
|
||||||
import org.jeecg.common.constant.CommonConstant;
|
import org.jeecg.common.constant.CommonConstant;
|
||||||
import org.jeecg.common.system.vo.LoginUser;
|
|
||||||
import org.jeecg.modules.base.service.BaseCommonService;
|
import org.jeecg.modules.base.service.BaseCommonService;
|
||||||
import org.jeecg.modules.openapi.mapper.OpenApiMapper;
|
|
||||||
import org.jeecg.modules.system.mapper.SysDictMapper;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
|
@ -64,8 +42,6 @@ public class PickServiceImpl extends ServiceImpl<PickMapper, Pick> implements IP
|
||||||
@Autowired
|
@Autowired
|
||||||
private BaseCommonService baseCommonService;
|
private BaseCommonService baseCommonService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private PickSerialNumberRule pickSerialNumberRule;
|
|
||||||
@Autowired
|
|
||||||
private AllocateProcessor allocateProcessor;
|
private AllocateProcessor allocateProcessor;
|
||||||
@Autowired
|
@Autowired
|
||||||
private CancelAllocateProcessor cancelAllocateProcessor;
|
private CancelAllocateProcessor cancelAllocateProcessor;
|
||||||
|
|
@ -84,7 +60,7 @@ public class PickServiceImpl extends ServiceImpl<PickMapper, Pick> implements IP
|
||||||
if (StringUtils.isEmpty(lockValue)) {
|
if (StringUtils.isEmpty(lockValue)) {
|
||||||
throw new RuntimeException("出库单创建中,请稍后重试");
|
throw new RuntimeException("出库单创建中,请稍后重试");
|
||||||
}
|
}
|
||||||
processorSaveMain(pick, pickDetailList);
|
pickDetailService.processorSaveMain(pick, pickDetailList);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("出库单创建异常", e);
|
log.error("出库单创建异常", e);
|
||||||
throw e;
|
throw e;
|
||||||
|
|
@ -95,43 +71,6 @@ public class PickServiceImpl extends ServiceImpl<PickMapper, Pick> implements IP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 保存主表及从表
|
|
||||||
*
|
|
||||||
* @param pick 出库单
|
|
||||||
* @param pickDetailList 出库单明细
|
|
||||||
*/
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
|
||||||
public void processorSaveMain(Pick pick, List<PickDetail> pickDetailList) {
|
|
||||||
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
|
||||||
pick.setTenantId(Long.parseLong(sysUser.getRelTenantIds()));
|
|
||||||
pick.setSysOrgCode(sysUser.getOrgCode());
|
|
||||||
String orderNo = pickSerialNumberRule.generateSerialNumber(GeneralConstant.PICK_ORDER_NO);
|
|
||||||
pick.setOrderNo(orderNo);
|
|
||||||
this.baseMapper.insert(pick);
|
|
||||||
|
|
||||||
if (pickDetailList == null || pickDetailList.isEmpty()) {
|
|
||||||
throw new RuntimeException("请新增出库明细");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取当前出库单下已存在的最大序号
|
|
||||||
Integer maxLineNo = pickDetailMapper.queryMaxLineNoByPickId(pick.getId());
|
|
||||||
AtomicInteger lineNoCounter = new AtomicInteger((maxLineNo != null) ? maxLineNo + 1 : 1);
|
|
||||||
|
|
||||||
for (PickDetail entity : pickDetailList) {
|
|
||||||
if (entity.getLineNo() == null || entity.getLineNo() == 0) {
|
|
||||||
entity.setLineNo(lineNoCounter.getAndIncrement());
|
|
||||||
}
|
|
||||||
entity.setPickId(pick.getId());
|
|
||||||
entity.setTenantId(Long.parseLong(sysUser.getRelTenantIds()));
|
|
||||||
entity.setSysOrgCode(sysUser.getOrgCode());
|
|
||||||
pickDetailMapper.insert(entity);
|
|
||||||
}
|
|
||||||
//刷新出库单
|
|
||||||
pickDetailService.refreshPick(pick, pickDetailList);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void updateMain(Pick pick, List<PickDetail> pickDetailList) {
|
public void updateMain(Pick pick, List<PickDetail> pickDetailList) {
|
||||||
|
|
@ -206,40 +145,7 @@ public class PickServiceImpl extends ServiceImpl<PickMapper, Pick> implements IP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Pick buildPick(OutboundRequest outboundRequest) {
|
|
||||||
return Pick.builder()
|
|
||||||
.thirdOrderNo(outboundRequest.getOrderNo())
|
|
||||||
.no(outboundRequest.getNo())
|
|
||||||
.whCode(outboundRequest.getWhCode())
|
|
||||||
.customerCode(outboundRequest.getCustomerCode())
|
|
||||||
.orderType(outboundRequest.getType())
|
|
||||||
.status(PickStatusEnum.CREATED.getValue())
|
|
||||||
.orderDate(new Date())
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<PickDetail> buildPickDetail(List<OutboundRequest.OutboundDetail> details, Map<String, Item> exitItemMap) {
|
|
||||||
List<PickDetail> newDetailList = new ArrayList<>();
|
|
||||||
for (OutboundRequest.OutboundDetail detail : details) {
|
|
||||||
PickDetail pickDetail = PickDetail.builder()
|
|
||||||
.lineNo(Integer.parseInt(detail.getLineNo()))
|
|
||||||
.itemId(exitItemMap.get(detail.getItem()).getId())
|
|
||||||
.unit(detail.getUnit())
|
|
||||||
.orderQty(BigDecimal.valueOf(detail.getQty()))
|
|
||||||
.allocatedQty(BigDecimal.ZERO)
|
|
||||||
.pickedQty(BigDecimal.ZERO)
|
|
||||||
.status(PickStatusEnum.CREATED.getValue())
|
|
||||||
.project(detail.getProject())
|
|
||||||
.taskNo(detail.getTaskNo())
|
|
||||||
.propC1(detail.getLotAtt04())
|
|
||||||
.propC3(detail.getLotAtt010())
|
|
||||||
.build();
|
|
||||||
newDetailList.add(pickDetail);
|
|
||||||
}
|
|
||||||
return newDetailList;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> allocatePick(List<Long> pickIds) {
|
public List<String> allocatePick(List<Long> pickIds) {
|
||||||
|
|
|
||||||
|
|
@ -26,12 +26,10 @@ import org.cpte.modules.shipping.service.ITaskService;
|
||||||
import org.cpte.modules.shipping.vo.AllocationData;
|
import org.cpte.modules.shipping.vo.AllocationData;
|
||||||
import org.cpte.modules.shipping.vo.InventoryScore;
|
import org.cpte.modules.shipping.vo.InventoryScore;
|
||||||
import org.cpte.modules.shipping.vo.ItemGroupKey;
|
import org.cpte.modules.shipping.vo.ItemGroupKey;
|
||||||
import org.cpte.modules.utils.BatchUtil;
|
|
||||||
import org.cpte.modules.utils.BigDecimalUtil;
|
import org.cpte.modules.utils.BigDecimalUtil;
|
||||||
import org.cpte.modules.utils.RedisDistributedLockUtil;
|
import org.cpte.modules.utils.RedisDistributedLockUtil;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
@ -83,9 +81,6 @@ public class AllocateProcessor {
|
||||||
@Autowired
|
@Autowired
|
||||||
private MoveSerialNumberRule moveSerialNumberRule;
|
private MoveSerialNumberRule moveSerialNumberRule;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private BatchUtil batchUtil;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private RedisDistributedLockUtil redissonLock;
|
private RedisDistributedLockUtil redissonLock;
|
||||||
|
|
||||||
|
|
@ -121,7 +116,7 @@ public class AllocateProcessor {
|
||||||
moveTask(createToTask, movePoints);
|
moveTask(createToTask, movePoints);
|
||||||
|
|
||||||
//6.批量操作
|
//6.批量操作
|
||||||
batchOperation(inventoryUpdateMap, pickDetailUpdateMap, createToTask);
|
pickDetailService.batchOperationAllocate(inventoryUpdateMap, pickDetailUpdateMap, createToTask);
|
||||||
|
|
||||||
//7.刷新出库单
|
//7.刷新出库单
|
||||||
refreshData(data);
|
refreshData(data);
|
||||||
|
|
@ -261,7 +256,7 @@ public class AllocateProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 分配库存
|
// 分配库存
|
||||||
String lockKey = "allocate:" + pickDetail.getId();
|
String lockKey = "allocate:" + pick.getId();
|
||||||
String lockValue = null;
|
String lockValue = null;
|
||||||
try {
|
try {
|
||||||
lockValue = redissonLock.tryLock(lockKey, 10);
|
lockValue = redissonLock.tryLock(lockKey, 10);
|
||||||
|
|
@ -271,7 +266,7 @@ public class AllocateProcessor {
|
||||||
allocateInventory(pickDetail, item, pick, matchedInventories, inventoryUpdateMap, pickDetailUpdateMap,
|
allocateInventory(pickDetail, item, pick, matchedInventories, inventoryUpdateMap, pickDetailUpdateMap,
|
||||||
createToTask, movePoints, data, unAllocatedQty, errorMsgSet);
|
createToTask, movePoints, data, unAllocatedQty, errorMsgSet);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("分配异常,明细ID: {}", pickDetail.getId(), e);
|
log.error("分配异常,出库单ID: {}", pick.getId(), e);
|
||||||
throw e;
|
throw e;
|
||||||
} finally {
|
} finally {
|
||||||
if (StringUtils.isNotEmpty(lockValue)) {
|
if (StringUtils.isNotEmpty(lockValue)) {
|
||||||
|
|
@ -279,7 +274,6 @@ public class AllocateProcessor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -339,15 +333,16 @@ public class AllocateProcessor {
|
||||||
List<Inventory> matchedInventories, Map<Long, Inventory> inventoryUpdateMap,
|
List<Inventory> matchedInventories, Map<Long, Inventory> inventoryUpdateMap,
|
||||||
Map<Long, PickDetail> pickDetailUpdateMap, List<Task> createToTask, List<Point> movePoints,
|
Map<Long, PickDetail> pickDetailUpdateMap, List<Task> createToTask, List<Point> movePoints,
|
||||||
AllocationData data, BigDecimal totalUnAllocatedQty, Set<String> errorMsgSet) {
|
AllocationData data, BigDecimal totalUnAllocatedQty, Set<String> errorMsgSet) {
|
||||||
|
|
||||||
// 智能排序库存
|
// 智能排序库存
|
||||||
List<InventoryScore> scoredInventories = scoreInventories(matchedInventories);
|
List<InventoryScore> scoredInventories = scoreInventories(matchedInventories);
|
||||||
//未分配数量
|
//未分配数量
|
||||||
BigDecimal remainingQty = totalUnAllocatedQty;
|
BigDecimal remainingQty = totalUnAllocatedQty;
|
||||||
for (InventoryScore inventoryScore : scoredInventories) {
|
for (InventoryScore inventoryScore : scoredInventories) {
|
||||||
|
|
||||||
if (remainingQty.compareTo(BigDecimal.ZERO) <= 0) {
|
if (remainingQty.compareTo(BigDecimal.ZERO) <= 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Inventory inventory = inventoryScore.getInventory();
|
Inventory inventory = inventoryScore.getInventory();
|
||||||
|
|
||||||
// 库存可用数量
|
// 库存可用数量
|
||||||
|
|
@ -363,13 +358,10 @@ public class AllocateProcessor {
|
||||||
updatePickDetailAllocation(pickDetail, allocateQty, pickDetailUpdateMap);
|
updatePickDetailAllocation(pickDetail, allocateQty, pickDetailUpdateMap);
|
||||||
// 创建任务
|
// 创建任务
|
||||||
createPickTask(pickDetail, pick, item, inventory, inventoryScore, allocateQty, createToTask, data);
|
createPickTask(pickDetail, pick, item, inventory, inventoryScore, allocateQty, createToTask, data);
|
||||||
|
|
||||||
// 获取需要移位的库位
|
// 获取需要移位的库位
|
||||||
getMovePoints(inventoryScore, movePoints);
|
getMovePoints(inventoryScore, movePoints);
|
||||||
|
|
||||||
// 记录分配日志
|
// 记录分配日志
|
||||||
inventoryLogService.addAllocInventoryLog(inventory, inventoryScore.getOutPoint().getId(), allocateQty, pick.getOrderNo(), pickDetail.getId(), pickDetail.getDescription());
|
inventoryLogService.addAllocInventoryLog(inventory, inventoryScore.getOutPoint().getId(), allocateQty, pick.getOrderNo(), pickDetail.getId(), pickDetail.getDescription());
|
||||||
|
|
||||||
// 更新剩余未分配数量
|
// 更新剩余未分配数量
|
||||||
remainingQty = BigDecimalUtil.subtract(remainingQty, allocateQty, 0);
|
remainingQty = BigDecimalUtil.subtract(remainingQty, allocateQty, 0);
|
||||||
|
|
||||||
|
|
@ -378,6 +370,8 @@ public class AllocateProcessor {
|
||||||
if (remainingQty.compareTo(BigDecimal.ZERO) > 0) {
|
if (remainingQty.compareTo(BigDecimal.ZERO) > 0) {
|
||||||
addInventoryErrorMsg(pick, pickDetail, item, remainingQty, errorMsgSet);
|
addInventoryErrorMsg(pick, pickDetail, item, remainingQty, errorMsgSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -527,6 +521,7 @@ public class AllocateProcessor {
|
||||||
Map<Long, Inventory> inventoryUpdateMap) {
|
Map<Long, Inventory> inventoryUpdateMap) {
|
||||||
Inventory targetInventory = inventoryUpdateMap.getOrDefault(inventory.getId(), inventory);
|
Inventory targetInventory = inventoryUpdateMap.getOrDefault(inventory.getId(), inventory);
|
||||||
BigDecimal newQueuedQty = BigDecimalUtil.add(targetInventory.getQueuedQty(), allocateQty, 0);
|
BigDecimal newQueuedQty = BigDecimalUtil.add(targetInventory.getQueuedQty(), allocateQty, 0);
|
||||||
|
log.info("更新库存分配数: {}", newQueuedQty);
|
||||||
targetInventory.setQueuedQty(newQueuedQty);
|
targetInventory.setQueuedQty(newQueuedQty);
|
||||||
targetInventory.setStatus(InventoryStatusEnum.ALLOCATED.getValue());
|
targetInventory.setStatus(InventoryStatusEnum.ALLOCATED.getValue());
|
||||||
inventoryUpdateMap.put(targetInventory.getId(), targetInventory);
|
inventoryUpdateMap.put(targetInventory.getId(), targetInventory);
|
||||||
|
|
@ -684,7 +679,7 @@ public class AllocateProcessor {
|
||||||
.filter(point -> !createTaskIds.contains(point.getId()))
|
.filter(point -> !createTaskIds.contains(point.getId()))
|
||||||
.toList();
|
.toList();
|
||||||
if (CollectionUtils.isNotEmpty(pointsToMove)) {
|
if (CollectionUtils.isNotEmpty(pointsToMove)) {
|
||||||
List<Task> moveToTask = bulidMoveTask(pointsToMove);
|
List<Task> moveToTask = buildMoveTask(pointsToMove);
|
||||||
if (CollectionUtils.isNotEmpty(moveToTask)) {
|
if (CollectionUtils.isNotEmpty(moveToTask)) {
|
||||||
createToTask.addAll(moveToTask);
|
createToTask.addAll(moveToTask);
|
||||||
}
|
}
|
||||||
|
|
@ -699,7 +694,7 @@ public class AllocateProcessor {
|
||||||
* @param movePoints 移位库位
|
* @param movePoints 移位库位
|
||||||
* @return 移位任务
|
* @return 移位任务
|
||||||
*/
|
*/
|
||||||
public List<Task> bulidMoveTask(List<Point> movePoints) {
|
public List<Task> buildMoveTask(List<Point> movePoints) {
|
||||||
List<Task> moveList = new ArrayList<>();
|
List<Task> moveList = new ArrayList<>();
|
||||||
|
|
||||||
//库存
|
//库存
|
||||||
|
|
@ -748,30 +743,6 @@ public class AllocateProcessor {
|
||||||
return scanTrayProcessor.allocatePoint(itemKeyIds, currentPoint, areaCode);
|
return scanTrayProcessor.allocatePoint(itemKeyIds, currentPoint, areaCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 批量操作
|
|
||||||
*
|
|
||||||
* @param inventoryUpdateMap 更新库存
|
|
||||||
* @param pickDetailUpdateMap 更新出库明细
|
|
||||||
* @param createToTask 创建出库任务
|
|
||||||
*/
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
|
||||||
public void batchOperation(Map<Long, Inventory> inventoryUpdateMap, Map<Long, PickDetail> pickDetailUpdateMap, List<Task> createToTask) {
|
|
||||||
|
|
||||||
List<Inventory> updateToInventory = new ArrayList<>(inventoryUpdateMap.values());
|
|
||||||
List<PickDetail> updateToPickDetail = new ArrayList<>(pickDetailUpdateMap.values());
|
|
||||||
if (CollectionUtils.isNotEmpty(updateToInventory)) {
|
|
||||||
batchUtil.updateBatchInventory(updateToInventory);
|
|
||||||
}
|
|
||||||
if (CollectionUtils.isNotEmpty(updateToPickDetail)) {
|
|
||||||
batchUtil.updateBatchPickDetail(updateToPickDetail);
|
|
||||||
}
|
|
||||||
if (CollectionUtils.isNotEmpty(createToTask)) {
|
|
||||||
batchUtil.saveBatchTask(createToTask);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 刷新出库单
|
* 刷新出库单
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package org.cpte.modules.shipping.service.processor;
|
package org.cpte.modules.shipping.service.processor;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.cpte.modules.constant.enums.InventoryStatusEnum;
|
import org.cpte.modules.constant.enums.InventoryStatusEnum;
|
||||||
import org.cpte.modules.constant.enums.PickStatusEnum;
|
import org.cpte.modules.constant.enums.PickStatusEnum;
|
||||||
import org.cpte.modules.inventory.entity.Inventory;
|
import org.cpte.modules.inventory.entity.Inventory;
|
||||||
|
|
@ -14,11 +14,10 @@ import org.cpte.modules.shipping.mapper.PickDetailMapper;
|
||||||
import org.cpte.modules.shipping.mapper.TaskMapper;
|
import org.cpte.modules.shipping.mapper.TaskMapper;
|
||||||
import org.cpte.modules.shipping.service.IPickDetailService;
|
import org.cpte.modules.shipping.service.IPickDetailService;
|
||||||
import org.cpte.modules.shipping.vo.CancelAllocateData;
|
import org.cpte.modules.shipping.vo.CancelAllocateData;
|
||||||
import org.cpte.modules.utils.BatchUtil;
|
|
||||||
import org.cpte.modules.utils.BigDecimalUtil;
|
import org.cpte.modules.utils.BigDecimalUtil;
|
||||||
|
import org.cpte.modules.utils.RedisDistributedLockUtil;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
@ -47,7 +46,7 @@ public class CancelAllocateProcessor {
|
||||||
private IInventoryLogService inventoryLogService;
|
private IInventoryLogService inventoryLogService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private BatchUtil batchUtils;
|
private RedisDistributedLockUtil redissonLock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 取消分配
|
* 取消分配
|
||||||
|
|
@ -71,7 +70,7 @@ public class CancelAllocateProcessor {
|
||||||
cancelAllocate(data, inventoryUpdateMap, pickDetailUpdateMap, deleteToTask, errorMsgSet);
|
cancelAllocate(data, inventoryUpdateMap, pickDetailUpdateMap, deleteToTask, errorMsgSet);
|
||||||
|
|
||||||
//4.批量操作
|
//4.批量操作
|
||||||
batchOperation(inventoryUpdateMap, pickDetailUpdateMap, deleteToTask);
|
pickDetailService.batchOperationCancel(inventoryUpdateMap, pickDetailUpdateMap, deleteToTask);
|
||||||
|
|
||||||
//5.刷新出库单
|
//5.刷新出库单
|
||||||
refreshData(data);
|
refreshData(data);
|
||||||
|
|
@ -125,7 +124,6 @@ public class CancelAllocateProcessor {
|
||||||
try {
|
try {
|
||||||
cancelAllocateTask(task, data, inventoryUpdateMap, pickDetailUpdateMap, deleteToTask, errorMsgSet);
|
cancelAllocateTask(task, data, inventoryUpdateMap, pickDetailUpdateMap, deleteToTask, errorMsgSet);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("取消任务失败,任务ID: {}", task.getId(), e);
|
|
||||||
errorMsgSet.add(String.format("取消任务失败,任务号:%s,原因:%s",
|
errorMsgSet.add(String.format("取消任务失败,任务号:%s,原因:%s",
|
||||||
task.getTaskNo(), e.getMessage()));
|
task.getTaskNo(), e.getMessage()));
|
||||||
}
|
}
|
||||||
|
|
@ -145,35 +143,49 @@ public class CancelAllocateProcessor {
|
||||||
private void cancelAllocateTask(Task task, CancelAllocateData data, Map<Long, Inventory> inventoryUpdateMap,
|
private void cancelAllocateTask(Task task, CancelAllocateData data, Map<Long, Inventory> inventoryUpdateMap,
|
||||||
Map<Long, PickDetail> pickDetailUpdateMap, List<Task> deleteToTask, Set<String> errorMsgSet) {
|
Map<Long, PickDetail> pickDetailUpdateMap, List<Task> deleteToTask, Set<String> errorMsgSet) {
|
||||||
Pick pick = data.getPickMap().get(task.getPickId());
|
Pick pick = data.getPickMap().get(task.getPickId());
|
||||||
PickDetail pickDetail = data.getPickDetailIdMap().get(task.getPickDetailId());
|
String lockKey = "cancel:" + pick.getId();
|
||||||
if (task.getAgvTaskId() != null) {
|
String lockValue = null;
|
||||||
errorMsgSet.add(String.format("取消失败:【%s】已生成AGV任务", task.getTaskNo()));
|
try {
|
||||||
return;
|
lockValue = redissonLock.tryLock(lockKey, 10);
|
||||||
|
if (StringUtils.isEmpty(lockValue)) {
|
||||||
|
throw new RuntimeException("分配处理中,请稍后重试");
|
||||||
|
}
|
||||||
|
PickDetail pickDetail = data.getPickDetailIdMap().get(task.getPickDetailId());
|
||||||
|
if (task.getAgvTaskId() != null) {
|
||||||
|
errorMsgSet.add(String.format("取消失败:【%s】已生成AGV任务", task.getTaskNo()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Inventory inventory = data.getInventoryMap().get(task.getInventoryId());
|
||||||
|
if (inventory == null) {
|
||||||
|
errorMsgSet.add(String.format("取消失败:【%s】库存不存在", task.getTaskNo()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (inventory.getQueuedQty().compareTo(BigDecimal.ZERO) <= 0) {
|
||||||
|
errorMsgSet.add(String.format("取消失败:【%s】库存已取消分配", task.getTaskNo()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
BigDecimal cancelQty = task.getPlanQty();
|
||||||
|
|
||||||
|
//更新库存
|
||||||
|
updateInventoryAllocation(inventory, cancelQty, inventoryUpdateMap);
|
||||||
|
|
||||||
|
//更新出库明细
|
||||||
|
updatePickDetailAllocation(pickDetail, cancelQty, pickDetailUpdateMap);
|
||||||
|
|
||||||
|
//删除任务
|
||||||
|
deleteToTask.add(task);
|
||||||
|
|
||||||
|
// 记录取消分配日志
|
||||||
|
inventoryLogService.addUnAllocInventoryLog(inventory, cancelQty, pick.getOrderNo(), pickDetail.getId(), pickDetail.getDescription());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("分配异常,出库单ID: {}", pick.getId(), e);
|
||||||
|
throw e;
|
||||||
|
} finally {
|
||||||
|
if (StringUtils.isNotEmpty(lockValue)) {
|
||||||
|
redissonLock.unlock(lockKey, lockValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Inventory inventory = data.getInventoryMap().get(task.getInventoryId());
|
|
||||||
if (inventory == null) {
|
|
||||||
errorMsgSet.add(String.format("取消失败:【%s】库存不存在", task.getTaskNo()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (inventory.getQueuedQty().compareTo(BigDecimal.ZERO) <= 0) {
|
|
||||||
errorMsgSet.add(String.format("取消失败:【%s】库存已取消分配", task.getTaskNo()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
BigDecimal cancelQty = task.getPlanQty();
|
|
||||||
|
|
||||||
//更新库存
|
|
||||||
updateInventoryAllocation(inventory, cancelQty, inventoryUpdateMap);
|
|
||||||
|
|
||||||
//更新出库明细
|
|
||||||
updatePickDetailAllocation(pickDetail, cancelQty, pickDetailUpdateMap);
|
|
||||||
|
|
||||||
//删除任务
|
|
||||||
deleteToTask.add(task);
|
|
||||||
|
|
||||||
// 记录取消分配日志
|
|
||||||
inventoryLogService.addUnAllocInventoryLog(inventory, cancelQty, pick.getOrderNo(), pickDetail.getId(), pickDetail.getDescription());
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -185,30 +197,13 @@ public class CancelAllocateProcessor {
|
||||||
*/
|
*/
|
||||||
private void updateInventoryAllocation(Inventory inventory, BigDecimal cancelQty,
|
private void updateInventoryAllocation(Inventory inventory, BigDecimal cancelQty,
|
||||||
Map<Long, Inventory> inventoryUpdateMap) {
|
Map<Long, Inventory> inventoryUpdateMap) {
|
||||||
|
Inventory targetInventory = inventoryUpdateMap.getOrDefault(inventory.getId(), inventory);
|
||||||
|
|
||||||
Inventory inventoryToUpdate = inventoryUpdateMap.computeIfAbsent(
|
BigDecimal newCancelQty = BigDecimalUtil.subtract(targetInventory.getQueuedQty(), cancelQty, 0);
|
||||||
inventory.getId(), id -> {
|
targetInventory.setQueuedQty(newCancelQty);
|
||||||
// 2. 用Builder实现拷贝
|
Integer inv_status = targetInventory.getQueuedQty().compareTo(BigDecimal.ZERO) > 0 ? InventoryStatusEnum.ALLOCATED.getValue() : InventoryStatusEnum.AVAILABLE.getValue();
|
||||||
return Inventory.builder()
|
targetInventory.setStatus(inv_status);
|
||||||
.id(inventory.getId())
|
inventoryUpdateMap.put(targetInventory.getId(), targetInventory);
|
||||||
.itemId(inventory.getItemId())
|
|
||||||
.itemKeyId(inventory.getItemKeyId())
|
|
||||||
.pointId(inventory.getPointId())
|
|
||||||
.stockId(inventory.getStockId())
|
|
||||||
.quantity(inventory.getQuantity())
|
|
||||||
.queuedQty(inventory.getQueuedQty())
|
|
||||||
.status(inventory.getStatus())
|
|
||||||
.description(inventory.getDescription())
|
|
||||||
.sysOrgCode(inventory.getSysOrgCode())
|
|
||||||
.tenantId(inventory.getTenantId())
|
|
||||||
.createBy(inventory.getCreateBy())
|
|
||||||
.createTime(inventory.getCreateTime())
|
|
||||||
.build();
|
|
||||||
});
|
|
||||||
BigDecimal newCancelQty = BigDecimalUtil.subtract(inventoryToUpdate.getQueuedQty(), cancelQty, 0);
|
|
||||||
inventoryToUpdate.setQueuedQty(newCancelQty);
|
|
||||||
Integer inv_status = inventoryToUpdate.getQueuedQty().compareTo(BigDecimal.ZERO) > 0 ? InventoryStatusEnum.ALLOCATED.getValue() : InventoryStatusEnum.AVAILABLE.getValue();
|
|
||||||
inventoryToUpdate.setStatus(inv_status);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -221,65 +216,21 @@ public class CancelAllocateProcessor {
|
||||||
private void updatePickDetailAllocation(PickDetail pickDetail, BigDecimal cancelQty,
|
private void updatePickDetailAllocation(PickDetail pickDetail, BigDecimal cancelQty,
|
||||||
Map<Long, PickDetail> pickDetailUpdateMap) {
|
Map<Long, PickDetail> pickDetailUpdateMap) {
|
||||||
|
|
||||||
PickDetail detailToUpdate = pickDetailUpdateMap.computeIfAbsent(
|
PickDetail targetPickDetail = pickDetailUpdateMap.getOrDefault(pickDetail.getId(), pickDetail);
|
||||||
pickDetail.getId(), id -> {
|
|
||||||
// 2. 用Builder实现拷贝
|
|
||||||
return PickDetail.builder()
|
|
||||||
.id(pickDetail.getId())
|
|
||||||
.pickId(pickDetail.getPickId())
|
|
||||||
.itemId(pickDetail.getItemId())
|
|
||||||
.lineNo(pickDetail.getLineNo())
|
|
||||||
.unit(pickDetail.getUnit())
|
|
||||||
.project(pickDetail.getProject())
|
|
||||||
.taskNo(pickDetail.getTaskNo())
|
|
||||||
.orderQty(pickDetail.getOrderQty())
|
|
||||||
.allocatedQty(pickDetail.getAllocatedQty())
|
|
||||||
.pickedQty(pickDetail.getPickedQty())
|
|
||||||
.status(pickDetail.getStatus())
|
|
||||||
.propC1(pickDetail.getPropC1())
|
|
||||||
.propC3(pickDetail.getPropC3())
|
|
||||||
.description(pickDetail.getDescription())
|
|
||||||
.tenantId(pickDetail.getTenantId())
|
|
||||||
.sysOrgCode(pickDetail.getSysOrgCode())
|
|
||||||
.createBy(pickDetail.getCreateBy())
|
|
||||||
.createTime(pickDetail.getCreateTime())
|
|
||||||
.build();
|
|
||||||
});
|
|
||||||
|
|
||||||
BigDecimal newCancelQty = BigDecimalUtil.subtract(detailToUpdate.getAllocatedQty(), cancelQty, 0);
|
BigDecimal newCancelQty = BigDecimalUtil.subtract(targetPickDetail.getAllocatedQty(), cancelQty, 0);
|
||||||
detailToUpdate.setAllocatedQty(newCancelQty);
|
targetPickDetail.setAllocatedQty(newCancelQty);
|
||||||
|
|
||||||
// 更新状态
|
// 更新状态
|
||||||
Integer status=PickStatusEnum.CREATED.getValue();
|
Integer status = PickStatusEnum.CREATED.getValue();
|
||||||
BigDecimal allocateQty = detailToUpdate.getAllocatedQty();
|
BigDecimal allocateQty = targetPickDetail.getAllocatedQty();
|
||||||
if (detailToUpdate.getOrderQty().compareTo(allocateQty)<=0) {
|
if (targetPickDetail.getOrderQty().compareTo(allocateQty) <= 0) {
|
||||||
status = PickStatusEnum.ASSIGNED.getValue();
|
status = PickStatusEnum.ASSIGNED.getValue();
|
||||||
} else if(detailToUpdate.getOrderQty().compareTo(allocateQty)>0 && allocateQty.compareTo(BigDecimal.ZERO)>0){
|
} else if (targetPickDetail.getOrderQty().compareTo(allocateQty) > 0 && allocateQty.compareTo(BigDecimal.ZERO) > 0) {
|
||||||
status = PickStatusEnum.PARTIAL.getValue();
|
status = PickStatusEnum.PARTIAL.getValue();
|
||||||
}
|
}
|
||||||
detailToUpdate.setStatus(status);
|
targetPickDetail.setStatus(status);
|
||||||
}
|
pickDetailUpdateMap.put(targetPickDetail.getId(), targetPickDetail);
|
||||||
|
|
||||||
/**
|
|
||||||
* 批量操作
|
|
||||||
*
|
|
||||||
* @param inventoryUpdateMap 更新库存
|
|
||||||
* @param pickDetailUpdateMap 更新出库明细
|
|
||||||
* @param deleteToTask 删除出库任务
|
|
||||||
*/
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
|
||||||
public void batchOperation(Map<Long, Inventory> inventoryUpdateMap, Map<Long, PickDetail> pickDetailUpdateMap, List<Task> deleteToTask) {
|
|
||||||
List<Inventory> updateToInventory = new ArrayList<>(inventoryUpdateMap.values());
|
|
||||||
List<PickDetail> updateToPickDetail = new ArrayList<>(pickDetailUpdateMap.values());
|
|
||||||
if (CollectionUtils.isNotEmpty(updateToInventory)) {
|
|
||||||
batchUtils.updateBatchInventory(updateToInventory);
|
|
||||||
}
|
|
||||||
if (CollectionUtils.isNotEmpty(updateToPickDetail)) {
|
|
||||||
batchUtils.updateBatchPickDetail(updateToPickDetail);
|
|
||||||
}
|
|
||||||
if (CollectionUtils.isNotEmpty(deleteToTask)) {
|
|
||||||
taskMapper.deleteByIds(deleteToTask);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,10 @@ package org.cpte.modules.shipping.service.processor;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.cpte.modules.base.entity.Point;
|
||||||
import org.cpte.modules.base.entity.Stock;
|
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.base.service.IStockService;
|
||||||
import org.cpte.modules.constant.enums.CommonStatusEnum;
|
import org.cpte.modules.constant.enums.CommonStatusEnum;
|
||||||
import org.cpte.modules.constant.enums.PickStatusEnum;
|
import org.cpte.modules.constant.enums.PickStatusEnum;
|
||||||
|
|
@ -18,14 +19,12 @@ import org.cpte.modules.shipping.entity.Task;
|
||||||
import org.cpte.modules.shipping.mapper.PickDetailMapper;
|
import org.cpte.modules.shipping.mapper.PickDetailMapper;
|
||||||
import org.cpte.modules.shipping.service.IPickDetailService;
|
import org.cpte.modules.shipping.service.IPickDetailService;
|
||||||
import org.cpte.modules.shipping.vo.PickData;
|
import org.cpte.modules.shipping.vo.PickData;
|
||||||
import org.cpte.modules.utils.BatchUtil;
|
|
||||||
import org.cpte.modules.utils.BigDecimalUtil;
|
import org.cpte.modules.utils.BigDecimalUtil;
|
||||||
import org.cpte.modules.utils.RedisDistributedLockUtil;
|
import org.cpte.modules.utils.RedisDistributedLockUtil;
|
||||||
import org.jeecg.common.constant.CommonConstant;
|
import org.jeecg.common.constant.CommonConstant;
|
||||||
import org.jeecg.modules.base.service.BaseCommonService;
|
import org.jeecg.modules.base.service.BaseCommonService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
@ -43,6 +42,9 @@ public class PickProcessor {
|
||||||
@Autowired
|
@Autowired
|
||||||
private PickDetailMapper pickDetailMapper;
|
private PickDetailMapper pickDetailMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IPointService pointService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private IStockService stockService;
|
private IStockService stockService;
|
||||||
|
|
||||||
|
|
@ -58,9 +60,6 @@ public class PickProcessor {
|
||||||
@Autowired
|
@Autowired
|
||||||
private BaseCommonService baseCommonService;
|
private BaseCommonService baseCommonService;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private BatchUtil batchUtil;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private PickBackProcessor pickBackProcessor;
|
private PickBackProcessor pickBackProcessor;
|
||||||
|
|
||||||
|
|
@ -78,15 +77,17 @@ public class PickProcessor {
|
||||||
|
|
||||||
//2.创建数据结构
|
//2.创建数据结构
|
||||||
List<Inventory> deleteToInventory = new ArrayList<>();
|
List<Inventory> deleteToInventory = new ArrayList<>();
|
||||||
|
Map<Long, Inventory> inventoryUpdateMap = new HashMap<>();
|
||||||
Map<Long, PickDetail> pickDetailUpdateMap = new HashMap<>();
|
Map<Long, PickDetail> pickDetailUpdateMap = new HashMap<>();
|
||||||
List<Task> updateToTask = new ArrayList<>();
|
List<Task> updateToTask = new ArrayList<>();
|
||||||
List<Stock> updateToStock = new ArrayList<>();
|
List<Stock> updateToStock = new ArrayList<>();
|
||||||
|
List<Point> updateToPoint = new ArrayList<>();
|
||||||
|
|
||||||
//3.拣货
|
//3.拣货
|
||||||
pickTask(data, pickDetailUpdateMap, updateToTask, deleteToInventory, updateToStock);
|
pickTask(data, pickDetailUpdateMap, updateToTask, deleteToInventory,inventoryUpdateMap, updateToStock, updateToPoint);
|
||||||
|
|
||||||
//4.批量操作
|
//4.批量操作
|
||||||
batchOperation(deleteToInventory, pickDetailUpdateMap, updateToTask, updateToStock);
|
pickDetailService.batchOperationPick(deleteToInventory, pickDetailUpdateMap, updateToTask, updateToStock, updateToPoint);
|
||||||
|
|
||||||
//5.刷新出库单
|
//5.刷新出库单
|
||||||
refreshData(data);
|
refreshData(data);
|
||||||
|
|
@ -124,6 +125,11 @@ public class PickProcessor {
|
||||||
List<Long> stockIds = inventoryMap.values().stream().map(Inventory::getStockId).distinct().toList();
|
List<Long> stockIds = inventoryMap.values().stream().map(Inventory::getStockId).distinct().toList();
|
||||||
Map<Long, Stock> stockMap = stockService.queryByStockIdsToMap(stockIds);
|
Map<Long, Stock> stockMap = stockService.queryByStockIdsToMap(stockIds);
|
||||||
data.setStockMap(stockMap);
|
data.setStockMap(stockMap);
|
||||||
|
|
||||||
|
//库存点位
|
||||||
|
List<Long> pointIds = inventoryMap.values().stream().map(Inventory::getPointId).distinct().toList();
|
||||||
|
Map<Long, Point> pointMap = pointService.queryByPointIdsToMap(pointIds);
|
||||||
|
data.setPointMap(pointMap);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -132,10 +138,10 @@ public class PickProcessor {
|
||||||
*
|
*
|
||||||
* @param data 数据
|
* @param data 数据
|
||||||
*/
|
*/
|
||||||
private void pickTask(PickData data, Map<Long, PickDetail> pickDetailUpdateMap, List<Task> updateToTask, List<Inventory> deleteToInventory, List<Stock> updateToStock) {
|
private void pickTask(PickData data, Map<Long, PickDetail> pickDetailUpdateMap, List<Task> updateToTask, List<Inventory> deleteToInventory, Map<Long, Inventory> inventoryUpdateMap, List<Stock> updateToStock, List<Point> updateToPoint) {
|
||||||
for (Task task : data.getTasks()) {
|
for (Task task : data.getTasks()) {
|
||||||
try {
|
try {
|
||||||
processorTaskLock(data, task, pickDetailUpdateMap, updateToTask, deleteToInventory, updateToStock);
|
processorTaskLock(data, task, pickDetailUpdateMap, updateToTask, deleteToInventory, inventoryUpdateMap,updateToStock, updateToPoint);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("拣货异常", e);
|
log.error("拣货异常", e);
|
||||||
//记录拣货异常日志
|
//记录拣货异常日志
|
||||||
|
|
@ -154,16 +160,17 @@ public class PickProcessor {
|
||||||
* @param deleteToInventory 删除库存集合
|
* @param deleteToInventory 删除库存集合
|
||||||
* @param updateToStock 更新容器状态集合
|
* @param updateToStock 更新容器状态集合
|
||||||
*/
|
*/
|
||||||
private void processorTaskLock(PickData data, Task task, Map<Long, PickDetail> pickDetailUpdateMap, List<Task> updateToTask, List<Inventory> deleteToInventory, List<Stock> updateToStock) {
|
private void processorTaskLock(PickData data, Task task, Map<Long, PickDetail> pickDetailUpdateMap, List<Task> updateToTask, List<Inventory> deleteToInventory, Map<Long, Inventory> inventoryUpdateMap, List<Stock> updateToStock, List<Point> updateToPoint) {
|
||||||
// 拣货处理
|
// 拣货处理
|
||||||
String lockKey = "task:" + task.getId();
|
Pick pick = data.getPickMap().get(task.getPickId());
|
||||||
|
String lockKey = "task:" + pick.getId();
|
||||||
String lockValue = null;
|
String lockValue = null;
|
||||||
try {
|
try {
|
||||||
lockValue = redissonLock.tryLock(lockKey, 10);
|
lockValue = redissonLock.tryLock(lockKey, 10);
|
||||||
if (StringUtils.isEmpty(lockValue)) {
|
if (StringUtils.isEmpty(lockValue)) {
|
||||||
throw new RuntimeException("拣货处理中,请稍后重试");
|
throw new RuntimeException("拣货处理中,请稍后重试");
|
||||||
}
|
}
|
||||||
processorTask(data, task, pickDetailUpdateMap, updateToTask, deleteToInventory, updateToStock);
|
processorTask(data, task, pickDetailUpdateMap, updateToTask, deleteToInventory, inventoryUpdateMap, updateToStock, updateToPoint);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("拣货异常", e);
|
log.error("拣货异常", e);
|
||||||
throw e;
|
throw e;
|
||||||
|
|
@ -172,6 +179,7 @@ public class PickProcessor {
|
||||||
redissonLock.unlock(lockKey, lockValue);
|
redissonLock.unlock(lockKey, lockValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -185,7 +193,7 @@ public class PickProcessor {
|
||||||
* @param deleteToInventory 删除库存集合
|
* @param deleteToInventory 删除库存集合
|
||||||
* @param updateToStock 更新容器状态集合
|
* @param updateToStock 更新容器状态集合
|
||||||
*/
|
*/
|
||||||
private void processorTask(PickData data, Task task, Map<Long, PickDetail> pickDetailUpdateMap, List<Task> updateToTask, List<Inventory> deleteToInventory, List<Stock> updateToStock) {
|
private void processorTask(PickData data, Task task, Map<Long, PickDetail> pickDetailUpdateMap, List<Task> updateToTask, List<Inventory> deleteToInventory, Map<Long, Inventory> inventoryUpdateMap, List<Stock> updateToStock, List<Point> updateToPoint) {
|
||||||
|
|
||||||
BigDecimal pickedQty = BigDecimalUtil.subtract(task.getPlanQty(), task.getMoveQty(), 0);
|
BigDecimal pickedQty = BigDecimalUtil.subtract(task.getPlanQty(), task.getMoveQty(), 0);
|
||||||
if (pickedQty.compareTo(BigDecimal.ZERO) <= 0) {
|
if (pickedQty.compareTo(BigDecimal.ZERO) <= 0) {
|
||||||
|
|
@ -208,8 +216,11 @@ public class PickProcessor {
|
||||||
//更新容器状态
|
//更新容器状态
|
||||||
updateToStock(data, task, updateToStock);
|
updateToStock(data, task, updateToStock);
|
||||||
|
|
||||||
|
//更新点位状态
|
||||||
|
updateToPoint(data, task, updateToPoint);
|
||||||
|
|
||||||
//添加库存日志
|
//添加库存日志
|
||||||
addInventoryLog(data, task, pickedQty);
|
addInventoryLog(data, task, pickedQty, inventoryUpdateMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -287,9 +298,23 @@ public class PickProcessor {
|
||||||
private void updateToStock(PickData data, Task task, List<Stock> updateToStock) {
|
private void updateToStock(PickData data, Task task, List<Stock> updateToStock) {
|
||||||
Stock stock = data.getStockMap().get(task.getStockId());
|
Stock stock = data.getStockMap().get(task.getStockId());
|
||||||
if (!updateToStock.contains(stock)) {
|
if (!updateToStock.contains(stock)) {
|
||||||
stock.setPointId(null);
|
|
||||||
stock.setStatus(CommonStatusEnum.FREE.getValue());
|
stock.setStatus(CommonStatusEnum.FREE.getValue());
|
||||||
updateToStock.add(stock);
|
updateToStock.add(stock);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新点位状态
|
||||||
|
*
|
||||||
|
* @param data 数据
|
||||||
|
* @param updateToPoint 点位更新集合
|
||||||
|
*/
|
||||||
|
private void updateToPoint(PickData data, Task task, List<Point> updateToPoint) {
|
||||||
|
Point point = data.getPointMap().get(task.getFromPointId());
|
||||||
|
if (!updateToPoint.contains(point)) {
|
||||||
|
point.setStatus(CommonStatusEnum.FREE.getValue());
|
||||||
|
updateToPoint.add(point);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -300,35 +325,11 @@ public class PickProcessor {
|
||||||
* @param task 任务
|
* @param task 任务
|
||||||
* @param pickedQty 拣货数量
|
* @param pickedQty 拣货数量
|
||||||
*/
|
*/
|
||||||
private void addInventoryLog(PickData data, Task task, BigDecimal pickedQty) {
|
private void addInventoryLog(PickData data, Task task, BigDecimal pickedQty, Map<Long, Inventory> inventoryUpdateMap) {
|
||||||
Inventory inventory = data.getInventoryMap().get(task.getInventoryId());
|
Inventory inventory = data.getInventoryMap().get(task.getInventoryId());
|
||||||
|
updateInventory(inventory, pickedQty, inventoryUpdateMap);
|
||||||
Pick pick = data.getPickMap().get(task.getPickId());
|
Pick pick = data.getPickMap().get(task.getPickId());
|
||||||
inventoryLogService.addPickInventoryLog(inventory, task.getToPointId(), pickedQty, pick.getOrderNo(), task.getId(), null);
|
inventoryLogService.addPickInventoryLog(inventoryUpdateMap.get(inventory.getId()), 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package org.cpte.modules.shipping.vo;
|
package org.cpte.modules.shipping.vo;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import org.cpte.modules.base.entity.Point;
|
||||||
import org.cpte.modules.base.entity.Stock;
|
import org.cpte.modules.base.entity.Stock;
|
||||||
import org.cpte.modules.inventory.entity.Inventory;
|
import org.cpte.modules.inventory.entity.Inventory;
|
||||||
import org.cpte.modules.shipping.entity.Pick;
|
import org.cpte.modules.shipping.entity.Pick;
|
||||||
|
|
@ -14,6 +15,7 @@ import java.util.Map;
|
||||||
public class PickData {
|
public class PickData {
|
||||||
private List<Task> tasks;
|
private List<Task> tasks;
|
||||||
private Map<Long, Stock> stockMap;
|
private Map<Long, Stock> stockMap;
|
||||||
|
private Map<Long, Point> pointMap;
|
||||||
private Map<Long, Pick> pickMap;
|
private Map<Long, Pick> pickMap;
|
||||||
private Map<Long, PickDetail> pickDetailMap;
|
private Map<Long, PickDetail> pickDetailMap;
|
||||||
private Map<Long, Inventory> inventoryMap;
|
private Map<Long, Inventory> inventoryMap;
|
||||||
|
|
|
||||||
|
|
@ -223,7 +223,7 @@ public class ITesAgvServiceImpl implements ITesAgvService {
|
||||||
private void handleEnd(Long asnId, AgvTask agvTask) {
|
private void handleEnd(Long asnId, AgvTask agvTask) {
|
||||||
if (BusinessTypeEnum.INBOUND.getValue().equals(agvTask.getType())) {
|
if (BusinessTypeEnum.INBOUND.getValue().equals(agvTask.getType())) {
|
||||||
//收货
|
//收货
|
||||||
asnService.receiveAsn(asnId, agvTask.getEndCode());
|
asnService.receiveAsn(asnId);
|
||||||
} else if (BusinessTypeEnum.OUTBOUND.getValue().equals(agvTask.getType())) {
|
} else if (BusinessTypeEnum.OUTBOUND.getValue().equals(agvTask.getType())) {
|
||||||
//拣货
|
//拣货
|
||||||
List<Task> tasks = taskMapper.queryByAgvTask(agvTask.getId());
|
List<Task> tasks = taskMapper.queryByAgvTask(agvTask.getId());
|
||||||
|
|
|
||||||
|
|
@ -265,7 +265,7 @@ public class BatchUtil {
|
||||||
ps.setLong(2, record.getAsnId());
|
ps.setLong(2, record.getAsnId());
|
||||||
ps.setLong(3, record.getAsnDetailId());
|
ps.setLong(3, record.getAsnDetailId());
|
||||||
ps.setLong(4, record.getStockId());
|
ps.setLong(4, record.getStockId());
|
||||||
ps.setLong(5, record.getFromPointId());
|
ps.setObject(5, record.getFromPointId());
|
||||||
ps.setLong(6, record.getToPointId());
|
ps.setLong(6, record.getToPointId());
|
||||||
ps.setLong(7, record.getItemId());
|
ps.setLong(7, record.getItemId());
|
||||||
ps.setLong(8, record.getItemKeyId());
|
ps.setLong(8, record.getItemKeyId());
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue