|
|
|
|
@ -1,149 +1,25 @@
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using Dapper;
|
|
|
|
|
using MySqlConnector;
|
|
|
|
|
using CncModels.Entity;
|
|
|
|
|
using CncModels.Enum;
|
|
|
|
|
using log4net;
|
|
|
|
|
|
|
|
|
|
namespace CncCollector.Core
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 日终汇总作业。
|
|
|
|
|
/// 在配置的时间(默认01:00)执行,结账所有活跃段,汇总日产量数据。
|
|
|
|
|
/// </summary>
|
|
|
|
|
public class DailySummaryJob
|
|
|
|
|
{
|
|
|
|
|
private static readonly ILog _log = LogManager.GetLogger(typeof(DailySummaryJob));
|
|
|
|
|
|
|
|
|
|
private readonly string _businessConnStr;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 初始化日终汇总作业
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="businessConnStr">业务库连接字符串</param>
|
|
|
|
|
public DailySummaryJob(string businessConnStr)
|
|
|
|
|
{
|
|
|
|
|
_businessConnStr = businessConnStr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 执行日终汇总,汇总指定日期的产量数据
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="summaryDate">要汇总的日期(通常为昨天)</param>
|
|
|
|
|
/// <returns>true=汇总成功,false=汇总失败(可重试)</returns>
|
|
|
|
|
public bool Execute(DateTime summaryDate)
|
|
|
|
|
{
|
|
|
|
|
_log.Info($"========== 日终汇总开始(日期={summaryDate:yyyy-MM-dd}) ==========");
|
|
|
|
|
var sw = System.Diagnostics.Stopwatch.StartNew();
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
using (var conn = new MySqlConnection(_businessConnStr))
|
|
|
|
|
{
|
|
|
|
|
conn.Open();
|
|
|
|
|
using (var tran = conn.BeginTransaction())
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
// 1. 结账所有活跃段(end_of_day)
|
|
|
|
|
conn.Execute(@"UPDATE cnc_production_segment
|
|
|
|
|
SET end_time = COALESCE(end_time, NOW()),
|
|
|
|
|
close_reason = @Reason, is_settled = 1, updated_at = NOW()
|
|
|
|
|
WHERE is_settled = 0 AND DATE(start_time) <= @Date",
|
|
|
|
|
new { Reason = SegmentCloseReason.EndOfDay, Date = summaryDate }, tran);
|
|
|
|
|
|
|
|
|
|
// 2. 为 quantity 为 NULL 的段计算产量
|
|
|
|
|
conn.Execute(@"UPDATE cnc_production_segment
|
|
|
|
|
SET quantity = GREATEST(0, COALESCE(end_part_count, 0) - start_part_count)
|
|
|
|
|
WHERE quantity IS NULL AND is_settled = 1 AND DATE(start_time) <= @Date",
|
|
|
|
|
new { Date = summaryDate }, tran);
|
|
|
|
|
|
|
|
|
|
// 3. 按 (machine_id, production_date, program_name) 汇总到 cnc_daily_production
|
|
|
|
|
// 先删除旧汇总(幂等)
|
|
|
|
|
conn.Execute(@"DELETE FROM cnc_daily_production WHERE production_date = @Date",
|
|
|
|
|
new { Date = summaryDate }, tran);
|
|
|
|
|
|
|
|
|
|
// 插入新汇总
|
|
|
|
|
conn.Execute(@"INSERT INTO cnc_daily_production (machine_id, production_date, program_name, total_quantity, segment_count, total_run_time, total_cutting_time, total_cycle_time, created_at, updated_at)
|
|
|
|
|
SELECT machine_id, @Date, program_name,
|
|
|
|
|
SUM(COALESCE(quantity, 0)),
|
|
|
|
|
COUNT(*),
|
|
|
|
|
NULL, NULL, NULL,
|
|
|
|
|
NOW(), NOW()
|
|
|
|
|
FROM cnc_production_segment
|
|
|
|
|
WHERE DATE(start_time) = @Date AND is_settled = 1
|
|
|
|
|
GROUP BY machine_id, program_name",
|
|
|
|
|
new { Date = summaryDate }, tran);
|
|
|
|
|
|
|
|
|
|
// 4. 汇总到 cnc_worker_daily_summary(通过绑定关系)
|
|
|
|
|
conn.Execute(@"DELETE FROM cnc_worker_daily_summary WHERE production_date = @Date",
|
|
|
|
|
new { Date = summaryDate }, tran);
|
|
|
|
|
|
|
|
|
|
conn.Execute(@"INSERT INTO cnc_worker_daily_summary (worker_id, production_date, total_quantity, machine_count, program_count, created_at, updated_at)
|
|
|
|
|
SELECT wm.worker_id, @Date,
|
|
|
|
|
SUM(dp.total_quantity),
|
|
|
|
|
COUNT(DISTINCT dp.machine_id),
|
|
|
|
|
COUNT(DISTINCT dp.program_name),
|
|
|
|
|
NOW(), NOW()
|
|
|
|
|
FROM cnc_daily_production dp
|
|
|
|
|
INNER JOIN cnc_worker_machine wm ON dp.machine_id = wm.machine_id
|
|
|
|
|
WHERE dp.production_date = @Date
|
|
|
|
|
GROUP BY wm.worker_id",
|
|
|
|
|
new { Date = summaryDate }, tran);
|
|
|
|
|
|
|
|
|
|
// 5. 更新 cnc_machine_daily_status
|
|
|
|
|
conn.Execute(@"DELETE FROM cnc_machine_daily_status WHERE production_date = @Date",
|
|
|
|
|
new { Date = summaryDate }, tran);
|
|
|
|
|
|
|
|
|
|
// 有采集记录的 → normal
|
|
|
|
|
conn.Execute(@"INSERT INTO cnc_machine_daily_status (machine_id, production_date, data_status, created_at, updated_at)
|
|
|
|
|
SELECT DISTINCT machine_id, @Date, 'normal', NOW(), NOW()
|
|
|
|
|
FROM cnc_collect_record WHERE DATE(collect_time) = @Date",
|
|
|
|
|
new { Date = summaryDate }, tran);
|
|
|
|
|
|
|
|
|
|
// 未开机 → offline
|
|
|
|
|
conn.Execute(@"INSERT INTO cnc_machine_daily_status (machine_id, production_date, data_status, created_at, updated_at)
|
|
|
|
|
SELECT m.id, @Date, 'offline', NOW(), NOW()
|
|
|
|
|
FROM cnc_machine m
|
|
|
|
|
WHERE m.is_enabled = 1 AND m.id NOT IN (
|
|
|
|
|
SELECT DISTINCT machine_id FROM cnc_collect_record WHERE DATE(collect_time) = @Date
|
|
|
|
|
) AND m.id NOT IN (
|
|
|
|
|
SELECT machine_id FROM cnc_machine_daily_status WHERE production_date = @Date
|
|
|
|
|
)",
|
|
|
|
|
new { Date = summaryDate }, tran);
|
|
|
|
|
|
|
|
|
|
tran.Commit();
|
|
|
|
|
}
|
|
|
|
|
catch
|
|
|
|
|
{
|
|
|
|
|
tran.Rollback();
|
|
|
|
|
throw;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sw.Stop();
|
|
|
|
|
_log.Info($"========== 日终汇总完成(日期={summaryDate:yyyy-MM-dd}, 耗时={sw.ElapsedMilliseconds}ms) ==========");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
_log.Error($"日终汇总失败(日期={summaryDate:yyyy-MM-dd})", ex);
|
|
|
|
|
// 写入告警:日终汇总失败意味着产量统计缺失
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
using (var conn2 = new MySqlConnection(_businessConnStr))
|
|
|
|
|
{
|
|
|
|
|
conn2.Execute(@"INSERT INTO cnc_alert (alert_type, title, detail, is_resolved, created_at)
|
|
|
|
|
VALUES (@Type, @Title, @Detail, 0, NOW())",
|
|
|
|
|
new { Type = "summary_error", Title = $"日终汇总失败({summaryDate:yyyy-MM-dd})",
|
|
|
|
|
Detail = ex.Message });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch { /* 告警写入失败不影响主流程 */ }
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
_log.Info(string.Format("日终汇总已跳过(新架构ProductionTracker直接写cnc_daily_production,日期={0:yyyy-MM-dd})", summaryDate));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|