新增产量报表三维度API端点(机床/员工/程序各含summary+list),从cnc_production_segment实时计算

main
haoliang 1 month ago
parent a781dfabb8
commit 56f00f4558

@ -0,0 +1,26 @@
namespace CncModels.Dto.Production
{
/// <summary>
/// 机床产量明细列表项(机床维度排行)
/// </summary>
public class MachineProductionListItem
{
/// <summary>排行名次</summary>
public int Rank { get; set; }
/// <summary>机床名称</summary>
public string MachineName { get; set; }
/// <summary>程序名</summary>
public string ProgramName { get; set; }
/// <summary>总产量</summary>
public int TotalQuantity { get; set; }
/// <summary>运行时长(小时)</summary>
public decimal? RunTime { get; set; }
/// <summary>日夜班标识</summary>
public string DayStatus { get; set; }
}
}

@ -0,0 +1,26 @@
namespace CncModels.Dto.Production
{
/// <summary>
/// 程序产量明细列表项(程序维度排行)
/// </summary>
public class ProgramProductionListItem
{
/// <summary>排行名次</summary>
public int Rank { get; set; }
/// <summary>程序名</summary>
public string ProgramName { get; set; }
/// <summary>使用机床数</summary>
public int MachineCount { get; set; }
/// <summary>总产量</summary>
public int TotalQuantity { get; set; }
/// <summary>平均单机产量</summary>
public decimal AvgPerMachine { get; set; }
/// <summary>产量占比(百分比)</summary>
public decimal Percentage { get; set; }
}
}

@ -0,0 +1,26 @@
namespace CncModels.Dto.Production
{
/// <summary>
/// 员工产量明细列表项(员工维度排行)
/// </summary>
public class WorkerProductionListItem
{
/// <summary>排行名次</summary>
public int Rank { get; set; }
/// <summary>员工姓名</summary>
public string WorkerName { get; set; }
/// <summary>操作机床数</summary>
public int MachineCount { get; set; }
/// <summary>程序数量</summary>
public int ProgramCount { get; set; }
/// <summary>总产量</summary>
public int TotalQuantity { get; set; }
/// <summary>产量占比(百分比)</summary>
public decimal Percentage { get; set; }
}
}

@ -198,5 +198,306 @@ namespace CncRepository.Impl
return conn.Query<DailyProduction>(sql, new { Start = startDate, End = endDate, Top = top }).ToList();
}
}
#region 三维度产量报表
/// <summary>
/// 机床维度统计卡片从cnc_production_segment实时计算
/// </summary>
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<MachineProductionSummaryResponse>(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<string>(topSql, parameters) ?? "";
return result;
}
}
/// <summary>
/// 机床维度明细列表(按机床+程序聚合,产量降序)
/// </summary>
public List<MachineProductionListItem> 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<MachineProductionListItem>(sql, parameters).ToList();
// 计算排行和日夜班标识
for (int i = 0; i < items.Count; i++)
{
items[i].Rank = i + 1;
items[i].DayStatus = items[i].DayStatus ?? "";
}
return items;
}
}
/// <summary>
/// 员工维度统计卡片通过cnc_worker_machine关联产量分段表
/// </summary>
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<WorkerProductionSummaryResponse>(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<string>(topSql, new { Start = startDate, End = endDate }) ?? "";
return result;
}
}
/// <summary>
/// 员工维度明细列表通过cnc_worker_machine关联产量降序
/// </summary>
public List<WorkerProductionListItem> 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<WorkerProductionListItem>(sql, parameters).ToList();
if (items.Count == 0) return items;
// 计算总量用于百分比
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;
}
}
/// <summary>
/// 程序维度统计卡片按program_name聚合
/// </summary>
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<ProgramProductionSummaryResponse>(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<string>(topSql, parameters) ?? "";
return result;
}
}
/// <summary>
/// 程序维度明细列表按program_name聚合产量降序
/// </summary>
public List<ProgramProductionListItem> 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<ProgramProductionListItem>(sql, parameters).ToList();
if (items.Count == 0) return items;
// 计算总量用于百分比
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
}
}

@ -19,5 +19,11 @@ namespace CncRepository.Interface
decimal GetTotalByWorkerAndDateRange(int workerId, DateTime startDate, DateTime endDate);
List<DailyProduction> GetMachineRankByDateRange(DateTime startDate, DateTime endDate, int top);
List<DailyProduction> GetWorkerRankByDateRange(DateTime startDate, DateTime endDate, int top);
MachineProductionSummaryResponse GetMachineSummary(DateTime startDate, DateTime endDate, int? workshopId);
List<MachineProductionListItem> GetMachineList(DateTime startDate, DateTime endDate, int? workshopId, int? machineId);
WorkerProductionSummaryResponse GetWorkerSummary(DateTime startDate, DateTime endDate);
List<WorkerProductionListItem> GetWorkerList(DateTime startDate, DateTime endDate, int? workerId);
ProgramProductionSummaryResponse GetProgramSummary(DateTime startDate, DateTime endDate, int? workshopId);
List<ProgramProductionListItem> GetProgramList(DateTime startDate, DateTime endDate, string programName);
}
}

