no message

main
HUOJIN\92525 2025-12-10 00:00:26 +08:00
parent 90a27ac851
commit 1cc3a8400e
28 changed files with 689 additions and 323 deletions

View File

@ -0,0 +1,106 @@
package org.cpte.modules.base.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
/**
* @Description:
* @author: cpte
* @Date: 2025-10-27
* @Version: V1.0
*/
@TableName("base_item_key")
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Schema(description = "物料属性表")
public class ItemKey implements Serializable {
private static final long serialVersionUID = 1L;
/**
*
*/
@TableId(type = IdType.ASSIGN_ID)
@Schema(description = "主键")
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
@Schema(description = "物料")
@JsonSerialize(using = ToStringSerializer.class)
private java.lang.Long itemId;
/**
*
*/
@Schema(description = "外部仓库")
private java.lang.String whCode;
/**
*
*/
@Schema(description = "项目号")
private java.lang.String project;
/**
*
*/
@Schema(description = "任务号")
private java.lang.String taskNo;
/**
*
*/
@Schema(description = "批次号")
private java.lang.String propC1;
/**
*
*/
@Schema(description = "外部库存状态")
private java.lang.String propC3;
/**
*
*/
@Schema(description = "所属部门")
private String sysOrgCode;
/**
* ID
*/
@Excel(name = "租户ID", width = 15)
@Schema(description = "租户ID")
private Long tenantId;
/**
*
*/
@Schema(description = "创建人")
private String createBy;
/**
*
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Schema(description = "创建日期")
private Date createTime;
/**
*
*/
@Schema(description = "更新人")
private String updateBy;
/**
*
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Schema(description = "更新日期")
private Date updateTime;
}

View File

@ -0,0 +1,39 @@
package org.cpte.modules.base.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.cpte.modules.base.entity.ItemKey;
import java.util.List;
/**
* @Description:
* @author: cpte
* @Date: 2025-10-27
* @Version: V1.0
*/
public interface ItemKeyMapper extends BaseMapper<ItemKey> {
/**
*
*
* @param itemId ID
* @param whCode
* @param project
* @param taskNo
* @param propC1
* @param propC3
* @return ItemKey
*/
ItemKey queryItemKey(@Param("itemId") Long itemId, @Param("whCode") String whCode,
@Param("project") String project, @Param("taskNo") String taskNo,
@Param("propC1") String propC1, @Param("propC3") String propC3);
List<ItemKey> queryItemKeyByIds(@Param("itemKeyIds") List<Long> itemKeyIds);
List<ItemKey> queryItemKeys(@Param("itemIds") List<Long> itemIds, @Param("whCodeList") List<String> whCodeList,
@Param("projectList") List<String> projectList, @Param("taskNoList") List<String> taskNoList,
@Param("propC1List") List<String> propC1List, @Param("propC3List") List<String> propC3List);
}

View File

@ -0,0 +1,119 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.cpte.modules.base.mapper.ItemKeyMapper">
<select id="queryItemKey" resultType="org.cpte.modules.base.entity.ItemKey">
SELECT * FROM base_item_key
WHERE item_id = #{itemId}
<choose>
<when test="whCode != null and whCode != ''">
AND wh_code = #{whCode}
</when>
<otherwise>
AND (wh_code IS NULL OR wh_code = '')
</otherwise>
</choose>
<choose>
<when test="project != null and project != ''">
AND project = #{project}
</when>
<otherwise>
AND (project IS NULL OR project = '')
</otherwise>
</choose>
<choose>
<when test="taskNo != null and taskNo != ''">
AND task_no = #{taskNo}
</when>
<otherwise>
AND (task_no IS NULL OR task_no = '')
</otherwise>
</choose>
<choose>
<when test="propC1 != null and propC1 != ''">
AND prop_c1 = #{propC1}
</when>
<otherwise>
AND (prop_c1 IS NULL OR prop_c1 = '')
</otherwise>
</choose>
<choose>
<when test="propC3 != null and propC3 != ''">
AND prop_c3 = #{propC3}
</when>
<otherwise>
AND (prop_c3 IS NULL OR prop_c3 = '')
</otherwise>
</choose>
</select>
<select id="queryItemKeyByIds" resultType="org.cpte.modules.base.entity.ItemKey">
SELECT * FROM base_item_key
WHERE id IN
<foreach collection="itemKeyIds" item="itemKeyId" open="(" separator="," close=")">
#{itemKeyId}
</foreach>
</select>
<select id="queryItemKeys" resultType="org.cpte.modules.base.entity.ItemKey">
SELECT * FROM base_item_key
WHERE item_id IN
<foreach collection="itemIds" item="itemId" open="(" separator="," close=")">
#{itemId}
</foreach>
<choose>
<when test="whCodeList != null and !whCodeList.isEmpty()">
AND wh_code IN
<foreach collection="whCodeList" item="whCode" open="(" separator="," close=")">
#{whCode}
</foreach>
</when>
<otherwise>
AND (wh_code IS NULL OR wh_code = '')
</otherwise>
</choose>
<choose>
<when test="projectList != null and !projectList.isEmpty()">
AND project IN
<foreach collection="projectList" item="project" open="(" separator="," close=")">
#{project}
</foreach>
</when>
<otherwise>
AND (project IS NULL OR project = '')
</otherwise>
</choose>
<choose>
<when test="taskNoList != null and !taskNoList.isEmpty()">
AND task_no IN
<foreach collection="taskNoList" item="taskNo" open="(" separator="," close=")">
#{taskNo}
</foreach>
</when>
<otherwise>
AND (task_no IS NULL OR task_no = '')
</otherwise>
</choose>
<choose>
<when test="propC1List != null and !propC1List.isEmpty()">
AND prop_c1 IN
<foreach collection="propC1List" item="propC1" open="(" separator="," close=")">
#{propC1}
</foreach>
</when>
<otherwise>
AND (prop_c1 IS NULL OR prop_c1 = '')
</otherwise>
</choose>
<choose>
<when test="propC3List != null and !propC3List.isEmpty()">
AND prop_c3 IN
<foreach collection="propC3List" item="propC3" open="(" separator="," close=")">
#{propC3}
</foreach>
</when>
<otherwise>
AND (prop_c3 IS NULL OR prop_c3 = '')
</otherwise>
</choose>
</select>
</mapper>

View File

@ -0,0 +1,26 @@
package org.cpte.modules.base.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.cpte.modules.base.entity.ItemKey;
/**
* @Description:
* @author: cpte
* @Date: 2025-10-27
* @Version: V1.0
*/
public interface IItemKeyService extends IService<ItemKey> {
/**
*
*
* @param itemId ID
* @param whCode
* @param project
* @param taskNo
* @param propC1
* @param propC3
* @return ItemKey
*/
ItemKey createItemKey(Long itemId, String whCode, String project, String taskNo, String propC1, String propC3);
}

View File

@ -1,10 +1,7 @@
package org.cpte.modules.base.service;
import org.apache.ibatis.annotations.Param;
import org.cpte.modules.base.entity.Point;
import com.baomidou.mybatisplus.extension.service.IService;
import org.cpte.modules.receive.entity.Asn;
import org.cpte.modules.receive.entity.AsnDetail;
import java.util.List;
import java.util.Map;

View File

@ -18,12 +18,9 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@Service
public class AreaServiceImpl extends ServiceImpl<AreaMapper, Area> implements IAreaService {
@Autowired
private AreaMapper areaMapper;
@Override
public Area validateArea(String areaCode) {
Area area = areaMapper.queryByAreaCode(areaCode);
Area area = this.baseMapper.queryByAreaCode(areaCode);
if (area == null) {
throw new RuntimeException("系统无【" + areaCode + "】库区,请维护");
}

View File

@ -0,0 +1,51 @@
package org.cpte.modules.base.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.shiro.SecurityUtils;
import org.cpte.modules.base.entity.ItemKey;
import org.cpte.modules.base.mapper.ItemKeyMapper;
import org.cpte.modules.base.service.IItemKeyService;
import org.jeecg.common.system.vo.LoginUser;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
/**
* @Description:
* @author: cpte
* @Date: 2025-10-27
* @Version: V1.0
*/
@Service
public class ItemKeyServiceImpl extends ServiceImpl<ItemKeyMapper, ItemKey> implements IItemKeyService {
@Override
@Transactional(rollbackFor = Exception.class)
public ItemKey createItemKey(Long itemId, String whCode, String project, String taskNo, String propC1, String propC3) {
LoginUser sysUser = null;
try {
sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
} catch (Exception e) {
log.error("获取登录用户信息失败");
}
ItemKey itemKey = this.baseMapper.queryItemKey(itemId, whCode, project, taskNo, propC1, propC3);
if (itemKey != null) {
return itemKey;
}
itemKey = ItemKey.builder()
.itemId(itemId)
.whCode(whCode)
.project(project)
.taskNo(taskNo)
.propC1(propC1)
.propC3(propC3)
.sysOrgCode(sysUser == null ? "A05" : sysUser.getOrgCode())
.tenantId(sysUser == null ? 1000L : Long.parseLong(sysUser.getRelTenantIds()))
.createBy(sysUser == null ? "saiWms" : sysUser.getUsername())
.createTime(new Date())
.build();
return this.save(itemKey) ? itemKey : null;
}
}

View File

@ -24,9 +24,6 @@ import java.util.Map;
@Service
public class ItemServiceImpl extends ServiceImpl<ItemMapper, Item> implements IItemService {
@Autowired
private ItemMapper itemMapper;
/**
*
*
@ -35,7 +32,7 @@ public class ItemServiceImpl extends ServiceImpl<ItemMapper, Item> implements II
*/
@Override
public Item validateItem(String itemCode) {
Item item = itemMapper.queryByItemCode(itemCode);
Item item = this.baseMapper.queryByItemCode(itemCode);
if (item == null) {
throw new RuntimeException("系统无【" + itemCode + "】物料,请维护");
}
@ -61,9 +58,7 @@ public class ItemServiceImpl extends ServiceImpl<ItemMapper, Item> implements II
//查询物料
LambdaQueryWrapper<Item> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.in(Item::getItemCode, itemCodes);
queryWrapper.eq(Item::getDelFlag, 0);
queryWrapper.eq(Item::getIzActive, 1);
return itemMapper.selectList(queryWrapper);
return this.baseMapper.selectList(queryWrapper);
}
/**

View File

@ -32,9 +32,6 @@ public class PointServiceImpl extends ServiceImpl<PointMapper, Point> implements
@Autowired
private IAreaService iAreaService;
@Autowired
private PointMapper pointMapper;
@Autowired
private RedisUtil redisUtil;
@ -46,7 +43,7 @@ public class PointServiceImpl extends ServiceImpl<PointMapper, Point> implements
*/
@Override
public Point validatePoint(String pointCode) {
Point point = pointMapper.queryByPointCode(pointCode);
Point point = this.baseMapper.queryByPointCode(pointCode);
if (point == null) {
throw new RuntimeException("系统无【" + pointCode + "】库位,请维护");
}
@ -62,13 +59,13 @@ public class PointServiceImpl extends ServiceImpl<PointMapper, Point> implements
@Override
public void bindPoint(Point point) {
point.setStatus(CommonStatusEnum.USED.getValue());
pointMapper.updateById(point);
this.baseMapper.updateById(point);
}
@Override
public void unbindPoint(Point point) {
point.setStatus(CommonStatusEnum.FREE.getValue());
pointMapper.updateById(point);
this.baseMapper.updateById(point);
}
/**
@ -84,9 +81,7 @@ public class PointServiceImpl extends ServiceImpl<PointMapper, Point> implements
//查询库位
LambdaQueryWrapper<Point> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.in(Point::getPointCode, pointCodes);
queryWrapper.eq(Point::getDelFlag, 0);
queryWrapper.eq(Point::getIzActive, 1);
return pointMapper.selectList(queryWrapper);
return this.baseMapper.selectList(queryWrapper);
}
/**
@ -124,7 +119,7 @@ public class PointServiceImpl extends ServiceImpl<PointMapper, Point> implements
@Override
public Point getWorkStationPoint(Integer status, String areaCode, String key) {
List<Point> dstPointList = pointMapper.queryPoints(null, status, areaCode);
List<Point> dstPointList = this.baseMapper.queryPoints(null, status, areaCode);
if (dstPointList.isEmpty()) {
String desc = AreaTypeEnum.getDescByValue(areaCode);
throw new RuntimeException("【" + desc + "】" + "无空闲库位");
@ -145,17 +140,17 @@ public class PointServiceImpl extends ServiceImpl<PointMapper, Point> implements
@Override
public List<Point> findByColAndLayer(String colNum, String layerNum) {
return pointMapper.findByColAndLayer(colNum, layerNum);
return this.baseMapper.findByColAndLayer(colNum, layerNum);
}
@Override
public List<Point> queryPoints(String pointCode, Integer status, String areaCode) {
return pointMapper.queryPoints(pointCode, status, areaCode);
return this.baseMapper.queryPoints(pointCode, status, areaCode);
}
@Override
public List<Point> findClusterPoint(Long itemId, String whCode, List<String> projects, List<String> taskNos, List<String> propC1List, List<String> propC3List, String areaCode) {
return pointMapper.findPointsWithSkuBatchPo(itemId, whCode,projects,taskNos, propC1List, propC3List, areaCode);
return this.baseMapper.findPointsWithSkuBatchPo(itemId, whCode,projects,taskNos, propC1List, propC3List, areaCode);
}
}

View File

@ -30,9 +30,6 @@ import java.util.Objects;
@Service
public class StockServiceImpl extends ServiceImpl<StockMapper, Stock> implements IStockService {
@Autowired
private StockMapper stockMapper;
/**
*
*
@ -41,7 +38,7 @@ public class StockServiceImpl extends ServiceImpl<StockMapper, Stock> implements
*/
@Override
public Stock validateStock(String StockCode) {
Stock stock = stockMapper.queryByStockCode(StockCode);
Stock stock = this.baseMapper.queryByStockCode(StockCode);
if (stock == null) {
throw new RuntimeException("系统无【" + StockCode + "】容器,请维护");
}
@ -65,7 +62,7 @@ public class StockServiceImpl extends ServiceImpl<StockMapper, Stock> implements
public void bindStock(Stock stock, Point point) {
stock.setPointId(point == null ? null : point.getId());
stock.setStatus(CommonStatusEnum.USED.getValue());
stockMapper.updateById(stock);
this.baseMapper.updateById(stock);
}
@ -82,7 +79,7 @@ public class StockServiceImpl extends ServiceImpl<StockMapper, Stock> implements
//查询容器
LambdaQueryWrapper<Stock> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.in(Stock::getStockCode, stockCodes);
return stockMapper.selectList(queryWrapper);
return this.baseMapper.selectList(queryWrapper);
}
/**

View File

@ -7,8 +7,10 @@ import org.apache.commons.lang3.StringUtils;
import org.cpte.modules.agvTask.entity.AgvTask;
import org.cpte.modules.agvTask.mapper.AgvTaskMapper;
import org.cpte.modules.agvTask.service.IAgvTaskService;
import org.cpte.modules.base.entity.ItemKey;
import org.cpte.modules.base.entity.Point;
import org.cpte.modules.base.entity.Stock;
import org.cpte.modules.base.mapper.ItemKeyMapper;
import org.cpte.modules.base.mapper.PointMapper;
import org.cpte.modules.base.mapper.StockMapper;
import org.cpte.modules.base.service.IPointService;
@ -22,7 +24,6 @@ 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.entity.PickDetail;
import org.cpte.modules.shipping.entity.Task;
import org.cpte.modules.shipping.mapper.TaskMapper;
import org.springframework.beans.factory.annotation.Autowired;
@ -55,6 +56,9 @@ public class IConveyorLineServiceImpl implements IConveyorLineService {
@Autowired
private AgvTaskMapper agvTaskMapper;
@Autowired
private ItemKeyMapper itemKeyMapper;
@Autowired
private InventoryMapper inventoryMapper;
@ -274,8 +278,10 @@ public class IConveyorLineServiceImpl implements IConveyorLineService {
List<Inventory> neighbors = inventoryMapper.findNeighborPoints(
point.getColNum(), point.getLayerNum(), String.valueOf(minDepth), String.valueOf(maxDepth));
List<Long> itemKeyIds = neighbors.stream().map(Inventory::getItemKeyId).distinct().toList();
List<ItemKey> itemKeys = itemKeyMapper.queryItemKeyByIds(itemKeyIds);
for (Inventory neighbor : neighbors) {
for (ItemKey neighbor : itemKeys) {
if (neighbor.getItemId() != null) {
// 同SKU加分
if (neighbor.getItemId().equals(itemId)) {

View File

@ -51,6 +51,15 @@ public class Inventory implements Serializable {
@Dict(dictTable = "base_item", dicCode = "id", dicText = "item_code")
@JsonSerialize(using = ToStringSerializer.class)
private java.lang.Long itemId;
/**
*
*/
@Excel(name = "物料属性", width = 15)
@Schema(description = "物料属性")
@JsonSerialize(using = ToStringSerializer.class)
private java.lang.Long itemKeyId;
/**
* ID
*/
@ -87,45 +96,6 @@ public class Inventory implements Serializable {
@JsonSerialize(using = ToStringSerializer.class)
private java.lang.Long receiveRecordId;
/**
*
*/
@Excel(name = "外部仓库", width = 15)
@Schema(description = "外部仓库")
private java.lang.String whCode;
/**
*
*/
@Schema(description = "项目号")
private java.lang.String project;
/**
*
*/
@Schema(description = "任务号")
private java.lang.String taskNo;
/**
*
*/
@Excel(name = "批次号", width = 15)
@Schema(description = "批次号")
private java.lang.String propC1;
/**
*
*/
@Excel(name = "外部库存状态", width = 15)
@Schema(description = "外部库存状态")
private java.lang.String propC3;
/**
*
*/
@Excel(name = "序列号", width = 15)
@Schema(description = "序列号")
private java.lang.String propC2;
/**
*
*/
@ -133,20 +103,14 @@ public class Inventory implements Serializable {
@Schema(description = "库存状态")
@Dict(dicCode = "inventory_status")
private java.lang.Integer status;
/**
*
*/
@Excel(name = "生产日期", width = 15, format = "yyyy-MM-dd")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
@Schema(description = "生产日期")
private java.util.Date propD1;
/**
*
*/
@Excel(name = "描述", width = 15)
@Schema(description = "描述")
private java.lang.String description;
/**
*
*/

View File

@ -26,17 +26,6 @@ public interface InventoryMapper extends BaseMapper<Inventory> {
@Select("select * from data_inventory where stock_id = #{stockId} and quantity>0 for update")
Inventory queryByStockId(@Param("stockId") Long stockId);
/**
*
*
* @param itemIds ID
* @param propC1List
* @param propC3List
* @param whCodeList
* @return List<Inventory>
*/
List<Inventory> queryInventory(@Param("itemIds") List<Long> itemIds, @Param("propC1List") List<String> propC1List, @Param("propC3List") List<String> propC3List, @Param("whCodeList") List<String> whCodeList);
// 查询相邻库位同一巷道深度±3范围内
@Select("SELECT di.* " +
"FROM data_inventory di " +
@ -49,6 +38,13 @@ public interface InventoryMapper extends BaseMapper<Inventory> {
@Param("layerNum") String layerNum,
@Param("minDepth") String minDepth,
@Param("maxDepth") String maxDepth);
/**
* ID
*
* @param itemKeyIds ID
* @return List<Inventory>
*/
List<Inventory> queryInventoryByItemKeyId(@Param("itemKeyIds") List<Long> itemKeyIds);
/**

View File

@ -1,50 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.cpte.modules.inventory.mapper.InventoryMapper">
<select id="queryInventory" resultType="org.cpte.modules.inventory.entity.Inventory">
SELECT * FROM data_inventory
WHERE status in (1,2)
AND quantity > 0
AND item_id IN
<foreach collection="itemIds" item="itemId" open="(" separator="," close=")">
#{itemId}
<select id="queryInventoryByItemKeyId" resultType="org.cpte.modules.inventory.entity.Inventory">
SELECT di.* FROM data_inventory di
JOIN base_item_key bik ON di.item_key_id = bik.id
WHERE di.status in (1,2)
AND di.quantity > 0
AND bik.id IN
<foreach collection="itemKeyIds" item="itemKeyId" open="(" separator="," close=")">
#{itemKeyId}
</foreach>
<choose>
<when test="propC1List != null and !propC1List.isEmpty()">
AND prop_c1 IN
<foreach collection="propC1List" item="propC1" open="(" separator="," close=")">
#{propC1}
</foreach>
</when>
<otherwise>
AND (prop_c1 IS NULL OR prop_c1 = '')
</otherwise>
</choose>
<choose>
<when test="propC3List != null and !propC3List.isEmpty()">
AND prop_c3 IN
<foreach collection="propC3List" item="propC3" open="(" separator="," close=")">
#{propC3}
</foreach>
</when>
<otherwise>
AND (prop_c3 IS NULL OR prop_c3 = '')
</otherwise>
</choose>
<choose>
<when test="whCodeList != null and !whCodeList.isEmpty()">
AND wh_code IN
<foreach collection="whCodeList" item="whCode" open="(" separator="," close=")">
#{whCode}
</foreach>
</when>
<otherwise>
AND (wh_code IS NULL OR wh_code = '')
</otherwise>
</choose>
ORDER BY create_time
ORDER BY di.create_time
</select>
<select id="queryByPointIds" resultType="org.cpte.modules.inventory.entity.Inventory">

View File

@ -17,6 +17,17 @@ import java.util.Map;
* @Version: V1.0
*/
public interface IInventoryService extends IService<Inventory> {
/**
*
*
* @param stockId
* @param receivedQty
* @param asn
* @param receiveRecord
* @return Inventory
*/
Inventory buildInventory(Long stockId, BigDecimal receivedQty, Asn asn, ReceiveRecord receiveRecord);
/**
*
*

View File

@ -1,20 +1,13 @@
package org.cpte.modules.inventory.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.commons.collections4.CollectionUtils;
import org.cpte.modules.base.entity.Area;
import org.cpte.modules.base.mapper.AreaMapper;
import org.cpte.modules.constant.enums.InventoryStatusEnum;
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.receive.entity.Asn;
import org.cpte.modules.receive.entity.AsnDetail;
import org.cpte.modules.receive.entity.ReceiveRecord;
import org.cpte.modules.shipping.entity.PickDetail;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;
@ -29,30 +22,37 @@ import java.util.*;
*/
@Service
public class InventoryServiceImpl extends ServiceImpl<InventoryMapper, Inventory> implements IInventoryService {
@Autowired
private AreaMapper areaMapper;
@Autowired
private InventoryMapper inventoryMapper;
@Override
public Inventory buildInventory(Long stockId, BigDecimal receivedQty, Asn asn, ReceiveRecord receiveRecord) {
return Inventory.builder()
.itemId(receiveRecord.getItemId())
.itemKeyId(receiveRecord.getItemKeyId())
.pointId(receiveRecord.getToPointId())
.stockId(receiveRecord.getStockId())
.quantity(receivedQty)
.queuedQty(BigDecimal.ZERO)
.receiveRecordId(receiveRecord.getId())
.status(InventoryStatusEnum.AVAILABLE.getValue())
.description(receiveRecord.getDescription())
.tenantId(receiveRecord.getTenantId())
.sysOrgCode(receiveRecord.getSysOrgCode())
.createBy(receiveRecord.getCreateBy())
.createTime(new Date())
.build();
}
@Override
@Transactional(rollbackFor = Exception.class)
public Inventory createInventory(Long stockId, BigDecimal receivedQty, Asn asn, ReceiveRecord receiveRecord) {
Inventory inventory = Inventory.builder()
.itemId(receiveRecord.getItemId())
.itemKeyId(receiveRecord.getItemKeyId())
.pointId(receiveRecord.getToPointId())
.stockId(receiveRecord.getStockId())
.quantity(receivedQty)
.queuedQty(BigDecimal.ZERO)
.receiveRecordId(receiveRecord.getId())
.project(receiveRecord.getProject())
.taskNo(receiveRecord.getTaskNo())
.whCode(asn.getWhCode())
.propC1(receiveRecord.getPropC1())
.propC2(receiveRecord.getPropC2())
.propC3(receiveRecord.getPropC3())
.status(InventoryStatusEnum.AVAILABLE.getValue())
.propD1(receiveRecord.getPropD1())
.description(receiveRecord.getDescription())
.tenantId(receiveRecord.getTenantId())
.sysOrgCode(receiveRecord.getSysOrgCode())
@ -68,7 +68,7 @@ public class InventoryServiceImpl extends ServiceImpl<InventoryMapper, Inventory
return Collections.emptyMap();
}
Map<Long, Inventory> inventoryMap = new HashMap<>();
List<Inventory> inventories = inventoryMapper.selectByIds(inventoryIds);
List<Inventory> inventories = this.baseMapper.selectByIds(inventoryIds);
for (Inventory inventory : inventories) {
inventoryMap.put(inventory.getId(), inventory);
}

View File

@ -75,6 +75,15 @@ public class InventoryLog implements Serializable {
@Schema(description = "物料ID")
@Dict(dictTable = "base_item", dicCode = "id", dicText = "item_code")
private java.lang.Long itemId;
/**
*
*/
@Excel(name = "物料属性", width = 15)
@Schema(description = "物料属性")
@JsonSerialize(using = ToStringSerializer.class)
private java.lang.Long itemKeyId;
/**
*
*/
@ -97,37 +106,7 @@ public class InventoryLog implements Serializable {
@Schema(description = "容器ID")
@Dict(dictTable = "base_stock", dicCode = "id", dicText = "stock_code")
private java.lang.Long stockId;
/**
*
*/
@Excel(name = "外部仓库", width = 15)
@Schema(description = "外部仓库")
private java.lang.String whCode;
/**
*
*/
@Schema(description = "项目号")
private java.lang.String project;
/**
*
*/
@Schema(description = "任务号")
private java.lang.String taskNo;
/**
*
*/
@Excel(name = "批次号", width = 15)
@Schema(description = "批次号")
private java.lang.String propC1;
/**
*
*/
@Excel(name = "外部库存状态", width = 15)
@Schema(description = "外部库存状态")
private java.lang.String propC3;
/**
*

View File

@ -21,6 +21,18 @@ public interface IInventoryLogService extends IService<InventoryLog> {
*/
void addInventoryLog(InventoryLog inventoryLog);
/**
*
*
* @param inventory
* @param srcPointId
* @param changeQty
* @param businessNo
* @param businessDetailId ID
* @param description
*/
InventoryLog buildInboundInventoryLog(Inventory inventory, Long srcPointId, BigDecimal changeQty, String businessNo, Long businessDetailId, String description);
/**
*
*
@ -33,6 +45,8 @@ public interface IInventoryLogService extends IService<InventoryLog> {
*/
void addInboundInventoryLog(Inventory inventory, Long srcPointId, BigDecimal changeQty, String businessNo, Long businessDetailId, String description);
/**
*
*

View File

@ -37,6 +37,15 @@ public class InventoryLogServiceImpl extends ServiceImpl<InventoryLogMapper, Inv
}
}
@Override
public InventoryLog buildInboundInventoryLog(Inventory inventory, Long srcPointId, BigDecimal changeQty, String businessNo, Long businessDetailId, String description) {
InventoryLog inventoryLog = buildInventoryLog(inventory, changeQty, businessNo, businessDetailId, description);
// 入库类型
inventoryLog.setLogType(InventoryLogEnum.INBOUND.getValue());
inventoryLog.setFromPointId(srcPointId);
return inventoryLog;
}
@Override
@Transactional(rollbackFor = Exception.class)
public void addInboundInventoryLog(Inventory inventory, Long srcPointId, BigDecimal changeQty, String businessNo, Long businessDetailId, String description) {
@ -47,6 +56,7 @@ public class InventoryLogServiceImpl extends ServiceImpl<InventoryLogMapper, Inv
addInventoryLog(inventoryLog);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void addOutboundInventoryLog(Inventory inventory, BigDecimal changeQty, String businessNo, Long businessDetailId, String description) {
@ -61,7 +71,7 @@ public class InventoryLogServiceImpl extends ServiceImpl<InventoryLogMapper, Inv
@Override
@Transactional(rollbackFor = Exception.class)
public void addAllocInventoryLog(Inventory inventory,Long dstPointId, BigDecimal AllocatedQty, String businessNo, Long businessDetailId, String description) {
public void addAllocInventoryLog(Inventory inventory, Long dstPointId, BigDecimal AllocatedQty, String businessNo, Long businessDetailId, String description) {
InventoryLog inventoryLog = buildInventoryLog(inventory, BigDecimal.ZERO, businessNo, businessDetailId, description);
//出库分配
inventoryLog.setLogType(InventoryLogEnum.ALLOC.getValue());
@ -165,14 +175,11 @@ public class InventoryLogServiceImpl extends ServiceImpl<InventoryLogMapper, Inv
return InventoryLog.builder()
.inventoryId(inventory.getId())
.itemId(inventory.getItemId())
.itemKeyId(inventory.getItemKeyId())
.toPointId(inventory.getPointId())
.stockId(inventory.getStockId())
.businessNo(businessNo)
.businessDetailId(businessDetailId)
.project(inventory.getProject())
.taskNo(inventory.getTaskNo())
.propC1(inventory.getPropC1())
.propC3(inventory.getPropC3())
.description(description)
//计算变动前后数量: 变动前数量 = 库存数量 - 变动数量
.beforeQty(BigDecimalUtil.subtract(inventory.getQuantity(), changeQty, 0))

View File

@ -64,53 +64,20 @@ public class ReceiveRecord implements Serializable {
@Schema(description = "物料")
@JsonSerialize(using = ToStringSerializer.class)
private java.lang.Long itemId;
/**
*
*/
@Schema(description = "物料属性")
@JsonSerialize(using = ToStringSerializer.class)
private java.lang.Long itemKeyId;
/**
*
*/
@Schema(description = "收货数量")
private java.math.BigDecimal receivedQty;
/**
*
*/
@Schema(description = "外部仓库")
private java.lang.String whCode;
/**
*
*/
@Schema(description = "项目号")
private java.lang.String project;
/**
*
*/
@Schema(description = "任务号")
private java.lang.String taskNo;
/**
*
*/
@Schema(description = "批次号")
private java.lang.String propC1;
/**
*
*/
@Schema(description = "外部库存状态")
private java.lang.String propC3;
/**
*
*/
@Schema(description = "序列号")
private java.lang.String propC2;
/**
*
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
@Schema(description = "生产日期")
private java.util.Date propD1;
/**
*
*/

View File

@ -16,12 +16,9 @@ import org.springframework.beans.factory.annotation.Autowired;
*/
@Service
public class AsnDetailServiceImpl extends ServiceImpl<AsnDetailMapper, AsnDetail> implements IAsnDetailService {
@Autowired
private AsnDetailMapper asnDetailMapper;
@Override
public List<AsnDetail> selectByMainId(Long mainId) {
return asnDetailMapper.selectByMainId(mainId);
return this.baseMapper.selectByMainId(mainId);
}
}

View File

@ -1,15 +1,17 @@
package org.cpte.modules.receive.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.cpte.modules.base.entity.ItemKey;
import org.cpte.modules.base.entity.Point;
import org.cpte.modules.base.entity.Stock;
import org.cpte.modules.base.mapper.PointMapper;
import org.cpte.modules.base.mapper.StockMapper;
import org.cpte.modules.base.service.IItemKeyService;
import org.cpte.modules.base.service.IPointService;
import org.cpte.modules.base.service.IStockService;
import org.cpte.modules.constant.GeneralConstant;
@ -17,6 +19,7 @@ import org.cpte.modules.constant.enums.AsnStatusEnum;
import org.cpte.modules.inventory.entity.Inventory;
import org.cpte.modules.inventory.mapper.InventoryMapper;
import org.cpte.modules.inventory.service.IInventoryService;
import org.cpte.modules.inventoryLog.entity.InventoryLog;
import org.cpte.modules.inventoryLog.service.IInventoryLogService;
import org.cpte.modules.receive.entity.Asn;
import org.cpte.modules.receive.entity.AsnDetail;
@ -26,6 +29,7 @@ import org.cpte.modules.receive.mapper.AsnMapper;
import org.cpte.modules.receive.mapper.ReceiveRecordMapper;
import org.cpte.modules.receive.service.IAsnService;
import org.cpte.modules.saiWms.request.SaiWmsRequest;
import org.cpte.modules.utils.BatchUtil;
import org.cpte.modules.utils.BigDecimalUtil;
import org.cpte.modules.utils.SwmsLoginUtil;
import org.jeecg.common.system.vo.LoginUser;
@ -59,12 +63,8 @@ public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnS
@Autowired
private PointMapper pointMapper;
@Autowired
private AsnMapper asnMapper;
@Autowired
private AsnDetailMapper asnDetailMapper;
@Autowired
private ReceiveRecordMapper receiveRecordMapper;
@Autowired
private InventoryMapper inventoryMapper;
@Autowired
private OpenApiMapper openApiMapper;
@ -75,11 +75,15 @@ public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnS
@Autowired
private IPointService iPointService;
@Autowired
private IItemKeyService iItemKeyService;
@Autowired
private IInventoryService iInventoryService;
@Autowired
private IInventoryLogService iInventoryLogService;
@Autowired
private SwmsLoginUtil swmsLoginUtil;
@Autowired
private BatchUtil batchUtil;
@Override
@Transactional(rollbackFor = Exception.class)
@ -87,7 +91,7 @@ public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnS
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
asn.setTenantId(Long.parseLong(sysUser.getRelTenantIds()));
asn.setSysOrgCode(sysUser.getOrgCode());
asnMapper.insert(asn);
this.baseMapper.insert(asn);
if (asnDetailList == null || asnDetailList.isEmpty()) {
throw new RuntimeException("请新增入库明细");
@ -139,13 +143,13 @@ public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnS
asn.setOrderQty(orderQty);
asn.setReceivedQty(receivedQty);
asn.setStatus(status);
asnMapper.updateById(asn);
this.baseMapper.updateById(asn);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateMain(Asn asn, List<AsnDetail> asnDetailList) {
asnMapper.updateById(asn);
this.baseMapper.updateById(asn);
if (asnDetailList == null || asnDetailList.isEmpty()) {
throw new RuntimeException("请新增入库明细");
@ -180,7 +184,7 @@ public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnS
throw new RuntimeException("操作失败:【" + asn.getOrderNo() + "】入库单,非创建状态不允许删除");
}
asnDetailMapper.deleteByMainId(id);
asnMapper.deleteById(id);
this.baseMapper.deleteById(id);
}
@Override
@ -194,7 +198,7 @@ public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnS
continue;
}
asnDetailMapper.deleteByMainId(Long.parseLong(id.toString()));
asnMapper.deleteById(id);
this.baseMapper.deleteById(id);
}
if (!orderNoList.isEmpty()) {
throw new RuntimeException("操作失败:【" + orderNoList + "】入库单,非创建状态不允许删除");
@ -205,52 +209,66 @@ public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnS
@Transactional(rollbackFor = Exception.class)
public void receiveGoods(Long asnId, String pointCode) {
//入库任务
Asn asn = asnMapper.selectById(asnId);
Asn asn = this.baseMapper.selectById(asnId);
if (asn == null) {
throw new RuntimeException("未匹配到入库任务【" + asnId + "】");
}
if (asn.getStatus() != 1) {
throw new RuntimeException("入库任务【" + asnId + "】已收货");
}
List<AsnDetail> asnDetails = asnDetailMapper.selectByMainId(asnId);
//验证容器是否入库
Stock stock = stockMapper.selectById(asnDetails.get(0).getStockId());
if (inventoryMapper.queryByStockId(stock.getId()) != null) {
throw new RuntimeException("【" + stock.getStockCode() + "】容器已入库");
throw new RuntimeException("【" + stock.getStockCode() + "】托盘已入库");
}
//实际的存储位置
//入库实际库位
Point dstPoint = pointMapper.queryByPointCode(pointCode);
//更新收货数量
for (AsnDetail ad : asnDetails) {
//已收货直接跳过
if (AsnStatusEnum.RECEIVED.getValue().equals(ad.getStatus())) {
continue;
}
BigDecimal receivedQty = BigDecimalUtil.add(ad.getReceivedQty(), ad.getOrderQty(), 0);
ad.setReceivedQty(receivedQty);
//批量操作
List<AsnDetail> updateToAsnDetail = new ArrayList<>();
List<ReceiveRecord> createToReceiveRecord = new ArrayList<>();
List<Inventory> createToInventory = new ArrayList<>();
List<InventoryLog> createToInventoryLog = new ArrayList<>();
//收货逻辑
for (AsnDetail asnDetail : asnDetails) {
BigDecimal receivedQty = BigDecimalUtil.add(asnDetail.getReceivedQty(), asnDetail.getOrderQty(), 0);
asnDetail.setReceivedQty(receivedQty);
//更新明细状态
if (receivedQty.compareTo(ad.getOrderQty()) >= 0) {
ad.setStatus(AsnStatusEnum.RECEIVED.getValue());
if (receivedQty.compareTo(asnDetail.getOrderQty()) >= 0) {
asnDetail.setStatus(AsnStatusEnum.RECEIVED.getValue());
} else {
ad.setStatus(AsnStatusEnum.RECEIVING.getValue());
asnDetail.setStatus(AsnStatusEnum.RECEIVING.getValue());
}
asnDetailMapper.updateById(ad);
updateToAsnDetail.add(asnDetail);
//获取itemKey
ItemKey itemKey = iItemKeyService.createItemKey(asnDetail.getItemId(), asn.getWhCode(), asnDetail.getProject(), asnDetail.getTaskNo(), asnDetail.getPropC1(), asnDetail.getPropC3());
//生成入库记录
ReceiveRecord receiveRecord = createReceiveRecord(ad, receivedQty, dstPoint.getId());
ReceiveRecord receiveRecord = buildReceiveRecord(asnDetail, receivedQty, itemKey, dstPoint.getId());
createToReceiveRecord.add(receiveRecord);
// 生成库存
Inventory inventory = iInventoryService.createInventory(stock.getId(), receivedQty, asn, receiveRecord);
Inventory inventory = iInventoryService.buildInventory(stock.getId(), receivedQty, asn, receiveRecord);
createToInventory.add(inventory);
//添加库存日志
iInventoryLogService.addInboundInventoryLog(inventory, ad.getToPointId(), receivedQty, asn.getOrderNo(), ad.getId(), ad.getDescription());
InventoryLog inventoryLog = iInventoryLogService.buildInboundInventoryLog(inventory, asnDetail.getToPointId(), receivedQty, asn.getOrderNo(), asnDetail.getId(), asnDetail.getDescription());
createToInventoryLog.add(inventoryLog);
}
if (CollectionUtils.isNotEmpty(updateToAsnDetail)) {
batchUtil.updateBatchAsnDetail(updateToAsnDetail);
}
if (CollectionUtils.isNotEmpty(createToReceiveRecord)) {
batchUtil.saveBatchReceiveRecord(createToReceiveRecord);
}
if (CollectionUtils.isNotEmpty(createToInventory)) {
batchUtil.saveBatchInventory(createToInventory);
}
if (CollectionUtils.isNotEmpty(createToInventoryLog)) {
batchUtil.saveBatchInventoryLog(createToInventoryLog);
}
//更新入库单
refreshAsn(asn, asnDetails);
@ -261,7 +279,7 @@ public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnS
//回传
// receiveCallback(asn, asnDetail, stock);
// receiveCallback(asn, asnDetail, stock);
}
@ -355,35 +373,28 @@ public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnS
if (asn != null) {
asn.setResMessage(message);
asn.setResTime(new Date());
asnMapper.updateById(asn);
this.baseMapper.updateById(asn);
}
}
/**
*
*/
public ReceiveRecord createReceiveRecord(AsnDetail asnDetail, BigDecimal receivedQty, Long dstPointId) {
ReceiveRecord receiveRecord = ReceiveRecord.builder()
public ReceiveRecord buildReceiveRecord(AsnDetail asnDetail, BigDecimal receivedQty, ItemKey itemKey, Long dstPointId) {
return ReceiveRecord.builder()
.asnDetailId(asnDetail.getId())
.stockId(asnDetail.getStockId())
.fromPointId(asnDetail.getToPointId())
.toPointId(dstPointId)
.itemId(asnDetail.getItemId())
.itemKeyId(itemKey.getId())
.receivedQty(receivedQty)
.project(asnDetail.getProject())
.taskNo(asnDetail.getTaskNo())
.propC1(asnDetail.getPropC1())
.propC2(asnDetail.getPropC2())
.propC3(asnDetail.getPropC3())
.propD1(asnDetail.getPropD1())
.description(asnDetail.getDescription())
.tenantId(asnDetail.getTenantId())
.sysOrgCode(asnDetail.getSysOrgCode())
.createBy(asnDetail.getCreateBy())
.createTime(new Date())
.build();
receiveRecordMapper.insert(receiveRecord);
return receiveRecord;
}
}

View File

@ -17,11 +17,8 @@ import org.springframework.beans.factory.annotation.Autowired;
@Service
public class PickDetailServiceImpl extends ServiceImpl<PickDetailMapper, PickDetail> implements IPickDetailService {
@Autowired
private PickDetailMapper pickDetailMapper;
@Override
public List<PickDetail> selectByMainId(Long mainId) {
return pickDetailMapper.selectByMainId(mainId);
return this.baseMapper.selectByMainId(mainId);
}
}

View File

@ -6,6 +6,8 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.cpte.modules.base.entity.ItemKey;
import org.cpte.modules.base.mapper.ItemKeyMapper;
import org.cpte.modules.constant.GeneralConstant;
import org.cpte.modules.base.entity.Item;
import org.cpte.modules.base.entity.Point;
@ -56,13 +58,13 @@ import java.util.stream.Collectors;
@Slf4j
public class PickServiceImpl extends ServiceImpl<PickMapper, Pick> implements IPickService {
@Autowired
private PickMapper pickMapper;
@Autowired
private PickDetailMapper pickDetailMapper;
@Autowired
private TaskMapper taskMapper;
@Autowired
private ItemKeyMapper itemKeyMapper;
@Autowired
private InventoryMapper inventoryMapper;
@Autowired
private SysDictMapper sysDictMapper;
@ -97,7 +99,7 @@ public class PickServiceImpl extends ServiceImpl<PickMapper, Pick> implements IP
return Collections.emptyMap();
}
Map<Long, Pick> pickMap = new HashMap<>();
List<Pick> pickList = pickMapper.selectByIds(pickIds);
List<Pick> pickList = this.baseMapper.selectByIds(pickIds);
for (Pick pick : pickList) {
pickMap.put(pick.getId(), pick);
}
@ -141,7 +143,7 @@ public class PickServiceImpl extends ServiceImpl<PickMapper, Pick> implements IP
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
pick.setTenantId(Long.parseLong(sysUser.getRelTenantIds()));
pick.setSysOrgCode(sysUser.getOrgCode());
pickMapper.insert(pick);
this.baseMapper.insert(pick);
if (pickDetailList == null || pickDetailList.isEmpty()) {
throw new RuntimeException("请新增出库明细");
@ -220,13 +222,13 @@ public class PickServiceImpl extends ServiceImpl<PickMapper, Pick> implements IP
pick.setAllocatedQty(allocatedQty);
pick.setPickedQty(pickedQty);
pick.setStatus(status);
pickMapper.updateById(pick);
this.baseMapper.updateById(pick);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateMain(Pick pick, List<PickDetail> pickDetailList) {
pickMapper.updateById(pick);
this.baseMapper.updateById(pick);
if (pickDetailList == null || pickDetailList.isEmpty()) {
throw new RuntimeException("请新增出库明细");
@ -276,7 +278,7 @@ public class PickServiceImpl extends ServiceImpl<PickMapper, Pick> implements IP
throw new RuntimeException("操作失败:【" + pick.getOrderNo() + "】出库单,非创建状态不允许删除");
}
pickDetailMapper.deleteByMainId(id);
pickMapper.deleteById(id);
this.baseMapper.deleteById(id);
}
@Override
@ -290,7 +292,7 @@ public class PickServiceImpl extends ServiceImpl<PickMapper, Pick> implements IP
continue;
}
pickDetailMapper.deleteByMainId(Long.parseLong(id.toString()));
pickMapper.deleteById(id);
this.baseMapper.deleteById(id);
}
if (!orderNoList.isEmpty()) {
throw new RuntimeException("操作失败:【" + orderNoList + "】出库单,非创建状态不允许删除");
@ -314,19 +316,26 @@ public class PickServiceImpl extends ServiceImpl<PickMapper, Pick> implements IP
List<Long> itemIds = pickDetails.stream().map(PickDetail::getItemId).distinct().toList();
Map<Long, Item> itemMap = iItemService.queryByItemIdsToMap(itemIds);
//筛选查询库存的条件(非空去重)批次、外部库存状态 、外部仓库
//筛选查询库存的条件(非空去重)外部仓库、项目号、任务号、批次、外部库存状态
List<String> whCodeList = pickMap.values().stream().map(Pick::getWhCode).filter(StringUtils::isNotBlank).distinct().toList();
List<String> projectList = pickDetails.stream().map(PickDetail::getProject).filter(StringUtils::isNotBlank).distinct().toList();
List<String> taskNoList = pickDetails.stream().map(PickDetail::getTaskNo).filter(StringUtils::isNotBlank).distinct().toList();
List<String> propC1List = pickDetails.stream().map(PickDetail::getPropC1).filter(StringUtils::isNotBlank).distinct().toList();
List<String> propC3List = pickDetails.stream().map(PickDetail::getPropC3).filter(StringUtils::isNotBlank).distinct().toList();
List<String> whCodeList = pickMap.values().stream().map(Pick::getWhCode).filter(StringUtils::isNotBlank).distinct().toList();
List<ItemKey> itemKeys = itemKeyMapper.queryItemKeys(itemIds, whCodeList, projectList, taskNoList, propC1List, propC3List);
List<Long> itemKeyIds = itemKeys.stream().map(ItemKey::getId).distinct().toList();
//查询库存
List<Inventory> inventories = inventoryMapper.queryInventory(itemIds, propC1List, propC3List, whCodeList);
List<Inventory> inventories = inventoryMapper.queryInventoryByItemKeyId(itemKeyIds);
if (CollectionUtils.isEmpty(inventories)) {
String itemCodes = itemMap.values().stream().map(Item::getItemCode).collect(Collectors.joining(","));
errorMsgSet.add("【" + itemCodes + "】物料库存不足");
return new ArrayList<>(errorMsgSet);
}
//根据itemKeyId分组
Map<Long, List<Inventory>> inventoryMap = inventories.stream().collect(Collectors.groupingBy(Inventory::getItemKeyId));
//获取容器
List<Long> stockIds = inventories.stream().map(Inventory::getStockId).distinct().toList();
Map<Long, Stock> stockMap = iStockService.queryByStockIdsToMap(stockIds);
@ -335,16 +344,21 @@ public class PickServiceImpl extends ServiceImpl<PickMapper, Pick> implements IP
List<Long> pointIds = inventories.stream().map(Inventory::getPointId).distinct().toList();
Map<Long, Point> pointMap = iPointService.queryByPointIdsToMap(pointIds);
// -------------------------- 2. 库存分组排序(优化匹配效率)--------------------------
// 按「物料ID+批次+库存状态+仓库」分组且按创建时间升序FIFO分配规则
Map<InventoryGroupKey, List<Inventory>> inventoryGroupMap = inventories.stream()
.sorted(Comparator.comparing(Inventory::getCreateTime))
.collect(Collectors.groupingBy(inv -> InventoryGroupKey.of(
inv.getItemId(),
inv.getPropC1(),
inv.getPropC3(),
inv.getWhCode()
)));
// 按「itemKeyId分组
Map<InventoryGroupKey, ItemKey> inventoryGroupMap = itemKeys.stream()
.collect(Collectors.toMap(
itemKey -> InventoryGroupKey.of(
itemKey.getItemId(),
itemKey.getWhCode(),
itemKey.getProject(),
itemKey.getTaskNo(),
itemKey.getPropC1(),
itemKey.getPropC3()
),
itemKey -> itemKey
));
// -------------------------- 3. 创建更新列表---------------------------
List<Inventory> updateToInventory = new ArrayList<>();
@ -365,11 +379,14 @@ public class PickServiceImpl extends ServiceImpl<PickMapper, Pick> implements IP
//匹配目标库存通过分组key快速定位
InventoryGroupKey groupKey = InventoryGroupKey.of(
pickDetail.getItemId(),
pick.getWhCode(),
pickDetail.getProject(),
pickDetail.getTaskNo(),
pickDetail.getPropC1(),
pickDetail.getPropC3(),
pick.getWhCode()
pickDetail.getPropC3()
);
List<Inventory> matchedInventories = inventoryGroupMap.getOrDefault(groupKey, Collections.emptyList());
ItemKey itemKey=inventoryGroupMap.get(groupKey);
List<Inventory> matchedInventories = inventoryMap.get(itemKey.getId());
if (CollectionUtils.isEmpty(matchedInventories)) {
errorMsgSet.add(String.format("物料【%s】无匹配库存物料ID:%s批次:%s库存状态:%s仓库:%s",
item.getItemCode(), item.getId(), pickDetail.getPropC1(), pickDetail.getPropC3(), pick.getWhCode()));

View File

@ -45,9 +45,6 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements IT
@Autowired
private PointMapper pointMapper;
@Autowired
private TaskMapper taskMapper;
@Autowired
private InventoryMapper inventoryMapper;
@ -142,7 +139,7 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements IT
@Transactional(rollbackFor = Exception.class)
public void generateAgvTask() {
List<Task> taskList = taskMapper.queryUnallocatedTask();
List<Task> taskList = this.baseMapper.queryUnallocatedTask();
if (CollectionUtils.isEmpty(taskList)) {
return;
}

View File

@ -11,17 +11,23 @@ import org.apache.commons.lang3.StringUtils;
@NoArgsConstructor
@EqualsAndHashCode
public class InventoryGroupKey {
private Long itemId;
private Long itemId;//物料
private String whCode; // 仓库代码
private String project;//项目号
private String taskNo;//任务号
private String propC1; // 批次号
private String propC3; // 库存状态
private String whCode; // 仓库代码
public static InventoryGroupKey of(Long itemId, String propC1, String propC3, String whCode) {
public static InventoryGroupKey of(Long itemId, String whCode, String project, String taskNo, String propC1, String propC3) {
return new InventoryGroupKey(
itemId,
StringUtils.defaultIfBlank(whCode, ""),
StringUtils.defaultIfBlank(project, ""),
StringUtils.defaultIfBlank(taskNo, ""),
StringUtils.defaultIfBlank(propC1, ""), // 空值统一为"",避免分组不一致
StringUtils.defaultIfBlank(propC3, ""),
StringUtils.defaultIfBlank(whCode, "")
StringUtils.defaultIfBlank(propC3, "")
);
}
}

View File

@ -159,10 +159,7 @@ public class ITesAgvServiceImpl implements ITesAgvService {
//6.已取消-任务取消
handleCelled(agvTask);
break;
case 7:
//7.自定义-重新发送任务
handleResend(agvTask);
break;
}
}

View File

@ -6,6 +6,9 @@ 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.inventoryLog.entity.InventoryLog;
import org.cpte.modules.receive.entity.AsnDetail;
import org.cpte.modules.receive.entity.ReceiveRecord;
import org.cpte.modules.shipping.entity.PickDetail;
import org.cpte.modules.shipping.entity.Task;
import org.springframework.beans.factory.annotation.Autowired;
@ -210,6 +213,24 @@ public class BatchUtil {
});
}
/**
*
*/
@Transactional
public void updateBatchAsnDetail(List<AsnDetail> asnDetails) {
String sql = "UPDATE data_asn_detail SET received_qty = ?, status = ? where id = ?";
batchUpdate(sql, asnDetails, (ps, asnDetail) -> {
try {
ps.setBigDecimal(1, asnDetail.getReceivedQty());
ps.setInt(2, asnDetail.getStatus());
ps.setLong(3, asnDetail.getId());
} catch (SQLException e) {
throw new RuntimeException(e);
}
});
}
/**
*
@ -230,6 +251,34 @@ public class BatchUtil {
}
/**
* ReceiveRecord
*/
@Transactional
public void saveBatchReceiveRecord(List<ReceiveRecord> receiveRecords) {
String sql = "INSERT INTO data_receive_record (id,asn_detail_id,stock_id,from_point_id,to_point_id, item_id,item_key_id,received_qty,description,sys_org_code,tenant_id,create_by,create_time) " +
"VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)";
batchInsert(sql, receiveRecords, (ps, record) -> {
try {
ps.setLong(1, IdWorker.getId());
ps.setLong(2, record.getAsnDetailId());
ps.setLong(3, record.getStockId());
ps.setLong(4, record.getFromPointId());
ps.setLong(5, record.getToPointId());
ps.setLong(6, record.getItemId());
ps.setLong(7, record.getItemKeyId());
ps.setBigDecimal(8, record.getReceivedQty());
ps.setString(9, record.getDescription());
ps.setString(10, record.getSysOrgCode());
ps.setLong(11, record.getTenantId());
ps.setString(12, record.getCreateBy());
ps.setDate(13, new Date(record.getCreateTime().getTime()));
} catch (SQLException e) {
throw new RuntimeException(e);
}
});
}
/**
* Task
*/
@ -296,7 +345,7 @@ public class BatchUtil {
batchInsert(sql, agvTasks, (ps, agvTask) -> {
try {
long id = IdWorker.getId();
agvTask.setId(id); // 关键将生成的ID赋值给对象解决null问题
agvTask.setId(IdWorker.getId()); // 关键将生成的ID赋值给对象解决null问题
ps.setLong(1, id);
ps.setObject(2, agvTask.getBusinessDetailId());
ps.setString(3, agvTask.getCarrierCode());
@ -319,6 +368,35 @@ public class BatchUtil {
});
}
/**
*
*/
@Transactional
public void saveBatchInventory(List<Inventory> inventories) {
String sql = "INSERT INTO data_inventory (id,item_key_id,item_id,point_id,stock_id,receive_record_id,quantity,queued_qty,status,description,sys_org_code,tenant_id,create_by,create_time) " +
"VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
batchInsert(sql, inventories, (ps, inventory) -> {
try {
ps.setLong(1, IdWorker.getId());
ps.setLong(2, inventory.getItemKeyId());
ps.setLong(3, inventory.getItemId());
ps.setLong(4, inventory.getPointId());
ps.setLong(5, inventory.getStockId());
ps.setLong(6, inventory.getReceiveRecordId());
ps.setBigDecimal(7, inventory.getQuantity());
ps.setBigDecimal(8, inventory.getQueuedQty());
ps.setInt(9, inventory.getStatus());
ps.setString(10, inventory.getDescription());
ps.setString(11, inventory.getSysOrgCode());
ps.setLong(12, inventory.getTenantId());
ps.setString(13, inventory.getCreateBy());
ps.setTimestamp(14, new Timestamp(inventory.getCreateTime().getTime()));
} catch (SQLException e) {
throw new RuntimeException(e);
}
});
}
/**
*
*/
@ -338,6 +416,40 @@ public class BatchUtil {
});
}
/**
*
*/
@Transactional
public void saveBatchInventoryLog(List<InventoryLog> inventoryLogs) {
String sql = "INSERT INTO data_inventory_log (id,log_type,business_no,business_detail_id,inventory_id,item_id,item_key_id,from_point_id,to_point_id,stock_id,change_qty,before_qty,after_qty,before_allocated_qty,after_allocated_qty,description,sys_org_code,tenant_id,create_by,create_time) " +
"VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
batchInsert(sql, inventoryLogs, (ps, inventoryLog) -> {
try {
ps.setLong(1, IdWorker.getId());
ps.setInt(2, inventoryLog.getLogType());
ps.setString(3, inventoryLog.getBusinessNo());
ps.setObject(4, inventoryLog.getBusinessDetailId());
ps.setObject(5, inventoryLog.getInventoryId());
ps.setObject(6, inventoryLog.getItemId());
ps.setObject(7, inventoryLog.getItemKeyId());
ps.setObject(8, inventoryLog.getFromPointId());
ps.setObject(9, inventoryLog.getToPointId());
ps.setObject(10, inventoryLog.getStockId());
ps.setBigDecimal(11, inventoryLog.getChangeQty());
ps.setBigDecimal(12, inventoryLog.getBeforeQty());
ps.setBigDecimal(13, inventoryLog.getAfterQty());
ps.setBigDecimal(14, inventoryLog.getBeforeAllocatedQty());
ps.setBigDecimal(15, inventoryLog.getAfterAllocatedQty());
ps.setString(16, inventoryLog.getDescription());
ps.setString(17, inventoryLog.getSysOrgCode());
ps.setLong(18, inventoryLog.getTenantId());
ps.setString(19, inventoryLog.getCreateBy());
ps.setTimestamp(20, new Timestamp(inventoryLog.getCreateTime().getTime()));
} catch (SQLException e) {
throw new RuntimeException(e);
}
});
}
}