feat(wms): 实现中心领料功能
- 新增中心领料单确认出库功能 - 实现根据预留号获取订单项信息 - 添加物料出库推荐批次功能 - 优化库存查询和推荐逻辑 - 完善中心领料相关的数据结构和接口
This commit is contained in:
parent
3671ba2232
commit
39a8bbac58
|
|
@ -1,17 +1,33 @@
|
|||
package com.nflg.wms.admin.service;
|
||||
|
||||
import com.nflg.wms.common.pojo.dto.SapImportResultDTO;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import com.lowagie.text.ImgTemplate;
|
||||
import com.nflg.wms.common.pojo.dto.*;
|
||||
import com.nflg.wms.common.pojo.qo.C_MaterialOutboundQO;
|
||||
import com.nflg.wms.common.pojo.qo.CommendationItemQO;
|
||||
import com.nflg.wms.common.pojo.vo.C_MaterialOutboundSAPItemVO;
|
||||
import com.nflg.wms.common.pojo.vo.C_MaterialOutboundreCommendationItemVO;
|
||||
import com.nflg.wms.common.util.UserUtil;
|
||||
import com.nflg.wms.repository.entity.WmsCenterOutbound;
|
||||
import com.nflg.wms.repository.entity.WmsCenterOutboundItem;
|
||||
import com.nflg.wms.repository.entity.WmsCenterOutboundScan;
|
||||
import com.nflg.wms.repository.entity.WmsInventory;
|
||||
import com.nflg.wms.repository.service.IWmsCenterOutboundItemService;
|
||||
import com.nflg.wms.repository.service.IWmsCenterOutboundScanService;
|
||||
import com.nflg.wms.repository.service.IWmsCenterOutboundService;
|
||||
import com.nflg.wms.repository.service.IWmsInventoryService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.poi.hssf.record.PageBreakRecord;
|
||||
import org.aspectj.weaver.Utils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
public class CenterOutboundControllerService {
|
||||
|
|
@ -27,16 +43,189 @@ public class CenterOutboundControllerService {
|
|||
@Resource
|
||||
private SapService sapService;
|
||||
|
||||
@Resource
|
||||
private IWmsInventoryService wmsInventoryService;
|
||||
|
||||
@Resource
|
||||
private BasdeSerialNumberControllerService basdeSerialNumberControllerService;
|
||||
|
||||
/**
|
||||
* 根据预留号获取订单项信息
|
||||
*
|
||||
* @param reservedNumber 预留号
|
||||
* @return 订单项信息列表
|
||||
*/
|
||||
public List<C_MaterialOutboundSAPItemVO> getOrderItem(String reservedNumber) {
|
||||
// 调用SAP服务获取物料出库查询数据
|
||||
C_MaterialOutboundQueryDTO dto = sapService.zwm00_MB026(reservedNumber);
|
||||
if (Objects.isNull(dto) || Objects.isNull(dto.getItems()) || CollectionUtil.isEmpty(dto.getItems()))
|
||||
return Collections.emptyList();
|
||||
|
||||
// 获取仓位信息映射
|
||||
Map<String, SAPSyncFromDTO> warehouseMap = getBinNos(dto.getItems());
|
||||
|
||||
List<C_MaterialOutboundSAPItemVO> vos = new ArrayList<>();
|
||||
dto.getItems().forEach(item -> {
|
||||
// 构造仓库映射key
|
||||
String key = item.getResbWerks() + "_" + item.getResbMatnr() + "_" + item.getResbLgort();
|
||||
SAPSyncFromDTO warehouse = warehouseMap.get(key);
|
||||
|
||||
// 转换为VO对象
|
||||
C_MaterialOutboundSAPItemVO vo = new C_MaterialOutboundSAPItemVO();
|
||||
vo.setReservedNumberId(item.getResbRsnum())
|
||||
.setMaterialNo(item.getResbMatnr())
|
||||
.setMaterialDesc(item.getMaktx())
|
||||
.setUnit(item.getResbMeins())
|
||||
.setFactory(item.getResbWerks())
|
||||
.setQty(item.getWqyls())
|
||||
.setWarehouseNumber(item.getResbLgort())
|
||||
.setBinNos(Objects.isNull(warehouse) ? "" : warehouse.getBinNos());
|
||||
|
||||
// 获取推荐项信息
|
||||
List<C_MaterialOutboundreCommendationItemVO> recommendationItems = getCommendationItems(new CommendationItemQO()
|
||||
.setMaterialNo(item.getResbMatnr())
|
||||
.setFactory(item.getResbWerks())
|
||||
.setWarehouseNumber(item.getResbLgort())
|
||||
.setQty(item.getWqyls())
|
||||
);
|
||||
if (Objects.nonNull(recommendationItems))
|
||||
vo.setRecommendationItems(recommendationItems);
|
||||
|
||||
vos.add(vo);
|
||||
});
|
||||
return vos;
|
||||
}
|
||||
|
||||
|
||||
private Map<String, SAPSyncFromDTO> getBinNos(List<C_MaterialOutboundItemQueryDTO> sapItems) {
|
||||
// 提取并去重所有不为空的工厂编码(ResbWerks)
|
||||
List<String> distinctResbWerks = sapItems.stream()
|
||||
.map(C_MaterialOutboundItemQueryDTO::getResbWerks)
|
||||
.filter(Objects::nonNull)
|
||||
.distinct()
|
||||
.toList();
|
||||
|
||||
// 存储所有工厂对应的仓库信息
|
||||
List<SAPSyncFromDTO> allWarehouse = new ArrayList<>();
|
||||
|
||||
// 遍历每个工厂,获取其对应的仓库和物料信息
|
||||
for (String werks : distinctResbWerks) {
|
||||
// 筛选出当前工厂的所有物料退货项
|
||||
List<C_MaterialOutboundItemQueryDTO> filteredItems = sapItems.stream()
|
||||
.filter(item -> werks.equals(item.getResbWerks()))
|
||||
.toList();
|
||||
|
||||
// 收集当前工厂下所有的仓库编号和物料编号
|
||||
List<String> warehouseNos = new ArrayList<>();
|
||||
List<String> materialNos = new ArrayList<>();
|
||||
|
||||
for (C_MaterialOutboundItemQueryDTO item : filteredItems) {
|
||||
if (item.getResbLgort() != null) {
|
||||
warehouseNos.add(item.getResbLgort());
|
||||
}
|
||||
if (item.getResbMatnr() != null) {
|
||||
materialNos.add(item.getResbMatnr());
|
||||
}
|
||||
}
|
||||
// 调用SAP服务获取仓库详细信息
|
||||
List<SAPSyncFromDTO> warehouseList = sapService.zwm3A01(werks, warehouseNos, materialNos, null, null);
|
||||
if (CollectionUtil.isNotEmpty(warehouseList)) {
|
||||
allWarehouse.addAll(warehouseList);
|
||||
}
|
||||
|
||||
}
|
||||
// 构建缓存 Map 提高查找效率
|
||||
Map<String, SAPSyncFromDTO> warehouseMap = allWarehouse.stream()
|
||||
.collect(Collectors.toMap(
|
||||
w -> w.getFactoryNo() + "_" + w.getMaterialNo() + "_" + w.getWarehouseNo(),
|
||||
Function.identity(),
|
||||
(existing, replacement) -> existing
|
||||
));
|
||||
return warehouseMap;
|
||||
}
|
||||
|
||||
|
||||
public void confirmOutbound(C_MaterialOutboundQO request) {
|
||||
if (Objects.isNull(request) || Objects.isNull(request.getItems()) || CollectionUtil.isEmpty(request.getItems()))
|
||||
return;
|
||||
//首先要保存SAP的信息
|
||||
C_MaterialOutboundDTO outboundDTO = sapService.ZWM00_MB115(request);
|
||||
|
||||
Long outBoundId = IdUtil.getSnowflakeNextId();
|
||||
String orderNumber = basdeSerialNumberControllerService.generateSerialNumber(1);
|
||||
|
||||
WmsCenterOutbound wmsCenterOutbound = new WmsCenterOutbound()
|
||||
.setId(outBoundId)
|
||||
.setOrderNumber(orderNumber)
|
||||
.setReservedNumber(request.getResbRsNum())
|
||||
.setMaterialDoc(outboundDTO.getEMblnr())
|
||||
.setMaterialDocYear(outboundDTO.getEMJahr())
|
||||
.setCreateTime(LocalDateTime.now())
|
||||
.setCreateUserName(UserUtil.getUserName())
|
||||
.setCreateUserId(UserUtil.getUserId())
|
||||
.setWorkstation(request.getRkpfWempf());
|
||||
|
||||
List<WmsCenterOutboundItem> wmsCenterOutboundItems = new ArrayList<>();
|
||||
List<WmsCenterOutboundScan> wmsCenterOutboundScans = new ArrayList<>();
|
||||
request.getItems().forEach(item -> {
|
||||
Long itemId = IdUtil.getSnowflakeNextId();
|
||||
WmsCenterOutboundItem wmsCenterOutboundItem = new WmsCenterOutboundItem()
|
||||
.setId(itemId)
|
||||
.setOrderId(outBoundId)
|
||||
.setMaterialNo(item.getResbMatnr())
|
||||
.setMaterialDesc(item.getMaktx())
|
||||
.setUnit(item.getResbMeins())
|
||||
.setFactory(item.getResbWerks())
|
||||
.setQty(item.getResbErfmg())
|
||||
.setWarehouseNumber(item.getResbLgort())
|
||||
.setReservedNumberId(item.getResbRspos());
|
||||
|
||||
if (CollectionUtil.isNotEmpty(item.getScanCodes())) {
|
||||
item.getScanCodes().forEach(scanCode -> {
|
||||
WmsCenterOutboundScan wmsCenterOutboundScan = new WmsCenterOutboundScan()
|
||||
.setId(IdUtil.getSnowflakeNextId())
|
||||
.setItemId(itemId)
|
||||
.setCodeId(scanCode.getCodeId())
|
||||
.setCodeNum(scanCode.getCodeNum())
|
||||
.setBatchNumber(scanCode.getBatchNumber())
|
||||
.setSerialNumber(scanCode.getSerialNumber());
|
||||
});
|
||||
}
|
||||
});
|
||||
wmsCenterOutboundService.confirmOutbound(wmsCenterOutbound, wmsCenterOutboundItems, wmsCenterOutboundScans);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据推荐条件获取物料出库推荐批次项列表
|
||||
*
|
||||
* @param request 推荐项查询条件对象,包含物料编号、工厂、仓库编号和需求数量等信息
|
||||
* @return 物料出库推荐项VO列表,包含推荐的批次号和推荐数量;如果无匹配库存则返回空列表
|
||||
*/
|
||||
public List<C_MaterialOutboundreCommendationItemVO> getCommendationItems(CommendationItemQO request) {
|
||||
// 查询符合条件的库存记录:物料号、工厂、仓库匹配且数量大于0的记录,按批次号升序排列
|
||||
List<WmsInventory> inventories = wmsInventoryService.lambdaQuery()
|
||||
.eq(WmsInventory::getMaterialNo, request.getMaterialNo())
|
||||
.eq(WmsInventory::getFactoryNo, request.getFactory())
|
||||
.eq(WmsInventory::getWarehouseNo, request.getWarehouseNumber())
|
||||
.gt(WmsInventory::getNum, 0)
|
||||
.orderByAsc(WmsInventory::getBatchNumber)
|
||||
.list();
|
||||
if (Objects.isNull(inventories) || CollectionUtil.isEmpty(inventories))
|
||||
return Collections.emptyList();
|
||||
|
||||
List<C_MaterialOutboundreCommendationItemVO> vos = new ArrayList<>();
|
||||
BigDecimal qty = request.getQty();
|
||||
// 遍历库存记录,按批次号顺序推荐出库批次,直到满足需求数量
|
||||
for (WmsInventory inventory : inventories) {
|
||||
qty = qty.subtract(inventory.getNum());
|
||||
C_MaterialOutboundreCommendationItemVO vo = new C_MaterialOutboundreCommendationItemVO();
|
||||
vo.setRecommendationBatchCode(inventory.getBatchNumber());
|
||||
// 如果剩余需求数量小于等于0,说明已满足需求,推荐数量为剩余需求数量;否则推荐当前批次的全部数量
|
||||
vo.setRecommendationBatchNum(qty.compareTo(BigDecimal.ZERO) <= 0 ? qty : inventory.getNum());
|
||||
vos.add(vo);
|
||||
if (qty.compareTo(BigDecimal.ZERO) <= 0)
|
||||
break;
|
||||
}
|
||||
return vos;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,5 +17,5 @@ public class C_MaterialOutboundDTO {
|
|||
private String eMJahr;
|
||||
|
||||
//中心退库的物料详情信息
|
||||
private C_MaterialOutboundQO requestQO;
|
||||
// private C_MaterialOutboundQO requestQO;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import java.util.List;
|
|||
@Accessors(chain = true)
|
||||
public class C_MaterialOutboundQueryDTO {
|
||||
private String resbRsnum;
|
||||
|
||||
// 预留项目号 RKPF-WEMPF
|
||||
private String rkpfWempf;
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,11 @@ public class C_MaterialOutboundItemQO {
|
|||
// 单位
|
||||
private String resbMeins;
|
||||
|
||||
/**
|
||||
* 实际领料数量
|
||||
*/
|
||||
private BigDecimal qty;
|
||||
|
||||
// 实际出库数量
|
||||
private BigDecimal resbErfmg;
|
||||
|
||||
|
|
|
|||
|
|
@ -11,9 +11,8 @@ public class C_MaterialOutboundQO {
|
|||
//预留号
|
||||
private String resbRsNum;
|
||||
|
||||
//PDA操作员
|
||||
private String pdaOperator;
|
||||
|
||||
// 工位
|
||||
private String rkpfWempf;
|
||||
// 预留单退料详情信息
|
||||
private List<C_MaterialOutboundItemQO> items;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,20 +66,6 @@ public class WmsCenterOutbound implements Serializable {
|
|||
*/
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* sap导入的状态
|
||||
*/
|
||||
private Boolean sapStatus;
|
||||
|
||||
/**
|
||||
* sap导入异常信息
|
||||
*/
|
||||
private String sapMsg;
|
||||
|
||||
/**
|
||||
* 流水号
|
||||
*/
|
||||
private Integer serialNumber;
|
||||
|
||||
/**
|
||||
* 工位
|
||||
|
|
|
|||
|
|
@ -66,6 +66,8 @@ public class WmsCenterOutboundItem implements Serializable {
|
|||
*/
|
||||
private BigDecimal qty;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 默认仓库
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -4,8 +4,12 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
|
|||
import com.nflg.wms.common.pojo.qo.C_MaterialOutboundSearchQO;
|
||||
import com.nflg.wms.repository.entity.WmsCenterOutbound;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.nflg.wms.repository.entity.WmsCenterOutboundItem;
|
||||
import com.nflg.wms.repository.entity.WmsCenterOutboundScan;
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 服务类
|
||||
|
|
@ -17,4 +21,8 @@ import jakarta.validation.Valid;
|
|||
public interface IWmsCenterOutboundService extends IService<WmsCenterOutbound> {
|
||||
|
||||
IPage<WmsCenterOutbound> search(@Valid C_MaterialOutboundSearchQO request);
|
||||
|
||||
void confirmOutbound(WmsCenterOutbound wmsCenterOutbound,
|
||||
List<WmsCenterOutboundItem> wmsCenterOutboundItems,
|
||||
List<WmsCenterOutboundScan> wmsCenterOutboundScans);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,12 +5,22 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.nflg.wms.common.pojo.qo.C_MaterialOutboundSearchQO;
|
||||
import com.nflg.wms.common.util.VUtil;
|
||||
import com.nflg.wms.repository.entity.WmsCenterOutbound;
|
||||
import com.nflg.wms.repository.entity.WmsCenterOutboundItem;
|
||||
import com.nflg.wms.repository.entity.WmsCenterOutboundScan;
|
||||
import com.nflg.wms.repository.entity.WmsCenterReturn;
|
||||
import com.nflg.wms.repository.mapper.WmsCenterOutboundMapper;
|
||||
import com.nflg.wms.repository.service.IWmsCenterOutboundItemService;
|
||||
import com.nflg.wms.repository.service.IWmsCenterOutboundScanService;
|
||||
import com.nflg.wms.repository.service.IWmsCenterOutboundService;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.nflg.wms.repository.service.IWmsCenterReturnScanService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
|
|
@ -23,6 +33,11 @@ import org.springframework.stereotype.Service;
|
|||
@Service
|
||||
public class WmsCenterOutboundServiceImpl extends ServiceImpl<WmsCenterOutboundMapper, WmsCenterOutbound> implements IWmsCenterOutboundService {
|
||||
|
||||
@Resource
|
||||
private IWmsCenterOutboundItemService wmsCenterOutboundItemService;
|
||||
@Resource
|
||||
private IWmsCenterOutboundScanService wmsCenterOutboundScanService;
|
||||
|
||||
@Override
|
||||
public IPage<WmsCenterOutbound> search(C_MaterialOutboundSearchQO request) {
|
||||
// 参数非空校验
|
||||
|
|
@ -48,4 +63,16 @@ public class WmsCenterOutboundServiceImpl extends ServiceImpl<WmsCenterOutboundM
|
|||
queryWrapper.orderByDesc(WmsCenterOutbound::getId);
|
||||
return baseMapper.selectPage(new Page<>(page, pageSize), queryWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void confirmOutbound(WmsCenterOutbound wmsCenterOutbound,
|
||||
List<WmsCenterOutboundItem> wmsCenterOutboundItems,
|
||||
List<WmsCenterOutboundScan> wmsCenterOutboundScans) {
|
||||
VUtil.trueThrowBusinessError(!this.save(wmsCenterOutbound)).throwMessage("中心领料单保存失败!");
|
||||
VUtil.trueThrowBusinessError(!wmsCenterOutboundItemService.saveBatch(wmsCenterOutboundItems)).throwMessage("中心领料单保存失败!");
|
||||
VUtil.trueThrowBusinessError(!wmsCenterOutboundScanService.saveBatch(wmsCenterOutboundScans)).throwMessage("中心领料单保存失败!");
|
||||
//todo 库存扣减
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue