using System; using System.Collections.Generic; using System.Linq; using Dapper; using CncModels.Entity; using CncModels.Dto.Production; using CncModels.Dto; using CncRepository.Base; using CncRepository.Interface; namespace CncRepository.Impl { /// /// cnc_daily_production 产量仓储实现(业务库) /// public class DailyProductionRepository : BusinessRepository, IDailyProductionRepository { public DailyProductionRepository(string connectionString) : base(connectionString) { } public DailyProduction GetById(int id) { using (var conn = CreateConnection()) { string sql = "SELECT * FROM cnc_daily_production WHERE id = @Id"; return conn.QuerySingleOrDefault(sql, new { Id = id }); } } public PagedResult GetList(ProductionQuery query) { using (var conn = CreateConnection()) { var parameters = new DynamicParameters(); string baseSql = @"SELECT dp.machine_id AS MachineId, m.name AS MachineName, dp.program_name AS ProgramName, dp.production_date AS ProductionDate, CAST(dp.total_quantity AS SIGNED) AS Quantity, dp.segment_count AS SegmentCount, dp.total_run_time AS TotalRunTime, dp.total_cutting_time AS TotalCuttingTime FROM cnc_daily_production dp JOIN cnc_machine m ON dp.machine_id = m.id WHERE dp.total_quantity > 0"; string realtimeSql = @"SELECT seg.machine_id AS MachineId, m.name AS MachineName, seg.program_name AS ProgramName, seg.production_date AS ProductionDate, CAST(SUM(CASE WHEN seg.is_settled=1 THEN seg.quantity ELSE COALESCE(seg.end_part_count, seg.start_part_count) - seg.start_part_count END) AS SIGNED) AS Quantity, COUNT(*) AS SegmentCount, 0 AS TotalRunTime, 0 AS TotalCuttingTime FROM cnc_production_segment seg JOIN cnc_machine m ON seg.machine_id = m.id WHERE 1=1"; if (query?.WorkshopId.HasValue == true) { baseSql += " AND m.workshop_id = @WorkshopId"; realtimeSql += " AND m.workshop_id = @WorkshopId"; parameters.Add("WorkshopId", query.WorkshopId); } if (query?.MachineId.HasValue == true) { baseSql += " AND dp.machine_id = @MachineId"; realtimeSql += " AND seg.machine_id = @MachineId"; parameters.Add("MachineId", query.MachineId); } if (query?.WorkerId.HasValue == true) { baseSql += " AND EXISTS (SELECT 1 FROM cnc_worker_machine wm WHERE wm.machine_id = dp.machine_id AND wm.worker_id = @WorkerId)"; realtimeSql += " AND EXISTS (SELECT 1 FROM cnc_worker_machine wm WHERE wm.machine_id = seg.machine_id AND wm.worker_id = @WorkerId)"; parameters.Add("WorkerId", query.WorkerId); } realtimeSql += " GROUP BY seg.machine_id, seg.production_date, seg.program_name, m.name"; string unionSql = $"{baseSql} UNION ALL {realtimeSql}"; string countSql = $"SELECT COUNT(*) FROM ({unionSql}) AS t"; int offset = (query.Page - 1) * query.PageSize; string paging = $" ORDER BY ProductionDate DESC, MachineName LIMIT @Limit OFFSET @Offset"; parameters.Add("Limit", query.PageSize); parameters.Add("Offset", offset); var items = conn.Query(unionSql + paging, parameters).ToList(); int total = conn.ExecuteScalar(countSql, parameters); return new PagedResult { Items = items, Total = total, Page = query.Page, PageSize = query.PageSize }; } } public List GetByMachineAndDate(int machineId, DateTime date) { using (var conn = CreateConnection()) { string sql = "SELECT * FROM cnc_daily_production WHERE machine_id = @MachineId AND production_date = @Date"; return conn.Query(sql, new { MachineId = machineId, Date = date }).ToList(); } } public List GetByDateRange(DateTime startDate, DateTime endDate) { using (var conn = CreateConnection()) { string sql = @"SELECT dp.* FROM cnc_daily_production dp LEFT JOIN cnc_machine m ON dp.machine_id = m.id WHERE dp.production_date BETWEEN @Start AND @End ORDER BY dp.production_date DESC"; return conn.Query(sql, new { Start = startDate, End = endDate }).ToList(); } } public decimal GetTotalByDateRange(DateTime startDate, DateTime endDate, int? workshopId) { using (var conn = CreateConnection()) { string sql = @"SELECT SUM(dp.total_quantity) FROM cnc_daily_production dp LEFT JOIN cnc_machine m ON dp.machine_id = m.id WHERE dp.production_date BETWEEN @Start AND @End"; if (workshopId.HasValue) { sql += " AND m.workshop_id = @WorkshopId"; return conn.ExecuteScalar(sql, new { Start = startDate, End = endDate, WorkshopId = workshopId.Value }); } return conn.ExecuteScalar(sql, new { Start = startDate, End = endDate }); } } public decimal GetTotalByWorkerAndDateRange(int workerId, DateTime startDate, DateTime endDate) { using (var conn = CreateConnection()) { string sql = @"SELECT SUM(total_quantity) FROM cnc_daily_production WHERE production_date BETWEEN @Start AND @End"; var res = conn.ExecuteScalar(sql, new { Start = startDate, End = endDate }); return res ?? 0m; } } public List GetMachineRankByDateRange(DateTime startDate, DateTime endDate, int top) { using (var conn = CreateConnection()) { string sql = @"SELECT m.id AS Id, m.id AS MachineId, m.name AS MachineName, SUM(dp.total_quantity) AS TotalQuantity, NULL AS ProgramName, NULL AS ProductionDate, NULL AS SegmentCount, NULL AS TotalRunTime, NULL AS TotalCuttingTime, NULL AS TotalCycleTime FROM cnc_daily_production dp JOIN cnc_machine m ON dp.machine_id = m.id WHERE dp.production_date BETWEEN @Start AND @End GROUP BY m.id, m.name ORDER BY SUM(dp.total_quantity) DESC LIMIT @Top"; return conn.Query(sql, new { Start = startDate, End = endDate, Top = top }).ToList(); } } public List GetWorkerRankByDateRange(DateTime startDate, DateTime endDate, int top) { using (var conn = CreateConnection()) { string sql = @"SELECT 0 AS Id, NULL AS MachineId, NULL AS MachineName, SUM(total_quantity) AS TotalQuantity, NULL AS ProductionDate, NULL AS ProgramName, NULL AS SegmentCount, NULL AS TotalRunTime, NULL AS TotalCuttingTime, NULL AS TotalCycleTime FROM cnc_daily_production WHERE production_date BETWEEN @Start AND @End GROUP BY machine_id ORDER BY SUM(total_quantity) DESC LIMIT @Top"; return conn.Query(sql, new { Start = startDate, End = endDate, Top = top }).ToList(); } } #region 三维度产量报表 public MachineProductionSummaryResponse GetMachineSummary(DateTime startDate, DateTime endDate, int? workshopId) { using (var conn = CreateConnection()) { string sql = @"SELECT COALESCE(SUM(CASE WHEN seg.is_settled=1 THEN seg.quantity ELSE COALESCE(seg.end_part_count, seg.start_part_count) - seg.start_part_count END), 0) AS TotalQuantity, COUNT(DISTINCT seg.machine_id) AS RunningMachineCount FROM cnc_production_segment seg LEFT JOIN cnc_machine m ON seg.machine_id = m.id WHERE seg.production_date BETWEEN @Start AND @End"; var parameters = new DynamicParameters(); parameters.Add("Start", startDate); parameters.Add("End", endDate); if (workshopId.HasValue) { sql += " AND m.workshop_id = @WorkshopId"; parameters.Add("WorkshopId", workshopId.Value); } var result = conn.QuerySingleOrDefault(sql, parameters); if (result == null) return new MachineProductionSummaryResponse(); if (result.RunningMachineCount > 0) result.AvgPerMachine = Math.Round((decimal)result.TotalQuantity / result.RunningMachineCount, 1); string topSql = @"SELECT m.name FROM cnc_production_segment seg LEFT JOIN cnc_machine m ON seg.machine_id = m.id WHERE seg.production_date BETWEEN @Start AND @End"; if (workshopId.HasValue) topSql += " AND m.workshop_id = @WorkshopId"; topSql += @" GROUP BY seg.machine_id ORDER BY SUM(CASE WHEN seg.is_settled=1 THEN seg.quantity ELSE COALESCE(seg.end_part_count, seg.start_part_count) - seg.start_part_count END) DESC LIMIT 1"; result.TopMachineName = conn.ExecuteScalar(topSql, parameters) ?? ""; return result; } } public List GetMachineList(DateTime startDate, DateTime endDate, int? workshopId, int? machineId) { using (var conn = CreateConnection()) { string sql = @"SELECT m.name AS MachineName, seg.program_name AS ProgramName, SUM(CASE WHEN seg.is_settled=1 THEN seg.quantity ELSE COALESCE(seg.end_part_count, seg.start_part_count) - seg.start_part_count END) AS TotalQuantity, cr_runtime.run_hours AS RunTime FROM cnc_production_segment seg LEFT JOIN cnc_machine m ON seg.machine_id = m.id LEFT JOIN ( SELECT cr.machine_id, DATE(cr.collect_time) AS d, COALESCE(ROUND(SUM(max_min.delta)/3600,1), 0) AS run_hours FROM cnc_collect_record cr JOIN (SELECT machine_id, DATE(collect_time) AS dd, MAX(cutting_time)-MIN(cutting_time) AS delta FROM cnc_collect_record GROUP BY machine_id, DATE(collect_time)) max_min ON cr.machine_id = max_min.machine_id AND DATE(cr.collect_time) = max_min.dd GROUP BY cr.machine_id, DATE(cr.collect_time) ) cr_runtime ON cr_runtime.machine_id = seg.machine_id AND cr_runtime.d = seg.production_date WHERE seg.production_date BETWEEN @Start AND @End"; var parameters = new DynamicParameters(); parameters.Add("Start", startDate); parameters.Add("End", endDate); if (workshopId.HasValue) { sql += " AND m.workshop_id = @WorkshopId"; parameters.Add("WorkshopId", workshopId.Value); } if (machineId.HasValue) { sql += " AND seg.machine_id = @MachineId"; parameters.Add("MachineId", machineId.Value); } sql += " GROUP BY seg.machine_id, seg.program_name, m.name, cr_runtime.run_hours ORDER BY TotalQuantity DESC"; var items = conn.Query(sql, parameters).ToList(); for (int i = 0; i < items.Count; i++) { items[i].Rank = i + 1; items[i].DayStatus = items[i].DayStatus ?? ""; } return items; } } public WorkerProductionSummaryResponse GetWorkerSummary(DateTime startDate, DateTime endDate) { using (var conn = CreateConnection()) { string sql = @"SELECT COALESCE(SUM(CASE WHEN seg.is_settled=1 THEN seg.quantity ELSE COALESCE(seg.end_part_count, seg.start_part_count) - seg.start_part_count END), 0) AS TotalQuantity, COUNT(DISTINCT w.id) AS ActiveWorkerCount FROM cnc_production_segment seg JOIN cnc_worker_machine wm ON seg.machine_id = wm.machine_id JOIN cnc_worker w ON wm.worker_id = w.id WHERE seg.production_date BETWEEN @Start AND @End"; var result = conn.QuerySingleOrDefault(sql, new { Start = startDate, End = endDate }); if (result == null) return new WorkerProductionSummaryResponse(); if (result.ActiveWorkerCount > 0) result.AvgPerWorker = Math.Round((decimal)result.TotalQuantity / result.ActiveWorkerCount, 1); string topSql = @"SELECT w.name FROM cnc_production_segment seg JOIN cnc_worker_machine wm ON seg.machine_id = wm.machine_id JOIN cnc_worker w ON wm.worker_id = w.id WHERE seg.production_date BETWEEN @Start AND @End GROUP BY w.id, w.name ORDER BY SUM(CASE WHEN seg.is_settled=1 THEN seg.quantity ELSE COALESCE(seg.end_part_count, seg.start_part_count) - seg.start_part_count END) DESC LIMIT 1"; result.TopWorkerName = conn.ExecuteScalar(topSql, new { Start = startDate, End = endDate }) ?? ""; return result; } } public List GetWorkerList(DateTime startDate, DateTime endDate, int? workerId) { using (var conn = CreateConnection()) { string sql = @"SELECT w.name AS WorkerName, COUNT(DISTINCT wm.machine_id) AS MachineCount, COUNT(DISTINCT seg.program_name) AS ProgramCount, COALESCE(SUM(CASE WHEN seg.is_settled=1 THEN seg.quantity ELSE COALESCE(seg.end_part_count, seg.start_part_count) - seg.start_part_count END), 0) AS TotalQuantity FROM cnc_worker w JOIN cnc_worker_machine wm ON wm.worker_id = w.id LEFT JOIN cnc_production_segment seg ON seg.machine_id = wm.machine_id AND seg.production_date BETWEEN @Start AND @End"; var parameters = new DynamicParameters(); parameters.Add("Start", startDate); parameters.Add("End", endDate); if (workerId.HasValue) { sql += " AND w.id = @WorkerId"; parameters.Add("WorkerId", workerId.Value); } sql += " GROUP BY w.id, w.name ORDER BY TotalQuantity DESC"; var items = conn.Query(sql, parameters).ToList(); if (items.Count > 0) { int grandTotal = items.Sum(x => x.TotalQuantity); for (int i = 0; i < items.Count; i++) { items[i].Rank = i + 1; if (grandTotal > 0) items[i].Percentage = Math.Round((decimal)items[i].TotalQuantity / grandTotal * 100, 1); } } return items; } } public ProgramProductionSummaryResponse GetProgramSummary(DateTime startDate, DateTime endDate, int? workshopId) { using (var conn = CreateConnection()) { string sql = @"SELECT COALESCE(SUM(CASE WHEN seg.is_settled=1 THEN seg.quantity ELSE COALESCE(seg.end_part_count, seg.start_part_count) - seg.start_part_count END), 0) AS TotalQuantity, COUNT(DISTINCT seg.program_name) AS RunningProgramCount FROM cnc_production_segment seg LEFT JOIN cnc_machine m ON seg.machine_id = m.id WHERE seg.production_date BETWEEN @Start AND @End"; var parameters = new DynamicParameters(); parameters.Add("Start", startDate); parameters.Add("End", endDate); if (workshopId.HasValue) { sql += " AND m.workshop_id = @WorkshopId"; parameters.Add("WorkshopId", workshopId.Value); } var result = conn.QuerySingleOrDefault(sql, parameters); if (result == null) return new ProgramProductionSummaryResponse(); if (result.RunningProgramCount > 0) result.AvgPerProgram = Math.Round((decimal)result.TotalQuantity / result.RunningProgramCount, 1); string topSql = @"SELECT seg.program_name FROM cnc_production_segment seg LEFT JOIN cnc_machine m ON seg.machine_id = m.id WHERE seg.production_date BETWEEN @Start AND @End"; if (workshopId.HasValue) topSql += " AND m.workshop_id = @WorkshopId"; topSql += @" GROUP BY seg.program_name ORDER BY SUM(CASE WHEN seg.is_settled=1 THEN seg.quantity ELSE COALESCE(seg.end_part_count, seg.start_part_count) - seg.start_part_count END) DESC LIMIT 1"; result.TopProgramName = conn.ExecuteScalar(topSql, parameters) ?? ""; return result; } } public List GetProgramList(DateTime startDate, DateTime endDate, string programName) { using (var conn = CreateConnection()) { string sql = @"SELECT seg.program_name AS ProgramName, COUNT(DISTINCT seg.machine_id) AS MachineCount, COALESCE(SUM(CASE WHEN seg.is_settled=1 THEN seg.quantity ELSE COALESCE(seg.end_part_count, seg.start_part_count) - seg.start_part_count END), 0) AS TotalQuantity FROM cnc_production_segment seg LEFT JOIN cnc_machine m ON seg.machine_id = m.id WHERE seg.production_date BETWEEN @Start AND @End"; var parameters = new DynamicParameters(); parameters.Add("Start", startDate); parameters.Add("End", endDate); if (!string.IsNullOrWhiteSpace(programName)) { sql += " AND seg.program_name = @ProgramName"; parameters.Add("ProgramName", programName); } sql += " GROUP BY seg.program_name ORDER BY TotalQuantity DESC"; var items = conn.Query(sql, parameters).ToList(); if (items.Count > 0) { int grandTotal = items.Sum(x => x.TotalQuantity); for (int i = 0; i < items.Count; i++) { items[i].Rank = i + 1; if (items[i].MachineCount > 0) items[i].AvgPerMachine = Math.Round((decimal)items[i].TotalQuantity / items[i].MachineCount, 1); if (grandTotal > 0) items[i].Percentage = Math.Round((decimal)items[i].TotalQuantity / grandTotal * 100, 1); } } return items; } } #endregion } }