入库单接收、AGV任务生成、下发、上报 TES任务生成、下发、上报
parent
de2ca95e1b
commit
6972fccd1c
|
|
@ -104,9 +104,6 @@ public class AutoLogAspect {
|
|||
if(sysUser!=null){
|
||||
dto.setUserid(sysUser.getUsername());
|
||||
dto.setUsername(sysUser.getRealname());
|
||||
}else {
|
||||
dto.setUserid("赛意");
|
||||
dto.setUsername("赛意");
|
||||
}
|
||||
//耗时
|
||||
dto.setCostTime(time);
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
|||
import org.springframework.context.annotation.*;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
|
||||
import org.springframework.data.redis.core.*;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.filter.DelegatingFilterProxy;
|
||||
|
|
@ -389,4 +390,31 @@ public class ShiroConfig {
|
|||
return seg.startsWith("/") ? seg : "/"+seg;
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
|
||||
return redisTemplate.opsForHash();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ValueOperations<String, String> valueOperations(RedisTemplate<String, String> redisTemplate) {
|
||||
return redisTemplate.opsForValue();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
|
||||
return redisTemplate.opsForList();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
|
||||
return redisTemplate.opsForSet();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
|
||||
return redisTemplate.opsForZSet();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,13 @@ public class AgvTask implements Serializable {
|
|||
@Schema(description = "id")
|
||||
private java.lang.String id;
|
||||
|
||||
/**
|
||||
* 业务ID
|
||||
*/
|
||||
@Excel(name = "业务ID", width = 15)
|
||||
@Schema(description = "业务ID")
|
||||
private java.lang.String businessDetailId;
|
||||
|
||||
/**
|
||||
* 载具编号
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -15,13 +15,32 @@ import java.util.List;
|
|||
*/
|
||||
public interface AgvTaskMapper extends BaseMapper<AgvTask> {
|
||||
/**
|
||||
* 验证AGV任务是否存在
|
||||
* 根据容器编码验证AGV任务是否存在
|
||||
*
|
||||
* @param carrierCode 容器
|
||||
* @param agvVendor 供应商;AGV/TES
|
||||
*/
|
||||
@Select(value = "select count(id) from data_agv_task where carrier_code = #{carrierCode} and agv_vendor = #{agvVendor} and status in (1,2,3) ")
|
||||
Long existsAGVTask(@Param("carrierCode") String carrierCode, @Param("agvVendor") String agvVendor);
|
||||
@Select(value = "select count(id) from data_agv_task where carrier_code = #{carrierCode} and agv_vendor = #{agvVendor} and status in (1,2,3) for update ")
|
||||
Long existsByStockCode(@Param("carrierCode") String carrierCode, @Param("agvVendor") String agvVendor);
|
||||
|
||||
/**
|
||||
* 根据起点编码验证AGV任务是否存在
|
||||
*
|
||||
* @param startCode 起点
|
||||
* @param agvVendor 供应商;AGV/TES
|
||||
*/
|
||||
@Select(value = "select count(id) from data_agv_task where start_code = #{startCode} and agv_vendor = #{agvVendor} and status in (2,3) for update ")
|
||||
Long existsByStartCode(@Param("startCode") String startCode, @Param("agvVendor") String agvVendor);
|
||||
|
||||
|
||||
/**
|
||||
* 根据终点编码验证AGV任务是否存在
|
||||
*
|
||||
* @param endCode 终点
|
||||
* @param agvVendor 供应商;AGV/TES
|
||||
*/
|
||||
@Select(value = "select count(id) from data_agv_task where end_code = #{pointCode} and agv_vendor = #{agvVendor} and status in (2,3) for update ")
|
||||
Long existsByEndCode(@Param("pointCode") String endCode, @Param("agvVendor") String agvVendor);
|
||||
|
||||
/**
|
||||
* 查询AGV任务列表
|
||||
|
|
|
|||
|
|
@ -15,14 +15,15 @@ public interface IAgvTaskService extends IService<AgvTask> {
|
|||
/**
|
||||
* 创建agvTask任务
|
||||
*
|
||||
* @param status 状态
|
||||
* @param carrierCode 容器
|
||||
* @param startCode 起点
|
||||
* @param endCode 终点
|
||||
* @param taskType 任务类型
|
||||
* @param type 业务类型
|
||||
* @param agvVendor 供应商
|
||||
* @param businessDetailId 业务ID
|
||||
* @param status 状态
|
||||
* @param carrierCode 容器
|
||||
* @param startCode 起点
|
||||
* @param endCode 终点
|
||||
* @param taskType 任务类型
|
||||
* @param type 业务类型
|
||||
* @param agvVendor 供应商
|
||||
*/
|
||||
AgvTask createAgvTask(Integer status, String carrierCode, String startCode, String endCode, String taskType, String type, String agvVendor);
|
||||
AgvTask createAgvTask(String businessDetailId, Integer status, String carrierCode, String startCode, String endCode, String taskType, String type, String agvVendor);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,12 +24,13 @@ public class AgvTaskServiceImpl extends ServiceImpl<AgvTaskMapper, AgvTask> impl
|
|||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public AgvTask createAgvTask(Integer status, String carrierCode, String startCode, String endCode, String taskType, String type, String agvVendor) {
|
||||
Integer priority = 99;
|
||||
public AgvTask createAgvTask(String businessDetailId, Integer status, String carrierCode, String startCode, String endCode, String taskType, String type, String agvVendor) {
|
||||
int priority = 99;
|
||||
if (AgvVendorEnum.TES.getValue().equals(agvVendor)) {
|
||||
priority = 3;
|
||||
}
|
||||
AgvTask agvTask = AgvTask.builder()
|
||||
.businessDetailId(businessDetailId)
|
||||
.carrierCode(carrierCode)
|
||||
.type(type)
|
||||
.status(status)
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@ public class AreaController extends JeecgController<Area, IAreaService> {
|
|||
* @param req
|
||||
* @return
|
||||
*/
|
||||
//@AutoLog(value = "库区-分页列表查询")
|
||||
@Operation(summary = "库区-分页列表查询")
|
||||
@GetMapping(value = "/list")
|
||||
public Result<IPage<Area>> queryPageList(Area area,
|
||||
|
|
|
|||
|
|
@ -14,5 +14,21 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|||
* @Version: V1.0
|
||||
*/
|
||||
public interface AreaMapper extends BaseMapper<Area> {
|
||||
/**
|
||||
* 通过库区编码查询库区信息
|
||||
*
|
||||
* @param areaCode 库区编码
|
||||
* @return Area
|
||||
*/
|
||||
@Select("select * from base_area where area_code = #{areaCode}")
|
||||
Area queryByAreaCode(@Param("areaCode") String areaCode);
|
||||
|
||||
/**
|
||||
* 通过库区编码查询库区信息
|
||||
*
|
||||
* @param areaCodes 库区编号集合
|
||||
* @return List<Item>
|
||||
*/
|
||||
@Select("select * from base_area where area_code in (#{areaCodes})")
|
||||
List<Area> queryByAreaCodes(@Param("areaCodes") List<String> areaCodes);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,35 @@
|
|||
package org.cpte.modules.base.mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import org.cpte.modules.base.entity.Item;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.cpte.modules.receive.entity.Asn;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Description: 物料
|
||||
* @author: cpte
|
||||
* @Date: 2025-10-27
|
||||
* @Date: 2025-10-27
|
||||
* @Version: V1.0
|
||||
*/
|
||||
public interface ItemMapper extends BaseMapper<Item> {
|
||||
/**
|
||||
* 通过物料编码查询物料信息
|
||||
*
|
||||
* @param itemCode 物料编号
|
||||
* @return Item
|
||||
*/
|
||||
@Select("select * from base_item where item_code = #{itemCode}")
|
||||
Item queryByItemCode(@Param("itemCode") String itemCode);
|
||||
|
||||
/**
|
||||
* 通过物料编码查询物料信息
|
||||
*
|
||||
* @param itemCodes 物料编号集合
|
||||
* @return List<Item>
|
||||
*/
|
||||
@Select("select * from base_item where item_code in (#{itemCodes})")
|
||||
List<Item> queryByItemCodes(@Param("itemCodes") List<String> itemCodes);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,15 +3,42 @@ package org.cpte.modules.base.mapper;
|
|||
import java.util.List;
|
||||
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import org.cpte.modules.base.entity.Point;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* @Description: 库位
|
||||
* @author: cpte
|
||||
* @Date: 2025-10-28
|
||||
* @Date: 2025-10-28
|
||||
* @Version: V1.0
|
||||
*/
|
||||
public interface PointMapper extends BaseMapper<Point> {
|
||||
/**
|
||||
* 通过库位编码查询库位信息
|
||||
*
|
||||
* @param pointCode 库位编号
|
||||
* @return Point
|
||||
*/
|
||||
@Select("select * from base_point where point_code = #{pointCode}")
|
||||
Point queryByPointCode(@Param("pointCode") String pointCode);
|
||||
|
||||
/**
|
||||
* 通过库位编码查询库位信息
|
||||
*
|
||||
* @param pointCodes 库位编号集合
|
||||
* @return List<Point>
|
||||
*/
|
||||
@Select("select * from base_point where point_code in (#{pointCodes})")
|
||||
List<Point> queryByPointCodes(@Param("pointCodes") List<String> pointCodes);
|
||||
|
||||
/**
|
||||
* 查询库位信息
|
||||
*
|
||||
* @param pointCode 库位编号
|
||||
* @param status 状态
|
||||
* @param areaCode 库区编号
|
||||
* @return List<Point>
|
||||
*/
|
||||
List<Point> queryPoints(@Param("pointCode") String pointCode, @Param("status") Integer status, @Param("areaCode") String areaCode);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,12 +5,30 @@ import org.apache.ibatis.annotations.Select;
|
|||
import org.cpte.modules.base.entity.Stock;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Description: 容器
|
||||
* @author: cpte
|
||||
* @Date: 2025-10-28
|
||||
* @Date: 2025-10-28
|
||||
* @Version: V1.0
|
||||
*/
|
||||
public interface StockMapper extends BaseMapper<Stock> {
|
||||
/**
|
||||
* 通过容器编码查询容器信息
|
||||
*
|
||||
* @param stockCode 容器编号
|
||||
* @return Stock
|
||||
*/
|
||||
@Select("select * from base_stock where stock_code = #{stockCode}")
|
||||
Stock queryByStockCode(@Param("stockCode") String stockCode);
|
||||
|
||||
/**
|
||||
* 通过容器编码查询容器信息
|
||||
*
|
||||
* @param stockCodes 容器编号集合
|
||||
* @return List<Stock>
|
||||
*/
|
||||
@Select("select * from base_stock where stock_code in (#{stockCodes})")
|
||||
List<Stock> queryByStockCodes(@Param("stockCodes") List<String> stockCodes);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,19 @@
|
|||
<?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.PointMapper">
|
||||
|
||||
<select id="queryPoints" resultType="org.cpte.modules.base.entity.Point">
|
||||
SELECT point.* FROM base_point point
|
||||
JOIN base_area area ON point.area_id = area.id
|
||||
<where>
|
||||
<if test="pointCode != null and pointCode != ''">
|
||||
AND point.point_code = #{pointCode}
|
||||
</if>
|
||||
<if test="status != null">
|
||||
AND point.status = #{status}
|
||||
</if>
|
||||
<if test="areaCode != null and areaCode != ''">
|
||||
AND area.area_code = #{areaCode}
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
</mapper>
|
||||
|
|
@ -34,16 +34,4 @@ public interface IPointService extends IService<Point> {
|
|||
* @return Map<String, pointEntity>
|
||||
*/
|
||||
Map<String, Point> queryByPointCodesToMap(List<String> pointCodes);
|
||||
|
||||
|
||||
/**
|
||||
* 查询库位信息
|
||||
*
|
||||
* @param pointCode 库位编码
|
||||
* @param status 状态
|
||||
* @param areaName 区域名称
|
||||
* @return List<point>
|
||||
*/
|
||||
List<Point> queryPoints(String pointCode, Integer status, String areaName);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|||
import org.cpte.modules.base.entity.Area;
|
||||
import org.cpte.modules.base.mapper.AreaMapper;
|
||||
import org.cpte.modules.base.service.IAreaService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
|
|
@ -17,12 +18,12 @@ 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) {
|
||||
LambdaQueryWrapper<Area> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(Area::getAreaCode, areaCode).or().eq(Area::getAreaName, areaCode);
|
||||
|
||||
Area area = this.getOne(queryWrapper);
|
||||
Area area = areaMapper.queryByAreaCode(areaCode);
|
||||
if (area == null) {
|
||||
throw new RuntimeException("系统无【" + areaCode + "】库区,请维护");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,9 @@ import java.util.Map;
|
|||
@Service
|
||||
public class ItemServiceImpl extends ServiceImpl<ItemMapper, Item> implements IItemService {
|
||||
|
||||
@Autowired
|
||||
private ItemMapper itemMapper;
|
||||
|
||||
/**
|
||||
* 验证物料
|
||||
*
|
||||
|
|
@ -32,9 +35,7 @@ public class ItemServiceImpl extends ServiceImpl<ItemMapper, Item> implements II
|
|||
*/
|
||||
@Override
|
||||
public Item validateItem(String itemCode) {
|
||||
LambdaQueryWrapper<Item> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(Item::getItemCode, itemCode);
|
||||
Item item = this.getOne(queryWrapper);
|
||||
Item item = itemMapper.queryByItemCode(itemCode);
|
||||
if (item == null) {
|
||||
throw new RuntimeException("系统无【" + itemCode + "】物料,请维护");
|
||||
}
|
||||
|
|
@ -54,13 +55,7 @@ public class ItemServiceImpl extends ServiceImpl<ItemMapper, Item> implements II
|
|||
* @return List<ItemEntity>
|
||||
*/
|
||||
public List<Item> queryByItemCodes(List<String> itemCodes) {
|
||||
if (CollectionUtils.isEmpty(itemCodes)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
//查询物料
|
||||
LambdaQueryWrapper<Item> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.in(Item::getItemCode, itemCodes);
|
||||
return this.list(queryWrapper);
|
||||
return itemMapper.queryByItemCodes(itemCodes);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -31,6 +31,9 @@ public class PointServiceImpl extends ServiceImpl<PointMapper, Point> implements
|
|||
@Autowired
|
||||
private IAreaService iAreaService;
|
||||
|
||||
@Autowired
|
||||
private PointMapper pointMapper;
|
||||
|
||||
/**
|
||||
* 验证库位
|
||||
*
|
||||
|
|
@ -39,9 +42,7 @@ public class PointServiceImpl extends ServiceImpl<PointMapper, Point> implements
|
|||
*/
|
||||
@Override
|
||||
public Point validatePoint(String pointCode) {
|
||||
LambdaQueryWrapper<Point> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(Point::getPointCode, pointCode);
|
||||
Point point = this.getOne(queryWrapper);
|
||||
Point point = pointMapper.queryByPointCode(pointCode);
|
||||
if (point == null) {
|
||||
throw new RuntimeException("系统无【" + pointCode + "】库位,请维护");
|
||||
}
|
||||
|
|
@ -61,13 +62,7 @@ public class PointServiceImpl extends ServiceImpl<PointMapper, Point> implements
|
|||
* @return List<PointEntity>
|
||||
*/
|
||||
public List<Point> queryByPointCodes(List<String> pointCodes) {
|
||||
if (CollectionUtils.isEmpty(pointCodes)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
//查询库位
|
||||
LambdaQueryWrapper<Point> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.in(Point::getPointCode, pointCodes);
|
||||
return this.list(queryWrapper);
|
||||
return pointMapper.queryByPointCodes(pointCodes);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -89,29 +84,4 @@ public class PointServiceImpl extends ServiceImpl<PointMapper, Point> implements
|
|||
}
|
||||
return PointMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Point> queryPoints(String pointCode, Integer status, String areaName) {
|
||||
//查询库位
|
||||
LambdaQueryWrapper<Point> queryWrapper = new LambdaQueryWrapper<>();
|
||||
|
||||
//点位编码
|
||||
if (StringUtils.isNotBlank(pointCode)) {
|
||||
queryWrapper.eq(Point::getPointCode, pointCode);
|
||||
}
|
||||
|
||||
//状态
|
||||
if (status != null) {
|
||||
queryWrapper.eq(Point::getStatus, status);
|
||||
}
|
||||
|
||||
//库区
|
||||
if (StringUtils.isNotBlank(areaName)) {
|
||||
Area area = iAreaService.validateArea(areaName);
|
||||
queryWrapper.eq(Point::getAreaId, area.getId());
|
||||
}
|
||||
|
||||
|
||||
return this.list(queryWrapper);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,9 @@ import java.util.Objects;
|
|||
@Service
|
||||
public class StockServiceImpl extends ServiceImpl<StockMapper, Stock> implements IStockService {
|
||||
|
||||
@Autowired
|
||||
private StockMapper stockMapper;
|
||||
|
||||
/**
|
||||
* 验证容器
|
||||
*
|
||||
|
|
@ -35,16 +38,14 @@ public class StockServiceImpl extends ServiceImpl<StockMapper, Stock> implements
|
|||
*/
|
||||
@Override
|
||||
public Stock validateStock(String StockCode) {
|
||||
LambdaQueryWrapper<Stock> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(Stock::getStockCode, StockCode);
|
||||
Stock stock = this.getOne(queryWrapper);
|
||||
Stock stock = stockMapper.queryByStockCode(StockCode);
|
||||
if (stock == null) {
|
||||
throw new RuntimeException("系统无【" + StockCode + "】容器,请维护");
|
||||
}
|
||||
if(stock.getIzActive()==0){
|
||||
if (stock.getIzActive() == 0) {
|
||||
throw new RuntimeException("此【" + StockCode + "】容器已禁用");
|
||||
}
|
||||
if(stock.getDelFlag()==1){
|
||||
if (stock.getDelFlag() == 1) {
|
||||
throw new RuntimeException("此【" + StockCode + "】容器已删除");
|
||||
}
|
||||
return stock;
|
||||
|
|
@ -58,12 +59,7 @@ public class StockServiceImpl extends ServiceImpl<StockMapper, Stock> implements
|
|||
* @return List<StockEntity>
|
||||
*/
|
||||
public List<Stock> queryByStockCodes(List<String> stockCodes) {
|
||||
if (CollectionUtils.isEmpty(stockCodes)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
LambdaQueryWrapper<Stock> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.in(Stock::getStockCode, stockCodes);
|
||||
return this.list(queryWrapper);
|
||||
return stockMapper.queryByStockCodes(stockCodes);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
package org.cpte.modules.constant;
|
||||
|
||||
public interface CommonConstant {
|
||||
//入库输送线任务均衡索引
|
||||
String RK_DOCK_TASK_INDEX = "rk_dock_task_index";
|
||||
}
|
||||
|
|
@ -11,6 +11,8 @@ public enum AreaTypeEnum {
|
|||
|
||||
CTQ("CTQ", "拆托区"),
|
||||
|
||||
CPCCQ("CPCCQ", "成品存储区"),
|
||||
|
||||
RK_DOCK("RK_DOCK", "入库输送线接驳口"),
|
||||
|
||||
CK_DOCK("CK_DOCK", "出库输送线接驳口"),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
package org.cpte.modules.constant.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum AsnOrderTypeEnum {
|
||||
PRODUCT(0, "成品入库"),
|
||||
|
||||
ACCESSORY(1, "配件入库"),
|
||||
|
||||
PRODUCT_UNPALLETIZE(2, "成品拆托入库"),
|
||||
|
||||
ACCESSORY_UNPALLETIZE(3, "配件拆托入库"),
|
||||
|
||||
|
||||
;
|
||||
|
||||
AsnOrderTypeEnum(Integer value, String desc) {
|
||||
this.value = value;
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
/**
|
||||
* 值
|
||||
*/
|
||||
final Integer value;
|
||||
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
final String desc;
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
package org.cpte.modules.constant.enums;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONAware;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.google.common.base.CaseFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 枚举类接口
|
||||
*
|
||||
* @Author YouChain: 胡克
|
||||
* @Date 2018-07-17 21:22:12
|
||||
* @Email huoj@youchain56.com
|
||||
*/
|
||||
public interface BaseEnum {
|
||||
|
||||
/**
|
||||
* 获取枚举类的值
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Object getValue();
|
||||
|
||||
/**
|
||||
* 获取枚举类的说明
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String getDesc();
|
||||
|
||||
/**
|
||||
* 比较参数是否与枚举类的value相同
|
||||
*
|
||||
* @param value
|
||||
* @return boolean
|
||||
*/
|
||||
default boolean equalsValue(Object value) {
|
||||
return Objects.equals(getValue(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 比较枚举类是否相同
|
||||
*
|
||||
* @param baseEnum
|
||||
* @return boolean
|
||||
*/
|
||||
default boolean equals(BaseEnum baseEnum) {
|
||||
return Objects.equals(getValue(), baseEnum.getValue()) && Objects.equals(getDesc(), baseEnum.getDesc());
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回枚举类的说明
|
||||
*
|
||||
* @param clazz 枚举类类对象
|
||||
* @return
|
||||
*/
|
||||
static String getInfo(Class<? extends BaseEnum> clazz) {
|
||||
BaseEnum[] enums = clazz.getEnumConstants();
|
||||
LinkedHashMap<String, JSONObject> json = new LinkedHashMap<>(enums.length);
|
||||
for (BaseEnum e : enums) {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("value", new DeletedQuotationAware(e.getValue()));
|
||||
jsonObject.put("desc", new DeletedQuotationAware(e.getDesc()));
|
||||
json.put(e.toString(), jsonObject);
|
||||
}
|
||||
|
||||
String enumJson = JSON.toJSONString(json, true);
|
||||
enumJson = enumJson.replaceAll("\"", "");
|
||||
enumJson = enumJson.replaceAll("\t", " ");
|
||||
enumJson = enumJson.replaceAll("\n", "<br>");
|
||||
String prefix = " <br> export const " + CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, clazz.getSimpleName() + " = <br> ");
|
||||
return prefix + enumJson + " <br>";
|
||||
}
|
||||
|
||||
@Data
|
||||
class DeletedQuotationAware implements JSONAware {
|
||||
|
||||
private String value;
|
||||
|
||||
public DeletedQuotationAware(Object value) {
|
||||
if (value instanceof String) {
|
||||
this.value = "'" + value + "'";
|
||||
} else {
|
||||
this.value = value.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toJSONString() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
package org.cpte.modules.constant.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum InventoryLogEnum {
|
||||
INBOUND(1, "入库"),
|
||||
|
||||
ALLOC(2, "分配"),
|
||||
|
||||
UNALLOC(3, "取消分配"),
|
||||
|
||||
PICK(4, "拣货"),
|
||||
|
||||
UNPICK(5, "退拣"),
|
||||
|
||||
OUTBOUND(6, "出库"),
|
||||
|
||||
ADJUST(7, "库存调整"),
|
||||
|
||||
MOVE(8, "库内移位"),
|
||||
|
||||
CHECK(9, "盘点调整"),
|
||||
|
||||
;
|
||||
|
||||
/**
|
||||
* 值
|
||||
*/
|
||||
private final Integer value;
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private final String desc;
|
||||
|
||||
InventoryLogEnum(Integer value, String desc) {
|
||||
this.value = value;
|
||||
this.desc = desc;
|
||||
}
|
||||
}
|
||||
|
|
@ -3,58 +3,80 @@ package org.cpte.modules.conveyorLine.service.impl;
|
|||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.cpte.modules.agvTask.mapper.AgvTaskMapper;
|
||||
import org.cpte.modules.agvTask.service.IAgvTaskService;
|
||||
import org.cpte.modules.base.entity.Point;
|
||||
import org.cpte.modules.base.entity.Stock;
|
||||
import org.cpte.modules.base.mapper.PointMapper;
|
||||
import org.cpte.modules.base.mapper.StockMapper;
|
||||
import org.cpte.modules.base.service.IStockService;
|
||||
import org.cpte.modules.constant.enums.AgvStatusEnum;
|
||||
import org.cpte.modules.constant.enums.AgvVendorEnum;
|
||||
import org.cpte.modules.constant.enums.AsnStatusEnum;
|
||||
import org.cpte.modules.constant.enums.BusinessTypeEnum;
|
||||
import org.cpte.modules.constant.enums.*;
|
||||
import org.cpte.modules.conveyorLine.request.ScanTrayRequest;
|
||||
import org.cpte.modules.conveyorLine.service.IConveyorLineService;
|
||||
import org.cpte.modules.inventory.mapper.InventoryMapper;
|
||||
import org.cpte.modules.receive.entity.AsnDetail;
|
||||
import org.cpte.modules.receive.mapper.AsnDetailMapper;
|
||||
import org.cpte.modules.receive.service.IAsnService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class IConveyorLineServiceImpl implements IConveyorLineService {
|
||||
|
||||
@Autowired
|
||||
private PointMapper pointMapper;
|
||||
|
||||
@Autowired
|
||||
private StockMapper stockMapper;
|
||||
|
||||
@Autowired
|
||||
private AsnDetailMapper asnDetailMapper;
|
||||
|
||||
@Autowired
|
||||
private IStockService iStockService;
|
||||
private AgvTaskMapper agvTaskMapper;
|
||||
|
||||
@Autowired
|
||||
private AgvTaskMapper agvTaskMapper;
|
||||
private InventoryMapper inventoryMapper;
|
||||
|
||||
@Autowired
|
||||
private IAgvTaskService iAgvTaskService;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void scanTray(ScanTrayRequest scanTrayRequest) {
|
||||
|
||||
//验证托盘
|
||||
Stock stock = iStockService.validateStock(scanTrayRequest.getStockCode());
|
||||
//容器
|
||||
Stock stock = stockMapper.queryByStockCode(scanTrayRequest.getStockCode());
|
||||
|
||||
//验证入库信息
|
||||
AsnDetail asnDetail = asnDetailMapper.queryByStockCode(stock.getId(), AsnStatusEnum.CREATED.getValue());
|
||||
if (asnDetail == null) {
|
||||
throw new RuntimeException("【" + scanTrayRequest.getStockCode() + "】托盘,无入库信息");
|
||||
}
|
||||
//验证当前托盘是否有库存
|
||||
|
||||
//通过算法获取目标点位
|
||||
String endCode = "CCQ01";
|
||||
//验证托盘是否有库存
|
||||
if (inventoryMapper.queryByStockId(stock.getId()) != null) {
|
||||
throw new RuntimeException("【" + scanTrayRequest.getStockCode() + "】托盘已入库");
|
||||
}
|
||||
|
||||
//验证当前托盘是否生成了TES任务
|
||||
if (agvTaskMapper.existsAGVTask(stock.getStockCode(), AgvVendorEnum.TES.getValue()) > 0) {
|
||||
if (agvTaskMapper.existsByStockCode(stock.getStockCode(), AgvVendorEnum.TES.getValue()) > 0) {
|
||||
throw new RuntimeException("【" + scanTrayRequest.getStockCode() + "】托盘已扫描,请勿重复扫描");
|
||||
}
|
||||
|
||||
//通过算法获取目标点位
|
||||
List<Point> dstPointList = pointMapper.queryPoints(null, CommonStatusEnum.FREE.getValue(), AreaTypeEnum.CPCCQ.getValue());
|
||||
if (dstPointList.isEmpty()) {
|
||||
throw new RuntimeException("【" + AreaTypeEnum.CPCCQ.getDesc() + "】无空闲库位");
|
||||
}
|
||||
Point dstPoint = dstPointList.get(0);
|
||||
|
||||
//锁定目标库位
|
||||
dstPoint.setStatus(CommonStatusEnum.USED.getValue());
|
||||
pointMapper.updateById(dstPoint);
|
||||
|
||||
//验证通过,生成Tes任务
|
||||
iAgvTaskService.createAgvTask(AgvStatusEnum.CREATED.getValue(), stock.getStockCode(), null, endCode, null, BusinessTypeEnum.INBOUND.getValue(), AgvVendorEnum.TES.getValue());
|
||||
iAgvTaskService.createAgvTask(asnDetail.getId(), AgvStatusEnum.CREATED.getValue(), stock.getStockCode(), null, dstPoint.getPointCode(), null, BusinessTypeEnum.INBOUND.getValue(), AgvVendorEnum.TES.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -176,11 +176,11 @@ public class IHikAgvServiceImpl implements IHikAgvService {
|
|||
* @param agvTask 任务
|
||||
*/
|
||||
private void handleResend(AgvTask agvTask) {
|
||||
Long count = agvTaskMapper.existsAGVTask(agvTask.getCarrierCode(),AgvVendorEnum.HIK.getValue());
|
||||
Long count = agvTaskMapper.existsByStockCode(agvTask.getCarrierCode(),AgvVendorEnum.HIK.getValue());
|
||||
if (count > 0) {
|
||||
throw new RuntimeException("任务已重新生成,请勿重复操作! ");
|
||||
}
|
||||
AgvTask newAgvTask = iAgvTaskService.createAgvTask(AgvStatusEnum.CREATED.getValue(), agvTask.getCarrierCode(), agvTask.getStartCode(), agvTask.getEndCode(), null, agvTask.getType(),AgvVendorEnum.HIK.getValue());
|
||||
AgvTask newAgvTask = iAgvTaskService.createAgvTask(agvTask.getBusinessDetailId(),AgvStatusEnum.CREATED.getValue(), agvTask.getCarrierCode(), agvTask.getStartCode(), agvTask.getEndCode(), null, agvTask.getType(),AgvVendorEnum.HIK.getValue());
|
||||
switch (agvTask.getType()) {
|
||||
case "INBOUND":
|
||||
case "OUTBOUND":
|
||||
|
|
|
|||
|
|
@ -37,9 +37,9 @@ public class Inventory implements Serializable {
|
|||
/**
|
||||
* ID
|
||||
*/
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
@Schema(description = "ID")
|
||||
private java.lang.Integer id;
|
||||
private java.lang.String id;
|
||||
/**
|
||||
* 物料ID
|
||||
*/
|
||||
|
|
@ -73,6 +73,12 @@ public class Inventory implements Serializable {
|
|||
@Excel(name = "分配数", width = 15)
|
||||
@Schema(description = "分配数")
|
||||
private java.math.BigDecimal queuedQty;
|
||||
/**
|
||||
* 入库记录ID
|
||||
*/
|
||||
@Excel(name = "入库记录ID", width = 15)
|
||||
@Schema(description = "入库记录ID")
|
||||
private java.lang.String receiveRecordId;
|
||||
/**
|
||||
* 外部仓库
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -21,6 +21,6 @@ public interface InventoryMapper extends BaseMapper<Inventory> {
|
|||
* @param stockId 容器
|
||||
* @return 库存数据
|
||||
*/
|
||||
@Select("select * from data_inventory where stock_id = #{stockId} ")
|
||||
Inventory selectByStockId(@Param("stockId") String stockId);
|
||||
@Select("select * from data_inventory where stock_id = #{stockId} and quantity>0 for update")
|
||||
Inventory queryByStockId(@Param("stockId") String stockId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,13 +2,28 @@ package org.cpte.modules.inventory.service;
|
|||
|
||||
import org.cpte.modules.inventory.entity.Inventory;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import org.cpte.modules.receive.entity.Asn;
|
||||
import org.cpte.modules.receive.entity.AsnDetail;
|
||||
import org.cpte.modules.receive.entity.ReceiveRecord;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* @Description: 库存表
|
||||
* @author: cpte
|
||||
* @Date: 2025-11-08
|
||||
* @Date: 2025-11-08
|
||||
* @Version: V1.0
|
||||
*/
|
||||
public interface IInventoryService extends IService<Inventory> {
|
||||
|
||||
/**
|
||||
* 创建库存
|
||||
*
|
||||
* @param stockId 容器
|
||||
* @param receivedQty 收货数量
|
||||
* @param asn 入库单
|
||||
* @param asnDetail 入库明细
|
||||
* @param receiveRecord 入库记录
|
||||
* @return Inventory
|
||||
*/
|
||||
Inventory createInventory(String stockId, BigDecimal receivedQty, Asn asn, AsnDetail asnDetail, ReceiveRecord receiveRecord);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,52 @@
|
|||
package org.cpte.modules.inventory.service.impl;
|
||||
|
||||
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.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @Description: 库存表
|
||||
* @author: cpte
|
||||
* @Date: 2025-11-08
|
||||
* @Date: 2025-11-08
|
||||
* @Version: V1.0
|
||||
*/
|
||||
@Service
|
||||
public class InventoryServiceImpl extends ServiceImpl<InventoryMapper, Inventory> implements IInventoryService {
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Inventory createInventory(String stockId, BigDecimal receivedQty, Asn asn, AsnDetail asnDetail, ReceiveRecord receiveRecord) {
|
||||
Inventory inventory = Inventory.builder()
|
||||
.itemId(asnDetail.getItemId())
|
||||
.pointId(receiveRecord.getPointId())
|
||||
.stockId(asnDetail.getStockId())
|
||||
.quantity(receivedQty)
|
||||
.queuedQty(BigDecimal.ZERO)
|
||||
.receiveRecordId(receiveRecord.getId())
|
||||
.whCode(asn.getWhCode())
|
||||
.propC1(asnDetail.getPropC1())
|
||||
.propC2(asnDetail.getPropC2())
|
||||
.propC3(asnDetail.getPropC3())
|
||||
.status(InventoryStatusEnum.AVAILABLE.getValue())
|
||||
.propD1(asnDetail.getPropD1())
|
||||
.description(asnDetail.getDescription())
|
||||
.tenantId(asnDetail.getTenantId())
|
||||
.sysOrgCode(asnDetail.getSysOrgCode())
|
||||
.createBy(asnDetail.getCreateBy())
|
||||
.createTime(new Date())
|
||||
.build();
|
||||
this.save(inventory);
|
||||
return inventory;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,182 @@
|
|||
package org.cpte.modules.inventoryLog.controller;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.system.query.QueryGenerator;
|
||||
import org.jeecg.common.system.query.QueryRuleEnum;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.cpte.modules.inventoryLog.entity.InventoryLog;
|
||||
import org.cpte.modules.inventoryLog.service.IInventoryLogService;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.jeecgframework.poi.excel.ExcelImportUtil;
|
||||
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
|
||||
import org.jeecgframework.poi.excel.entity.ExportParams;
|
||||
import org.jeecgframework.poi.excel.entity.ImportParams;
|
||||
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
|
||||
import org.jeecg.common.system.base.controller.JeecgController;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.multipart.MultipartHttpServletRequest;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import org.jeecg.common.aspect.annotation.AutoLog;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
/**
|
||||
* @Description: 库存日志
|
||||
* @author: cpte
|
||||
* @Date: 2025-11-10
|
||||
* @Version: V1.0
|
||||
*/
|
||||
@Tag(name="库存日志")
|
||||
@RestController
|
||||
@RequestMapping("/inventoryLog")
|
||||
@Slf4j
|
||||
public class InventoryLogController extends JeecgController<InventoryLog, IInventoryLogService> {
|
||||
@Autowired
|
||||
private IInventoryLogService inventoryLogService;
|
||||
|
||||
/**
|
||||
* 分页列表查询
|
||||
*
|
||||
* @param inventoryLog
|
||||
* @param pageNo
|
||||
* @param pageSize
|
||||
* @param req
|
||||
* @return
|
||||
*/
|
||||
//@AutoLog(value = "库存日志-分页列表查询")
|
||||
@Operation(summary="库存日志-分页列表查询")
|
||||
@GetMapping(value = "/list")
|
||||
public Result<IPage<InventoryLog>> queryPageList(InventoryLog inventoryLog,
|
||||
@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
|
||||
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
|
||||
HttpServletRequest req) {
|
||||
|
||||
|
||||
QueryWrapper<InventoryLog> queryWrapper = QueryGenerator.initQueryWrapper(inventoryLog, req.getParameterMap());
|
||||
Page<InventoryLog> page = new Page<InventoryLog>(pageNo, pageSize);
|
||||
IPage<InventoryLog> pageList = inventoryLogService.page(page, queryWrapper);
|
||||
return Result.OK(pageList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加
|
||||
*
|
||||
* @param inventoryLog
|
||||
* @return
|
||||
*/
|
||||
@AutoLog(value = "库存日志-添加")
|
||||
@Operation(summary="库存日志-添加")
|
||||
@RequiresPermissions("inventoryLog:data_inventory_log:add")
|
||||
@PostMapping(value = "/add")
|
||||
public Result<String> add(@RequestBody InventoryLog inventoryLog) {
|
||||
inventoryLogService.save(inventoryLog);
|
||||
|
||||
return Result.OK("添加成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
*
|
||||
* @param inventoryLog
|
||||
* @return
|
||||
*/
|
||||
@AutoLog(value = "库存日志-编辑")
|
||||
@Operation(summary="库存日志-编辑")
|
||||
@RequiresPermissions("inventoryLog:data_inventory_log:edit")
|
||||
@RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST})
|
||||
public Result<String> edit(@RequestBody InventoryLog inventoryLog) {
|
||||
inventoryLogService.updateById(inventoryLog);
|
||||
return Result.OK("编辑成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过id删除
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@AutoLog(value = "库存日志-通过id删除")
|
||||
@Operation(summary="库存日志-通过id删除")
|
||||
@RequiresPermissions("inventoryLog:data_inventory_log:delete")
|
||||
@DeleteMapping(value = "/delete")
|
||||
public Result<String> delete(@RequestParam(name="id",required=true) String id) {
|
||||
inventoryLogService.removeById(id);
|
||||
return Result.OK("删除成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除
|
||||
*
|
||||
* @param ids
|
||||
* @return
|
||||
*/
|
||||
@AutoLog(value = "库存日志-批量删除")
|
||||
@Operation(summary="库存日志-批量删除")
|
||||
@RequiresPermissions("inventoryLog:data_inventory_log:deleteBatch")
|
||||
@DeleteMapping(value = "/deleteBatch")
|
||||
public Result<String> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
|
||||
this.inventoryLogService.removeByIds(Arrays.asList(ids.split(",")));
|
||||
return Result.OK("批量删除成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过id查询
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
//@AutoLog(value = "库存日志-通过id查询")
|
||||
@Operation(summary="库存日志-通过id查询")
|
||||
@GetMapping(value = "/queryById")
|
||||
public Result<InventoryLog> queryById(@RequestParam(name="id",required=true) String id) {
|
||||
InventoryLog inventoryLog = inventoryLogService.getById(id);
|
||||
if(inventoryLog==null) {
|
||||
return Result.error("未找到对应数据");
|
||||
}
|
||||
return Result.OK(inventoryLog);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出excel
|
||||
*
|
||||
* @param request
|
||||
* @param inventoryLog
|
||||
*/
|
||||
@RequiresPermissions("inventoryLog:data_inventory_log:exportXls")
|
||||
@RequestMapping(value = "/exportXls")
|
||||
public ModelAndView exportXls(HttpServletRequest request, InventoryLog inventoryLog) {
|
||||
return super.exportXls(request, inventoryLog, InventoryLog.class, "库存日志");
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过excel导入数据
|
||||
*
|
||||
* @param request
|
||||
* @param response
|
||||
* @return
|
||||
*/
|
||||
@RequiresPermissions("inventoryLog:data_inventory_log:importExcel")
|
||||
@RequestMapping(value = "/importExcel", method = RequestMethod.POST)
|
||||
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
|
||||
return super.importExcel(request, response, InventoryLog.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,174 @@
|
|||
package org.cpte.modules.inventoryLog.entity;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.Date;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import lombok.*;
|
||||
import org.jeecg.common.constant.ProvinceCityArea;
|
||||
import org.jeecg.common.util.SpringContextUtils;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.jeecgframework.poi.excel.annotation.Excel;
|
||||
import org.jeecg.common.aspect.annotation.Dict;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* @Description: 库存日志
|
||||
* @author: cpte
|
||||
* @Date: 2025-11-10
|
||||
* @Version: V1.0
|
||||
*/
|
||||
@Data
|
||||
@TableName("data_inventory_log")
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Schema(description = "库存日志")
|
||||
public class InventoryLog implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
@Schema(description = "id")
|
||||
private java.lang.String id;
|
||||
/**
|
||||
* 日志类型:1入库,2分配,3取消分配,4拣货,5退拣,6.出库,7库存调整,8库位转移,9盘点调整
|
||||
*/
|
||||
@Excel(name = "日志类型", width = 15)
|
||||
@Schema(description = "日志类型")
|
||||
@Dict(dicCode = "inventory_log_type")
|
||||
private java.lang.Integer logType;
|
||||
/**
|
||||
* 业务单号
|
||||
*/
|
||||
@Excel(name = "业务单号", width = 15)
|
||||
@Schema(description = "业务单号")
|
||||
private java.lang.String businessNo;
|
||||
/**
|
||||
* 业务明细ID
|
||||
*/
|
||||
@Excel(name = "业务明细ID", width = 15)
|
||||
@Schema(description = "业务明细ID")
|
||||
private java.lang.String businessDetailId;
|
||||
/**
|
||||
* 库存ID
|
||||
*/
|
||||
@Excel(name = "库存ID", width = 15)
|
||||
@Schema(description = "库存ID")
|
||||
private java.lang.String inventoryId;
|
||||
/**
|
||||
* 物料ID
|
||||
*/
|
||||
@Excel(name = "物料ID", width = 15)
|
||||
@Schema(description = "物料ID")
|
||||
@Dict(dictTable = "base_item", dicCode = "id", dicText = "item_code")
|
||||
private java.lang.String itemId;
|
||||
/**
|
||||
* 原库位置
|
||||
*/
|
||||
@Excel(name = "原库位置", width = 15)
|
||||
@Schema(description = "原库位置")
|
||||
@Dict(dictTable = "base_point", dicCode = "id", dicText = "point_code")
|
||||
private java.lang.String fromPointId;
|
||||
|
||||
/**
|
||||
* 目标库位
|
||||
*/
|
||||
@Excel(name = "目标库位", width = 15)
|
||||
@Schema(description = "目标库位")
|
||||
@Dict(dictTable = "base_point", dicCode = "id", dicText = "point_code")
|
||||
private java.lang.String toPointId;
|
||||
/**
|
||||
* 容器ID
|
||||
*/
|
||||
@Excel(name = "容器ID", width = 15)
|
||||
@Schema(description = "容器ID")
|
||||
@Dict(dictTable = "base_stock", dicCode = "id", dicText = "stock_code")
|
||||
private java.lang.String stockId;
|
||||
/**
|
||||
* 批次号
|
||||
*/
|
||||
@Excel(name = "批次号", width = 15)
|
||||
@Schema(description = "批次号")
|
||||
private java.lang.String propC1;
|
||||
/**
|
||||
* 变动数量
|
||||
*/
|
||||
@Excel(name = "变动数量", width = 15)
|
||||
@Schema(description = "变动数量")
|
||||
private java.math.BigDecimal changeQty;
|
||||
/**
|
||||
* 变动前数量
|
||||
*/
|
||||
@Excel(name = "变动前数量", width = 15)
|
||||
@Schema(description = "变动前数量")
|
||||
private java.math.BigDecimal beforeQty;
|
||||
/**
|
||||
* 变动后数量
|
||||
*/
|
||||
@Excel(name = "变动后数量", width = 15)
|
||||
@Schema(description = "变动后数量")
|
||||
private java.math.BigDecimal afterQty;
|
||||
/**
|
||||
* 变动前已分配数量
|
||||
*/
|
||||
@Excel(name = "变动前已分配数量", width = 15)
|
||||
@Schema(description = "变动前已分配数量")
|
||||
private java.math.BigDecimal beforeAllocatedQty;
|
||||
/**
|
||||
* 变动后已分配数量
|
||||
*/
|
||||
@Excel(name = "变动后已分配数量", width = 15)
|
||||
@Schema(description = "变动后已分配数量")
|
||||
private java.math.BigDecimal afterAllocatedQty;
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
@Excel(name = "描述", width = 15)
|
||||
@Schema(description = "描述")
|
||||
private java.lang.String description;
|
||||
/**
|
||||
* 所属部门
|
||||
*/
|
||||
@Schema(description = "所属部门")
|
||||
private java.lang.String sysOrgCode;
|
||||
/**
|
||||
* 租户ID
|
||||
*/
|
||||
@Excel(name = "租户ID", width = 15)
|
||||
@Schema(description = "租户ID")
|
||||
private java.lang.Integer tenantId;
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
@Schema(description = "创建人")
|
||||
private java.lang.String createBy;
|
||||
/**
|
||||
* 创建日期
|
||||
*/
|
||||
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@Schema(description = "创建日期")
|
||||
private java.util.Date createTime;
|
||||
/**
|
||||
* 更新人
|
||||
*/
|
||||
@Schema(description = "更新人")
|
||||
private java.lang.String updateBy;
|
||||
/**
|
||||
* 更新日期
|
||||
*/
|
||||
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@Schema(description = "更新日期")
|
||||
private java.util.Date updateTime;
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package org.cpte.modules.inventoryLog.mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.cpte.modules.inventoryLog.entity.InventoryLog;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* @Description: 库存日志
|
||||
* @author: cpte
|
||||
* @Date: 2025-11-10
|
||||
* @Version: V1.0
|
||||
*/
|
||||
public interface InventoryLogMapper extends BaseMapper<InventoryLog> {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<?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.inventoryLog.mapper.InventoryLogMapper">
|
||||
|
||||
</mapper>
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
package org.cpte.modules.inventoryLog.service;
|
||||
|
||||
import org.cpte.modules.inventory.entity.Inventory;
|
||||
import org.cpte.modules.inventoryLog.entity.InventoryLog;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* @Description: 库存日志
|
||||
* @author: cpte
|
||||
* @Date: 2025-11-10
|
||||
* @Version: V1.0
|
||||
*/
|
||||
public interface IInventoryLogService extends IService<InventoryLog> {
|
||||
|
||||
/**
|
||||
* 添加库存日志
|
||||
*
|
||||
* @param inventoryLog 日志实体
|
||||
*/
|
||||
void addInventoryLog(InventoryLog inventoryLog);
|
||||
|
||||
/**
|
||||
* 添加入库库存日志
|
||||
*
|
||||
* @param inventory 库存
|
||||
* @param srcPointId 原库位
|
||||
* @param changeQty 变动数量
|
||||
* @param businessNo 业务单号
|
||||
* @param businessDetailId 业务明细ID
|
||||
* @param description 描述
|
||||
*/
|
||||
void addInboundInventoryLog(Inventory inventory, String srcPointId, BigDecimal changeQty, String businessNo, String businessDetailId, String description);
|
||||
|
||||
/**
|
||||
* 添加出库库存日志
|
||||
*
|
||||
* @param inventory 库存
|
||||
* @param changeQty 变动数量
|
||||
* @param businessNo 业务单号
|
||||
* @param businessDetailId 业务明细ID
|
||||
* @param description 描述
|
||||
*/
|
||||
void addOutboundInventoryLog(Inventory inventory, BigDecimal changeQty, String businessNo, String businessDetailId, String description);
|
||||
|
||||
|
||||
/**
|
||||
* 添加分配库存日志
|
||||
*
|
||||
* @param inventory 库存
|
||||
* @param AllocatedQty 分配数量
|
||||
* @param businessNo 业务单号
|
||||
* @param businessDetailId 业务明细ID
|
||||
* @param description 描述
|
||||
*/
|
||||
void addAllocInventoryLog(Inventory inventory, BigDecimal AllocatedQty, String businessNo, String businessDetailId, String description);
|
||||
|
||||
|
||||
/**
|
||||
* 添加取消分配库存日志
|
||||
*
|
||||
* @param inventory 库存
|
||||
* @param cancelQty 取消分配数量
|
||||
* @param businessNo 业务单号
|
||||
* @param businessDetailId 业务明细ID
|
||||
* @param description 描述
|
||||
*/
|
||||
void addUnAllocInventoryLog(Inventory inventory, BigDecimal cancelQty, String businessNo, String businessDetailId, String description);
|
||||
|
||||
|
||||
/**
|
||||
* 添加拣货库存日志
|
||||
*
|
||||
* @param inventory 库存
|
||||
* @param changeQty 变动数量
|
||||
* @param businessNo 业务单号
|
||||
* @param businessDetailId 业务明细ID
|
||||
* @param description 描述
|
||||
*/
|
||||
void addPickInventoryLog(Inventory inventory, BigDecimal changeQty, String businessNo, String businessDetailId, String description);
|
||||
|
||||
/**
|
||||
* 添加退拣库存日志-拣货后取消,库存回退
|
||||
*
|
||||
* @param inventory 库存
|
||||
* @param returnQty 退回数量
|
||||
* @param businessNo 业务单号
|
||||
* @param businessDetailId 业务明细ID
|
||||
* @param description 描述
|
||||
*/
|
||||
void addUnPickInventoryLog(Inventory inventory, BigDecimal returnQty, String businessNo, String businessDetailId, String description);
|
||||
|
||||
/**
|
||||
* 添加库存调整库存日志
|
||||
*
|
||||
* @param inventory 库存
|
||||
* @param adjustQty 调整数量
|
||||
* @param businessNo 业务单号
|
||||
* @param description 描述
|
||||
*/
|
||||
void addAdjustInventoryLog(Inventory inventory, BigDecimal adjustQty, String businessNo, String description);
|
||||
|
||||
/**
|
||||
* 添加库内移位存日志
|
||||
*
|
||||
* @param inventory 库存
|
||||
* @param toPointId 目标库位
|
||||
* @param moveQty 移位数量
|
||||
* @param businessNo 业务单号
|
||||
* @param description 描述
|
||||
*/
|
||||
void addMoveInventoryLog(Inventory inventory, String toPointId, BigDecimal moveQty, String businessNo, String description);
|
||||
|
||||
/**
|
||||
* 添加库存盘点库存日志
|
||||
*
|
||||
* @param inventory 库存
|
||||
* @param actualQty 实际数量
|
||||
* @param systemQty 系统数量
|
||||
* @param businessNo 业务单号
|
||||
* @param description 描述
|
||||
*/
|
||||
void addCheckInventoryLog(Inventory inventory, BigDecimal actualQty, BigDecimal systemQty, String businessNo, String description);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,181 @@
|
|||
package org.cpte.modules.inventoryLog.service.impl;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.cpte.modules.constant.enums.InventoryLogEnum;
|
||||
import org.cpte.modules.inventory.entity.Inventory;
|
||||
import org.cpte.modules.inventoryLog.entity.InventoryLog;
|
||||
import org.cpte.modules.inventoryLog.mapper.InventoryLogMapper;
|
||||
import org.cpte.modules.inventoryLog.service.IInventoryLogService;
|
||||
import org.cpte.modules.utils.BigDecimalUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @Description: 库存日志
|
||||
* @author: cpte
|
||||
* @Date: 2025-11-10
|
||||
* @Version: V1.0
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class InventoryLogServiceImpl extends ServiceImpl<InventoryLogMapper, InventoryLog> implements IInventoryLogService {
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void addInventoryLog(InventoryLog inventoryLog) {
|
||||
try {
|
||||
this.save(inventoryLog);
|
||||
log.debug("库存变动日志记录成功,库存ID: {}, 变动数量: {}",
|
||||
inventoryLog.getInventoryId(), inventoryLog.getChangeQty());
|
||||
} catch (Exception e) {
|
||||
log.error("记录库存变动日志失败,库存ID: {}", inventoryLog.getInventoryId(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void addInboundInventoryLog(Inventory inventory,String srcPointId, BigDecimal changeQty, String businessNo, String businessDetailId, String description) {
|
||||
InventoryLog inventoryLog = buildInventoryLog(inventory, changeQty, businessNo, businessDetailId, description);
|
||||
// 入库类型
|
||||
inventoryLog.setLogType(InventoryLogEnum.INBOUND.getValue());
|
||||
inventoryLog.setFromPointId(srcPointId);
|
||||
addInventoryLog(inventoryLog);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void addOutboundInventoryLog(Inventory inventory, BigDecimal changeQty, String businessNo, String businessDetailId, String description) {
|
||||
InventoryLog inventoryLog = buildInventoryLog(inventory, changeQty, businessNo, businessDetailId, description);
|
||||
// 出库数量为负数
|
||||
inventoryLog.setChangeQty(changeQty.negate());
|
||||
inventoryLog.setAfterQty(inventory.getQuantity());
|
||||
// 出库类型
|
||||
inventoryLog.setLogType(InventoryLogEnum.OUTBOUND.getValue());
|
||||
addInventoryLog(inventoryLog);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void addAllocInventoryLog(Inventory inventory, BigDecimal AllocatedQty, String businessNo, String businessDetailId, String description) {
|
||||
InventoryLog inventoryLog = buildInventoryLog(inventory, AllocatedQty, businessNo, businessDetailId, description);
|
||||
//出库分配
|
||||
inventoryLog.setLogType(InventoryLogEnum.ALLOC.getValue());
|
||||
//实际数量不变
|
||||
inventoryLog.setChangeQty(BigDecimal.ZERO);
|
||||
inventoryLog.setBeforeAllocatedQty(BigDecimalUtil.subtract(inventory.getQueuedQty(), AllocatedQty, 0));
|
||||
inventoryLog.setAfterAllocatedQty(inventory.getQueuedQty());
|
||||
addInventoryLog(inventoryLog);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void addUnAllocInventoryLog(Inventory inventory, BigDecimal cancelQuantity, String businessNo, String businessDetailId, String description) {
|
||||
InventoryLog inventoryLog = buildInventoryLog(inventory, BigDecimal.ZERO, businessNo, businessDetailId, description);
|
||||
inventoryLog.setLogType(InventoryLogEnum.UNALLOC.getValue());
|
||||
// 实际数量不变
|
||||
inventoryLog.setChangeQty(BigDecimal.ZERO);
|
||||
inventoryLog.setBeforeAllocatedQty(BigDecimalUtil.add(inventory.getQueuedQty(), cancelQuantity, 0));
|
||||
inventoryLog.setAfterAllocatedQty(inventory.getQueuedQty());
|
||||
addInventoryLog(inventoryLog);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void addPickInventoryLog(Inventory inventory, BigDecimal changeQty, String businessNo, String businessDetailId, String description) {
|
||||
InventoryLog inventoryLog = buildInventoryLog(inventory, changeQty, businessNo, businessDetailId, description);
|
||||
// 拣货类型
|
||||
inventoryLog.setLogType(InventoryLogEnum.PICK.getValue());
|
||||
// 出库数量为负数
|
||||
inventoryLog.setChangeQty(changeQty.negate());
|
||||
inventoryLog.setAfterQty(inventory.getQuantity());
|
||||
addInventoryLog(inventoryLog);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void addUnPickInventoryLog(Inventory inventory, BigDecimal returnQuantity, String businessNo, String businessDetailId, String description) {
|
||||
InventoryLog inventoryLog = buildInventoryLog(inventory, returnQuantity, businessNo, businessDetailId, description);
|
||||
//退拣
|
||||
inventoryLog.setLogType(InventoryLogEnum.UNPICK.getValue());
|
||||
inventoryLog.setChangeQty(returnQuantity); // 正数表示增加库存
|
||||
inventoryLog.setAfterQty(inventory.getQuantity());
|
||||
addInventoryLog(inventoryLog);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void addAdjustInventoryLog(Inventory inventory, BigDecimal adjustQuantity, String businessNo, String description) {
|
||||
InventoryLog inventoryLog = buildInventoryLog(inventory, adjustQuantity, businessNo, null, description);
|
||||
inventoryLog.setLogType(InventoryLogEnum.ADJUST.getValue()); // 调整类型
|
||||
inventoryLog.setChangeQty(adjustQuantity); // 可正可负
|
||||
inventoryLog.setAfterQty(inventory.getQuantity());
|
||||
addInventoryLog(inventoryLog);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void addMoveInventoryLog(Inventory inventory, String toPointId, BigDecimal moveQty, String businessNo, String description) {
|
||||
InventoryLog inventoryLog = buildInventoryLog(inventory, BigDecimal.ZERO, businessNo, null, description);
|
||||
inventoryLog.setLogType(InventoryLogEnum.MOVE.getValue());
|
||||
//目标库位
|
||||
inventoryLog.setToPointId(toPointId);
|
||||
// 数量不变,只是位置变化
|
||||
inventoryLog.setChangeQty(BigDecimal.ZERO);
|
||||
addInventoryLog(inventoryLog);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void addCheckInventoryLog(Inventory inventory, BigDecimal actualQty, BigDecimal systemQty, String businessNo, String description) {
|
||||
// 调整数量=实际数量-系统数量
|
||||
BigDecimal adjustQuantity = BigDecimalUtil.subtract(actualQty, systemQty, 0);
|
||||
InventoryLog inventoryLog = buildInventoryLog(inventory, adjustQuantity, businessNo, null, description);
|
||||
inventoryLog.setLogType(InventoryLogEnum.CHECK.getValue());
|
||||
inventoryLog.setChangeQty(adjustQuantity);
|
||||
inventoryLog.setBeforeQty(systemQty);
|
||||
inventoryLog.setAfterQty(actualQty);
|
||||
addInventoryLog(inventoryLog);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 构建库存日志
|
||||
*
|
||||
* @param inventory 库存
|
||||
* @param changeQty 变动数量
|
||||
* @param businessNo 业务单号
|
||||
* @param businessDetailId 业务单明细ID
|
||||
* @param description 描述
|
||||
* @return InventoryLog
|
||||
*/
|
||||
private InventoryLog buildInventoryLog(Inventory inventory, BigDecimal changeQty, String businessNo, String businessDetailId, String description) {
|
||||
|
||||
return InventoryLog.builder()
|
||||
.inventoryId(inventory.getId())
|
||||
.itemId(inventory.getItemId())
|
||||
.toPointId(inventory.getPointId())
|
||||
.stockId(inventory.getStockId())
|
||||
.businessNo(businessNo)
|
||||
.businessDetailId(businessDetailId)
|
||||
.propC1(inventory.getPropC1())
|
||||
.description(description)
|
||||
//计算变动前后数量: 变动前数量 = 库存数量 - 变动数量
|
||||
.beforeQty(BigDecimalUtil.subtract(inventory.getQuantity(), changeQty, 0))
|
||||
.changeQty(changeQty)
|
||||
.afterQty(inventory.getQuantity())
|
||||
// 分配数量变动
|
||||
.afterAllocatedQty(inventory.getQueuedQty())
|
||||
.beforeAllocatedQty(inventory.getQueuedQty())
|
||||
.sysOrgCode(inventory.getSysOrgCode())
|
||||
.tenantId(inventory.getTenantId())
|
||||
.createBy(inventory.getCreateBy())
|
||||
.createTime(new Date())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
|
@ -25,14 +25,21 @@ public class HikAgvJob implements Job {
|
|||
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
|
||||
// 查询待执行任务
|
||||
List<AgvTask> agvTaskList = agvTaskMapper.queryAgvTaskList(AgvStatusEnum.CREATED.getValue(), AgvVendorEnum.HIK.getValue());
|
||||
if (agvTaskList.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
String taskSubmitUrl = "http://localhost:8000/cpte-wms/rcs/rtas/api/robot/controller/task/submit";
|
||||
for (AgvTask agvTask : agvTaskList) {
|
||||
try {
|
||||
hikAgvService.sendHikAgvTask(
|
||||
taskSubmitUrl,
|
||||
hikAgvService.generateHikAgvTaskJson(agvTask),
|
||||
agvTask
|
||||
);
|
||||
// 判断起点无任务才允许下发
|
||||
boolean isStartCodeAvailable = agvTaskMapper.existsByStartCode(agvTask.getStartCode(), AgvVendorEnum.HIK.getValue()) == 0;
|
||||
if (isStartCodeAvailable) {
|
||||
hikAgvService.sendHikAgvTask(
|
||||
taskSubmitUrl,
|
||||
hikAgvService.generateHikAgvTaskJson(agvTask),
|
||||
agvTask
|
||||
);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("发送AGV任务失败,任务ID: {}", agvTask.getId(), e);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ public class AsnController {
|
|||
@PostMapping(value = "/add")
|
||||
public Result<String> add(@RequestBody AsnPage asnPage) {
|
||||
Asn asn = new Asn();
|
||||
asn.setOrderNo(codeGeneratorUtil.generateCode("RK"));
|
||||
asn.setOrderNo(codeGeneratorUtil.generateSerialNumber("RK"));
|
||||
BeanUtils.copyProperties(asnPage, asn);
|
||||
asnService.saveMain(asn, asnPage.getAsnDetailList());
|
||||
return Result.OK("添加成功!");
|
||||
|
|
|
|||
|
|
@ -40,6 +40,6 @@ public interface AsnDetailMapper extends BaseMapper<AsnDetail> {
|
|||
* @param status 状态
|
||||
* @return AsnDetail
|
||||
*/
|
||||
@Select("select * from data_asn_detail where stock_id = #{stockId} and status = #{status} ")
|
||||
@Select("select * from data_asn_detail where stock_id = #{stockId} and status = #{status} for update")
|
||||
AsnDetail queryByStockCode(@Param("stockId") String stockId, @Param("status") Integer status);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,9 @@
|
|||
package org.cpte.modules.receive.mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import org.cpte.modules.receive.entity.Asn;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* @Description: 入库单
|
||||
* @author: cpte
|
||||
|
|
@ -20,7 +17,7 @@ public interface AsnMapper extends BaseMapper<Asn> {
|
|||
* @param no 任务号
|
||||
* @return Asn
|
||||
*/
|
||||
@Select("select * from data_asn where no = #{no}")
|
||||
@Select("select * from data_asn where no = #{no} for update ")
|
||||
Asn queryByNo(@Param("no") String no);
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package org.cpte.modules.receive.service;
|
|||
import org.cpte.modules.receive.entity.AsnDetail;
|
||||
import org.cpte.modules.receive.entity.Asn;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Collection;
|
||||
|
|
@ -11,46 +12,47 @@ import java.util.List;
|
|||
/**
|
||||
* @Description: 入库单
|
||||
* @author: cpte
|
||||
* @Date: 2025-11-03
|
||||
* @Date: 2025-11-03
|
||||
* @Version: V1.0
|
||||
*/
|
||||
public interface IAsnService extends IService<Asn> {
|
||||
|
||||
/**
|
||||
* 添加一对多
|
||||
*
|
||||
* @param asn
|
||||
* @param asnDetailList
|
||||
*/
|
||||
public void saveMain(Asn asn,List<AsnDetail> asnDetailList) ;
|
||||
/**
|
||||
* 添加一对多
|
||||
*
|
||||
* @param asn
|
||||
* @param asnDetailList
|
||||
*/
|
||||
public void saveMain(Asn asn, List<AsnDetail> asnDetailList);
|
||||
|
||||
/**
|
||||
* 修改一对多
|
||||
*
|
||||
* @param asn
|
||||
* @param asnDetailList
|
||||
*/
|
||||
public void updateMain(Asn asn,List<AsnDetail> asnDetailList);
|
||||
/**
|
||||
* 修改一对多
|
||||
*
|
||||
* @param asn
|
||||
* @param asnDetailList
|
||||
*/
|
||||
public void updateMain(Asn asn, List<AsnDetail> asnDetailList);
|
||||
|
||||
/**
|
||||
* 删除一对多
|
||||
*
|
||||
* @param id
|
||||
*/
|
||||
public void delMain (String id);
|
||||
/**
|
||||
* 删除一对多
|
||||
*
|
||||
* @param id
|
||||
*/
|
||||
public void delMain(String id);
|
||||
|
||||
/**
|
||||
* 批量删除一对多
|
||||
*
|
||||
* @param idList
|
||||
*/
|
||||
public void delBatchMain (Collection<? extends Serializable> idList);
|
||||
/**
|
||||
* 批量删除一对多
|
||||
*
|
||||
* @param idList
|
||||
*/
|
||||
public void delBatchMain(Collection<? extends Serializable> idList);
|
||||
|
||||
/**
|
||||
* 收货操作
|
||||
*
|
||||
* @param stockCode 容器
|
||||
*/
|
||||
void receiveGoods(String stockCode);
|
||||
/**
|
||||
* 收货操作
|
||||
*
|
||||
* @param asnDetailId 入库明细ID
|
||||
* @param pointCode 目标库位
|
||||
*/
|
||||
void receiveGoods(String asnDetailId, String pointCode);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,9 +8,10 @@ import org.cpte.modules.base.mapper.StockMapper;
|
|||
import org.cpte.modules.base.service.IStockService;
|
||||
import org.cpte.modules.constant.enums.AsnStatusEnum;
|
||||
import org.cpte.modules.constant.enums.CommonStatusEnum;
|
||||
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.inventoryLog.service.IInventoryLogService;
|
||||
import org.cpte.modules.receive.entity.Asn;
|
||||
import org.cpte.modules.receive.entity.AsnDetail;
|
||||
import org.cpte.modules.receive.entity.ReceiveRecord;
|
||||
|
|
@ -19,7 +20,6 @@ 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.utils.BigDecimalUtil;
|
||||
import org.jeecg.common.constant.CommonSendStatus;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
|
@ -56,7 +56,9 @@ public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnS
|
|||
@Autowired
|
||||
private InventoryMapper inventoryMapper;
|
||||
@Autowired
|
||||
private IStockService iStockService;
|
||||
private IInventoryService iInventoryService;
|
||||
@Autowired
|
||||
private IInventoryLogService iInventoryLogService;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
|
|
@ -131,7 +133,7 @@ public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnS
|
|||
@Transactional(rollbackFor = Exception.class)
|
||||
public void delMain(String id) {
|
||||
Asn asn = this.getById(id);
|
||||
if(!AsnStatusEnum.CREATED.getValue().equals(asn.getStatus())){
|
||||
if (!AsnStatusEnum.CREATED.getValue().equals(asn.getStatus())) {
|
||||
throw new RuntimeException("操作失败:【" + asn.getOrderNo() + "】入库单,非创建状态不允许删除");
|
||||
}
|
||||
asnDetailMapper.deleteByMainId(id);
|
||||
|
|
@ -144,30 +146,43 @@ public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnS
|
|||
List<String> orderNoList = new ArrayList<>();
|
||||
for (Serializable id : idList) {
|
||||
Asn asn = this.getById(id);
|
||||
if(!AsnStatusEnum.CREATED.getValue().equals(asn.getStatus())){
|
||||
if (!AsnStatusEnum.CREATED.getValue().equals(asn.getStatus())) {
|
||||
orderNoList.add(asn.getOrderNo());
|
||||
continue;
|
||||
}
|
||||
asnDetailMapper.deleteByMainId(id.toString());
|
||||
asnMapper.deleteById(id);
|
||||
}
|
||||
if(!orderNoList.isEmpty()){
|
||||
if (!orderNoList.isEmpty()) {
|
||||
throw new RuntimeException("操作失败:【" + orderNoList + "】入库单,非创建状态不允许删除");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void receiveGoods(String stockCode) {
|
||||
//验证容器
|
||||
Stock stock = iStockService.validateStock(stockCode);
|
||||
AsnDetail asnDetail = asnDetailMapper.queryByStockCode(stock.getId(), AsnStatusEnum.CREATED.getValue());
|
||||
public void receiveGoods(String asnDetailId, String pointCode) {
|
||||
//入库明细任务
|
||||
AsnDetail asnDetail = asnDetailMapper.selectById(asnDetailId);
|
||||
if (asnDetail == null) {
|
||||
throw new RuntimeException("【" + stockCode + "】托盘,无入库信息");
|
||||
throw new RuntimeException("未匹配到入库任务【" + asnDetailId + "】");
|
||||
}
|
||||
|
||||
//入库单
|
||||
Asn asn = this.getById(asnDetail.getAsnId());
|
||||
|
||||
//实际的存储位置
|
||||
Point dstPoint = pointMapper.queryByPointCode(pointCode);
|
||||
|
||||
//容器
|
||||
Stock stock = stockMapper.selectById(asnDetail.getStockId());
|
||||
|
||||
//验证当前托盘是否有库存
|
||||
/* Stock stock = stockMapper.selectById(asnDetail.getStockId());
|
||||
Inventory existingInventory = inventoryMapper.selectByStockId(stock.getId());
|
||||
if (existingInventory != null) {
|
||||
throw new RuntimeException("【" + stock.getStockCode() + "】托盘已入库");
|
||||
}*/
|
||||
|
||||
//更新收货数量
|
||||
BigDecimal receivedQty = BigDecimalUtil.add(asnDetail.getReceivedQty(), asnDetail.getOrderQty(), 0);
|
||||
asnDetail.setReceivedQty(receivedQty);
|
||||
|
|
@ -180,48 +195,30 @@ public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnS
|
|||
}
|
||||
asnDetailMapper.updateById(asnDetail);
|
||||
|
||||
// 根据容器ID查询库存
|
||||
Inventory existingInventory = inventoryMapper.selectByStockId(asnDetail.getStockId());
|
||||
if (existingInventory != null) {
|
||||
// 更新库存
|
||||
existingInventory.setQuantity(receivedQty);
|
||||
existingInventory.setQueuedQty(BigDecimal.ZERO);
|
||||
existingInventory.setStatus(InventoryStatusEnum.AVAILABLE.getValue());
|
||||
inventoryMapper.updateById(existingInventory);
|
||||
} else {
|
||||
//生成新库存
|
||||
Inventory inventory = Inventory.builder()
|
||||
.itemId(asnDetail.getItemId())
|
||||
.pointId(asnDetail.getPointId())
|
||||
.stockId(asnDetail.getStockId())
|
||||
.quantity(receivedQty)
|
||||
.queuedQty(BigDecimal.ZERO)
|
||||
.whCode(asn.getWhCode())
|
||||
.propC1(asnDetail.getPropC1())
|
||||
.propC2(asnDetail.getPropC2())
|
||||
.propC3(asnDetail.getPropC3())
|
||||
.status(InventoryStatusEnum.AVAILABLE.getValue())
|
||||
.propD1(asnDetail.getPropD1())
|
||||
.description(asnDetail.getDescription())
|
||||
.tenantId(asnDetail.getTenantId())
|
||||
.sysOrgCode(asnDetail.getSysOrgCode())
|
||||
.createBy(asnDetail.getCreateBy())
|
||||
.createTime(new Date())
|
||||
.build();
|
||||
inventoryMapper.insert(inventory);
|
||||
}
|
||||
//生成入库记录
|
||||
ReceiveRecord receiveRecord = createReceiveRecord(asnDetail, receivedQty, dstPoint.getId());
|
||||
|
||||
//更新容器状态和位置
|
||||
updateStockPoint(asnDetail.getStockId(), asnDetail.getPointId());
|
||||
// 生成库存
|
||||
Inventory inventory = iInventoryService.createInventory(stock.getId(), receivedQty, asn, asnDetail, receiveRecord);
|
||||
|
||||
//更新入库单
|
||||
refreshAsn(asn, asnDetailMapper.selectByMainId(asn.getId()));
|
||||
|
||||
//创建入库记录
|
||||
//更新容器状态和位置
|
||||
updateStockPoint(stock, dstPoint);
|
||||
|
||||
//添加库存日志
|
||||
iInventoryLogService.addInboundInventoryLog(inventory, asnDetail.getPointId(), receivedQty, asn.getOrderNo(), asnDetail.getId(), asnDetail.getDescription());
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建入库记录
|
||||
*/
|
||||
public ReceiveRecord createReceiveRecord(AsnDetail asnDetail, BigDecimal receivedQty, String dstPointId) {
|
||||
ReceiveRecord receiveRecord = ReceiveRecord.builder()
|
||||
.asnDetailId(asnDetail.getId())
|
||||
.stockId(asnDetail.getStockId())
|
||||
.pointId(asnDetail.getPointId())
|
||||
.pointId(dstPointId)
|
||||
.itemId(asnDetail.getItemId())
|
||||
.receivedQty(receivedQty)
|
||||
.propC1(asnDetail.getPropC1())
|
||||
|
|
@ -235,22 +232,19 @@ public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnS
|
|||
.createTime(new Date())
|
||||
.build();
|
||||
receiveRecordMapper.insert(receiveRecord);
|
||||
|
||||
//TODO: 在此处添加库存操作日志
|
||||
return receiveRecord;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 更新容器位置和状态
|
||||
*/
|
||||
private void updateStockPoint(String stockId, String pointId) {
|
||||
Stock stock = stockMapper.selectById(stockId);
|
||||
stock.setPointId(pointId);
|
||||
private void updateStockPoint(Stock stock, Point point) {
|
||||
stock.setPointId(point.getId());
|
||||
stock.setStatus(CommonStatusEnum.USED.getValue());
|
||||
stockMapper.updateById(stock);
|
||||
|
||||
// 更新库位状态为占用
|
||||
Point point = pointMapper.selectById(pointId);
|
||||
point.setStatus(CommonStatusEnum.USED.getValue()); // 占用状态
|
||||
pointMapper.updateById(point);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,9 +5,11 @@ import org.cpte.modules.agvTask.service.IAgvTaskService;
|
|||
import org.cpte.modules.base.entity.Item;
|
||||
import org.cpte.modules.base.entity.Point;
|
||||
import org.cpte.modules.base.entity.Stock;
|
||||
import org.cpte.modules.base.mapper.PointMapper;
|
||||
import org.cpte.modules.base.service.IItemService;
|
||||
import org.cpte.modules.base.service.IPointService;
|
||||
import org.cpte.modules.base.service.IStockService;
|
||||
import org.cpte.modules.constant.CommonConstant;
|
||||
import org.cpte.modules.constant.enums.*;
|
||||
import org.cpte.modules.receive.entity.Asn;
|
||||
import org.cpte.modules.receive.entity.AsnDetail;
|
||||
|
|
@ -17,9 +19,11 @@ import org.cpte.modules.saiWms.request.InboundRequest;
|
|||
import org.cpte.modules.saiWms.service.ISaiWmsService;
|
||||
import org.cpte.modules.utils.CodeGeneratorUtil;
|
||||
import org.jeecg.common.config.TenantContext;
|
||||
import org.jeecg.common.util.RedisUtil;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
|
|
@ -31,6 +35,9 @@ public class ISaiWmsServiceImpl implements ISaiWmsService {
|
|||
@Autowired
|
||||
private AsnMapper asnMapper;
|
||||
|
||||
@Autowired
|
||||
private PointMapper pointMapper;
|
||||
|
||||
@Autowired
|
||||
private IItemService itemService;
|
||||
|
||||
|
|
@ -44,21 +51,26 @@ public class ISaiWmsServiceImpl implements ISaiWmsService {
|
|||
private IAsnService asnService;
|
||||
|
||||
@Autowired
|
||||
private IAgvTaskService iAgvTaskService ;
|
||||
private IAgvTaskService iAgvTaskService;
|
||||
|
||||
@Autowired
|
||||
private CodeGeneratorUtil codeGeneratorUtil;
|
||||
|
||||
@Override
|
||||
public void inBoundTask(InboundRequest inboundRequest) {
|
||||
//任务号
|
||||
String no = inboundRequest.getNo();
|
||||
@Autowired
|
||||
private RedisUtil redisUtil;
|
||||
|
||||
// 验证任务号是否存在
|
||||
if (asnMapper.queryByNo(no) != null) {
|
||||
throw new RuntimeException("【" + no + "】" + "任务号系统已接收,请勿重复下发");
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void inBoundTask(InboundRequest inboundRequest) {
|
||||
//验证任务号
|
||||
String no = inboundRequest.getNo();
|
||||
Asn asn = asnMapper.queryByNo(no);
|
||||
if (asn != null) {
|
||||
throw new RuntimeException("【" + no + "】任务号已接收,请勿重复下发");
|
||||
}
|
||||
|
||||
//一个托盘一个任务,不允许一个多盘多个任务
|
||||
|
||||
// 获取唯一的明细
|
||||
InboundRequest.InboundDetail detail = inboundRequest.getDetails().get(0);
|
||||
|
||||
|
|
@ -71,12 +83,14 @@ public class ISaiWmsServiceImpl implements ISaiWmsService {
|
|||
Item item = itemService.validateItem(itemCode);
|
||||
Stock stock = iStockService.validateStock(stockCode);
|
||||
|
||||
//获取目标库位
|
||||
List<Point> dstPointList = iPointService.queryPoints(null, CommonStatusEnum.FREE.getValue(), AreaTypeEnum.RK_DOCK.getValue());
|
||||
if(dstPointList.isEmpty()){
|
||||
//获取输送线工作台点位,均衡分配点位任务-轮询方式
|
||||
List<Point> dstPointList = pointMapper.queryPoints(null, CommonStatusEnum.FREE.getValue(), AreaTypeEnum.RK_DOCK.getValue());
|
||||
if (dstPointList.isEmpty()) {
|
||||
throw new RuntimeException("【" + AreaTypeEnum.RK_DOCK.getDesc() + "】" + "无空闲库位");
|
||||
}
|
||||
Point dstPoint = dstPointList.get(0);
|
||||
String key = CommonConstant.RK_DOCK_TASK_INDEX;
|
||||
long currentIndex = redisUtil.incr(key, 1) % dstPointList.size();
|
||||
Point dstPoint = dstPointList.get((int) currentIndex);
|
||||
|
||||
// 创建入库单和明细
|
||||
Asn createAsn = buildAsn(inboundRequest);
|
||||
|
|
@ -85,17 +99,21 @@ public class ISaiWmsServiceImpl implements ISaiWmsService {
|
|||
// 保存入库单和入库明细
|
||||
asnService.saveMain(createAsn, Collections.singletonList(asnDetail));
|
||||
|
||||
//创建AGV任务
|
||||
iAgvTaskService.createAgvTask(AgvStatusEnum.CREATED.getValue(), stock.getStockCode(), srcPoint.getPointCode(), dstPoint.getPointCode(), null, BusinessTypeEnum.INBOUND.getValue(),AgvVendorEnum.HIK.getValue());
|
||||
//成品入库需要生成AGV
|
||||
if (AsnOrderTypeEnum.PRODUCT.getValue().equals(createAsn.getOrderType())) {
|
||||
//创建AGV任务
|
||||
iAgvTaskService.createAgvTask(asnDetail.getId(), AgvStatusEnum.CREATED.getValue(), stock.getStockCode(), srcPoint.getPointCode(), dstPoint.getPointCode(), null, BusinessTypeEnum.INBOUND.getValue(), AgvVendorEnum.HIK.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建入库单
|
||||
*/
|
||||
private Asn buildAsn(InboundRequest inboundRequest) {
|
||||
int tenantId = oConvertUtils.getInt(TenantContext.getTenant(), 0);
|
||||
int tenantId = oConvertUtils.getInt(TenantContext.getTenant(), 1000);
|
||||
String orderNo = (codeGeneratorUtil.generateSerialNumber("RK"));
|
||||
return Asn.builder()
|
||||
.orderNo(codeGeneratorUtil.generateCode("RK"))
|
||||
.orderNo(orderNo)
|
||||
.thirdPartyOrderNo(inboundRequest.getOrderNo())
|
||||
.no(inboundRequest.getNo())
|
||||
.whCode(inboundRequest.getWhCode())
|
||||
|
|
|
|||
|
|
@ -132,7 +132,6 @@ public class ITesAgvServiceImpl implements ITesAgvService {
|
|||
public void callBackTask(TesCallbackRequest tesCallbackRequest) {
|
||||
//根据任务ID查询任务
|
||||
AgvTask agvTask = agvTaskMapper.selectById(tesCallbackRequest.getContent().getBizID());
|
||||
String stockCode=tesCallbackRequest.getContent().getPodID();
|
||||
if (agvTask == null) {
|
||||
throw new RuntimeException("【" + tesCallbackRequest.getContent().getBizID() + "】任务不存在");
|
||||
}
|
||||
|
|
@ -140,7 +139,7 @@ public class ITesAgvServiceImpl implements ITesAgvService {
|
|||
switch (status) {
|
||||
case 4:
|
||||
//4.成功-任务完成
|
||||
handleEnd(stockCode,agvTask);
|
||||
handleEnd(agvTask.getBusinessDetailId(), agvTask);
|
||||
break;
|
||||
case 6:
|
||||
//6.已取消-任务取消
|
||||
|
|
@ -158,8 +157,9 @@ public class ITesAgvServiceImpl implements ITesAgvService {
|
|||
*
|
||||
* @param agvTask 任务
|
||||
*/
|
||||
private void handleEnd(String stockCode,AgvTask agvTask) {
|
||||
iAsnService.receiveGoods(stockCode);
|
||||
private void handleEnd(String asnDetailId, AgvTask agvTask) {
|
||||
//确认收货
|
||||
iAsnService.receiveGoods(asnDetailId, agvTask.getEndCode());
|
||||
agvTask.setStatus(AgvStatusEnum.COMPLETED.getValue());
|
||||
agvTask.setEndTime(new Date());
|
||||
agvTaskMapper.updateById(agvTask);
|
||||
|
|
@ -182,11 +182,11 @@ public class ITesAgvServiceImpl implements ITesAgvService {
|
|||
* @param agvTask 任务
|
||||
*/
|
||||
private void handleResend(AgvTask agvTask) {
|
||||
Long count = agvTaskMapper.existsAGVTask(agvTask.getCarrierCode(),AgvVendorEnum.TES.getValue());
|
||||
Long count = agvTaskMapper.existsByStockCode(agvTask.getCarrierCode(), AgvVendorEnum.TES.getValue());
|
||||
if (count > 0) {
|
||||
throw new RuntimeException("任务已重新生成,请勿重复操作! ");
|
||||
}
|
||||
AgvTask newAgvTask = iAgvTaskService.createAgvTask(AgvStatusEnum.CREATED.getValue(), agvTask.getCarrierCode(), agvTask.getStartCode(), agvTask.getEndCode(), null, agvTask.getType(), AgvVendorEnum.TES.getValue());
|
||||
AgvTask newAgvTask = iAgvTaskService.createAgvTask(agvTask.getBusinessDetailId(), AgvStatusEnum.CREATED.getValue(), agvTask.getCarrierCode(), agvTask.getStartCode(), agvTask.getEndCode(), null, agvTask.getType(), AgvVendorEnum.TES.getValue());
|
||||
switch (agvTask.getType()) {
|
||||
case "INBOUND":
|
||||
case "OUTBOUND":
|
||||
|
|
|
|||
|
|
@ -1,17 +1,20 @@
|
|||
package org.cpte.modules.utils;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import jakarta.annotation.Resource;
|
||||
import com.jeecg.weibo.exception.BusinessException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jeecg.common.handler.IFillRuleHandler;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.CannotAcquireLockException;
|
||||
import org.springframework.dao.DeadlockLoserDataAccessException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
|
|
@ -29,33 +32,39 @@ public class CodeGeneratorUtil implements IFillRuleHandler {
|
|||
* @return 完整业务编号
|
||||
*/
|
||||
@Transactional
|
||||
public String generateCode(String type) {
|
||||
String dateStr = LocalDate.now().format(DATE_FORMATTER);
|
||||
public String generateSerialNumber(String type) {
|
||||
try {
|
||||
String dateStr = LocalDate.now().format(DATE_FORMATTER);
|
||||
|
||||
// 尝试更新当前序列号
|
||||
String updateSql = "UPDATE generator_sequence SET current_seq = current_seq + 1 WHERE type = ? AND date_str = ?";
|
||||
int updated = jdbcTemplate.update(updateSql, type, dateStr);
|
||||
// 使用 SELECT FOR UPDATE 加锁查询并更新
|
||||
String lockAndUpdateSql =
|
||||
"SELECT current_seq FROM generator_sequence WHERE type = ? AND date_str = ? FOR UPDATE";
|
||||
|
||||
if (updated == 0) {
|
||||
// 如果没有记录,则插入初始记录
|
||||
String insertSql = "INSERT IGNORE INTO generator_sequence (type, date_str, current_seq) VALUES (?, ?, 1)";
|
||||
jdbcTemplate.update(insertSql, type, dateStr);
|
||||
List<Integer> result = jdbcTemplate.queryForList(lockAndUpdateSql, Integer.class, type, dateStr);
|
||||
|
||||
if (result.isEmpty()) {
|
||||
// 插入初始值
|
||||
String insertSql = "INSERT INTO generator_sequence (type, date_str, current_seq) VALUES (?, ?, 1)";
|
||||
jdbcTemplate.update(insertSql, type, dateStr);
|
||||
return type + dateStr + "000001";
|
||||
} else {
|
||||
// 获取当前序列号并更新
|
||||
Integer currentSeq = result.get(0);
|
||||
String updateSql = "UPDATE generator_sequence SET current_seq = current_seq + 1 WHERE type = ? AND date_str = ?";
|
||||
jdbcTemplate.update(updateSql, type, dateStr);
|
||||
|
||||
String seqStr = String.format("%06d", currentSeq + 1);
|
||||
return type + dateStr + seqStr;
|
||||
}
|
||||
} catch (CannotAcquireLockException e) {
|
||||
throw new RuntimeException("系统繁忙,请稍后重试", e);
|
||||
}
|
||||
|
||||
// 查询最新的序列号
|
||||
String selectSql = "SELECT current_seq FROM generator_sequence WHERE type = ? AND date_str = ?";
|
||||
Integer currentSeq = jdbcTemplate.queryForObject(selectSql, Integer.class, type, dateStr);
|
||||
|
||||
// 格式化为6位数字
|
||||
String seqStr = String.format("%06d", currentSeq);
|
||||
|
||||
return type + dateStr + seqStr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object execute(JSONObject params, JSONObject formData) {
|
||||
String prefix = params.getString("prefix");
|
||||
Object code = generateCode(prefix);
|
||||
Object code = generateSerialNumber(prefix);
|
||||
log.info("生成业务编号:{}", code);
|
||||
return code;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,163 @@
|
|||
package org.cpte.modules.utils;
|
||||
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.cpte.modules.constant.enums.BaseEnum;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* 枚举工具类
|
||||
*
|
||||
* @Author YouChain: 胡克
|
||||
* @Date 2017/10/10 18:17
|
||||
* @Email huoj@youchain56.com
|
||||
*/
|
||||
public class SmartEnumUtil {
|
||||
|
||||
/**
|
||||
* 校验参数与枚举类比较是否合法
|
||||
*
|
||||
* @param value 参数
|
||||
* @param enumClass 枚举类必须实现BaseEnum接口
|
||||
* @return boolean
|
||||
* @Author 胡克
|
||||
*/
|
||||
public static boolean checkEnum(Object value, Class<? extends BaseEnum> enumClass) {
|
||||
if (null == value) {
|
||||
return false;
|
||||
}
|
||||
return Stream.of(enumClass.getEnumConstants()).anyMatch(e -> e.equalsValue(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个具有唯一array值的数组,每个值不包含在其他给定的数组中。
|
||||
*
|
||||
* @param enumClass
|
||||
* @param exclude
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public static <T extends BaseEnum> List<Object> differenceValueList(Class<? extends BaseEnum> enumClass, T... exclude) {
|
||||
HashSet<Object> valueSet = new HashSet<>();
|
||||
if (exclude != null) {
|
||||
valueSet.addAll(Stream.of(exclude).map(BaseEnum::getValue).collect(Collectors.toSet()));
|
||||
}
|
||||
|
||||
return Stream.of(enumClass.getEnumConstants())
|
||||
.filter(e -> !valueSet.contains(e.getValue()))
|
||||
.map(BaseEnum::getValue)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取枚举类的说明 value : info 的形式
|
||||
*
|
||||
* @param enumClass
|
||||
* @return String
|
||||
*/
|
||||
public static String getEnumDesc(Class<? extends BaseEnum> enumClass) {
|
||||
BaseEnum[] enums = enumClass.getEnumConstants();
|
||||
// value : info 的形式
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (BaseEnum baseEnum : enums) {
|
||||
sb.append(baseEnum.getValue()).append(":").append(baseEnum.getDesc()).append(",");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取与参数相匹配的枚举类实例的 说明
|
||||
*
|
||||
* @param value 参数
|
||||
* @param enumClass 枚举类必须实现BaseEnum接口
|
||||
* @return String 如无匹配枚举则返回null
|
||||
*/
|
||||
public static String getEnumDescByValue(Object value, Class<? extends BaseEnum> enumClass) {
|
||||
if (null == value) {
|
||||
return null;
|
||||
}
|
||||
return Stream.of(enumClass.getEnumConstants())
|
||||
.filter(e -> e.equalsValue(value))
|
||||
.findFirst()
|
||||
.map(BaseEnum::getDesc)
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
public static <T> String getEnumDescByValueList(Collection<T> values, Class<? extends BaseEnum> enumClass) {
|
||||
if (CollectionUtils.isEmpty(values)) {
|
||||
return "";
|
||||
}
|
||||
return Stream.of(enumClass.getEnumConstants()).filter(e -> values.contains(e.getValue())).map(BaseEnum::getDesc).collect(Collectors.joining(","));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据参数获取枚举类的实例
|
||||
*
|
||||
* @param value 参数
|
||||
* @param enumClass 枚举类必须实现BaseEnum接口
|
||||
* @return BaseEnum 无匹配值返回null
|
||||
* @Author 胡克
|
||||
*/
|
||||
public static <T extends BaseEnum> T getEnumByValue(Object value, Class<T> enumClass) {
|
||||
if (null == value) {
|
||||
return null;
|
||||
}
|
||||
return Stream.of(enumClass.getEnumConstants())
|
||||
.filter(e -> e.equalsValue(value))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据实例描述与获取枚举类的实例
|
||||
*
|
||||
* @param desc 参数描述
|
||||
* @param enumClass 枚举类必须实现BaseEnum接口
|
||||
* @return BaseEnum 无匹配值返回null
|
||||
* @Author 胡克
|
||||
*/
|
||||
public static <T extends BaseEnum> T getEnumByDesc(String desc, Class<T> enumClass) {
|
||||
return Stream.of(enumClass.getEnumConstants())
|
||||
.filter(e -> Objects.equals(e.getDesc(), desc))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
|
||||
public static <T extends BaseEnum> T getEnumByName(String name, Class<T> enumClass) {
|
||||
return Stream.of(enumClass.getEnumConstants())
|
||||
.filter(e -> StringUtils.equalsIgnoreCase(e.toString(), name))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据lambda getter/setter 注入
|
||||
*
|
||||
* @param list
|
||||
* @param getter
|
||||
* @param setter
|
||||
* @param enumClass
|
||||
* @param <T>
|
||||
*/
|
||||
public static <T> void inject(List<T> list, Function<T, Integer> getter, BiConsumer<T, String> setter, Class<? extends BaseEnum> enumClass) {
|
||||
if (list == null || list.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
for (T t : list) {
|
||||
Integer enumValue = getter.apply(t);
|
||||
if (enumValue != null) {
|
||||
setter.accept(t, getEnumDescByValue(enumValue, enumClass));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +1,14 @@
|
|||
package org.jeecg.modules.monitor.service;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import org.jeecg.modules.monitor.domain.RedisInfo;
|
||||
import org.jeecg.modules.monitor.exception.RedisConnectException;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* @Description: redis信息service接口
|
||||
|
|
@ -13,42 +16,61 @@ import org.jeecg.modules.monitor.exception.RedisConnectException;
|
|||
*/
|
||||
public interface RedisService {
|
||||
|
||||
/**
|
||||
* 获取 redis 的详细信息
|
||||
*
|
||||
* @return List
|
||||
/**
|
||||
* 获取 redis 的详细信息
|
||||
*
|
||||
* @return List
|
||||
* @throws RedisConnectException
|
||||
*/
|
||||
List<RedisInfo> getRedisInfo() throws RedisConnectException;
|
||||
*/
|
||||
List<RedisInfo> getRedisInfo() throws RedisConnectException;
|
||||
|
||||
/**
|
||||
* 获取 redis key 数量
|
||||
*
|
||||
* @return Map
|
||||
/**
|
||||
* 获取 redis key 数量
|
||||
*
|
||||
* @return Map
|
||||
* @throws RedisConnectException
|
||||
*/
|
||||
Map<String, Object> getKeysSize() throws RedisConnectException;
|
||||
*/
|
||||
Map<String, Object> getKeysSize() throws RedisConnectException;
|
||||
|
||||
/**
|
||||
* 获取 redis 内存信息
|
||||
*
|
||||
* @return Map
|
||||
/**
|
||||
* 获取 redis 内存信息
|
||||
*
|
||||
* @return Map
|
||||
* @throws RedisConnectException
|
||||
*/
|
||||
Map<String, Object> getMemoryInfo() throws RedisConnectException;
|
||||
/**
|
||||
* 获取 报表需要个redis信息
|
||||
* @param type
|
||||
* @return Map
|
||||
* @throws RedisConnectException
|
||||
*/
|
||||
Map<String, JSONArray> getMapForReport(String type) throws RedisConnectException ;
|
||||
*/
|
||||
Map<String, Object> getMemoryInfo() throws RedisConnectException;
|
||||
|
||||
/**
|
||||
* 获取历史性能指标
|
||||
* @return
|
||||
* @author chenrui
|
||||
* @date 2024/5/14 14:57
|
||||
*/
|
||||
Map<String, List<Map<String, Object>>> getMetricsHistory();
|
||||
/**
|
||||
* 获取 报表需要个redis信息
|
||||
*
|
||||
* @param type
|
||||
* @return Map
|
||||
* @throws RedisConnectException
|
||||
*/
|
||||
Map<String, JSONArray> getMapForReport(String type) throws RedisConnectException;
|
||||
|
||||
/**
|
||||
* 获取历史性能指标
|
||||
*
|
||||
* @return
|
||||
* @author chenrui
|
||||
* @date 2024/5/14 14:57
|
||||
*/
|
||||
Map<String, List<Map<String, Object>>> getMetricsHistory();
|
||||
|
||||
|
||||
/**
|
||||
* 删除缓存
|
||||
*
|
||||
* @param key 可以传一个值 或多个
|
||||
*/
|
||||
void delete(String... key);
|
||||
|
||||
void mset(String key, String hashKey, Object value);
|
||||
|
||||
Object mget(String key, String hashKey);
|
||||
|
||||
boolean getLock(String key, long expire);
|
||||
|
||||
void unLock(String key);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package org.jeecg.modules.monitor.service.impl;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
|
|
@ -12,12 +13,17 @@ import org.jeecg.common.util.oConvertUtils;
|
|||
import org.jeecg.modules.monitor.domain.RedisInfo;
|
||||
import org.jeecg.modules.monitor.exception.RedisConnectException;
|
||||
import org.jeecg.modules.monitor.service.RedisService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cglib.beans.BeanMap;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.HashOperations;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.core.ValueOperations;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* Redis 监控信息获取
|
||||
|
|
@ -28,9 +34,19 @@ import lombok.extern.slf4j.Slf4j;
|
|||
@Slf4j
|
||||
public class RedisServiceImpl implements RedisService {
|
||||
|
||||
@Autowired
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
@Resource
|
||||
private RedisConnectionFactory redisConnectionFactory;
|
||||
|
||||
|
||||
@Resource
|
||||
private HashOperations<String, String, Object> redisHashOperations;
|
||||
|
||||
@Resource
|
||||
private ValueOperations<String, String> redisValueOperations;
|
||||
|
||||
/**
|
||||
* redis信息
|
||||
*/
|
||||
|
|
@ -140,6 +156,37 @@ public class RedisServiceImpl implements RedisService {
|
|||
return REDIS_METRICS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String... key) {
|
||||
if (key != null && key.length > 0) {
|
||||
if (key.length == 1) {
|
||||
redisTemplate.delete(key[0]);
|
||||
} else {
|
||||
redisTemplate.delete((Collection<String>) CollectionUtils.arrayToList(key));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mset(String key, String hashKey, Object value) {
|
||||
redisHashOperations.put(key, hashKey, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object mget(String key, String hashKey) {
|
||||
return redisHashOperations.get(key, hashKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getLock(String key, long expire) {
|
||||
return redisValueOperations.setIfAbsent(key, String.valueOf(System.currentTimeMillis()), expire, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unLock(String key) {
|
||||
redisValueOperations.getOperations().delete(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录近一小时redis监控数据 <br/>
|
||||
* 60s一次,,记录存储keysize和内存
|
||||
|
|
|
|||
Loading…
Reference in New Issue