仓库管理修改

liweidong
wusiyu 2 days ago
parent 155f0bc501
commit 67e7b15e2c
  1. 10
      blade-service-api/blade-wms-api/src/main/java/org/springblade/wms/pojo/entity/StGlassCakeOut.java
  2. 4
      blade-service/blade-scheduling/src/main/java/org/springblade/scheduling/scheduling/service/impl/WorkOrderServiceImpl.java
  3. 3
      blade-service/blade-wms/src/main/java/org/springblade/wms/mapper/StGlassCakeOutMapper.java
  4. 6
      blade-service/blade-wms/src/main/java/org/springblade/wms/mapper/StGlassCakeOutMapper.xml
  5. 132
      blade-service/blade-wms/src/main/java/org/springblade/wms/service/impl/StGlassCakeOutServiceImpl.java
  6. 32
      blade-service/blade-wms/src/main/java/org/springblade/wms/service/impl/StRealtimeStockServiceImpl.java

@ -33,6 +33,11 @@ public class StGlassCakeOut extends TenantEntity {
*/
@Schema(description = "出库凭证信息")
private Long sirId;
/**
* 部件生产单号
*/
@TableField(value = "YO_CODE")
private String yoCode;
/**
* 车间订单号
*/
@ -128,6 +133,11 @@ public class StGlassCakeOut extends TenantEntity {
*/
@Schema(description = "备注")
private String memo;
/**
* 领料人ID
*/
@Schema(description = "领料人ID")
private Long picker;
/**
* 是否印字
*/

@ -975,7 +975,7 @@ public class WorkOrderServiceImpl extends BaseServiceImpl<WorkOrderMapper, WorkO
log.info("当前订单:" + order.getId() + "结束!");
}
if(CollectionUtils.isNotEmpty(glassCakeOutList)){
glassCakeOutClient.batchGeneratePreOutOrder(glassCakeOutList);
// glassCakeOutClient.batchGeneratePreOutOrder(glassCakeOutList);
}
/* if (CollectionUtils.isNotEmpty(workOrderList)) {
this.sendWorkOrderToOldMes(workOrderList);
@ -1953,7 +1953,7 @@ public class WorkOrderServiceImpl extends BaseServiceImpl<WorkOrderMapper, WorkO
glassDto.setMaterialNo("2");
glassDto.setThickness("3");
list.add(glassDto);
glassCakeOutClient.batchGeneratePreOutOrder(list);
// glassCakeOutClient.batchGeneratePreOutOrder(list);
}
public Double calPersonHours(Integer qty,YieldOrderCraftEntity craft,PartEntity part){

@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.apache.ibatis.annotations.Param;
import org.springblade.desk.order.pojo.entity.YieldOrder;
import org.springblade.desk.produce.pojo.entity.WorkOrder;
import org.springblade.wms.excel.StGlassCakeOutExcel;
import org.springblade.wms.pojo.entity.StGlassCakeOut;
@ -46,5 +47,7 @@ public interface StGlassCakeOutMapper extends BaseMapper<StGlassCakeOut> {
StGlassCakeOut getBySirId(Long sirId);
WorkOrder getByWoCode(String cardNo);
YieldOrder getByYoCode(String cardNo);
}

@ -204,4 +204,10 @@
WHERE card_no = #{cardNo}
</select>
<select id="getByYoCode" resultType="org.springblade.desk.order.pojo.entity.YieldOrder">
SELECT *
FROM MES_YIELD_ORDER
WHERE card_no = #{cardNo}
</select>
</mapper>

@ -12,7 +12,6 @@ import org.springblade.desk.dashboard.feign.IPartClient;
import org.springblade.desk.dashboard.pojo.entity.DsPartEntity;
import org.springblade.desk.dashboard.pojo.entity.DsPartRelationEntity;
import org.springblade.desk.order.pojo.entity.YieldOrder;
import org.springblade.desk.produce.pojo.entity.WorkOrder;
import org.springblade.wms.excel.StGlassCakeOutExcel;
import org.springblade.wms.mapper.StGlassCakeOutMapper;
import org.springblade.wms.mapper.StOtherReceiptRecordMapper;
@ -56,14 +55,7 @@ public class StGlassCakeOutServiceImpl extends BaseServiceImpl<StGlassCakeOutMap
StOtherReceiptRecordMapper stOtherReceiptRecordMapper;
@Resource
IPartClient partClient;
// @Resource
// IDsPartService dsPartService;
// @Resource
// IDsPartRelationService partRelationService;
// @Resource
// IWorkOrderService workOrderService;
// @Resource
// WorkOrderMapper workOrderMapper;
@Override
public IPage<StGlassCakeOutVO> selectStGlassCakeOutPage(IPage<StGlassCakeOutVO> page, StGlassCakeOutVO stGlassCakeOut) {
return page.setRecords(baseMapper.selectStGlassCakeOutPage(page, stGlassCakeOut));
@ -84,24 +76,24 @@ public class StGlassCakeOutServiceImpl extends BaseServiceImpl<StGlassCakeOutMap
// Long userId = Long.valueOf(user.getUserId());
Date now = new Date();
WorkOrder workOrder = stOtherReceiptRecordMapper.getByWoCode(dto.getWoCode());
if (workOrder == null) {
throw new RuntimeException("根据工单编号【" + dto.getWoCode() + "】未查询到工单信息");
}
Long yoId = workOrder.getYoId();
if (yoId == null) {
throw new RuntimeException("工单【" + dto.getWoCode() + "】未查到生产订单ID");
}
// WorkOrder workOrder = stOtherReceiptRecordMapper.getByWoCode(dto.getWoCode());
// if (workOrder == null) {
// throw new RuntimeException("根据工单编号【" + dto.getWoCode() + "】未查询到工单信息");
// }
//
// Long yoId = workOrder.getYoId();
// if (yoId == null) {
// throw new RuntimeException("工单【" + dto.getWoCode() + "】未查到生产订单ID");
// }
YieldOrder yieldOrder = stOtherReceiptRecordMapper.getByYoId(workOrder.getYoId());
YieldOrder yieldOrder = stOtherReceiptRecordMapper.getByYoId(dto.getYoCode());
if (yieldOrder == null) {
throw new RuntimeException("根据生产订单ID【" + yoId + "】未查询到生产订单信息");
throw new RuntimeException("根据生产订单ID【" + dto.getYoCode() + "】未查询到生产订单信息");
}
DsPartEntity partOne = partClient.getPart(workOrder.getPartCode(),yieldOrder.getPartVersion());
DsPartEntity partOne = partClient.getPart(yieldOrder.getPartCode(),yieldOrder.getPartVersion());
if (partOne == null) {
throw new RuntimeException("根据零件编号【" + workOrder.getPartCode() + "】未查询到零件信息");
throw new RuntimeException("根据零件编号【" + yieldOrder.getPartCode() + "】未查询到零件信息");
}
List<DsPartRelationEntity> partRelationEntityList = partClient.getSubPart(partOne.getId());
@ -191,32 +183,79 @@ public class StGlassCakeOutServiceImpl extends BaseServiceImpl<StGlassCakeOutMap
// // ========== 查询库存量最大的库存记录 ==========
// StRealtimeStock maxStock = stRealtimeStockService.getOne(stockQuery);
StRealtimeStock maxStock = stRealtimeStockMapper.selectMaxUsableStockByCakeAttr(isPrint, powderWeight, materialNo, thickness, goodsCode);
// StRealtimeStock maxStock = stRealtimeStockMapper.selectMaxUsableStockByCakeAttr(isPrint, powderWeight, materialNo, thickness, goodsCode);
// if (maxStock == null) {
// System.out.println("玻璃饼[编码:" + goodsCode + "]未查询到匹配库存,无法生成预出库");
// continue;
// }
Double requireQty = yieldOrder.getYpQty()*glassCake.getQuota();
System.out.println("玻璃饼编码:" + goodsCode + ",总需求:" + requireQty);
// =====================【校验】总可用库存是否足够 =====================
List<StRealtimeStock> candidateStockList = new ArrayList<>();
double totalUsable = 0.0;
// 循环查询所有可用库存,累加可用量,直到凑够 or 无库存
while (true) {
StRealtimeStock maxStock = stRealtimeStockMapper.selectMaxUsableStockByCakeAttr(
isPrint, powderWeight, materialNo, thickness, goodsCode);
if (maxStock == null) {
System.out.println("玻璃饼[编码:" + goodsCode + "]未查询到匹配库存,无法生成预出库");
break; // 没有更多库存了
}
double occupyQty = Optional.ofNullable(maxStock.getOccupyQuantity()).orElse(0D);
double usableQty = maxStock.getQuantity() - occupyQty;
if (usableQty <= 0) {
break;
}
candidateStockList.add(maxStock);
totalUsable += usableQty;
if (totalUsable >= requireQty) {
break; // 已凑够
}
}
// ===================== 不够则直接抛异常,不生成任何单据 =====================
if (totalUsable < requireQty - 0.001) {
System.out.println("玻璃饼[编码:" + goodsCode + "]库存不足,跳过生成!需求:" + requireQty + ",可分配:" + totalUsable);
// 跳过当前这条,继续下一条玻璃饼
continue;
}
Double requireQty = workOrder.getMakeQty()*glassCake.getQuota();
// ===================== 走到这里 = 库存足够,开始真正生成预出库 =====================
double remainingQty = requireQty;
for (StRealtimeStock maxStock : candidateStockList) {
if (remainingQty <= 0.001) {
break;
}
double occupyQty = Optional.ofNullable(maxStock.getOccupyQuantity()).orElse(0D);
double usableQty = maxStock.getQuantity() - occupyQty;
double actualTake = Math.min(usableQty, remainingQty);
// StRealtimeStockLock stockLock = stRealtimeStockMapper.selectByRlsId(maxStock.getId());
// ========== 库存充足性校验:可用量 >= 预出库目标数量才生成 ==========
Double stockQty;
if (maxStock != null && maxStock.getOccupyQuantity() != null) {
stockQty = maxStock.getQuantity() - maxStock.getOccupyQuantity();
} else {
stockQty = maxStock.getQuantity();
}
if (stockQty == null || stockQty.compareTo(requireQty) < 0) {
throw new ServiceException(String.format("工作订单号:%s,玻璃饼号: %s,库存不足无法生成预出库单!",
dto.getWoCode(), maxStock.getGoodsId()));
}
// Double stockQty;
// if (maxStock != null && maxStock.getOccupyQuantity() != null) {
// stockQty = maxStock.getQuantity() - maxStock.getOccupyQuantity();
// } else {
// stockQty = maxStock.getQuantity();
// }
// if (stockQty == null || stockQty.compareTo(requireQty) < 0) {
// throw new ServiceException(String.format("工作订单号:%s,玻璃饼号: %s,库存不足无法生成预出库单!",
// dto.getWoCode(), maxStock.getGoodsId()));
// }
// ========== 库存充足:构建该玻璃饼的预出库实体 ==========
StGlassCakeOut preOutStock = new StGlassCakeOut();
// 关联玻璃饼信息
preOutStock.setWoCode(workOrder.getWoCode());
// preOutStock.setWoCode(workOrder.getWoCode());
preOutStock.setYoCode(yieldOrder.getYoCode());
preOutStock.setCardNo(dto.getCardNo());
preOutStock.setQuantity(workOrder.getMakeQty());
preOutStock.setQuantity(yieldOrder.getYpQty());
preOutStock.setPartCode(partOne.getPartCode());
preOutStock.setPartName(partOne.getPartName());
@ -251,16 +290,24 @@ public class StGlassCakeOutServiceImpl extends BaseServiceImpl<StGlassCakeOutMap
// 添加到预出库列表
preOutStockList.add(preOutStock);
System.out.println("玻璃饼[编码:" + goodsCode + "]库存充足,已构建预出库信息,库存ID:" + maxStock.getId());
maxStock.setOccupyQuantity(requireQty);
// maxStock.setOccupyQuantity(requireQty);
// stRealtimeStockService.updateById(maxStock);
double newOccupy = occupyQty + actualTake;
maxStock.setOccupyQuantity(newOccupy);
stRealtimeStockService.updateById(maxStock);
StRealtimeStockLock lock = new StRealtimeStockLock();
lock.setId(IdUtil.getSnowflake().nextId());
lock.setRlsId(maxStock.getId());
lock.setWoNo(preOutStock.getWoCode());
lock.setOccupyQuantity(preOutStock.getRequireQty());
// lock.setOccupyQuantity(preOutStock.getRequireQty());
// 锁本次扣的数量
lock.setOccupyQuantity(actualTake);
lock.setStatus(0);
stRealtimeStockMapper.insertStockLock(lock);
remainingQty -= actualTake;
}
System.out.println("玻璃饼[编码:" + goodsCode + "] 预出库全部完成!");
}
}
@ -364,8 +411,9 @@ public class StGlassCakeOutServiceImpl extends BaseServiceImpl<StGlassCakeOutMap
StGlassCakeOutDTO dto = new StGlassCakeOutDTO();
dto.setCardNo(cardNo);
WorkOrder workOrder = baseMapper.getByWoCode(dto.getCardNo());
dto.setWoCode(workOrder.getWoCode());
// WorkOrder workOrder = baseMapper.getByWoCode(dto.getCardNo());
YieldOrder yieldOrder = baseMapper.getByYoCode(dto.getCardNo());
dto.setYoCode(yieldOrder.getYoCode());
List<StGlassCakeOut> stGlassCakeOutList = this.generatePreOutOrder(dto);
if (!CollectionUtils.isEmpty(stGlassCakeOutList)) {
@ -459,6 +507,7 @@ public class StGlassCakeOutServiceImpl extends BaseServiceImpl<StGlassCakeOutMap
outEntity.setOutUsers(userId); // 出库人ID
outEntity.setOutTime(nowDate); // 实际出库时间
outEntity.setCurStatus(1L); // 状态变更:1=已出库
outEntity.setPicker(param.getPicker());
outEntity.setUpdateUser(userId);
outEntity.setUpdateTime(nowDate);
this.updateById(outEntity);
@ -497,6 +546,7 @@ public class StGlassCakeOutServiceImpl extends BaseServiceImpl<StGlassCakeOutMap
inoutRecord.setWoCode(outEntity.getWoCode());
inoutRecord.setUserId(userId);
// 租户/创建人基础字段(继承TenantEntity)
inoutRecord.setUserId(param.getPicker());
inoutRecord.setCreateUser(userId);
inoutRecord.setCreateTime(nowDate);
inoutRecord.setUpdateUser(userId);

@ -19,11 +19,13 @@ import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.desk.common.feign.IMesNotifyMessageClient;
import org.springblade.desk.common.pojo.entity.MesNotifyMessageEntity;
import org.springblade.desk.order.feign.IMoldDemandClient;
import org.springblade.desk.order.feign.IOrderClient;
import org.springblade.wms.excel.StRealtimeStockExcel;
import org.springblade.wms.mapper.*;
import org.springblade.wms.pojo.entity.*;
import org.springblade.wms.pojo.vo.*;
import org.springblade.wms.service.*;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
@ -35,6 +37,7 @@ import java.io.ByteArrayOutputStream;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
@ -74,6 +77,17 @@ public class StRealtimeStockServiceImpl extends BaseServiceImpl<StRealtimeStockM
private IMesNotifyMessageClient mesNotifyMessageClient;
@Resource
private IMoldDemandClient moldDemandClient;
@Resource
private IOrderClient orderClient;
@Resource
private RedisTemplate<String, Object> redisTemplate;
// 7天过期时间(秒)
private static final long EXPIRE_SEVEN_DAYS = 7 * 24 * 60 * 60;
// Redis 键前缀
private static final String REDIS_KEY_MOLD = "stock:reissue:limit:mold:";
private static final String REDIS_KEY_GLASS = "stock:reissue:limit:glass:";
@Override
@ -688,7 +702,7 @@ public class StRealtimeStockServiceImpl extends BaseServiceImpl<StRealtimeStockM
notifyMessage.setReceiveUserId(AuthUtil.getUserId());
mesNotifyMessageClient.save(notifyMessage);
// 执行玻璃饼类物料出库补制
// generateGlassPieOutReissueOrder(goodsId, outQuantity);
orderClient.createBlbYieldOrder(stGoods.getGoodsCode(),stGoods.getMinNum(),"仓库补制计划");
} else {
reissueMsg = String.format("物料编码:%s 类别为%s,暂未配置【物料出库】补制逻辑,跳过补制",
@ -717,15 +731,12 @@ public class StRealtimeStockServiceImpl extends BaseServiceImpl<StRealtimeStockM
reissueMsg = String.format("物料编码:%s 类别为%s,当前库存:%.2f ≥ 最低库存:%.2f,无需触发【最低库存】补制",
goodsCode, goodsCategoryName, currentStock, minStock);
log.info(reissueMsg);
MesNotifyMessageEntity notifyMessage = new MesNotifyMessageEntity();
notifyMessage.setContent(reissueMsg);
notifyMessage.setReceiveUserId(AuthUtil.getUserId());
mesNotifyMessageClient.save(notifyMessage);
return reissueMsg;
}
// 按物料类别执行专属补制方法
if ("模具类".equals(goodsCategoryName)) {
String key = REDIS_KEY_MOLD + goodsCode;
reissueMsg = String.format("物料编码:%s 名称:%s(类别:%s)触发【最低库存】补制!当前库存:%.2f,最低库存:%.2f,开始生成模具采购计划",
goodsCode, stGoods.getGoodsName(), goodsCategoryName, currentStock, minStock);
log.info(reissueMsg);
@ -735,8 +746,11 @@ public class StRealtimeStockServiceImpl extends BaseServiceImpl<StRealtimeStockM
mesNotifyMessageClient.save(notifyMessage);
// 执行模具类最低库存补制
moldDemandClient.saveMoldDemand(stGoods.getGoodsCode());
// 存入Redis,7天过期
redisTemplate.opsForValue().set(key, "1", EXPIRE_SEVEN_DAYS, TimeUnit.SECONDS);
} else if ("玻璃饼".equals(goodsCategoryName)) {
String key = REDIS_KEY_GLASS + goodsCode;
reissueMsg = String.format("物料编码:%s 名称:%s(类别:%s)触发【最低库存】补制!当前库存:%.2f,最低库存:%.2f,开始生成玻璃饼生产订单",
goodsCode, stGoods.getGoodsName(), goodsCategoryName, currentStock, minStock);
log.info(reissueMsg);
@ -745,16 +759,14 @@ public class StRealtimeStockServiceImpl extends BaseServiceImpl<StRealtimeStockM
notifyMessage.setReceiveUserId(AuthUtil.getUserId());
mesNotifyMessageClient.save(notifyMessage);
// 执行玻璃饼类最低库存补制
// generateGlassPieMinStockProductionOrder(goodsId, currentStock, minStock);
orderClient.createBlbYieldOrder(goodsCode,stGoods.getMinNum(),"仓库补制计划");
// 存入Redis,7天过期
redisTemplate.opsForValue().set(key, "1", EXPIRE_SEVEN_DAYS, TimeUnit.SECONDS);
} else {
reissueMsg = String.format("物料编码:%s 类别为%s,当前库存:%.2f < 最低库存:%.2f,但暂未配置【最低库存】补制逻辑,跳过补制",
goodsCode, goodsCategoryName, currentStock, minStock);
log.info(reissueMsg);
MesNotifyMessageEntity notifyMessage = new MesNotifyMessageEntity();
notifyMessage.setContent(reissueMsg);
notifyMessage.setReceiveUserId(AuthUtil.getUserId());
mesNotifyMessageClient.save(notifyMessage);
}
return reissueMsg;
}

Loading…
Cancel
Save