using AngleSharp.Dom; using Magicodes.ExporterAndImporter.Core; using Magicodes.ExporterAndImporter.Excel; using Mapster; using Masuit.Tools; using SqlSugar; using System.Collections; using System.Collections.Generic; using System.Drawing.Printing; using System.Linq.Expressions; using System.Threading.Tasks; using WIDESEA_Cache; using WIDESEA_Common; using WIDESEA_Core; using WIDESEA_IStorageBasicService; using WIDESEA_Model.Models.BasicModel; namespace WIDESEA_StorageBasicService; public class StockInfoService : ServiceBase, IStockInfoService { private readonly ISimpleCacheService _simpleCacheService; private readonly ILocationStatusChangeRecordRepository _locationStatusChangeRecordRepository; private readonly IStockInfoDetailRepository _IStockInfoDetailRepository; public StockInfoService(IStockInfoRepository BaseDal, ISimpleCacheService simpleCacheService, ILocationStatusChangeRecordRepository locationStatusChangeRecordRepository, IStockInfoDetailRepository stockInfoDetailService) : base(BaseDal) { _simpleCacheService = simpleCacheService; _locationStatusChangeRecordRepository = locationStatusChangeRecordRepository; _IStockInfoDetailRepository = stockInfoDetailService; } /// /// 分页 /// /// /// public override PageGridData GetPageData(PageDataOptions options) { string wheres = ValidatePageOptions(options); //获取排序字段 Dictionary orderbyDic = GetPageDataSort(options, TProperties); List orderByModels = new List(); foreach (var item in orderbyDic) { OrderByModel orderByModel = new() { FieldName = item.Key, OrderByType = item.Value }; orderByModels.Add(orderByModel); } int totalCount = 0; List searchParametersList = new List(); if (!string.IsNullOrEmpty(options.Wheres)) { try { searchParametersList = options.Wheres.DeserializeObject>(); options.Filter = searchParametersList; } catch { } } Expression> locationStatus = null; Expression> roadwayNo = null; Expression> materielCode = null; foreach (var item in searchParametersList) { if (item.Name.Contains("locationStatus")) { locationStatus = x => x.LocationInfo.LocationStatus == Convert.ToInt32(item.Value); } else if (item.Name.Contains("roadwayNo")) { roadwayNo = x => x.LocationInfo.RoadwayNo.Contains(item.Value); } else if (item.Name.Contains("materielCode")) { materielCode = x => x.StockInfoDetails.Any(d => d.MaterielCode.Contains(item.Value)); } } //.IncludesAllFirstLayer() var data = BaseDal.Db.Queryable() .Includes(x => x.StockInfoDetails) .Includes(x => x.LocationInfo) .WhereIF(!wheres.IsNullOrEmpty(), wheres) .WhereIF(locationStatus != null, locationStatus) .WhereIF(roadwayNo != null, roadwayNo) .WhereIF(materielCode != null, materielCode) .OrderBy(orderByModels) .ToPageList(options.Page, options.Rows, ref totalCount); new PageGridData(totalCount, data); return new PageGridData(totalCount, data); } /// /// 批量删除 /// /// /// public override WebResponseContent DeleteData(object[] keys) { try { List stockInfos = new List(); List locationInfos = new List(); var stocks = new List(); foreach (var item in keys) { var stock = BaseDal.QueryFirstNavAsync(x => x.Id == item.ObjToInt()).Result; var stockHty = stock.Adapt(); stockInfos.Add(stockHty); var location = SqlSugarHelper.DbWMS.Queryable().FirstAsync(x => x.Id == stock.LocationId).Result; var lastStatus = location.LocationStatus; location.LocationStatus = (int)LocationEnum.Free; locationInfos.Add(location); stocks.Add(stock.PalletCode); _locationStatusChangeRecordRepository.AddLocationStatusChangeRecord(location, lastStatus, (int)StatusChangeTypeEnum.ManualOperation, 0); } //_simpleCacheService.HashDel(CacheConst.Cache_DtStockInfo, stocks.ToArray()); //var hty = BaseDal.Db.InsertNav(stockInfos) // .Include(x => x.StockInfoDetails) // .ExecuteCommand(); //var locationd = SqlSugarHelper.DbWMS.Updateable(locationInfos).ExecuteCommandHasChange(); //return base.DeleteData(keys); var hty = BaseDal.Db.InsertNav(stockInfos) .Include(x => x.StockInfoDetails) .ExecuteCommand(); var locationd = SqlSugarHelper.DbWMS.Updateable(locationInfos).ExecuteCommandHasChange(); return base.DeleteData(keys); } catch (Exception ex) { return WebResponseContent.Instance.Error(ex.Message); } } // 根据传入库存类型获取不同巷道的库存 public async Task> GetLocationByStockType(bool stockType, string areaCode) { var stockInfos = await BaseDal.Db.Queryable().Where(x => x.IsFull == stockType && x.AreaCode == areaCode) .Includes(x => x.LocationInfo).ToListAsync(); var result = stockInfos .GroupBy(x => x.LocationInfo.RoadwayNo) .ToDictionary(x => x.Key, x => x.Count()); return result; } public override WebResponseContent Export(PageDataOptions options) { WebResponseContent content = new WebResponseContent(); try { // 1. 构建主表查询条件和排序 string wheres = ValidatePageOptions(options); Dictionary orderbyDic = GetPageDataSort(options, TProperties); // 2. 查询主表数据 List mainList = BaseDal.QueryData(wheres, orderbyDic); if (!mainList.Any()) { return WebResponseContent.Instance.OK("无数据可导出"); } // 3. 批量查询子表数据(通过主表Id关联) var mainIds = mainList.Select(m => m.Id).Distinct().ToList(); List detailList = _IStockInfoDetailRepository.Db .Queryable() .Where(d => mainIds.Contains(d.StockId)) .ToList(); // 4. 关联主表和子表数据(只取子表第一条) var exportData = new List(); foreach (var main in mainList) { // 只取当前主表数据关联的子表第一条(可通过OrderBy指定排序,确保取到想要的第一条) var firstDetail = detailList .Where(d => d.StockId == main.Id) .OrderBy(d => d.Id) // 可选:按子表Id排序,确保结果稳定(可替换为其他字段) .FirstOrDefault(); var exportModel = new PalletWithDetailExportModel { Id = main.Id, PalletCode = main.PalletCode, LocationCode = main.LocationCode, IsFull = main.IsFull, Remark = main.Remark, Creater = main.Creater, CreateDate = main.CreateDate, OutboundTime = (DateTime)main.OutboundTime, // 有子表数据则取第一条的物料编码,无则为空 MaterielCode = firstDetail?.MaterielCode ?? "" }; exportData.Add(exportModel); } // 5. 导出数据(逻辑不变) string savePath = AppDomain.CurrentDomain.BaseDirectory + "ExcelExport"; IExporter exporter = new ExcelExporter(); byte[] data = exporter.ExportAsByteArray(exportData).Result; string fileName = "托盘及物料编码数据.xlsx"; FileHelper.WriteFile(savePath, fileName, data); content = WebResponseContent.Instance.OK(data: Path.Combine(savePath, fileName)); } catch (Exception ex) { content = WebResponseContent.Instance.Error(ex.Message); } return content; } //public override WebResponseContent UpdateData(DtStockInfo entity) //{ // return base.UpdateData(entity); //} }