using Aliyun.OSS; using DOAN.Model.MES; 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 JinianNet.JNTemplate.Dynamic; using System.Data; namespace DOAN.Service.MES.report { [AppService(ServiceType = typeof(IReportService), ServiceLifetime = LifeTime.Transient)] public class ReportService : BaseService, IReportService { public List DevicePoweronRate(DeviceReportDto param) { 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, c) => a.GroupCode == c.GroupCode && c.WorkorderDate.Value.ToString("yyyy-MM-dd") == a.ScheduleDate.Value.ToString("yyyy-MM-dd")) .Where((a, c) => a.ScheduleDate.Value >= param.StartTime && a.ScheduleDate.Value <= param.EndTime) .Select((a, c) => new { c.LineCode, a.StartTime, a.EndTime, a.PlanRestTime }).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.PlanRestTime, 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) { minutes += (t2.EndTime.Value - t2.StartTime.Value).TotalMinutes - t2.PlanRestTime; 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(DeviceReportDto param) { List list = new List(); //var dt = dateTime.ToString("yyyy-MM-dd"); list = Context.Queryable() .LeftJoin((a, b) => a.Code == b.LineCode && b.WorkorderDate.Value>= param.StartTime && b.WorkorderDate.Value<= param.EndTime) .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 groupListWorkRoute = list.GroupBy(it => new { it.LineCode,it.LineName }).Select(it => new { LineCode = it.Key.LineCode, LineName = it.Key.LineName, PlanHours = it.ToList().Sum(t => t.PlanHours) }).ToList(); var response = Context.Queryable() .Where(t=>t.FaultDict== "设备异常" && t.StartTime.HasValue && t.EndTime.HasValue && t.EndTime.Value>= param.StartTime && t.EndTime.Value<= param.EndTime) .Select(it => new { it.LineCode, it.StartTime, it.EndTime, DowntimeHours = (it.EndTime.Value - it.StartTime.Value).TotalHours, }).ToList(); var totalDowntimeHours = response.Sum(it => it.DowntimeHours); var totalPlanHours = groupListWorkRoute.Sum(it => it.PlanHours); var groupList = response.GroupBy(it => it.LineCode).Select(it => new { LineCode = it.Key, DowntimeHours = it.ToList().Sum(t=>t.DowntimeHours) }).ToList(); var result = groupListWorkRoute.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), TotalDowntimeHours = totalDowntimeHours, TotalPlanHours = totalPlanHours, TotalDowntimeRate = totalPlanHours == 0 ? 0 : Math.Round(totalDowntimeHours / totalPlanHours, 2) }).ToList(); return result; } public List ProductionCompletionRate(string groupName, 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, d) => a.GroupCode == d.GroupCode) .Where((a, b, d) => a.WorkorderDate.Value.ToString("yyyy-MM-dd") == dt && b.ScheduleDate.Value.ToString("yyyy-MM-dd") == dt && (string.IsNullOrEmpty(groupName) || d.GroupName.Contains(groupName))) .Select((a, b, d) => new { a.Workorder, a.GroupCode, a.DeliveryNum, a.ProductionName, a.LineCode, a.Beat, a.Status, b.StartTime, b.EndTime, b.PlanRestTime, 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"; string sql = $@"SELECT TimePeriod,WorkOrder,count(0) AS Count from ( SELECT FROM_UNIXTIME( FLOOR( UNIX_TIMESTAMP( d.created_time ) / 3600 ) * 3600 ) AS TimePeriod, r.workorder as WorkOrder 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 )t group by TimePeriod,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, Beat = t.Beat ?? 0, Status = GetStatusName(t.Status ?? 0), StartTime = t.StartTime, EndTime = t.EndTime, Model = t.ProductionName }).ToList(); list.ForEach(t => { var productionCompletionList = workDetailList.Where(wd => wd.WorkOrder == t.WorkOrder).ToList(); //var hours = (t.EndTime - t.StartTime).Value.TotalHours; var planNum = t.Beat == 0 ? 0 : 3600 / t.Beat; for (int i = 8; i < 24; i++) { var productionCompletionModel = productionCompletionList.Where(t => t.TimePeriod.Hour == i).FirstOrDefault(); t.List.Add(new PlanModel { StartTime = $"{i}:00", PlanNum = planNum, CompletionNum = productionCompletionModel?.Count ?? 0, }); } for (int i = 0; i < 8; i++) { var productionCompletionModel = productionCompletionList.Where(t => t.TimePeriod.Hour == i).FirstOrDefault(); t.List.Add(new PlanModel { StartTime = $"{i}:00", PlanNum = planNum, 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); } public List ProductionReport(DateTime dateTime) { var dt = dateTime.ToString("yyyy-MM-dd"); var woList = Context.Queryable() .LeftJoin((a, b) => a.Workorder == b.FkWorkorder) .LeftJoin((a, b, c) => a.LineCode == c.Code) .LeftJoin((a, b, c, d) => a.GroupCode == d.GroupCode) .Where((a, b, c, d) => a.WorkorderDate.Value.ToString("yyyy-MM-dd") == dt) .Select((a, b, c, d) => new ProductionReportModel { WorkOrder = a.Workorder, ProductionName = a.ProductionName, PlanNum = a.DeliveryNum ?? 0, CompletionNum = b.FinishedNum ?? 0, CompletionRate = SqlFunc.Round((b.FinishedNum ?? 0) * 100.0 / (a.DeliveryNum ?? 0), 2), QualifiedRate = b.FinishedNum.HasValue ? SqlFunc.Round((b.QualifiedNumber ?? 0) * 100.0 / (b.FinishedNum ?? 0), 2) : 0, UnqualifiedRate = b.FinishedNum.HasValue ? SqlFunc.Round((b.UnqualifiedNumber ?? 0) * 100.0 / (b.FinishedNum ?? 0), 2) : 0, Status = a.Status, LineName = c.Name, GroupName = d.GroupName }).ToList(); woList.ForEach(t => t.StatusName = GetStatusName(t.Status ?? 0)); return woList; } public ProductionReportToalRate ProductionReportRate(DateTime dateTime, int type) { DateTime startDate, endDate; if (type == 1) { var dateRange = GetWeekRange(dateTime); startDate = dateRange.StartOfWeek; endDate = dateRange.EndOfWeek; } else { var dateRange = GetMonthRange(dateTime); startDate = dateRange.StartOfMonth; endDate = dateRange.EndOfMonth; } var woList = Context.Queryable() .LeftJoin((a, b) => a.Workorder == b.FkWorkorder) .Where((a, b) => a.WorkorderDate >= startDate && a.WorkorderDate <= endDate) .Select((a, b) => new { PlanNum = a.DeliveryNum ?? 0, CompletionNum = b.FinishedNum ?? 0, QualifiedNumber = b.QualifiedNumber ?? 0, UnqualifiedNumber = b.UnqualifiedNumber ?? 0 }).ToList(); var totalPlanNum = woList.Sum(t => t.PlanNum); var totalCompletionNum = woList.Sum(t => t.CompletionNum); var totalQualifiedNum = woList.Sum(t => t.QualifiedNumber); var totalUnqualifiedNum = woList.Sum(t => t.UnqualifiedNumber); ProductionReportToalRate rate = new ProductionReportToalRate() { CompleteRate = totalPlanNum == 0 ? 0 : Math.Round(totalCompletionNum * 100.0 / totalPlanNum, 2), QualifiedRate = totalCompletionNum == 0 ? 0 : Math.Round(totalQualifiedNum * 100.0 / totalCompletionNum, 2), UnqualifiedRate = totalCompletionNum == 0 ? 0 : Math.Round(totalUnqualifiedNum * 100.0 / totalCompletionNum, 2) }; return rate; } private (DateTime StartOfWeek, DateTime EndOfWeek) GetWeekRange(DateTime date) { // 计算本周第一天(周一) int diff = (7 + (date.DayOfWeek - DayOfWeek.Monday)) % 7; DateTime startOfWeek = date.AddDays(-1 * diff).Date; // 计算本周最后一天(周日) DateTime endOfWeek = startOfWeek.AddDays(6); return (startOfWeek, endOfWeek); } // 获取当月时间范围 private (DateTime StartOfMonth, DateTime EndOfMonth) GetMonthRange(DateTime date) { // 本月第一天 DateTime startOfMonth = new DateTime(date.Year, date.Month, 1); // 本月最后一天 int daysInMonth = DateTime.DaysInMonth(date.Year, date.Month); DateTime endOfMonth = new DateTime(date.Year, date.Month, daysInMonth); return (startOfMonth, endOfMonth); } public ProductionReportRateModel ProductionReportRate2(DateTime dateTime) { var dt = dateTime.ToString("yyyy-MM-dd"); ProductionReportRateModel model = new ProductionReportRateModel(); var productionCompletionRate = ProductionCompletionRate("", dateTime); model.CompletionRateList = productionCompletionRate.Select(t => new ProductionReportRate { WorkTimePeriod = t.WorkTimePeriod, Rate = t.CompletionRate }).ToList(); string sql = @"SELECT FROM_UNIXTIME( FLOOR( UNIX_TIMESTAMP( d.created_time ) / 3600 ) * 3600 ) AS TimePeriod, sum(number) AS Count FROM pro_workorder AS r RIGHT JOIN qc_finishedproduct_defect_collection AS d ON r.workorder = d.workorder WHERE r.workorder_date = @dt GROUP BY FLOOR( UNIX_TIMESTAMP( d.created_time ) / 600 ) ORDER BY TimePeriod"; var defectList = Context.Ado.SqlQuery(sql, new { dt = dt, }); var tempList = defectList.Select(t => new { Count = t.Count, WorkTimePeriod = t.TimePeriod.ToString("HH:00") } ).ToList(); productionCompletionRate.ForEach(t => { var defectModel = tempList.Where(d => d.WorkTimePeriod == t.WorkTimePeriod).FirstOrDefault(); var rate= defectModel==null ? 0 : Math.Round(defectModel.Count * 100.0 / t.DeliveryNum, 2); model.UnqualifiedRateList.Add(new ProductionReportRate { WorkTimePeriod = t.WorkTimePeriod, Rate = rate }); model.QualifiedRateList.Add(new ProductionReportRate { WorkTimePeriod = t.WorkTimePeriod, Rate = 100 - rate }); }); return model; } } }