@ -104,5 +104,53 @@ namespace CncService.Impl
}
return result;
}
/// <inheritdoc/>
public MachineProductionSummaryResponse GetMachineSummary(DateTime? startDate, DateTime? endDate, int? workshopId)
{
var s = startDate ?? DateTime.Today;
var e = endDate ?? DateTime.Today;
return _dailyProductionRepository.GetMachineSummary(s, e, workshopId);
}
/// <inheritdoc/>
public List<MachineProductionListItem> GetMachineList(DateTime? startDate, DateTime? endDate, int? workshopId, int? machineId)
{
var s = startDate ?? DateTime.Today;
var e = endDate ?? DateTime.Today;
return _dailyProductionRepository.GetMachineList(s, e, workshopId, machineId);
}
/// <inheritdoc/>
public WorkerProductionSummaryResponse GetWorkerSummary(DateTime? startDate, DateTime? endDate)
{
var s = startDate ?? DateTime.Today;
var e = endDate ?? DateTime.Today;
return _dailyProductionRepository.GetWorkerSummary(s, e);
}
/// <inheritdoc/>
public List<WorkerProductionListItem> GetWorkerList(DateTime? startDate, DateTime? endDate, int? workerId)
{
var s = startDate ?? DateTime.Today;
var e = endDate ?? DateTime.Today;
return _dailyProductionRepository.GetWorkerList(s, e, workerId);
}
/// <inheritdoc/>
public ProgramProductionSummaryResponse GetProgramSummary(DateTime? startDate, DateTime? endDate, int? workshopId)
{
var s = startDate ?? DateTime.Today;
var e = endDate ?? DateTime.Today;
return _dailyProductionRepository.GetProgramSummary(s, e, workshopId);
}
/// <inheritdoc/>
public List<ProgramProductionListItem> GetProgramList(DateTime? startDate, DateTime? endDate, string programName = null)
{
var s = startDate ?? DateTime.Today;
var e = endDate ?? DateTime.Today;
return _dailyProductionRepository.GetProgramList(s, e, programName);
}
}
}

@ -26,5 +26,23 @@ namespace CncService.Interface
/// 获取某条产量记录的修正历史
/// </summary>
List<AdjustmentHistoryItem> GetAdjustmentHistory(int recordId);
/// <summary>获取设备产量汇总(按日期范围)</summary>
MachineProductionSummaryResponse GetMachineSummary(DateTime? startDate, DateTime? endDate, int? workshopId);
/// <summary>获取设备产量明细列表(按日期范围)</summary>
List<MachineProductionListItem> GetMachineList(DateTime? startDate, DateTime? endDate, int? workshopId, int? machineId);
/// <summary>获取员工产量汇总(按日期范围)</summary>
WorkerProductionSummaryResponse GetWorkerSummary(DateTime? startDate, DateTime? endDate);
/// <summary>获取员工产量明细列表(按日期范围)</summary>
List<WorkerProductionListItem> GetWorkerList(DateTime? startDate, DateTime? endDate, int? workerId);
/// <summary>获取程序产量汇总(按日期范围)</summary>
ProgramProductionSummaryResponse GetProgramSummary(DateTime? startDate, DateTime? endDate, int? workshopId);
/// <summary>获取程序产量明细列表(按日期范围)</summary>
List<ProgramProductionListItem> GetProgramList(DateTime? startDate, DateTime? endDate, string programName);
}
}

@ -84,5 +84,77 @@ namespace CncWebApi.Controllers
// 导出功能暂不实现,返回提示
return Ok(ApiResponse<object>.Fail(40001, "导出功能尚未实现"));
}
/// <summary>
/// 机床维度统计卡片
/// GET /api/admin/production/machine/summary
/// </summary>
[HttpGet]
[Route("machine/summary")]
public IHttpActionResult GetMachineSummary(DateTime? startDate = null, DateTime? endDate = null, int? workshopId = null)
{
var result = _productionService.GetMachineSummary(startDate, endDate, workshopId);
return Ok(ApiResponse<MachineProductionSummaryResponse>.Success(result));
}
/// <summary>
/// 机床维度明细列表
/// GET /api/admin/production/machine/list
/// </summary>
[HttpGet]
[Route("machine/list")]
public IHttpActionResult GetMachineList(DateTime? startDate = null, DateTime? endDate = null, int? workshopId = null, int? machineId = null)
{
var result = _productionService.GetMachineList(startDate, endDate, workshopId, machineId);
return Ok(ApiResponse<object>.Success(new { items = result }));
}
/// <summary>
/// 员工维度统计卡片
/// GET /api/admin/production/worker/summary
/// </summary>
[HttpGet]
[Route("worker/summary")]
public IHttpActionResult GetWorkerSummary(DateTime? startDate = null, DateTime? endDate = null)
{
var result = _productionService.GetWorkerSummary(startDate, endDate);
return Ok(ApiResponse<WorkerProductionSummaryResponse>.Success(result));
}
/// <summary>
/// 员工维度明细列表
/// GET /api/admin/production/worker/list
/// </summary>
[HttpGet]
[Route("worker/list")]
public IHttpActionResult GetWorkerList(DateTime? startDate = null, DateTime? endDate = null, int? workerId = null)
{
var result = _productionService.GetWorkerList(startDate, endDate, workerId);
return Ok(ApiResponse<object>.Success(new { items = result }));
}
/// <summary>
/// 程序维度统计卡片
/// GET /api/admin/production/program/summary
/// </summary>
[HttpGet]
[Route("program/summary")]
public IHttpActionResult GetProgramSummary(DateTime? startDate = null, DateTime? endDate = null, int? workshopId = null)
{
var result = _productionService.GetProgramSummary(startDate, endDate, workshopId);
return Ok(ApiResponse<ProgramProductionSummaryResponse>.Success(result));
}
/// <summary>
/// 程序维度明细列表
/// GET /api/admin/production/program/list
/// </summary>
[HttpGet]
[Route("program/list")]
public IHttpActionResult GetProgramList(DateTime? startDate = null, DateTime? endDate = null, string programName = null)
{
var result = _productionService.GetProgramList(startDate, endDate, programName);
return Ok(ApiResponse<object>.Success(new { items = result }));
}
}
}

Loading…
Cancel
Save