using DocumentFormat.OpenXml.Drawing.Charts; using Volo.Abp.AutoMapper; namespace Win_in.Sfs.Wms.Pda.Controllers.Inventories; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using AutoMapper; using Castle.Components.DictionaryAdapter; using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using Volo.Abp; using Volo.Abp.Application.Dtos; using Volo.Abp.AspNetCore.Mvc; using Win_in.Sfs.Basedata.Application.Contracts; using Win_in.Sfs.Shared.Domain; using Win_in.Sfs.Shared.Domain.Shared; using Win_in.Sfs.Wms.Inventory.Application.Contracts; using Win_in.Sfs.Wms.Pda.Controllers.BaseDatas.Dtos; using Win_in.Sfs.Wms.Pda.Models; using JsonSerializer = System.Text.Json.JsonSerializer; /// /// /// [ApiController] [Route($"{PdaHostConst.ROOT_ROUTE}inventory/balances")] public class BalanceController : AbpController { private readonly IBalanceAppService _balanceAppService; private readonly IItemBasicAppService _itemBasicAppService; private readonly ILocationAppService _locationAppService; private readonly IExpectOutAppService _expectOutAppService; private readonly IProductionLineItemAppService _productionLineItemAppService; private IMapper _mapper; /// /// /// /// /// /// /// public BalanceController( IBalanceAppService balanceAppService, IItemBasicAppService itemBasicAppService, ILocationAppService locationAppService, IExpectOutAppService expectOutAppService, IProductionLineItemAppService productionLineItemAppService) { this._balanceAppService = balanceAppService; this._locationAppService = locationAppService; _expectOutAppService = expectOutAppService; _productionLineItemAppService = productionLineItemAppService; this._itemBasicAppService = itemBasicAppService; } /// /// 根据库位获取零件信息 /// /// /// [HttpGet("get-item-by-location")] public virtual async Task> GetItemBasicListByLocationCodeAsync(string locationCode) { var input = new SfsInventoryRequestInputBase { Condition = new Condition { Filters = new List() } }; if (!string.IsNullOrWhiteSpace(locationCode)) { input.Condition.Filters.Add(new Filter("LocationCode", locationCode)); } var list = await _balanceAppService.GetAllListByFilterAsync(input).ConfigureAwait(false); var partCodes = list.Select(p => p.ItemCode).Distinct().ToList(); var itemInput = new SfsBaseDataRequestInputBase(); if (partCodes.Count > 0) { var partCodesStr = JsonSerializer.Serialize(partCodes); itemInput.Condition.Filters.Add( new Filter { Action = EnumFilterAction.In.ToString(), Column = "Code", Logic = EnumFilterLogic.And.ToString(), Value = partCodesStr }); } var itemBaseList = await _itemBasicAppService.GetAllListByFilterAsync(itemInput).ConfigureAwait(false); return new List(itemBaseList); } /// /// 获取【库存】根据【库位】和【物品】 /// /// /// /// [HttpGet("get-by-location-and-item")] public virtual async Task> GetListByLocationCodeAndItemCodeAsync(string locationCode, string itemCode) { return await _balanceAppService.GetListByLocationCodeAndItemCodeAsync(locationCode, itemCode).ConfigureAwait(false); } /// /// 【获取】【库存余额】根据【箱码】 /// /// [HttpGet("get-by-packing-code")] public virtual async Task GetByPackingCode(string packingCode) { return await _balanceAppService.GetByPackingCodeAsync(packingCode).ConfigureAwait(false); } /// /// 库存列表 /// /// /// /// /// /// /// /// /// /// /// /// [HttpGet("")] public virtual async Task> GetListAsync( string itemCode, string locationCode, string packingCode, string containerCode, EnumInventoryStatus? inventoryStatus, EnumLocationType? locationType, bool? isEnablePick, int pageSize, int pageIndex, string sortBy) { var input = new SfsInventoryRequestInputBase { MaxResultCount = pageSize, SkipCount = (pageIndex - 1) * pageSize, Sorting = sortBy, Condition = new Condition { Filters = new List() } }; if (!string.IsNullOrWhiteSpace(itemCode)) { input.Condition.Filters.Add(new Filter("ItemCode", itemCode)); } if (!string.IsNullOrWhiteSpace(locationCode)) { input.Condition.Filters.Add(new Filter("LocationCode", locationCode)); } if (!string.IsNullOrWhiteSpace(packingCode)) { input.Condition.Filters.Add(new Filter("PackingCode", packingCode)); } if (!string.IsNullOrWhiteSpace(containerCode)) { input.Condition.Filters.Add(new Filter("ContainerCode", containerCode)); } if (!string.IsNullOrWhiteSpace(inventoryStatus.ToString())) { input.Condition.Filters.Add(new Filter("Status", inventoryStatus.ToString())); } var balanceDTOs = await _balanceAppService.GetPagedListByFilterAsync(input, false).ConfigureAwait(false); return balanceDTOs; } /// /// 条件筛选获取列表 /// /// /// [HttpPost("filter")] public virtual async Task> GetListOnFilterAsync(SfsInventoryRequestInputBase input) { return await _balanceAppService.GetPagedListByFilterAsync(input, false).ConfigureAwait(false); } /// /// 发料执行时查询 /// /// /// [HttpPost("by-issue")] public async Task> GetListForIssueAsync(BalanceListByIssueInput listInput) { var input = new BalanceByIssueRequestInput { MaxResultCount = listInput.pageSize, SkipCount = (listInput.pageIndex - 1) * listInput.pageSize, Sorting = listInput.sortBy, Condition = new Condition { Filters = new List() } }; if (!string.IsNullOrWhiteSpace(listInput.itemCode)) { input.Condition.Filters.Add(new Filter("ItemCode", listInput.itemCode)); } if (!string.IsNullOrWhiteSpace(listInput.locationCode)) { input.Condition.Filters.Add(new Filter("LocationCode", listInput.locationCode)); } if (!string.IsNullOrWhiteSpace(listInput.packingCode)) { input.Condition.Filters.Add(new Filter("PackingCode", listInput.packingCode)); } if (!string.IsNullOrWhiteSpace(listInput.containerCode)) { input.Condition.Filters.Add(new Filter("ContainerCode", listInput.containerCode)); } if (!string.IsNullOrWhiteSpace(listInput.inventoryStatus.ToString())) { input.Condition.Filters.Add(new Filter("Status", listInput.inventoryStatus.ToString())); } input.IsEnablePick = listInput.isEnablePick; input.LocationTypes = listInput.locationTypes; var balanceDTOs = await _balanceAppService.GetListByLocationTypeAsync(input).ConfigureAwait(false); return balanceDTOs; } /// /// 查询库存余额 根据 物品 库位 库位类型 库存状态 批次 /// /// /// [HttpPost("by-balances-request-many-parameter")] public async Task> GetListByLocationTypeAndInventoryStatusAsync( BalanceListByIssueInputByInventoryStatusAndLocationType listInput) { var input = new SfsInventoryRequestInputBase { MaxResultCount = listInput.pageSize, SkipCount = (listInput.pageIndex - 1) * listInput.pageSize, Sorting = listInput.sortBy, Condition = new Condition { Filters = new List() } }; if (!string.IsNullOrWhiteSpace(listInput.itemCode)) { input.Condition.Filters.Add(new Filter("ItemCode", listInput.itemCode)); } if (!string.IsNullOrWhiteSpace(listInput.locationCode)) { input.Condition.Filters.Add(new Filter("LocationCode", listInput.locationCode)); } if (!string.IsNullOrWhiteSpace(listInput.lot)) { input.Condition.Filters.Add(new Filter("Lot", listInput.lot)); } if (!string.IsNullOrWhiteSpace(listInput.packingCode)) { input.Condition.Filters.Add(new Filter("PackingCode", listInput.packingCode)); } if (!string.IsNullOrWhiteSpace(listInput.containerCode)) { input.Condition.Filters.Add(new Filter("ContainerCode", listInput.containerCode)); } if (listInput.locationTypes != null && listInput.locationTypes.Any()) { var locationCodes = (await _locationAppService.GetListByTypesAsync(listInput.locationTypes).ConfigureAwait(false)) .Select(t => t.Code).ToList(); if (locationCodes.Any()) { input.Condition.Filters.Add( new Filter("LocationCode", JsonSerializer.Serialize(locationCodes), "In")); } } if (listInput.inventoryStatuses != null && listInput.inventoryStatuses.Any()) { input.Condition.Filters.Add( new Filter("Status", JsonSerializer.Serialize(listInput.inventoryStatuses), "In")); } var balanceDTOs = await _balanceAppService.GetPagedListByFilterAsync(input, false).ConfigureAwait(false); return balanceDTOs; } /// /// 根据零件获取库位信息 /// /// /// [HttpGet("get-location-by-item")] public virtual async Task> GetLocationsOfItemAsync(string itemCode) { var input = new SfsInventoryRequestInputBase { Condition = new Condition { Filters = new List() } }; if (!string.IsNullOrWhiteSpace(itemCode)) { input.Condition.Filters.Add(new Filter("ItemCode", itemCode)); } var list = await _balanceAppService.GetAllListByFilterAsync(input).ConfigureAwait(false); var locationCodes = list.Select(p => p.LocationCode).Distinct().ToList(); var locInput = new SfsBaseDataRequestInputBase(); if (locationCodes.Count > 0) { var locationCodesStr = JsonSerializer.Serialize(locationCodes); locInput.Condition.Filters.Add( new Filter { Action = EnumFilterAction.In.ToString(), Column = "Code", Logic = EnumFilterLogic.And.ToString(), Value = locationCodesStr }); } var locationList = await _locationAppService.GetAllListByFilterAsync(locInput).ConfigureAwait(false); return new List(locationList); } /// /// 条件筛选获取统计 /// /// /// /// /// /// [HttpGet("summary")] public virtual async Task> GetSummaryAsync( string itemCode, string locationCode, string packingCode, string containerCode) { var input = new SfsInventoryRequestInputBase { Condition = new Condition { Filters = new List() } }; if (!string.IsNullOrWhiteSpace(itemCode)) { input.Condition.Filters.Add(new Filter("ItemCode", itemCode)); } if (!string.IsNullOrWhiteSpace(locationCode)) { input.Condition.Filters.Add(new Filter("LocationCode", locationCode)); } if (!string.IsNullOrWhiteSpace(packingCode)) { input.Condition.Filters.Add(new Filter("PackingCode", packingCode)); } if (!string.IsNullOrWhiteSpace(containerCode)) { input.Condition.Filters.Add(new Filter("ContainerCode", containerCode)); } var list = await _balanceAppService.GetSummaryAsync(input).ConfigureAwait(false); return new ListResultDto(list); } /// /// 修改批次 /// /// /// /// [HttpPost("update-batch")] public virtual async Task UpdateBatchAsync(Guid id, [FromBody] BatchInput batchInput) { await _balanceAppService.UpdateBatchAsync( id, batchInput.Lot, batchInput.SupplierBatch, batchInput.ArriveDate, batchInput.ProduceDate, batchInput.ExpireDate).ConfigureAwait(false); } /// /// 修改库存状态 /// /// /// /// [HttpPost("update-status")] public virtual async Task UpdateStatusAsync(Guid id, [FromBody] EnumInventoryStatus newStatus) { await _balanceAppService.UpdateStatusAsync(id, newStatus).ConfigureAwait(false); } /// /// 获取线边库库存(箱码为空) /// /// /// /// [HttpGet("get-wip-list")] public virtual async Task> GetWIPListAsync( string itemCode, string locationCode) { var input = new SfsInventoryRequestInputBase { Condition = new Condition { Filters = new List() } }; if (!string.IsNullOrWhiteSpace(itemCode)) { input.Condition.Filters.Add(new Filter("ItemCode", itemCode)); } if (!string.IsNullOrWhiteSpace(locationCode)) { input.Condition.Filters.Add(new Filter("LocationCode", locationCode)); } input.Condition.Filters.Add(new Filter("PackingCode", "")); input.Condition.Filters.Add(new Filter("Lot", "")); var balanceDTOs = await _balanceAppService.GetPagedListByFilterAsync(input, false).ConfigureAwait(false); return balanceDTOs; } /// /// 查询库存余额 根据 物品 库位 库位类型 库存状态 批次 并且没有被预计出 占用 /// /// /// [HttpPost("by-balances-request-many-parameter-not-in-expect-out")] public async Task> GetListByLocationTypeAndInventoryStatusAndNotExpectOutAsync( BalanceListByIssueInputByInventoryStatusAndLocationType listInput) { var expectOut = await _expectOutAppService.GetListByPackingCodeAsync(listInput.packingCode).ConfigureAwait(false); if (expectOut != null && expectOut.Any()) { throw new UserFriendlyException($"箱码为 {listInput.packingCode} 已被任务{expectOut[0].JobNumber}使用"); } var input = new SfsInventoryRequestInputBase() { MaxResultCount = listInput.pageSize, SkipCount = (listInput.pageIndex - 1) * listInput.pageSize, Sorting = listInput.sortBy, Condition = new Condition { Filters = new List() } }; if (!string.IsNullOrWhiteSpace(listInput.itemCode)) input.Condition.Filters.Add(new Filter("ItemCode", listInput.itemCode)); if (!string.IsNullOrWhiteSpace(listInput.locationCode)) input.Condition.Filters.Add(new Filter("LocationCode", listInput.locationCode)); if (!string.IsNullOrWhiteSpace(listInput.lot)) input.Condition.Filters.Add(new Filter("Lot", listInput.lot)); if (!string.IsNullOrWhiteSpace(listInput.packingCode)) input.Condition.Filters.Add(new Filter("PackingCode", listInput.packingCode)); if (!string.IsNullOrWhiteSpace(listInput.containerCode)) input.Condition.Filters.Add(new Filter("ContainerCode", listInput.containerCode)); if (listInput.locationTypes != null && listInput.locationTypes.Any()) { var locationCodes = (await this._locationAppService.GetListByTypesAsync(listInput.locationTypes).ConfigureAwait(false)) .Select(t => t.Code).ToList(); if (locationCodes.Any()) input.Condition.Filters.Add( new Filter("LocationCode", JsonConvert.SerializeObject(locationCodes), "In")); } if (listInput.inventoryStatuses != null && listInput.inventoryStatuses.Any()) input.Condition.Filters.Add( new Filter("Status", JsonConvert.SerializeObject(listInput.inventoryStatuses), "In")); return await this._balanceAppService.GetPagedListByFilterAsync(input, false).ConfigureAwait(false); } /// /// /// /// /// /// /// [HttpPost("get-recommend-balance")] public async Task> GetRecommendBalance(string itemCode,string productLine,bool isPackingCode) { var productionLineItemDto = await _productionLineItemAppService.GetByProductLineCodeAndItemCodeAsync(productLine, itemCode).ConfigureAwait(false); var locationList = new List(); if (productionLineItemDto.RawLocationCodeListJson != null&& productionLineItemDto.RawLocationCodeListJson.Length > 0) { var temp=JsonSerializer.Deserialize>(productionLineItemDto.RawLocationCodeListJson); locationList.AddRange(temp); } if (productionLineItemDto.ProductLocationCodeListJson != null && productionLineItemDto.ProductLocationCodeListJson.Length > 0) { var temp = JsonSerializer.Deserialize>(productionLineItemDto.ProductLocationCodeListJson); locationList.AddRange(temp); } //获取可用库存 var input = new RecommendBalanceRequestInput { ItemCode = itemCode, Qty = decimal.MaxValue, Statuses = new EditableList { EnumInventoryStatus.OK }, Locations = locationList, IsPackingCode = isPackingCode }; var usableList = await _balanceAppService.GetUsableListAsync(input).ConfigureAwait(false); return await SortByFifoAsync(usableList).ConfigureAwait(false); } /// /// 排序规则 1.批次正序 2.底层 3.到货日期正序 4.数量倒序(整箱优先) 5.库位正序 6.箱码正序 /// /// /// private async Task> SortByFifoAsync(List balances) { var sortBalances = new List(); var config = new MapperConfiguration(cfg => { cfg.CreateMap() .Ignore(x => x.LocationRow); }); _mapper = new Mapper(config); var resultBalances = _mapper.Map, List>(balances); foreach (var resultBalance in resultBalances) { var locationDto = await _locationAppService.GetByCodeAsync(resultBalance.LocationCode).ConfigureAwait(false); resultBalance.LocationRow = locationDto.RowCode; } resultBalances .OrderBy(p => p.Lot) .ThenBy(p => p.LocationRow) .ThenBy(p => p.PutInTime) .ThenBy(p => p.Qty)//2023-9-14 苑静雯 从小数开始发料 .ThenBy(p => p.LocationCode) .ThenBy(p => p.PackingCode) .ToList(); return resultBalances; } /// /// /// public class SortBalance : BalanceDTO { /// /// /// public int LocationRow { get; set; } } /* /// /// 查询库余额 /// /// /// [HttpPost("get-list-balance-by-input")] public async Task> GetListBalanceByInputAsync(List enumLocationTypes) { var sfsInventoryRequestInputBase= new BalanceRequestInput { MaxResultCount =list.pageSize, SkipCount = (listInput.pageIndex - 1) * listInput.pageSize, Sorting = listInput.sortBy, Condition = new Condition() { Filters = new List() } } var balanceDTOs = await _balanceAppService.GetListAsync(); return balanceDTOs; } /// /// 获取可以上架的库存状态 /// /// /// [HttpGet("allow-putaway-inventory-status")] public virtual async Task> GetAllowPutawayInventoryStatusAsync() { return await _balanceAppService .GetAllowPutawayInventoryStatusAsync(); } */ }