| | |
| | | package com.vincent.rsf.server.manager.utils; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.vincent.rsf.framework.common.Cools; |
| | | import com.vincent.rsf.framework.common.SpringUtils; |
| | | import com.vincent.rsf.framework.exception.CoolException; |
| | | import com.vincent.rsf.server.manager.entity.DeviceSite; |
| | | import com.vincent.rsf.server.manager.entity.Loc; |
| | | import com.vincent.rsf.server.manager.service.DeviceSiteService; |
| | | import com.vincent.rsf.server.manager.service.LocService; |
| | | import com.vincent.rsf.server.system.enums.LocStsType; |
| | | import com.vincent.rsf.server.api.utils.LocUtils; |
| | | import com.vincent.rsf.server.manager.controller.dto.ExistDto; |
| | | import com.vincent.rsf.server.manager.controller.dto.OrderOutItemDto; |
| | | import com.vincent.rsf.server.manager.controller.params.WaveToLocParams; |
| | | import com.vincent.rsf.server.manager.entity.*; |
| | | import com.vincent.rsf.server.manager.enums.TaskType; |
| | | import com.vincent.rsf.server.manager.enums.WaveRuleType; |
| | | import com.vincent.rsf.server.manager.service.*; |
| | | import com.vincent.rsf.server.manager.enums.LocStsType; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | |
| | | import java.util.Objects; |
| | | import java.math.BigDecimal; |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | |
| | | public class LocManageUtil { |
| | | |
| | | /** |
| | | * @author Ryan |
| | | * @description 获取目标库位, 包含库位获取策略 |
| | | * @param |
| | | * @return |
| | | * @author Ryan |
| | | * @description 获取目标库位, 包含库位获取策略 |
| | | * @time 2025/3/31 08:50 |
| | | */ |
| | | public static String getTargetLoc() { |
| | | public static String getTargetLoc(Long areaId) { |
| | | //TODO 库位策略后续排期 |
| | | |
| | | return getTargetLoc(areaId, null); |
| | | } |
| | | |
| | | public static String getTargetLoc(Long areaId, Long containerType,List<Integer> rowList) { |
| | | |
| | | Long locType = containerType; |
| | | //TODO 库位策略后续排期 |
| | | LocService locService = SpringUtils.getBean(LocService.class); |
| | | Loc loc = locService.getOne(new LambdaQueryWrapper<Loc>() |
| | | .eq(!Objects.isNull(locType), Loc::getType, locType) |
| | | .eq(Loc::getAreaId, areaId) |
| | | .eq(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_O.type) |
| | | .in(Objects.nonNull(rowList) && !rowList.isEmpty(), Loc::getRow, rowList) |
| | | .orderByAsc(Loc::getLev) |
| | | .orderByAsc(Loc::getCol) |
| | | .orderByAsc(Loc::getRow) |
| | | .last("LIMIT 1") |
| | | ); |
| | | |
| | | Loc loc = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_D.type), false); |
| | | return !Objects.isNull(loc) ? loc.getCode() : null; |
| | | } |
| | | |
| | | return Objects.isNull(loc) ? loc.getCode() : null; |
| | | public static String getTargetLoc(Long areaId, Long containerType) { |
| | | Long locType = containerType; |
| | | // if (!Objects.isNull(containerType)) { |
| | | // LocTypeService locService = SpringUtils.getBean(LocTypeService.class); |
| | | // if (containerType.equals(ContainerType.CONTAINER_TYPE_NORMAL.val)) { |
| | | // LocType low = locService.getOne(new LambdaQueryWrapper<LocType>() |
| | | // .eq(LocType::getCode, "L")); |
| | | // if (Objects.isNull(low)) { |
| | | // throw new CoolException("庫位類型不存在!!"); |
| | | // } |
| | | // locType = low.getId(); |
| | | // } else { |
| | | // LocType low = locService.getOne(new LambdaQueryWrapper<LocType>() |
| | | // .eq(LocType::getCode, "H")); |
| | | // if (Objects.isNull(low)) { |
| | | // throw new CoolException("庫位類型不存在!!"); |
| | | // } |
| | | // locType = low.getId(); |
| | | // } |
| | | // } |
| | | //TODO 库位策略后续排期 |
| | | LocService locService = SpringUtils.getBean(LocService.class); |
| | | Loc loc = locService.getOne(new LambdaQueryWrapper<Loc>() |
| | | .eq(!Objects.isNull(locType), Loc::getType, locType) |
| | | .eq(Loc::getAreaId, areaId) |
| | | .eq(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_O.type) |
| | | .orderByAsc(Loc::getLev) |
| | | .orderByAsc(Loc::getCol) |
| | | .orderByAsc(Loc::getRow) |
| | | .last("LIMIT 1") |
| | | ); |
| | | |
| | | return !Objects.isNull(loc) ? loc.getCode() : null; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * @author Ryan |
| | | * @description 获取目标站点 |
| | | * @param |
| | | * @return |
| | | * @time 2025/3/31 09:49 |
| | | */ |
| | | * @param |
| | | * @return |
| | | * @author Ryan |
| | | * @description 获取目标站点 |
| | | * @time 2025/3/31 09:49 |
| | | */ |
| | | public static String getTargetSite() { |
| | | //TODO 站点策略后续排期 |
| | | DeviceSiteService deviceSite = SpringUtils.getBean(DeviceSiteService.class); |
| | | DeviceSite loc = deviceSite.getOne(new LambdaQueryWrapper<DeviceSite>().eq(DeviceSite::getStatus, 1), false); |
| | | return Objects.isNull(loc) ? loc.getSite() : null; |
| | | return !Objects.isNull(loc) ? loc.getSite() : null; |
| | | } |
| | | |
| | | /** |
| | | * 出库策略:--〈效率优化〉 |
| | | * |
| | | * @param matnrCode |
| | | * @param splrBatch |
| | | * @param anfme |
| | | * @return |
| | | */ |
| | | public static List<LocItem> getEfficiencyFirstItemList(String matnrCode, String splrBatch, Double anfme) { |
| | | LambdaQueryWrapper<LocItem> locItemQueryWrapper = new LambdaQueryWrapper<>(); |
| | | locItemQueryWrapper.eq(LocItem::getMatnrCode, matnrCode); |
| | | locItemQueryWrapper.eq(StringUtils.isNotBlank(splrBatch), LocItem::getBatch, splrBatch); |
| | | String applySql = String.format( |
| | | "EXISTS (SELECT 1 FROM man_loc ml " + |
| | | "WHERE ml.use_status = '%s'" + |
| | | "AND ml.id = man_loc_item.loc_id " + |
| | | ")", |
| | | LocStsType.LOC_STS_TYPE_F.type |
| | | ); |
| | | locItemQueryWrapper.apply(applySql); |
| | | LocItemService locItemService = SpringUtils.getBean(LocItemService.class); |
| | | List<LocItem> locItems = locItemService.list(locItemQueryWrapper); |
| | | locItems.sort(Comparator.comparing((LocItem item) -> !LocUtils.isShallowLoc(item.getLocCode()))); |
| | | List<LocItem> locsSet = locItems.stream().filter(locItem -> locItem.getAnfme().compareTo(anfme) == 0.0).collect(Collectors.toList()); |
| | | if (!locsSet.isEmpty()) { |
| | | return locsSet; |
| | | } |
| | | return locItems; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 出库策略:--<先进先出> |
| | | * |
| | | * @param matnrCode |
| | | * @param splrBatch |
| | | * @param anfme |
| | | * @return |
| | | */ |
| | | public static List<LocItem> getFirstInFirstOutItemList(String matnrCode, String splrBatch, Double anfme) { |
| | | LambdaQueryWrapper<LocItem> locItemQueryWrapper = new LambdaQueryWrapper<>(); |
| | | locItemQueryWrapper.eq(LocItem::getMatnrCode, matnrCode); |
| | | locItemQueryWrapper.eq(StringUtils.isNotEmpty(splrBatch), LocItem::getBatch, splrBatch); |
| | | //如果批次不为空,按批次先后出库 |
| | | if (StringUtils.isNotBlank(splrBatch)) { |
| | | locItemQueryWrapper.orderByAsc(LocItem::getBatch); |
| | | } else { |
| | | locItemQueryWrapper.orderByAsc(LocItem::getCreateTime); |
| | | } |
| | | String applySql = String.format( |
| | | "EXISTS (SELECT 1 FROM man_loc ml " + |
| | | "WHERE ml.use_status = '%s'" + |
| | | "AND ml.id = man_loc_item.loc_id " + |
| | | ")", |
| | | LocStsType.LOC_STS_TYPE_F.type |
| | | ); |
| | | locItemQueryWrapper.apply(applySql); |
| | | LocItemService locItemService = SpringUtils.getBean(LocItemService.class); |
| | | List<LocItem> locItems = locItemService.list(locItemQueryWrapper); |
| | | return locItems; |
| | | } |
| | | |
| | | /** |
| | | * 获取出库库位信息 |
| | | * |
| | | * @param params |
| | | * @param waveRule |
| | | * @return |
| | | */ |
| | | public static List<OrderOutItemDto> getOutOrderList(List<WaveToLocParams> params, WaveRule waveRule) { |
| | | LocService locService = SpringUtils.getBean(LocService.class); |
| | | LocItemService locItemService = SpringUtils.getBean(LocItemService.class); |
| | | DeviceSiteService deviceSiteService = SpringUtils.getBean(DeviceSiteService.class); |
| | | BasStationAreaService basStationAreaService = SpringUtils.getBean(BasStationAreaService.class); |
| | | // List<BasStationArea> basStationAreas = basStationAreaService.list(new LambdaQueryWrapper<>());// |
| | | List<Loc> locList = new ArrayList<>(); |
| | | List<OrderOutItemDto> list = new ArrayList<>(); |
| | | //不让站点重复使用问题 |
| | | List<BasStation> stations = new ArrayList<>(); |
| | | Set<ExistDto> existDtos = new HashSet<>(); |
| | | for (WaveToLocParams item : params) { |
| | | BigDecimal issued = new BigDecimal(item.getAnfme().toString()) |
| | | .subtract(new BigDecimal(item.getWorkQty().toString())); |
| | | if (issued.doubleValue() <= 0) { |
| | | continue; |
| | | } |
| | | List<LocItem> locItems; |
| | | if (Objects.isNull(waveRule)) { |
| | | locItems = LocManageUtil.getFirstInFirstOutItemList(item.getMatnrCode(), item.getBatch(), item.getAnfme()); |
| | | } else { |
| | | if (WaveRuleType.Efficiency_First.type.equals(waveRule.getType())) { |
| | | locItems = LocManageUtil.getEfficiencyFirstItemList(item.getMatnrCode(), item.getBatch(), item.getAnfme()); |
| | | } else if (WaveRuleType.First_In_First_Out.type.equals(waveRule.getType())) { |
| | | locItems = LocManageUtil.getFirstInFirstOutItemList(item.getMatnrCode(), item.getBatch(), item.getAnfme()); |
| | | } else { |
| | | locItems = LocManageUtil.getFirstInFirstOutItemList(item.getMatnrCode(), item.getBatch(), item.getAnfme()); |
| | | } |
| | | } |
| | | |
| | | for (LocItem locItem : locItems) { |
| | | Loc loc = locService.getById(locItem.getLocId()); |
| | | List<LocItem> itemList = locItemService.list(new LambdaQueryWrapper<LocItem>().eq(LocItem::getLocId, loc.getId())); |
| | | |
| | | if (issued.doubleValue() > 0 && locList.contains(loc)) { |
| | | for (OrderOutItemDto itemDto : list) { |
| | | if (itemDto.getLoc().equals(loc)) { |
| | | ExistDto existDto = new ExistDto().setBatch(locItem.getBatch()).setMatnr(locItem.getMatnrCode()).setLocNo(locItem.getLocCode()); |
| | | if (existDtos.add(existDto)) { |
| | | locItem.setOutQty(issued.doubleValue() >= locItem.getAnfme() ? locItem.getAnfme() : issued.doubleValue()); |
| | | locItem.setBarcode(loc.getBarcode()) |
| | | .setSourceId(item.getWaveId())//波次ID |
| | | .setSource(item.getItemId());//波次明细ID |
| | | itemDto.getLocItemList().add(locItem); |
| | | issued = issued.subtract(new BigDecimal(locItem.getAnfme().toString())); |
| | | } |
| | | break; |
| | | } |
| | | } |
| | | } else if (issued.doubleValue() > 0) { |
| | | ExistDto existDto = new ExistDto().setBatch(locItem.getBatch()).setMatnr(locItem.getMatnrCode()).setLocNo(locItem.getLocCode()); |
| | | if (existDtos.add(existDto)) { |
| | | locItem.setOutQty(issued.doubleValue() >= locItem.getAnfme() ? locItem.getAnfme() : issued.doubleValue()); |
| | | locItem.setBarcode(loc.getBarcode()) |
| | | .setSourceId(item.getWaveId())//波次ID |
| | | .setSource(item.getItemId());//波次明细ID |
| | | OrderOutItemDto orderOutItemDto = new OrderOutItemDto(); |
| | | // orderOutItemDto.setLocItem(locItem); |
| | | orderOutItemDto.setLoc(loc); |
| | | orderOutItemDto.getLocItemList().add(locItem); |
| | | BasContainer containerType = getContainerType(loc.getBarcode()); |
| | | List<BasStationArea> basStationAreas = basStationAreaService.list(new LambdaQueryWrapper<BasStationArea>() |
| | | .apply("JSON_CONTAINS(cross_zone_area, '{0}') = 1", loc.getAreaId())//可执行库区区区域id |
| | | .apply("JSON_CONTAINS(container_type, '{0}') = 1", containerType)//容器类型 |
| | | // .apply("JSON_CONTAINS(station_alias, '\"{0}\"') = 1", null)//区域包含站点集 |
| | | .eq(BasStationArea::getDeleted, 0));// 通常需要加上未删除条件 |
| | | List<String> targSiteAreaList = new ArrayList<>(); |
| | | for (BasStationArea basStationArea : basStationAreas) { |
| | | targSiteAreaList.add(basStationArea.getStationAreaId()); |
| | | } |
| | | int count = 0; |
| | | for (BasStationArea basStationArea : basStationAreas) { |
| | | count++; |
| | | if (!basStationArea.getStationAlias().isEmpty()) { |
| | | List<OrderOutItemDto.staListDto> maps = new ArrayList<>(); |
| | | for (String site : basStationArea.getStationAlias()) { |
| | | OrderOutItemDto.staListDto staListDto = new OrderOutItemDto.staListDto(); |
| | | staListDto.setStaNo(site); |
| | | staListDto.setStaName(site); |
| | | maps.add(staListDto); |
| | | } |
| | | orderOutItemDto.setStaNos(maps); |
| | | //获取满足条件站点 |
| | | Set<String> stationSet = new HashSet<>(basStationArea.getStationAlias()); |
| | | // Set<String> stationSet = basStationArea.getStationAlias().stream().collect(Collectors.toSet()); |
| | | // Set<String> stationSet = deviceSites.stream().map(DeviceSite::getSite).collect(Collectors.toSet()); |
| | | //已使用站点 |
| | | Set<String> stas = stations.stream().map(BasStation::getStationName).collect(Collectors.toSet()); |
| | | BasStationService basStationService = SpringUtils.getBean(BasStationService.class); |
| | | BasStation basStation = basStationService.getOne(new LambdaQueryWrapper<BasStation>() |
| | | .eq(BasStation::getUseStatus, LocStsType.LOC_STS_TYPE_O.type) |
| | | .in(BasStation::getStationName, stationSet) |
| | | .notIn(!stas.isEmpty(), BasStation::getStationName, stas) |
| | | .last("LIMIT 1")); |
| | | if (!Objects.isNull(basStation)) { |
| | | stations.add(basStation); |
| | | } |
| | | |
| | | if (count == basStationAreas.size()) { |
| | | if (!Objects.isNull(basStation)) { |
| | | orderOutItemDto.setSiteNo(basStation.getStationName()); |
| | | // throw new CoolException("站點不存在!!"); |
| | | } |
| | | } else { |
| | | if (Objects.isNull(basStation)) { |
| | | continue; |
| | | // throw new CoolException("站點不存在!!"); |
| | | } |
| | | orderOutItemDto.setSiteNo(basStation.getStationName()); |
| | | } |
| | | |
| | | } |
| | | |
| | | orderOutItemDto.setSource(item.getItemId().toString()) |
| | | .setTargSiteAreaList(targSiteAreaList) |
| | | .setSourceId(item.getWaveId().toString()); |
| | | list.add(orderOutItemDto); |
| | | locList.add(loc); |
| | | |
| | | issued = issued.subtract(new BigDecimal(locItem.getAnfme().toString())); |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | return list; |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | //根据条码获取规则 |
| | | private static BasContainer getContainerType(String barcode) { |
| | | BasContainerService basContainerService = SpringUtils.getBean(BasContainerService.class); |
| | | if (Cools.isEmpty(barcode)) { |
| | | throw new CoolException("容器码不能为空"); |
| | | } |
| | | List<BasContainer> containers = basContainerService.list(new LambdaQueryWrapper<>()); |
| | | for (BasContainer container : containers) { |
| | | String codeType = container.getCodeType(); // 获取正则表达式 |
| | | if (barcode.matches(codeType)) { // 判断条码是否符合这个正则 |
| | | return container; |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | } |