From 5a149d626ae8bc3fa4bddbb53f8caf40f51f6da6 Mon Sep 17 00:00:00 2001 From: zs <zhousong@weben-smart.com> Date: 周三, 04 6月 2025 17:42:13 +0800 Subject: [PATCH] Merge branch 'master' of http://222.71.245.114:9086/r/HIA24016N_PipeLineDemo --- HIAWms/server/src/CMS.Plugin.HIAWms.Application/Implements/WmsCommonAppService.cs | 288 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 274 insertions(+), 14 deletions(-) diff --git a/HIAWms/server/src/CMS.Plugin.HIAWms.Application/Implements/WmsCommonAppService.cs b/HIAWms/server/src/CMS.Plugin.HIAWms.Application/Implements/WmsCommonAppService.cs index e8ef141..1545536 100644 --- a/HIAWms/server/src/CMS.Plugin.HIAWms.Application/Implements/WmsCommonAppService.cs +++ b/HIAWms/server/src/CMS.Plugin.HIAWms.Application/Implements/WmsCommonAppService.cs @@ -1,45 +1,70 @@ 锘縰sing CMS.Plugin.HIAWms.Application.Contracts.Dtos.CommonDto; +using CMS.Plugin.HIAWms.Application.Contracts.Dtos.WmsMaterialStocks; +using CMS.Plugin.HIAWms.Application.Contracts.Dtos.WmsPlace; +using CMS.Plugin.HIAWms.Application.Contracts.Services; +using CMS.Plugin.HIAWms.Domain.Shared.Enums; +using CMS.Plugin.HIAWms.Domain.WmsInOutStockRecord; using CMS.Plugin.HIAWms.Domain.WmsMaterials; using CMS.Plugin.HIAWms.Domain.WmsMaterialStocks; using CMS.Plugin.HIAWms.Domain.WmsPlaces; +using CmsQueryExtensions.Extension; +using Microsoft.Extensions.DependencyInjection; using System; using System.Collections.Generic; using System.Linq; +using System.Linq.Expressions; using System.Text; using System.Threading.Tasks; using Volo.Abp; +using Volo.Abp.Uow; namespace CMS.Plugin.HIAWms.Application.Implements { /// <summary> /// 鍏叡鎿嶄綔鏈嶅姟 /// </summary> - public class WmsCommonAppService : CMSPluginAppService + public class WmsCommonAppService : CMSPluginAppService, IWmsCommonAppService { private readonly IWmsMaterialRepository _wmsMaterialRepository; private readonly IWmsPlaceRepository _wmsPlaceRepository; private readonly IWmsMaterialStockRepository _wmsMaterialStockRepository; + private readonly IWmsInOutStockRecordRepository _wmsInOutStockRecordRepository; + private readonly IServiceProvider _serviceProvider; public WmsCommonAppService(IWmsMaterialRepository wmsMaterialRepository, IWmsPlaceRepository wmsPlaceRepository, IWmsMaterialStockRepository wmsMaterialStockRepository - ) +, + IServiceProvider serviceProvider, + IWmsInOutStockRecordRepository wmsInOutStockRecordRepository) { _wmsMaterialRepository = wmsMaterialRepository; _wmsPlaceRepository = wmsPlaceRepository; _wmsMaterialStockRepository = wmsMaterialStockRepository; + _serviceProvider = serviceProvider; + _wmsInOutStockRecordRepository = wmsInOutStockRecordRepository; } - public async Task<List<MaterialModelOutput>> GetMaterialModeListAsync() + /// 鍔ㄦ�佹瀯閫犳煡璇㈡潯浠� + /// </summary> + /// <param name="input">杈撳叆鍙傛暟</param> + /// <returns></returns> + private FunReturnResultModel<Expression<Func<WmsPlace, bool>>> DynamicGetQueryPlaceParams(GetWmsPlaceInput input) { - var materialList = await _wmsMaterialRepository.GetMaterialListAsync(new WmsMaterial()); - if (materialList == null || materialList.Count <= 0) return new List<MaterialModelOutput>(); ; - - return materialList.Select(material => new MaterialModelOutput + // 鍔ㄦ�佹瀯閫犳煡璇㈡潯浠� + var whereConditions = WhereConditionsExtensions.GetWhereConditions<WmsPlace, GetWmsPlaceInput>(input); + if (!whereConditions.IsSuccess) { - MaterialModel = material.MaterialModel, - MaterialModelDesc = material.MaterialModel - }).ToList(); + throw new Exception("鍔ㄦ�佹瀯閫犳煡璇㈡潯浠跺け璐�:" + whereConditions.ErrMsg); + } + + //涔熷彲鍐嶆鑷畾涔夋瀯寤烘煡璇㈡潯浠� + Expression<Func<WmsPlace, bool>> extendExpression = a => a.IsDeleted == false; + // 浣跨敤 System.Linq.PredicateBuilder 鐨� And + var pres = (System.Linq.Expressions.Expression<Func<WmsPlace, bool>>)(whereConditions.data); + whereConditions.data = System.Linq.PredicateBuilder.And(pres, extendExpression); + + return whereConditions; } /// <summary> @@ -50,11 +75,17 @@ /// <param name="requiredNum"></param> /// <returns></returns> /// <exception cref="UserFriendlyException"></exception> - public async Task<Dictionary<WmsPlace, int>> FindAvailablePlacesAsync(string materialModel, string materialNo, int requiredNum) + public async Task<Dictionary<WmsPlaceDto, int>> FindAvailablePlacesAsync(string materialModel, int requiredNum, string materialNo = "") { + + var whereConditions = DynamicGetQueryParams(new GetWmsMaterialStockInput { StorageTypeNo = Domain.Shared.Enums.PlaceTypeEnum.YUANLIAOKUWEI }); // 1. 鑾峰彇鎵�鏈夊簱瀛樺拰搴撲綅淇℃伅 - var stockList = await _wmsMaterialStockRepository.GetListAsync(new WmsMaterialStock()); - var allPlaceList = await _wmsPlaceRepository.GetListAsync(new WmsPlace()); + var stockList = await _wmsMaterialStockRepository.GetListAsync(whereConditions); + + var placeConditions = DynamicGetQueryPlaceParams(new GetWmsPlaceInput { StorageTypeNo = (int)PlaceTypeEnum.YUANLIAOKUWEI }); + + var placeList = await _wmsPlaceRepository.GetListByFilterAsync(placeConditions.data); + var allPlaceList = ObjectMapper.Map<List<WmsPlace>, List<WmsPlaceDto>>(placeList.Where(x => !x.IsDisabled).ToList()); // 2. 鏌ユ壘鐩稿悓鐗╂枡鍨嬪彿鍜岀紪鍙风殑搴撳瓨锛堟寜搴撳瓨閲忛檷搴忥級 var sameModelStocks = stockList @@ -63,7 +94,7 @@ .OrderByDescending(x => x.StockNumber) .ToList(); - var availablePlaces = new Dictionary<WmsPlace, int>(); + var availablePlaces = new Dictionary<WmsPlaceDto, int>(); int remainingNum = requiredNum; // 3. 浼樺厛妫�鏌ュ凡鏈夊簱瀛樼殑搴撲綅鏄惁鑳藉瓨鏀撅紙鐩稿悓 MaterialNo锛� @@ -108,5 +139,234 @@ return availablePlaces; } + + /// <summary> + /// 鏌ユ壘搴撳瓨 + /// </summary> + /// <param name="materialModel"></param> + /// <param name="requiredNum"></param> + /// <param name="materialNo"></param> + /// <returns></returns> + public async Task<Dictionary<WmsMaterialStockDto, int>> FindStockAsync(string materialModel, int requiredNum, string placeNo = "", PlaceTypeEnum placeType = PlaceTypeEnum.YUANLIAOKUWEI, string materialNo = "") + { + var allocation = new Dictionary<WmsMaterialStockDto, int>(); // <搴撲綅鍙�, 鍑哄簱鏁�> + // 1. 鑾峰彇鎵�鏈夊簱瀛橈紙鎺掗櫎閿佸畾搴撳瓨锛� + var input = new GetWmsMaterialStockInput(); + var whereConditions = DynamicGetQueryParams(new GetWmsMaterialStockInput()); + var stockList = (await _wmsMaterialStockRepository.GetListAsync(whereConditions)) + .Where(x => x.IsLock == Domain.Shared.Enums.YesNoEnum.N) + .Where(x => x.StorageTypeNo == placeType) + .ToList(); + + if (!string.IsNullOrEmpty(placeNo)) + { + var stock = stockList.Where(x => x.PlaceNo == placeNo).FirstOrDefault(); + if (stock.StockNumber < requiredNum) + { + throw new UserFriendlyException($"搴撲綅{placeNo}搴撳瓨涓嶈冻,鍙敤: {stock.StockNumber}, 缂�: {requiredNum - stock.StockNumber}"); + } + + allocation.Add(ObjectMapper.Map<WmsMaterialStock, WmsMaterialStockDto>(stock), requiredNum); + return allocation; + } + + // 2. 绛涢�夊尮閰嶇墿鏂� + var availableStocklist = stockList + .Where(x => x.MaterialModel == materialModel) + .WhereIf(!string.IsNullOrEmpty(materialNo), x => x.MaterialNo == materialNo) + .OrderBy(x => x.StockNumber) // 浼樺厛浠庡簱瀛樺皯鐨勫簱浣嶅嚭 + .ToList(); + + var availableStocks = ObjectMapper.Map<List<WmsMaterialStock>, List<WmsMaterialStockDto>>(availableStocklist); + + // 3. 妫�鏌ユ�诲簱瀛樻槸鍚﹁冻澶� + int totalAvailable = availableStocks.Sum(x => x.StockNumber); + if (totalAvailable < requiredNum) + { + throw new UserFriendlyException( + $"搴撳瓨涓嶈冻锛侀渶姹�: {requiredNum}, 鍙敤: {totalAvailable}, 缂�: {requiredNum - totalAvailable}"); + } + + // 4. 璁$畻鍚勫簱浣嶅嚭搴撴暟閲� + int remaining = requiredNum; + + foreach (var stock in availableStocks) + { + if (remaining <= 0) break; + + int deductAmount = Math.Min(stock.StockNumber, remaining); + allocation.Add(stock, deductAmount); + remaining -= deductAmount; + } + + return allocation; + } + + private FunReturnResultModel<Expression<Func<WmsMaterialStock, bool>>> DynamicGetQueryParams(GetWmsMaterialStockInput input) + { + //鍔ㄦ�佹瀯閫犳煡璇㈡潯浠� + var whereConditions = WhereConditionsExtensions.GetWhereConditions<WmsMaterialStock, GetWmsMaterialStockInput>(input); + if (!whereConditions.IsSuccess) + { + throw new Exception("鍔ㄦ�佹瀯閫犳煡璇㈡潯浠跺け璐�:" + whereConditions.ErrMsg); + } + + //涔熷彲鍐嶆鑷畾涔夋瀯寤烘煡璇㈡潯浠� + Expression<Func<WmsMaterialStock, bool>> extendExpression = a => a.IsDeleted == false; + // 浣跨敤 System.Linq.PredicateBuilder 鐨� And + var pres = (System.Linq.Expressions.Expression<Func<WmsMaterialStock, bool>>)(whereConditions.data); + whereConditions.data = System.Linq.PredicateBuilder.And(pres, extendExpression); + + return whereConditions; + } + + + /// <summary> + /// 鎵e噺搴撳瓨 + /// </summary> + /// <returns></returns> + public async Task<List<WmsMaterialStockDto>> ReduceMaterialStockAsync(ReduceStockInput input) + { + using var scope = _serviceProvider.CreateScope(); + var unitOfWorkManager = scope.ServiceProvider.GetRequiredService<IUnitOfWorkManager>(); + using var uow = unitOfWorkManager.Begin(requiresNew: true); + + var materialModel = await _wmsMaterialRepository.FindByModelAsync(input.MaterialModel); + if (materialModel == null) + { + throw new UserFriendlyException("鐗╂枡鍨嬪彿涓嶅瓨鍦�"); + } + var placeInfo = await _wmsPlaceRepository.FindByNameAsync(input.PlaceNo); + if (placeInfo == null) + { + throw new UserFriendlyException("搴撲綅淇℃伅涓嶅瓨鍦�"); + } + var stockresult = await FindStockAsync(input.MaterialModel, input.StockNumber, input.PlaceNo, placeInfo.StorageTypeNo); + if (stockresult == null) + { + throw new UserFriendlyException("褰撳墠鏃犲簱瀛�"); + } + var recordList = new List<WmsInOutStockRecord>(); + var delStock = new List<WmsMaterialStock>(); + foreach (var kvp in stockresult) + { + var stock = kvp.Key; // WmsPlace瀵硅薄 + var quantity = kvp.Value; // 鍒嗛厤鏁伴噺 + + // 鎵e噺搴撳瓨 + var stockList = await _wmsMaterialStockRepository.GetStockListAsync(new WmsMaterialStock { MaterialModel = input.MaterialModel, PlaceNo = stock.PlaceNo }); + var reduceStockList = stockList.OrderBy(x => x.InStockTime).Take(quantity).ToList(); + delStock.AddRange(reduceStockList); + + // 鍑哄叆搴撹褰� + foreach (var item in reduceStockList) + { + var record = new WmsInOutStockRecord + { + TaskNo = string.IsNullOrEmpty(input.OrderNo) ? "Task_" + DateTime.Now.ToString("yyyyMMddHHmmssfff") : input.OrderNo, + OrderNo = input.OrderNo, + StockType = StockTypeEnum.Move, + ContainerNo = item.ContainerNo, + MaterialId = item.MaterialId, + MaterialModel = item.MaterialModel, + MaterialName = item.MaterialName, + MaterialNo = item.MaterialNo, + MaterialBatch = item.MaterialBatch, + SourcePlace = item.PlaceNo, + ToPlace = "鍑哄簱", + OperateTime = DateTime.Now, + Remark = "鍑哄簱鎵e噺", + }; + recordList.Add(record); + } + } + await _wmsMaterialStockRepository.DeleteManyAsync(delStock); + await _wmsInOutStockRecordRepository.InsertManyAsync(recordList); + + await uow.SaveChangesAsync(); + await uow.CompleteAsync(); + + var result = ObjectMapper.Map<List<WmsMaterialStock>, List<WmsMaterialStockDto>>(delStock); + return result; + } + + /// <summary> + /// 搴撳瓨杞Щ + /// </summary> + /// <param name="input"></param> + /// <returns></returns> + public async Task<List<WmsMaterialStockDto>> MoveMaterialStock(MoveStockInput input) + { + using var scope = _serviceProvider.CreateScope(); + var unitOfWorkManager = scope.ServiceProvider.GetRequiredService<IUnitOfWorkManager>(); + using var uow = unitOfWorkManager.Begin(requiresNew: true); + + var materialModel = await _wmsMaterialRepository.FindByModelAsync(input.MaterialModel); + if (materialModel == null) + { + throw new UserFriendlyException("鐗╂枡鍨嬪彿涓嶅瓨鍦�"); + } + + var placeInfo = await _wmsPlaceRepository.FindByNameAsync(input.SourcePlace); + if (placeInfo == null) + { + throw new UserFriendlyException("鏉ユ簮搴撲綅淇℃伅涓嶅瓨鍦�"); + } + var toPlace = await _wmsPlaceRepository.FindByNameAsync(input.ToPlace); + if (toPlace == null) + { + throw new UserFriendlyException("鐩爣搴撲綅淇℃伅涓嶅瓨鍦�"); + } + var stockresult = await FindStockAsync(input.MaterialModel, input.StockNumber, input.SourcePlace, placeInfo.StorageTypeNo); + if (stockresult == null) + { + throw new UserFriendlyException("褰撳墠鏃犲簱瀛�"); + } + + var recordList = new List<WmsInOutStockRecord>(); + var result = new List<WmsMaterialStockDto>(); + foreach (var kvp in stockresult) + { + var stock = kvp.Key; // WmsPlace瀵硅薄 + var quantity = kvp.Value; // 鍒嗛厤鏁伴噺 + + // 鎵e噺杞Щ + var stockList = await _wmsMaterialStockRepository.GetStockListAsync(new WmsMaterialStock { MaterialModel = input.MaterialModel, PlaceNo = stock.PlaceNo }); + var reduceStockList = stockList.OrderBy(x => x.InStockTime).Take(quantity).ToList(); + + // 鍑哄叆搴撹褰� + foreach (var item in reduceStockList) + { + var record = new WmsInOutStockRecord + { + TaskNo = string.IsNullOrEmpty(input.OrderNo) ? "Task_" + DateTime.Now.ToString("yyyyMMddHHmmssfff") : input.OrderNo, + OrderNo = input.OrderNo, + StockType = StockTypeEnum.Move, + ContainerNo = item.ContainerNo, + MaterialId = item.MaterialId, + MaterialModel = item.MaterialModel, + MaterialName = item.MaterialName, + MaterialNo = item.MaterialNo, + MaterialBatch = item.MaterialBatch, + SourcePlace = item.PlaceNo, + ToPlace = input.ToPlace, + OperateTime = DateTime.Now, + Remark = "鍑哄簱鎵e噺", + }; + recordList.Add(record); + item.PlaceNo = input.ToPlace; + } + + await _wmsMaterialStockRepository.UpdateManyAsync(reduceStockList); + await _wmsInOutStockRecordRepository.InsertManyAsync(recordList); + + result.AddRange(ObjectMapper.Map<List<WmsMaterialStock>, List<WmsMaterialStockDto>>(reduceStockList)); + } + + await uow.SaveChangesAsync(); + await uow.CompleteAsync(); + + return result; + } } } -- Gitblit v1.9.3