using CMS.Plugin.HIAWms.Application.Contracts.Dtos.CommonDto; using CMS.Plugin.HIAWms.Domain.WmsMaterials; using CMS.Plugin.HIAWms.Domain.WmsMaterialStocks; using CMS.Plugin.HIAWms.Domain.WmsPlaces; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Volo.Abp; namespace CMS.Plugin.HIAWms.Application.Implements { /// /// 公共操作服务 /// public class WmsCommonAppService : CMSPluginAppService { private readonly IWmsMaterialRepository _wmsMaterialRepository; private readonly IWmsPlaceRepository _wmsPlaceRepository; private readonly IWmsMaterialStockRepository _wmsMaterialStockRepository; public WmsCommonAppService(IWmsMaterialRepository wmsMaterialRepository, IWmsPlaceRepository wmsPlaceRepository, IWmsMaterialStockRepository wmsMaterialStockRepository ) { _wmsMaterialRepository = wmsMaterialRepository; _wmsPlaceRepository = wmsPlaceRepository; _wmsMaterialStockRepository = wmsMaterialStockRepository; } public async Task> GetMaterialModeListAsync() { var materialList = await _wmsMaterialRepository.GetMaterialListAsync(new WmsMaterial()); if (materialList == null || materialList.Count <= 0) return new List(); ; return materialList.Select(material => new MaterialModelOutput { MaterialModel = material.MaterialModel, MaterialModelDesc = material.MaterialModel }).ToList(); } /// /// 查找空库位 /// /// /// /// /// /// public async Task> FindAvailablePlacesAsync(string materialModel, string materialNo, int requiredNum) { // 1. 获取所有库存和库位信息 var stockList = await _wmsMaterialStockRepository.GetListAsync(new WmsMaterialStock()); var allPlaceList = await _wmsPlaceRepository.GetListAsync(new WmsPlace()); // 2. 查找相同物料型号和编号的库存(按库存量降序) var sameModelStocks = stockList .Where(x => x.MaterialModel == materialModel) .WhereIf(!string.IsNullOrEmpty(materialNo), x => x.MaterialNo == materialNo) .OrderByDescending(x => x.StockNumber) .ToList(); var availablePlaces = new Dictionary(); int remainingNum = requiredNum; // 3. 优先检查已有库存的库位是否能存放(相同 MaterialNo) foreach (var stock in sameModelStocks) { if (remainingNum <= 0) break; // 数量已分配完 var placeInfo = allPlaceList.FirstOrDefault(x => x.PlaceNo == stock.PlaceNo); if (placeInfo == null) continue; int availableSpace = placeInfo.MaxStockNumber - stock.StockNumber; if (availableSpace <= 0) continue; int allocatedNum = Math.Min(availableSpace, remainingNum); availablePlaces.Add(placeInfo, allocatedNum); remainingNum -= allocatedNum; } // 4. 如果仍有剩余,查找空库位 if (remainingNum > 0) { var usedPlaceNos = stockList.Select(x => x.PlaceNo).Distinct().ToList(); var emptyPlaces = allPlaceList .Where(x => !usedPlaceNos.Contains(x.PlaceNo)) .ToList(); foreach (var place in emptyPlaces) { if (remainingNum <= 0) break; int allocatedNum = Math.Min(place.MaxStockNumber, remainingNum); availablePlaces.Add(place, allocatedNum); remainingNum -= allocatedNum; } } // 5. 如果仍有剩余,说明库位不足 if (remainingNum > 0) { throw new UserFriendlyException($"库位不足,还差 {remainingNum} 个无法存放!"); } return availablePlaces; } } }