入库单接收、AGV任务生成、下发、上报 TES任务生成、下发、上报

main
HUOJIN\92525 2025-11-13 16:56:03 +08:00
parent de2ca95e1b
commit 6972fccd1c
46 changed files with 1583 additions and 293 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -15,6 +15,7 @@ public interface IAgvTaskService extends IService<AgvTask> {
/**
* agvTask
*
* @param businessDetailId ID
* @param status
* @param carrierCode
* @param startCode
@ -23,6 +24,6 @@ public interface IAgvTaskService extends IService<AgvTask> {
* @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);
}

View File

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

View File

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

View File

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

View File

@ -1,12 +1,12 @@
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:
@ -15,5 +15,21 @@ import org.cpte.modules.receive.entity.Asn;
* @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);
}

View File

@ -3,6 +3,7 @@ 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;
@ -13,5 +14,31 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
* @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);
}

View File

@ -5,6 +5,8 @@ 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
@ -12,5 +14,21 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
* @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);
}

View File

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

View File

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

View File

@ -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 + "】库区,请维护");
}

View File

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

View File

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

View File

@ -27,6 +27,9 @@ import java.util.Objects;
@Service
public class StockServiceImpl extends ServiceImpl<StockMapper, Stock> implements IStockService {
@Autowired
private StockMapper stockMapper;
/**
*
*
@ -35,9 +38,7 @@ 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 + "】容器,请维护");
}
@ -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);
}
/**

View File

@ -0,0 +1,6 @@
package org.cpte.modules.constant;
public interface CommonConstant {
//入库输送线任务均衡索引
String RK_DOCK_TASK_INDEX = "rk_dock_task_index";
}

View File

@ -11,6 +11,8 @@ public enum AreaTypeEnum {
CTQ("CTQ", "拆托区"),
CPCCQ("CPCCQ", "成品存储区"),
RK_DOCK("RK_DOCK", "入库输送线接驳口"),
CK_DOCK("CK_DOCK", "出库输送线接驳口"),

View File

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

View File

@ -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", "&nbsp;&nbsp;");
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;
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,6 +2,11 @@ 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:
@ -10,5 +15,15 @@ import com.baomidou.mybatisplus.extension.service.IService;
* @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);
}

View File

@ -1,11 +1,20 @@
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:
@ -15,5 +24,29 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
*/
@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;
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 {
// 判断起点无任务才允许下发
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);
}

View File

@ -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("添加成功!");

View File

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

View File

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

View File

@ -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;
@ -49,8 +50,9 @@ public interface IAsnService extends IService<Asn> {
/**
*
*
* @param stockCode
* @param asnDetailId ID
* @param pointCode
*/
void receiveGoods(String stockCode);
void receiveGoods(String asnDetailId, String pointCode);
}

View File

@ -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)
@ -158,16 +160,29 @@ public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnS
@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);
}

View File

@ -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;
@ -49,16 +56,21 @@ public class ISaiWmsServiceImpl implements ISaiWmsService {
@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());
//获取输送线工作台点位,均衡分配点位任务-轮询方式
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
if (AsnOrderTypeEnum.PRODUCT.getValue().equals(createAsn.getOrderType())) {
//创建AGV任务
iAgvTaskService.createAgvTask(AgvStatusEnum.CREATED.getValue(), stock.getStockCode(), srcPoint.getPointCode(), dstPoint.getPointCode(), null, BusinessTypeEnum.INBOUND.getValue(),AgvVendorEnum.HIK.getValue());
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())

View File

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

View File

@ -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) {
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)";
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);
}
// 查询最新的序列号
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 + "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);
}
}
@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;
}

View File

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

View File

@ -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: redisservice
@ -36,8 +39,10 @@ public interface RedisService {
* @throws RedisConnectException
*/
Map<String, Object> getMemoryInfo() throws RedisConnectException;
/**
* redis
*
* @param type
* @return Map
* @throws RedisConnectException
@ -46,9 +51,26 @@ public interface RedisService {
/**
*
*
* @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);
}

View File

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