using IBigBreenService; using Microsoft.IdentityModel.Tokens; using OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime; using SqlSugar; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using WIDESEA_Common.CommonEnum; using WIDESEA_Common.LocationEnum; using WIDESEA_Common.OrderEnum; using WIDESEA_Common.TaskEnum; using WIDESEA_Core; using WIDESEA_Core.BaseRepository; using WIDESEA_Core.Helper; using WIDESEA_Model.Models; using WIDESEA_Model.Models.Basic; namespace BigGreenService { public class BigGreenService : IBigGreenService { private readonly IRepository _stockInfoDetailRepository; private readonly IRepository _outBoundOrderRepository; private readonly IRepository _locationInfoRepository; private readonly IRepository _outBoundOrderDetailRepository; private readonly IRepository _inboundOrderDetailRepository; private readonly IRepository _taskHtyRepository; private readonly IRepository _taskRepository; private readonly IRepository _stockInfoRepository; private readonly IRepository _materialExpirationDateRepository; private readonly IRepository _inboundRepository; public BigGreenService(IRepository stockInfoDetailRepository, IRepository outBoundOrderRepository, IRepository locationInfoRepository, IRepository outBoundOrderDetailRepository, IRepository inboundOrderDetailRepository, IRepository taskRepository, IRepository taskHtyRepository, IRepository stockInfoRepository, IRepository materialExpirationDateRepository,IRepository inboundRepository) { _stockInfoDetailRepository = stockInfoDetailRepository; _outBoundOrderRepository = outBoundOrderRepository; _locationInfoRepository = locationInfoRepository; _outBoundOrderDetailRepository = outBoundOrderDetailRepository; _inboundOrderDetailRepository = inboundOrderDetailRepository; _taskRepository = taskRepository; _taskHtyRepository = taskHtyRepository; _stockInfoRepository = stockInfoRepository; _materialExpirationDateRepository = materialExpirationDateRepository; _inboundRepository = inboundRepository; } public WebResponseContent GetBigGreenData() { //计算总库存数量 var totalStockQuantity = _stockInfoDetailRepository.Db.Queryable().Sum(x => (decimal?)x.StockQuantity) ?? 0; //计算待出库订单 var targetStatus = new List { (int)OutOrderStatusEnum.出库中, (int)OutOrderStatusEnum.未开始 }; var targetInStatus = new List { (int)InOrderStatusEnum.入库中, (int)InOrderStatusEnum.未开始 }; var unOutBound = _outBoundOrderRepository.Db.Queryable().Where(x => targetStatus.Contains(x.OrderStatus) && x.CreateDate.ToString("MM-dd") == DateTime.Now.ToString("MM-dd")).Count(); var unInBound = _inboundRepository.Db.Queryable().Where(x => targetInStatus.Contains(x.OrderStatus) && x.CreateDate.ToString("MM-dd") == DateTime.Now.ToString("MM-dd")).Count(); //计算库位利用率 var totalLocation = _locationInfoRepository.Db.Queryable().Select(x=>x.Id).Count(); var inStockLocation = _locationInfoRepository.Db.Queryable().Where(x => x.LocationStatus == (int)LocationStatusEnum.InStock).Count(); decimal locationUtilizationRate = totalLocation == 0 ? 0 : Math.Round((decimal)inStockLocation / totalLocation, 4) * 100; //计算入库任务和出库任务完成数量 var inboundCount = _taskHtyRepository.Db.Queryable().Where(x => x.TaskType >= 500 && x.TaskType < 900 && x.CreateDate.ToString("yyyy-MM-dd") == DateTime.Now.ToString("yyyy-MM-dd")).Count(); var outboundCount = _taskHtyRepository.Db.Queryable().Where(x => x.TaskType >= 100 && x.TaskType < 500 && x.CreateDate.ToString("yyyy-MM-dd") == DateTime.Now.ToString("yyyy-MM-dd")).Count(); //计算有货料箱数量 var inStockPallet = _stockInfoRepository.Db.Queryable().Where(x => x.PalletType == (int)PalletTypeEnum.None && !string.IsNullOrEmpty(x.LocationCode)).Count(); //计算空箱数量 var freeStockPallet = _stockInfoRepository.Db.Queryable().Where(x => x.PalletType == (int)PalletTypeEnum.Empty && !string.IsNullOrEmpty(x.LocationCode)).Count(); // 4. 获取近7日每日出入库明细(核心修改:调用上面的方法) var dailyInOutBoundList = Get7DaysDailyInOutBound(); List nearExpirationList = GetMaterialsNearExpiration(); //获取作业统计 var completeTask = SimpleStatistics(); //任务 List tasks = _taskRepository.QueryData(); var bigGreenData = new BigGreenDataDto { TotalStockQuantity = totalStockQuantity, UnOutBoundOrderCount = unOutBound, LocationUtilizationRate = locationUtilizationRate, DailyInOutBoundList = dailyInOutBoundList, TaskList = tasks, InboundCount = inboundCount, OutboundCount = outboundCount, InStockPallet = inStockPallet, FreeStockPallet = freeStockPallet, CompleteTask = completeTask, NearExpirationList = nearExpirationList, UnInBoundOrderCount = unInBound }; return WebResponseContent.Instance.OK(data: bigGreenData); } /// /// 获取近7日每日出入库明细 /// /// 每日出入库明细列表 private List Get7DaysDailyInOutBound() { // 1. 定义时间范围(近7个自然日) DateTime endDate = DateTime.Today; DateTime startDate = endDate.AddDays(-6); // 生成近7日所有日期(确保无缺失,即使某一天无数据也返回0) var all7Days = Enumerable.Range(0, 7) .Select(i => endDate.AddDays(-i).ToString("MM-dd")) .Reverse() // 按日期升序排列(从7天前到今日) .ToList(); // 2. 查询每日出库明细(按日期分组) var dailyOutboundList = _outBoundOrderRepository.Db .Queryable() .Where(x => x.CreateDate >= startDate && x.CreateDate < endDate.AddDays(1)) .Select(x => new { Date = x.CreateDate.ToString("MM-dd"), x.OrderStatus }) .ToList() .GroupBy(x => x.Date) .ToDictionary(k => k.Key, g => g.Count(x => x.OrderStatus == (int)OutOrderStatusEnum.出库完成)); // 转为字典方便匹配 // 3. 查询每日入库明细(按日期分组) var dailyInboundList = _inboundRepository.Db .Queryable() .Where(x => x.CreateDate >= startDate && x.CreateDate < endDate.AddDays(1)) .Select(x => new { Date = x.CreateDate.ToString("MM-dd"), x.OrderStatus }) .ToList() .GroupBy(x => x.Date) .ToDictionary(k => k.Key, g => g.Count(x => x.OrderStatus == (int)InOrderStatusEnum.入库完成)); // 转为字典方便匹配 // 4. 合并每日数据(确保7天日期完整,无数据补0) var dailyInOutBoundList = all7Days.Select(date => new DailyInOutBoundDto { Date = date, DailyOutboundQuantity = dailyOutboundList.ContainsKey(date) ? dailyOutboundList[date] : 0, DailyInboundQuantity = dailyInboundList.ContainsKey(date) ? dailyInboundList[date] : 0, }).ToList(); return dailyInOutBoundList; } public List SimpleStatistics() { var today = DateTime.Now.Date; var threeDaysAgo = today.AddDays(-3); var targetStatuses = new List { (int)InOrderStatusEnum.入库中, (int)InOrderStatusEnum.未开始, (int)OutOrderStatusEnum.未开始, (int)OutOrderStatusEnum.出库中 }; var failReturnStatuses = new List {4,2}; var inboundToday = QueryInboundOrders(today, today, targetStatuses); var outboundToday = QueryOutboundOrders(today, today, targetStatuses); var inboundFail3Days = QueryInboundOrders(threeDaysAgo, today, failReturnStatuses, isReturnStatus: true); var outboundFail3Days = QueryOutboundOrders(threeDaysAgo, today, failReturnStatuses, isReturnStatus: true); return new List { new() { inboundOrders = inboundToday, outboundOrders = outboundToday, inboundReturnFailOrders = inboundFail3Days, outboundReturnFailOrders = outboundFail3Days }}; } private List QueryInboundOrders(DateTime startDate, DateTime endDate, List statusList, bool isReturnStatus = false) { return _inboundRepository.QueryData(x => x.CreateDate.Date >= startDate && x.CreateDate.Date <= endDate && (isReturnStatus ? statusList.Contains(x.ReturnToMESStatus) : statusList.Contains(x.OrderStatus))).ToList(); } private List QueryOutboundOrders(DateTime startDate, DateTime endDate, List statusList, bool isReturnStatus = false) { return _outBoundOrderRepository.QueryData(x => x.CreateDate.Date >= startDate && x.CreateDate.Date <= endDate && (isReturnStatus ? statusList.Contains(x.ReturnToMESStatus) : statusList.Contains(x.OrderStatus))).ToList(); } /// /// 大屏/汇总数据返回DTO(大绿数据汇总) /// public class BigGreenDataDto { /// /// 入库完成数量 /// public int InboundCount { get; set; } /// /// 出库完成数量 /// public int OutboundCount { get; set; } /// /// 总库存数量 /// public decimal TotalStockQuantity { get; set; } /// /// 待出库订单数量(出库中+未开始) /// public int UnOutBoundOrderCount { get; set; } public int UnInBoundOrderCount { get; set; } /// /// 空闲库位数量 /// public int FreeLocationCount { get; set; } /// /// 占用库位数量(已存库) /// public int InStockLocationCount { get; set; } /// /// 库位利用率(小数形式,如0.85对应85%) /// public decimal LocationUtilizationRate { get; set; } /// /// 近7日每日出入库明细 /// public List DailyInOutBoundList { get; set; } = new List(); /// /// 近7日净入库量(入库-出库) /// public decimal NetStock7Days { get; set; } /// /// 近7日净入库量(入库-出库) /// public decimal TotalStockChangeRate { get; set; } /// /// 任务列表 /// public List TaskList { get; set; } = new List(); public int InStockPallet { get; set; } public int FreeStockPallet { get; set; } public List CompleteTask { get; set; } public List NearExpirationList { get; set; } } /// /// 每日出入库明细DTO /// public class DailyInOutBoundDto { /// /// 日期(格式:yyyy-MM-dd) /// public string Date { get; set; } /// /// 当日出库总量 /// public decimal DailyOutboundQuantity { get; set; } /// /// 当日入库总量 /// public decimal DailyInboundQuantity { get; set; } } public class SimpleStatisticsDTO { public List inboundOrders { get; set; } public List outboundOrders { get; set; } public List inboundReturnFailOrders { get; set; } public List outboundReturnFailOrders { get; set; } } public class StockInfoDetailExtDTO : Dt_StockInfoDetail { public string LocationCode { get; set; } public string PalletCode { get; set; } public int DaysToExpiration { get; set; } } /// ///获取近30天要过期的物料 /// public List GetMaterialsNearExpiration() { List resultDTO = new List(); var nearExpirationList = _stockInfoDetailRepository.QueryData() .Join( _stockInfoRepository.QueryData(), detail => detail.StockId, stock => stock.Id, (detail, stock) => new { Detail = detail, LocationCode = stock.LocationCode, PalletCode = stock.PalletCode } ) .Where(x => x.Detail.ValidDate.HasValue && (x.Detail.ValidDate.Value - x.Detail.CreateDate).TotalDays <= 30) .ToList(); if (!nearExpirationList.Any()) { return resultDTO; } foreach (var item in nearExpirationList) { int daysToExpire = item.Detail.ValidDate.HasValue ? Math.Max(0, (item.Detail.ValidDate.Value - item.Detail.CreateDate).Days) : 0; var extDetail = new StockInfoDetailExtDTO { MaterielCode = item.Detail.MaterielCode, MaterielName = item.Detail.MaterielName, BatchNo = item.Detail.BatchNo, SupplyCode = item.Detail.SupplyCode, StockQuantity = item.Detail.StockQuantity, CreateDate = item.Detail.CreateDate, ValidDate = item.Detail.ValidDate, LocationCode = item.LocationCode, PalletCode = item.PalletCode, Barcode = item.Detail.Barcode, DaysToExpiration = daysToExpire }; resultDTO.Add(extDetail); } resultDTO = resultDTO.OrderBy(d => d.DaysToExpiration).ToList(); return resultDTO; } } }