1
heshaofeng
2026-03-25 37454e625df68d40897112b2e8c2e3cf4d7163e3
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/BigGreenService/BigGreenService.cs
@@ -30,8 +30,9 @@
        private readonly IRepository<Dt_Task> _taskRepository;
        private readonly IRepository<Dt_StockInfo> _stockInfoRepository;
        private readonly IRepository<Dt_MaterialExpirationDate> _materialExpirationDateRepository;
        private readonly IRepository<Dt_InboundOrder> _inboundRepository;
        public BigGreenService(IRepository<Dt_StockInfoDetail> stockInfoDetailRepository, IRepository<Dt_OutboundOrder> outBoundOrderRepository, IRepository<Dt_LocationInfo> locationInfoRepository, IRepository<Dt_OutboundOrderDetail> outBoundOrderDetailRepository, IRepository<Dt_InboundOrderDetail> inboundOrderDetailRepository, IRepository<Dt_Task> taskRepository, IRepository<Dt_Task_Hty> taskHtyRepository, IRepository<Dt_StockInfo> stockInfoRepository, IRepository<Dt_MaterialExpirationDate> materialExpirationDateRepository)
        public BigGreenService(IRepository<Dt_StockInfoDetail> stockInfoDetailRepository, IRepository<Dt_OutboundOrder> outBoundOrderRepository, IRepository<Dt_LocationInfo> locationInfoRepository, IRepository<Dt_OutboundOrderDetail> outBoundOrderDetailRepository, IRepository<Dt_InboundOrderDetail> inboundOrderDetailRepository, IRepository<Dt_Task> taskRepository, IRepository<Dt_Task_Hty> taskHtyRepository, IRepository<Dt_StockInfo> stockInfoRepository, IRepository<Dt_MaterialExpirationDate> materialExpirationDateRepository,IRepository<Dt_InboundOrder> inboundRepository)
        {
            _stockInfoDetailRepository = stockInfoDetailRepository;
            _outBoundOrderRepository = outBoundOrderRepository;
@@ -42,6 +43,7 @@
            _taskHtyRepository = taskHtyRepository;
            _stockInfoRepository = stockInfoRepository;
            _materialExpirationDateRepository = materialExpirationDateRepository;
            _inboundRepository = inboundRepository;
        }
        public WebResponseContent GetBigGreenData()
        {
@@ -54,12 +56,17 @@
                (int)OutOrderStatusEnum.出库中,
                (int)OutOrderStatusEnum.未开始
            };
            var unOutBound = _outBoundOrderRepository.Db.Queryable<Dt_OutboundOrder>().Where(x => targetStatus.Contains(x.OrderStatus)).Count();
            var targetInStatus = new List<int>
            {
                (int)InOrderStatusEnum.入库中,
                (int)InOrderStatusEnum.未开始
            };
            var unOutBound = _outBoundOrderRepository.Db.Queryable<Dt_OutboundOrder>().Where(x => targetStatus.Contains(x.OrderStatus) && x.CreateDate.ToString("MM-dd") == DateTime.Now.ToString("MM-dd")).Count();
            var unInBound = _inboundRepository.Db.Queryable<Dt_InboundOrder>().Where(x => targetInStatus.Contains(x.OrderStatus) && x.CreateDate.ToString("MM-dd") == DateTime.Now.ToString("MM-dd")).Count();
            //计算库位利用率
            var freeLocation = _locationInfoRepository.Db.Queryable<Dt_LocationInfo>().Where(x => x.LocationStatus == (int)LocationStatusEnum.Free).Count();
            var inStockLocation = _locationInfoRepository.Db.Queryable<Dt_LocationInfo>().Where(x => x.LocationStatus == (int)LocationStatusEnum.InStock || x.LocationStatus == (int)LocationStatusEnum.Pallet).Count();
            int totalLocation = freeLocation + inStockLocation;
            var totalLocation = _locationInfoRepository.Db.Queryable<Dt_LocationInfo>().Select(x=>x.Id).Count();
            var inStockLocation = _locationInfoRepository.Db.Queryable<Dt_LocationInfo>().Where(x => x.LocationStatus == (int)LocationStatusEnum.InStock).Count();
            decimal locationUtilizationRate = totalLocation == 0
                ? 0
                : Math.Round((decimal)inStockLocation / totalLocation, 4) * 100;
