using Aliyun.OSS; using DOAN.Model.MES.andon; using DOAN.Model.MES.base_; using DOAN.Model.MES.group; using DOAN.Model.MES.product; using DOAN.Model.MES.report; using DOAN.Service.MES.report.IService; using Infrastructure.Attribute; using System.Data; namespace DOAN.Service.MES.report { [AppService(ServiceType = typeof(IReportService), ServiceLifetime = LifeTime.Transient)] public class ReportService : BaseService, IReportService { public List DevicePoweronRate(DateTime dateTime) { List list = new List(); var response = Context.Queryable().OrderBy(t => t.Id).ToList(); var dt = dateTime.ToString("yyyy-MM-dd"); var shiftList = Context.Queryable() .LeftJoin((a, b) => a.FkShift == b.Id) .LeftJoin((a, b, c) => a.GroupCode == c.GroupCode && c.WorkorderDate.Value.ToString("yyyy-MM-dd") == dt) .Where((a, b, c) => a.ScheduleDate.Value.ToString("yyyy-MM-dd") == dt) .Select((a, b, c) => new { b.Name, b.WorkHours, b.StartTime, b.EndTime, c.LineCode }).ToList(); var tempList = response.Select(it => new { LineCode = it.Code, LineName = it.Name, List = shiftList.Where(it2 => it2.LineCode == it.Code).Select(it2 => new { it2.Name, it2.StartTime, it2.EndTime }).ToList() }).ToList(); tempList.ForEach(t => { double poweronRate = 0; double minutes = 0; int shiftCount = 0; t.List.ForEach(t2 => { if (t2.EndTime.HasValue && t2.StartTime.HasValue) { if (t2.EndTime.Value.Hour == 16) { minutes += (t2.EndTime.Value - t2.StartTime.Value).TotalMinutes - 50; shiftCount++; } else if (t2.EndTime.Value.Hour == 20) { minutes += (t2.EndTime.Value - t2.StartTime.Value).TotalMinutes - 80; shiftCount++; } else if (t2.EndTime.Value.Hour == 22) { minutes += (t2.EndTime.Value - t2.StartTime.Value).TotalMinutes - 100; shiftCount++; } } }); if (shiftCount > 0) { poweronRate = Math.Round(minutes * 100.0 / (24 * 60 * shiftCount), 2); } list.Add(new DevicePoweronRateModel() { LineCode = t.LineCode, LineName = t.LineName, ShiftCount = shiftCount, PoweronHours = minutes, PoweronRate = poweronRate }); }); return list; } public List DeviceDowntimeRate(DateTime dateTime) { List list = new List(); var dt = dateTime.ToString("yyyy-MM-dd"); list = Context.Queryable() .LeftJoin((a, b) => a.Code == b.LineCode && b.WorkorderDate.Value.ToString("yyyy-MM-dd") == dt) .OrderBy((a,b)=>a.Id) .Select((a, b) => new DeviceDowntimeRateModel { LineCode = a.Code, LineName = a.Name, PlanHours = SqlFunc.Round((b.Beat * b.DeliveryNum ?? 0) / 3600.0, 2) }).ToList(); var response = Context.Queryable() .Where(t=>t.FaultDict== "设备异常" && t.StartTime.HasValue && t.EndTime.HasValue && t.EndTime.Value.ToString("yyyy-MM-dd") ==dt) .Select(it => new { it.LineCode, it.StartTime, it.EndTime, DowntimeHours = (it.EndTime.Value - it.StartTime.Value).TotalHours, }).ToList(); var groupList = response.GroupBy(it => it.LineCode).Select(it => new { LineCode = it.Key, DowntimeHours = it.ToList().Sum(t=>t.DowntimeHours) }).ToList(); var result = list.GroupJoin(groupList, l => l.LineCode, g => g.LineCode, (l, gList) => new DeviceDowntimeRateModel { LineCode = l.LineCode, LineName = l.LineName, PlanHours = l.PlanHours, DowntimeHours = gList.FirstOrDefault()?.DowntimeHours ?? 0, // 如果没有停机时间则为0 DowntimeRate = l.PlanHours == 0 ? 0 : Math.Round((gList.FirstOrDefault()?.DowntimeHours ?? 0) / l.PlanHours, 2) }).ToList(); return result; } public List ProductionCompletionRate(DateTime dateTime) { List list = new List(); var dt = dateTime.ToString("yyyy-MM-dd"); var woList = Context.Queryable() .LeftJoin((a, b) => a.GroupCode == b.GroupCode) .LeftJoin((a, b, c) => b.FkShift == c.Id) .LeftJoin((a, b, c, d) => a.GroupCode == d.GroupCode) .Where((a, b, c, d) => a.WorkorderDate.Value.ToString("yyyy-MM-dd") == dt && b.ScheduleDate.Value.ToString("yyyy-MM-dd") == dt) .Select((a, b, c, d) => new { a.Workorder, a.GroupCode, a.DeliveryNum, a.LineCode, a.Status, c.StartTime, c.EndTime, d.GroupName }).ToList(); string year = dateTime.Year.ToString("D4"); string month = dateTime.Month.ToString("D2"); string day = "01"; string sql = $@"SELECT FROM_UNIXTIME( FLOOR( UNIX_TIMESTAMP( d.created_time ) / 3600 ) * 3600 ) AS TimePeriod, r.workorder as WorkOrder, COUNT(*) AS Count FROM pro_workorder AS r RIGHT JOIN pro_reportwork_detail_{year}{month}{day} AS d ON r.workorder = d.workorder WHERE r.workorder_date = @dt GROUP BY FLOOR( UNIX_TIMESTAMP( d.created_time ) / 600 ),r.workorder ORDER BY TimePeriod"; var workDetailList = Context.Ado.SqlQuery(sql, new { dt = dt, }); list = woList.Select(t => new ProductionCompletionRate { WorkOrder = t.Workorder, GroupName = t.GroupName, WorkTimePeriod = $"{t.StartTime?.ToString("HH:mm")}-{t.EndTime?.ToString("HH:mm")}", DeliveryNum = t.DeliveryNum ?? 0, Status = GetStatusName(t.Status??0), StartTime=t.StartTime, EndTime=t.EndTime }).ToList(); list.ForEach(t => { var productionCompletionList = workDetailList.Where(wd => wd.WorkOrder == t.WorkOrder).ToList(); var hours = (t.EndTime - t.StartTime).Value.TotalHours; for (int i = 0; i < hours; i++) { var productionCompletionModel = productionCompletionList.Where(t => t.TimePeriod.Hour == (8 + i)).FirstOrDefault(); t.List.Add(new PlanModel { StartTime = $"{8 + i}:00", PlanNum = t.DeliveryNum / 8, CompletionNum = productionCompletionModel?.Count ?? 0, }); } t.CompletionNum = productionCompletionList.Sum(t => t.Count); t.CompletionRate = Math.Round(t.CompletionNum*100.0 / t.DeliveryNum,2); }); return list; } public List MonthlyProductionCompletionRate(DateTime dateTime) { (DateTime FirstDay, DateTime LastDay) Handlemonth = GetFirstAndLastDayOfMonth(dateTime); List list = new List(); var woList = Context.Queryable() .LeftJoin((a, b) => a.GroupCode == b.GroupCode) .LeftJoin((a, b, c) => b.FkShift == c.Id) .LeftJoin((a, b, c, d) => a.GroupCode == d.GroupCode) .Where((a, b, c, d) => a.WorkorderDate.Value>= Handlemonth.FirstDay && a.WorkorderDate.Value<= Handlemonth.LastDay && b.ScheduleDate.Value>= Handlemonth.FirstDay && b.ScheduleDate.Value<= Handlemonth.LastDay) .Select((a, b, c, d) => new { a.Workorder, a.GroupCode, a.DeliveryNum, a.LineCode, a.Status, c.StartTime, c.EndTime, d.GroupName }).ToList(); string year = dateTime.Year.ToString("D4"); string month = dateTime.Month.ToString("D2"); string day = "01"; string sql = $@"SELECT FROM_UNIXTIME( FLOOR( UNIX_TIMESTAMP( d.created_time ) / 3600 ) * 3600 ) AS TimePeriod, r.workorder as WorkOrder, COUNT(*) AS Count FROM pro_workorder AS r RIGHT JOIN pro_reportwork_detail_{year}{month}{day} AS d ON r.workorder = d.workorder WHERE r.workorder_date >= @firstDay and r.workorder_date<=@lastDay GROUP BY FLOOR( UNIX_TIMESTAMP( d.created_time ) / 600 ),r.workorder ORDER BY TimePeriod"; var workDetailList = Context.Ado.SqlQuery(sql, new { firstDay = Handlemonth.FirstDay, lastDay= Handlemonth.LastDay }); list = woList.Select(t => new ProductionCompletionRate { WorkOrder = t.Workorder, GroupName = t.GroupName, WorkTimePeriod = $"{t.StartTime?.ToString("HH:mm")}-{t.EndTime?.ToString("HH:mm")}", DeliveryNum = t.DeliveryNum ?? 0, Status = GetStatusName(t.Status ?? 0), StartTime = t.StartTime, EndTime = t.EndTime }).ToList(); list.ForEach(t => { var productionCompletionList = workDetailList.Where(wd => wd.WorkOrder == t.WorkOrder).ToList(); var hours = (t.EndTime - t.StartTime).Value.TotalHours; for (int i = 0; i < hours; i++) { var productionCompletionModel = productionCompletionList.Where(t => t.TimePeriod.Hour == (8 + i)).FirstOrDefault(); t.List.Add(new PlanModel { StartTime = $"{8 + i}:00", PlanNum = t.DeliveryNum / 8, CompletionNum = productionCompletionModel?.Count ?? 0, }); } t.CompletionNum = productionCompletionList.Sum(t => t.Count); t.CompletionRate = Math.Round(t.CompletionNum * 100.0 / t.DeliveryNum, 2); }); return list; } private string GetStatusName(int status) { if (status == 1) return "未开始"; else if (status == 2) return "开始"; else if (status == 3) return "完成"; else if (status == 4) return "暂停"; else return ""; } private (DateTime FirstDay, DateTime LastDay) GetFirstAndLastDayOfMonth(DateTime date) { DateTime firstDay = new DateTime(date.Year, date.Month, 1); int lastDay = DateTime.DaysInMonth(date.Year, date.Month); DateTime lastDayDate = new DateTime(date.Year, date.Month, lastDay); return (firstDay, lastDayDate); } } }