@@ -75,7 +82,7 @@
            // 4. èŽ·å–è¿‘7日每日出入库明细(核心修改:调用上面的方法)
            var dailyInOutBoundList = Get7DaysDailyInOutBound();
            var nearExpirationList = GetMaterialsNearExpiration();
            List<StockInfoDetailExtDTO> nearExpirationList = GetMaterialsNearExpiration();
            //获取作业统计
            var completeTask = SimpleStatistics();
            //任务
@@ -93,7 +100,8 @@
                InStockPallet = inStockPallet,
                FreeStockPallet = freeStockPallet,
                CompleteTask = completeTask,
                NearExpirationList = nearExpirationList
                NearExpirationList = nearExpirationList,
                UnInBoundOrderCount = unInBound
            };
            return WebResponseContent.Instance.OK(data: bigGreenData);
        }
@@ -114,33 +122,33 @@
                .ToList();
            // 2. æŸ¥è¯¢æ¯æ—¥å‡ºåº“明细(按日期分组)
            var dailyOutboundList = _outBoundOrderDetailRepository.Db
                .Queryable<Dt_OutboundOrderDetail>()
            var dailyOutboundList = _outBoundOrderRepository.Db
                .Queryable<Dt_OutboundOrder>()
                .Where(x => x.CreateDate >= startDate
                         && x.CreateDate < endDate.AddDays(1))
                .Select(x => new
                {
                    Date = x.CreateDate.ToString("MM-dd"),
                    x.OverOutQuantity
                    x.OrderStatus
                })
                .ToList()
                .GroupBy(x => x.Date)
                .ToDictionary(k => k.Key, g => g.Sum(x => (decimal?)x.OverOutQuantity) ?? 0); // è½¬ä¸ºå­—典方便匹配
                .ToDictionary(k => k.Key, g => g.Count(x => x.OrderStatus == (int)OutOrderStatusEnum.出库完成)); // è½¬ä¸ºå­—典方便匹配
            // 3. æŸ¥è¯¢æ¯æ—¥å…¥åº“明细(按日期分组)
            var dailyInboundList = _inboundOrderDetailRepository.Db
                .Queryable<Dt_InboundOrderDetail>()
            var dailyInboundList = _inboundRepository.Db
                .Queryable<Dt_InboundOrder>()
                .Where(x => x.CreateDate >= startDate
                         && x.CreateDate < endDate.AddDays(1))
                .Select(x => new
                {
                    Date = x.CreateDate.ToString("MM-dd"),
                    x.OverInQuantity
                    x.OrderStatus
                })
                .ToList()
                .GroupBy(x => x.Date)
                .ToDictionary(k => k.Key, g => g.Sum(x => (decimal?)x.OverInQuantity) ?? 0); // è½¬ä¸ºå­—典方便匹配
                .ToDictionary(k => k.Key, g => g.Count(x => x.OrderStatus == (int)InOrderStatusEnum.入库完成)); // è½¬ä¸ºå­—典方便匹配
            // 4. åˆå¹¶æ¯æ—¥æ•°æ®ï¼ˆç¡®ä¿7天日期完整,无数据补0)
            var dailyInOutBoundList = all7Days.Select(date => new DailyInOutBoundDto
@@ -156,23 +164,46 @@
        public List<SimpleStatisticsDTO> SimpleStatistics()
        {
            DateTime sevenDaysAgo = DateTime.Now.AddDays(-7);
            var today = DateTime.Now.Date;
            var threeDaysAgo = today.AddDays(-3);
            var stats = _taskHtyRepository
                .QueryData(x => x.TaskStatus == (int)TaskStatusEnum.Finish && x.CreateDate >= sevenDaysAgo)
                .GroupBy(t =>
                    (int)t.TaskType >= 100 && (int)t.TaskType <= 299 ? "出库" :
                    (int)t.TaskType >= 500 && (int)t.TaskType <= 699 ? "入库" : "其他"
                )
                .Where(g => g.Key == "出库" || g.Key == "入库")
                .Select(g => new SimpleStatisticsDTO
                {
                    TaskType = g.Key,
                    Count = g.Count()
                })
                .ToList();
            var targetStatuses = new List<int> { (int)InOrderStatusEnum.入库中, (int)InOrderStatusEnum.未开始,
                                         (int)OutOrderStatusEnum.未开始, (int)OutOrderStatusEnum.出库中 };
            var failReturnStatuses = new List<int> {4,2};
            return stats;
            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<SimpleStatisticsDTO> { new()
    {
        inboundOrders = inboundToday,
        outboundOrders = outboundToday,
        inboundReturnFailOrders = inboundFail3Days,
        outboundReturnFailOrders = outboundFail3Days
    }};
        }
        private List<Dt_InboundOrder> QueryInboundOrders(DateTime startDate, DateTime endDate,
                                                      List<int> 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<Dt_OutboundOrder> QueryOutboundOrders(DateTime startDate, DateTime endDate,
                                                        List<int> 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();
        }
        /// <summary>
@@ -197,6 +228,8 @@
            /// å¾…出库订单数量(出库中+未开始)
            /// </summary>
            public int UnOutBoundOrderCount { get; set; }
            public int UnInBoundOrderCount { get; set; }
            /// <summary>
            /// ç©ºé—²åº“位数量
@@ -239,7 +272,7 @@
            public List<SimpleStatisticsDTO> CompleteTask { get; set; }
            public NearExpirationDTO NearExpirationList { get; set; }
            public List<StockInfoDetailExtDTO> NearExpirationList { get; set; }
        }
        /// <summary>
@@ -266,86 +299,76 @@
        public class SimpleStatisticsDTO
        {
            public string TaskType { get; set; }
            public int Count { get; set; }
            public List<Dt_InboundOrder> inboundOrders { get; set; }
            public List<Dt_OutboundOrder> outboundOrders { get; set; }
            public List<Dt_InboundOrder> inboundReturnFailOrders { get; set; }
            public List<Dt_OutboundOrder> outboundReturnFailOrders { get; set; }
        }
        public class NearExpirationDTO
        public class StockInfoDetailExtDTO : Dt_StockInfoDetail
        {
            public int DaysToExpiration { get; set; }
            public List<Dt_StockInfoDetail> Details { get; set; }
            public string LocationCode { get; set; }
            public string PalletCode { get; set; }
            public int DaysToExpiration { get; set; }
        }
        ///<summary>
        ///获取近30天要过期的物料
        /// </summary>
        public NearExpirationDTO GetMaterialsNearExpiration()
        public List<StockInfoDetailExtDTO> GetMaterialsNearExpiration()
        {
            // åˆå§‹åŒ–返回DTO
            var resultDTO = new NearExpirationDTO
            {
                Details = new List<Dt_StockInfoDetail>(),
                LocationCode = string.Empty,
                PalletCode = string.Empty,
                DaysToExpiration = 0 // åˆå§‹åŒ–天数
            };
            List<StockInfoDetailExtDTO> resultDTO = new List<StockInfoDetailExtDTO>();
            DateTime currentTime = DateTime.Now;
            DateTime thirtyDaysLater = currentTime.AddDays(30);
            // ç­›é€‰30天内过期的库存明细
            var nearExpirationList = _stockInfoDetailRepository.Db.Queryable<Dt_StockInfoDetail>()
                .Where(x => (x.ValidDate.Value - x.CreateDate).TotalDays <= 30)
            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;
            }
            
            var firstStockId = nearExpirationList.First().StockId;
            var stock = _stockInfoRepository.Db.Queryable<Dt_StockInfo>()
                .First(x => x.Id == firstStockId);
            if (stock == null)
            foreach (var item in nearExpirationList)
            {
                return resultDTO;
            }
                int daysToExpire = item.Detail.ValidDate.HasValue
                    ? Math.Max(0, (item.Detail.ValidDate.Value - item.Detail.CreateDate).Days)
                    : 0;
            resultDTO.LocationCode = stock.LocationCode;
            resultDTO.PalletCode = stock.PalletCode;
            int minDaysToExpiration = int.MaxValue;
            foreach (var detail in nearExpirationList)
            {
                TimeSpan totalDaysToExpiration = detail.ValidDate.Value - detail.CreateDate;
                double remainingDays = totalDaysToExpiration.TotalDays;
                int daysToExpiration = (int)Math.Ceiling(Math.Max(0, remainingDays));
                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
                };
               
                if (daysToExpiration < minDaysToExpiration)
                {
                    minDaysToExpiration = daysToExpiration;
                }
                resultDTO.Details.Add(detail);
                resultDTO.Add(extDetail);
            }
            resultDTO.DaysToExpiration = minDaysToExpiration;
            resultDTO = resultDTO.OrderBy(d => d.DaysToExpiration).ToList();
            return resultDTO;
        }