1286 lines
54 KiB
C#
1286 lines
54 KiB
C#
using FreeSql;
|
||
using Microsoft.AspNetCore.Authorization;
|
||
using Microsoft.AspNetCore.Mvc;
|
||
using Microsoft.Extensions.Logging;
|
||
using NPP.SmartSchedue.Api.Contracts.Core.Enums;
|
||
using NPP.SmartSchedue.Api.Contracts.Domain.Integration;
|
||
using NPP.SmartSchedue.Api.Contracts.Domain.Work;
|
||
using NPP.SmartSchedue.Api.Contracts.Services.Integration;
|
||
using NPP.SmartSchedue.Api.Contracts.Services.Integration.Input;
|
||
using NPP.SmartSchedue.Api.Contracts.Services.Integration.Output;
|
||
using NPP.SmartSchedue.Api.Repositories.Work;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Text.Json;
|
||
using System.Threading.Tasks;
|
||
using ZhonTai.Admin.Services;
|
||
using ZhonTai.DynamicApi;
|
||
using ZhonTai.DynamicApi.Attributes;
|
||
|
||
namespace NPP.SmartSchedue.Api.Services.Integration
|
||
{
|
||
/// <summary>
|
||
/// 整合记录服务
|
||
/// </summary>
|
||
[DynamicApi(Area = "app")]
|
||
public partial class IntegrationRecordService : BaseService, IIntegrationRecordService, IDynamicApi
|
||
{
|
||
private readonly IIntegrationRecordRepository _integrationRecordRepository;
|
||
private readonly WorkOrderRepository _workOrderRepository;
|
||
private readonly ILogger<IntegrationRecordService> _logger;
|
||
|
||
public IntegrationRecordService(
|
||
IIntegrationRecordRepository integrationRecordRepository,
|
||
WorkOrderRepository workOrderRepository,
|
||
ILogger<IntegrationRecordService> logger)
|
||
{
|
||
_integrationRecordRepository = integrationRecordRepository;
|
||
_workOrderRepository = workOrderRepository;
|
||
_logger = logger;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 生成整合记录核心方法
|
||
/// 深度业务思考:按照文档5.1-5.5步骤实现完整的记录生成流程
|
||
/// </summary>
|
||
[HttpPost]
|
||
public async Task<IntegrationRecord> GenerateIntegrationRecordAsync(IntegrationRecordInput input)
|
||
{
|
||
try
|
||
{
|
||
// 5.1 整合记录数据准备
|
||
var batchCode = await GenerateUniqueBatchCodeAsync();
|
||
var taskEntities = await GetTaskEntitiesForRecordAsync(input.TaskIds);
|
||
var projectNumbers = ExtractProjectNumbers(taskEntities);
|
||
|
||
// 5.2 分配结果序列化
|
||
var strategyConfigJson = SerializeStrategyConfig(input.Strategy);
|
||
var personnelAllocationJson = SerializePersonnelAllocationResult(input.PersonnelAllocation);
|
||
var equipmentAllocationJson = SerializeEquipmentAllocationResult(input.EquipmentAllocation);
|
||
|
||
// 5.3 统计信息计算与记录
|
||
var statistics = await CalculateIntegrationStatisticsAsync(input);
|
||
var failureAnalysis = await GenerateFailureAnalysisAsync(input);
|
||
|
||
// 构建整合记录实体
|
||
var integrationRecord = new IntegrationRecordEntity
|
||
{
|
||
IntegrationBatchCode = batchCode,
|
||
IntegrationTime = DateTime.Now,
|
||
ProjectNumbers = string.Join(",", projectNumbers),
|
||
OriginalTaskCount = taskEntities.Count,
|
||
SuccessTaskCount = input.PersonnelAllocation?.SuccessfulMatches?.Count ?? 0,
|
||
FailedTaskCount = statistics.FailedTaskCount,
|
||
// SuccessRate is a calculated property
|
||
|
||
// 序列化结果存储
|
||
StrategyConfigJson = strategyConfigJson,
|
||
PersonnelAllocationResultJson = personnelAllocationJson,
|
||
EquipmentAllocationResultJson = equipmentAllocationJson,
|
||
TaskIdsJson = JsonSerializer.Serialize(input.TaskIds),
|
||
|
||
// 统计分析数据
|
||
ElapsedMilliseconds = statistics.ExecutionTimeMs,
|
||
PersonnelFairnessScore = input.PersonnelAllocation?.FairnessScore ?? 0,
|
||
EquipmentUtilizationRate = (decimal)(input.EquipmentAllocation?.OverallUtilizationRate ?? 0),
|
||
|
||
// 失败分析
|
||
FailureReasonStats = JsonSerializer.Serialize(failureAnalysis),
|
||
|
||
// 操作员信息
|
||
OperatorUserId = input.OperatorUserId,
|
||
OperatorUserName = input.OperatorName,
|
||
OperatorRealName = input.OperatorName,
|
||
Remarks = input.Remarks ?? "",
|
||
|
||
CreatedTime = DateTime.Now,
|
||
CreatedUserId = input.OperatorUserId,
|
||
CreatedUserName = input.OperatorName
|
||
};
|
||
|
||
// 5.4 数据库持久化与事务管理
|
||
var record = await _integrationRecordRepository.InsertAsync(integrationRecord);
|
||
|
||
// 创建关联数据
|
||
await CreateTaskIntegrationRelationsAsync(record.Id, taskEntities);
|
||
|
||
// 生成索引数据
|
||
await GenerateSearchIndexDataAsync(record.Id, taskEntities);
|
||
|
||
// 记录审计信息
|
||
await RecordAuditInfoAsync(record.Id, input.OperatorUserId);
|
||
|
||
// Transaction handled by UnitOfWork
|
||
|
||
_logger.LogInformation("整合记录生成成功: BatchCode={BatchCode}, RecordId={RecordId}",
|
||
batchCode, record.Id);
|
||
|
||
// 5.5 记录转换与API返回
|
||
return ConvertToIntegrationRecord(record);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
// Transaction handled by UnitOfWork
|
||
_logger.LogError(ex, "整合记录生成失败: {Message}", ex.Message);
|
||
throw new IntegrationRecordException($"记录生成失败: {ex.Message}", ex);
|
||
}
|
||
}
|
||
|
||
#region 5.1 整合记录数据准备
|
||
|
||
/// <summary>
|
||
/// 生成唯一批次编码
|
||
/// 格式:INT + yyyyMMddHHmmss + XXX,总长度23字符,符合数据库30字符限制
|
||
/// 业务思考:确保编码唯一性和数据库兼容性,与编排服务保持一致
|
||
/// </summary>
|
||
private async Task<string> GenerateUniqueBatchCodeAsync()
|
||
{
|
||
var timestamp = DateTime.Now.ToString("yyyyMMddHHmmss");
|
||
var random = new Random().Next(100, 999);
|
||
var batchCode = $"INT{timestamp}{random}";
|
||
|
||
// 唯一性验证
|
||
var exists = await _integrationRecordRepository
|
||
.Where(r => r.IntegrationBatchCode == batchCode)
|
||
.AnyAsync();
|
||
|
||
if (exists)
|
||
{
|
||
// 递归重新生成,增加延时避免时间戳冲突
|
||
await Task.Delay(1);
|
||
return await GenerateUniqueBatchCodeAsync();
|
||
}
|
||
|
||
return batchCode;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取任务实体数据
|
||
/// 包含关联数据的批量获取
|
||
/// </summary>
|
||
private async Task<List<WorkOrderEntity>> GetTaskEntitiesForRecordAsync(List<long> taskIds)
|
||
{
|
||
return await _workOrderRepository.Select
|
||
.Where(w => taskIds.Contains(w.Id))
|
||
.IncludeMany(w => w.WorkOrderFLPersonnels)
|
||
.Include(w => w.ShiftEntity)
|
||
.Include(w => w.ProcessEntity)
|
||
.ToListAsync();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 提取项目编号
|
||
/// 去重并格式化处理
|
||
/// </summary>
|
||
private List<string> ExtractProjectNumbers(List<WorkOrderEntity> tasks)
|
||
{
|
||
return tasks.Select(t => t.ProjectNumber)
|
||
.Where(pn => !string.IsNullOrEmpty(pn))
|
||
.Distinct()
|
||
.OrderBy(pn => pn)
|
||
.ToList();
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 5.2 分配结果序列化
|
||
|
||
/// <summary>
|
||
/// 策略配置序列化
|
||
/// 深度业务思考:保存完整的策略配置以便后续分析和重现
|
||
/// </summary>
|
||
private string SerializeStrategyConfig(IntegrationStrategy strategy)
|
||
{
|
||
if (strategy == null) return "{}";
|
||
|
||
var config = new
|
||
{
|
||
PersonnelStrategy = strategy.PersonnelStrategy.ToString() ?? "FairDistribution",
|
||
EquipmentStrategy = strategy.EquipmentStrategy.ToString() ?? "UtilizationBalance",
|
||
EnforceShiftRules = strategy.EnforceShiftRules,
|
||
TargetEquipmentUtilization = strategy.TargetEquipmentUtilization,
|
||
AllowCrossShiftAllocation = true,
|
||
PreferredPersonnelWeighting = 0.3,
|
||
FairnessWeighting = 0.4,
|
||
EfficiencyWeighting = 0.3
|
||
};
|
||
|
||
return JsonSerializer.Serialize(config, new JsonSerializerOptions
|
||
{
|
||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||
WriteIndented = true
|
||
});
|
||
}
|
||
|
||
/// <summary>
|
||
/// 人员分配结果序列化
|
||
/// 包含详细的匹配信息和分析数据
|
||
/// </summary>
|
||
private string SerializePersonnelAllocationResult(PersonnelAllocationResult result)
|
||
{
|
||
if (result == null) return "{}";
|
||
|
||
var serializedResult = new
|
||
{
|
||
SuccessfulMatches = (result.SuccessfulMatches?.Select(m => new
|
||
{
|
||
TaskId = m.TaskId,
|
||
TaskCode = m.TaskCode,
|
||
AssignedPersonnelId = m.PersonnelId,
|
||
PersonnelName = m.PersonnelName ?? "未知",
|
||
MatchScore = m.MatchScore,
|
||
MatchReason = m.MatchReason ?? "智能分配",
|
||
AllocationStrategy = "智能匹配"
|
||
}).ToList() as IEnumerable<object>) ?? new List<object>(),
|
||
|
||
FailedTasks = (result.FailedTasks?.Select(f => new
|
||
{
|
||
TaskId = f.TaskId,
|
||
TaskCode = f.TaskCode,
|
||
FailureReason = f.FailureReason,
|
||
FailureType = f.FailureType.ToString(),
|
||
ConflictDetails = f.ConflictDetails ?? new List<string>()
|
||
}).ToList() as IEnumerable<object>) ?? new List<object>(),
|
||
|
||
FairnessScore = result.FairnessScore,
|
||
WorkloadAnalysis = result.WorkloadAnalysis?.Cast<object>().ToList() ?? new List<object>(),
|
||
AllocationSummary = result.AllocationSummary ?? "人员分配完成"
|
||
};
|
||
|
||
return JsonSerializer.Serialize(serializedResult, new JsonSerializerOptions
|
||
{
|
||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||
WriteIndented = true
|
||
});
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设备分配结果序列化
|
||
/// 包含利用率分析和冲突解决信息
|
||
/// </summary>
|
||
private string SerializeEquipmentAllocationResult(EquipmentAllocationResult result)
|
||
{
|
||
if (result == null) return "{}";
|
||
|
||
var serializedResult = new
|
||
{
|
||
SuccessfulAllocations = (result.SuccessfulMatches?.Select(a => new
|
||
{
|
||
TaskId = a.TaskId,
|
||
EquipmentId = a.EquipmentId,
|
||
EquipmentCode = a.EquipmentCode ?? $"EQP-{a.EquipmentId}",
|
||
UtilizationRate = 0.75, // 示例值,实际需要计算
|
||
AllocationReason = a.AllocationReason ?? "利用率均衡分配"
|
||
}).ToList() as IEnumerable<object>) ?? new List<object>(),
|
||
|
||
FailedAllocations = (result.FailedAllocations?.Select(f => new
|
||
{
|
||
TaskId = f.TaskId,
|
||
TaskCode = f.TaskCode,
|
||
EquipmentType = "未知类型",
|
||
FailureReason = f.FailureReason,
|
||
SuggestedActions = f.ConflictDetails ?? new List<string>()
|
||
}).ToList() as IEnumerable<object>) ?? new List<object>(),
|
||
|
||
OverallUtilizationRate = result.OverallUtilizationRate,
|
||
EquipmentLoadBalance = new { /* 负载均衡数据 */ },
|
||
UtilizationReport = result.AllocationSummary ?? $"平均设备利用率{result.OverallUtilizationRate:F1}%"
|
||
};
|
||
|
||
return JsonSerializer.Serialize(serializedResult, new JsonSerializerOptions
|
||
{
|
||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||
WriteIndented = true
|
||
});
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 5.3 统计信息计算与记录
|
||
|
||
/// <summary>
|
||
/// 统计信息结构
|
||
/// </summary>
|
||
private class IntegrationStatistics
|
||
{
|
||
public int FailedTaskCount { get; set; }
|
||
public double SuccessRate { get; set; }
|
||
public long ExecutionTimeMs { get; set; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// 计算整合统计信息
|
||
/// </summary>
|
||
private async Task<IntegrationStatistics> CalculateIntegrationStatisticsAsync(IntegrationRecordInput input)
|
||
{
|
||
var successfulCount = input.PersonnelAllocation?.SuccessfulMatches?.Count ?? 0;
|
||
var totalTasks = input.TaskIds.Count;
|
||
var failedCount = totalTasks - successfulCount;
|
||
|
||
return new IntegrationStatistics
|
||
{
|
||
FailedTaskCount = failedCount,
|
||
SuccessRate = totalTasks > 0 ? (double)successfulCount / totalTasks : 0,
|
||
ExecutionTimeMs = 0 // 由调用方传入或计算
|
||
};
|
||
}
|
||
|
||
/// <summary>
|
||
/// 生成失败分析数据
|
||
/// 深度业务思考:详细分析失败原因,为系统优化提供数据支持
|
||
/// </summary>
|
||
private async Task<Dictionary<string, object>> GenerateFailureAnalysisAsync(IntegrationRecordInput input)
|
||
{
|
||
var failureAnalysis = new Dictionary<string, object>();
|
||
|
||
// 人员分配失败分析
|
||
if (input.PersonnelAllocation?.FailedTasks?.Any() == true)
|
||
{
|
||
var personnelFailures = input.PersonnelAllocation.FailedTasks
|
||
.GroupBy(f => f.FailureType)
|
||
.ToDictionary(g => g.Key.ToString(), g => g.Count());
|
||
|
||
failureAnalysis["PersonnelAllocationFailures"] = personnelFailures;
|
||
}
|
||
|
||
// 设备分配失败分析
|
||
if (input.EquipmentAllocation?.FailedAllocations?.Any() == true)
|
||
{
|
||
var equipmentFailures = input.EquipmentAllocation.FailedAllocations
|
||
.GroupBy(f => f.FailureReason)
|
||
.ToDictionary(g => g.Key ?? "未知", g => g.Count());
|
||
|
||
failureAnalysis["EquipmentAllocationFailures"] = equipmentFailures;
|
||
}
|
||
|
||
// 改进建议生成
|
||
failureAnalysis["ImprovementSuggestions"] = await GenerateImprovementSuggestionsAsync(input);
|
||
|
||
return failureAnalysis;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 生成改进建议
|
||
/// </summary>
|
||
private async Task<List<string>> GenerateImprovementSuggestionsAsync(IntegrationRecordInput input)
|
||
{
|
||
var suggestions = new List<string>();
|
||
|
||
var successRate = input.TaskIds.Count > 0 ?
|
||
(double)(input.PersonnelAllocation?.SuccessfulMatches?.Count ?? 0) / input.TaskIds.Count : 0;
|
||
|
||
if (successRate < 0.8)
|
||
{
|
||
suggestions.Add("建议增加人员培训以提高资质匹配率");
|
||
suggestions.Add("考虑优化任务时间安排以减少冲突");
|
||
}
|
||
|
||
if (input.EquipmentAllocation?.FailedAllocations?.Any() == true)
|
||
{
|
||
suggestions.Add("建议评估设备维护计划以提高可用性");
|
||
suggestions.Add("考虑增加关键设备的数量配置");
|
||
}
|
||
|
||
return suggestions;
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 5.4 数据库持久化与事务管理
|
||
|
||
/// <summary>
|
||
/// 创建任务整合关联数据
|
||
/// </summary>
|
||
private async Task CreateTaskIntegrationRelationsAsync(long recordId, List<WorkOrderEntity> tasks)
|
||
{
|
||
// 创建任务-记录关联表数据(如果需要)
|
||
foreach (var task in tasks)
|
||
{
|
||
// 更新任务的整合记录ID
|
||
task.IntegrationRecordId = recordId;
|
||
}
|
||
|
||
if (tasks.Any())
|
||
{
|
||
await _workOrderRepository.UpdateAsync(tasks);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 生成搜索索引数据
|
||
/// 优化后续查询性能
|
||
/// </summary>
|
||
private async Task GenerateSearchIndexDataAsync(long recordId, List<WorkOrderEntity> tasks)
|
||
{
|
||
// 生成项目编号索引
|
||
var projectNumbers = tasks.Select(t => t.ProjectNumber).Distinct().ToList();
|
||
|
||
// 生成时间范围索引
|
||
var dateRange = new
|
||
{
|
||
StartDate = tasks.Min(t => t.PlannedStartTime),
|
||
EndDate = tasks.Max(t => t.PlannedEndTime)
|
||
};
|
||
|
||
// 这里可以创建专门的索引表或使用全文搜索引擎
|
||
await Task.CompletedTask; // 占位实现
|
||
}
|
||
|
||
/// <summary>
|
||
/// 记录审计信息
|
||
/// </summary>
|
||
private async Task RecordAuditInfoAsync(long recordId, long operatorUserId)
|
||
{
|
||
// 记录操作审计日志
|
||
_logger.LogInformation("整合记录创建审计: RecordId={RecordId}, OperatorUserId={OperatorUserId}",
|
||
recordId, operatorUserId);
|
||
|
||
// 这里可以创建专门的审计日志记录
|
||
await Task.CompletedTask; // 占位实现
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 5.5 记录转换与API返回
|
||
|
||
/// <summary>
|
||
/// 转换为API返回格式
|
||
/// 深度业务思考:提供用户友好的数据格式,隐藏内部技术细节
|
||
/// </summary>
|
||
private IntegrationRecord ConvertToIntegrationRecord(IntegrationRecordEntity entity)
|
||
{
|
||
return new IntegrationRecord
|
||
{
|
||
Id = entity.Id,
|
||
IntegrationBatchCode = entity.IntegrationBatchCode,
|
||
IntegrationTime = entity.IntegrationTime,
|
||
ProjectNumbers = entity.ProjectNumbers ?? "",
|
||
TaskCount = entity.OriginalTaskCount,
|
||
SuccessTaskCount = entity.SuccessTaskCount,
|
||
FailedTaskCount = entity.FailedTaskCount,
|
||
SuccessRate = entity.SuccessRate,
|
||
ElapsedMilliseconds = entity.ElapsedMilliseconds,
|
||
PersonnelFairnessScore = entity.PersonnelFairnessScore,
|
||
EquipmentUtilizationRate = entity.EquipmentUtilizationRate,
|
||
OperatorUserId = entity.OperatorUserId,
|
||
OperatorName = entity.OperatorUserName,
|
||
Remarks = entity.Remarks,
|
||
CreatedTime = entity.CreatedTime ?? DateTime.Now
|
||
};
|
||
}
|
||
|
||
#endregion
|
||
|
||
/// <summary>
|
||
/// 根据记录ID查询整合记录信息并附加任务集
|
||
/// </summary>
|
||
/// <param name="recordId">整合记录ID</param>
|
||
/// <returns>包含任务集的整合记录信息</returns>
|
||
[HttpGet]
|
||
public async Task<IntegrationRecordWithTasksOutput> GetIntegrationRecordWithTasksAsync(long recordId)
|
||
{
|
||
try
|
||
{
|
||
// 查询整合记录
|
||
var integrationRecord = await _integrationRecordRepository.GetAsync(recordId);
|
||
if (integrationRecord == null)
|
||
{
|
||
throw new IntegrationRecordException($"未找到ID为{recordId}的整合记录");
|
||
}
|
||
|
||
// 获取任务ID列表
|
||
var taskIds = integrationRecord.GetTaskIds();
|
||
if (!taskIds.Any())
|
||
{
|
||
// 如果没有任务,返回基本记录信息
|
||
return ConvertToIntegrationRecordWithTasks(integrationRecord, new List<WorkOrderEntity>());
|
||
}
|
||
|
||
// 查询任务详细信息
|
||
var taskEntities = await GetTaskEntitiesForRecordAsync(taskIds);
|
||
|
||
// 转换为输出格式
|
||
var result = ConvertToIntegrationRecordWithTasks(integrationRecord, taskEntities);
|
||
|
||
_logger.LogInformation("成功查询整合记录及任务集: RecordId={RecordId}, TaskCount={TaskCount}",
|
||
recordId, taskEntities.Count);
|
||
|
||
return result;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogError(ex, "查询整合记录及任务集失败: RecordId={RecordId}, Error={Message}",
|
||
recordId, ex.Message);
|
||
throw new IntegrationRecordException($"查询整合记录及任务集失败: {ex.Message}", ex);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 转换为包含任务集的整合记录输出格式
|
||
/// </summary>
|
||
private IntegrationRecordWithTasksOutput ConvertToIntegrationRecordWithTasks(
|
||
IntegrationRecordEntity entity,
|
||
List<WorkOrderEntity> tasks)
|
||
{
|
||
var result = new IntegrationRecordWithTasksOutput
|
||
{
|
||
Id = entity.Id,
|
||
IntegrationBatchCode = entity.IntegrationBatchCode,
|
||
IntegrationTime = entity.IntegrationTime,
|
||
OperatorUserId = entity.OperatorUserId,
|
||
OperatorUserName = entity.OperatorUserName,
|
||
OperatorRealName = entity.OperatorRealName,
|
||
SuccessTaskCount = entity.SuccessTaskCount,
|
||
FailedTaskCount = entity.FailedTaskCount,
|
||
ElapsedMilliseconds = entity.ElapsedMilliseconds,
|
||
FairnessScore = entity.PersonnelFairnessScore,
|
||
UtilizationRate = entity.EquipmentUtilizationRate,
|
||
Remarks = entity.Remarks,
|
||
CreatedTime = entity.CreatedTime ?? DateTime.Now,
|
||
ProjectNumbers = entity.GetProjectNumbers(),
|
||
IntegrationType = entity.IntegrationType,
|
||
PublishStatus = entity.PublishStatus,
|
||
TaskDetails = ConvertToTaskDetails(tasks)
|
||
};
|
||
|
||
// 解析策略配置
|
||
try
|
||
{
|
||
if (!string.IsNullOrEmpty(entity.StrategyConfigJson))
|
||
{
|
||
var strategyConfig = JsonSerializer.Deserialize<IntegrationStrategyConfig>(
|
||
entity.StrategyConfigJson,
|
||
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
|
||
if (strategyConfig != null)
|
||
{
|
||
result.StrategyConfig = strategyConfig;
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogWarning(ex, "解析策略配置失败: RecordId={RecordId}", entity.Id);
|
||
}
|
||
|
||
// 解析人员分配结果
|
||
try
|
||
{
|
||
if (!string.IsNullOrEmpty(entity.PersonnelAllocationResultJson))
|
||
{
|
||
var personnelResult = JsonSerializer.Deserialize<PersonnelAllocationResult>(
|
||
entity.PersonnelAllocationResultJson,
|
||
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
|
||
result.PersonnelAllocationResult = personnelResult;
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogWarning(ex, "解析人员分配结果失败: RecordId={RecordId}", entity.Id);
|
||
}
|
||
|
||
// 解析设备分配结果
|
||
try
|
||
{
|
||
if (!string.IsNullOrEmpty(entity.EquipmentAllocationResultJson))
|
||
{
|
||
var equipmentResult = JsonSerializer.Deserialize<EquipmentAllocationResult>(
|
||
entity.EquipmentAllocationResultJson,
|
||
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
|
||
result.EquipmentAllocationResult = equipmentResult;
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogWarning(ex, "解析设备分配结果失败: RecordId={RecordId}", entity.Id);
|
||
}
|
||
|
||
// 解析失败原因统计
|
||
try
|
||
{
|
||
if (!string.IsNullOrEmpty(entity.FailureReasonStats))
|
||
{
|
||
var failureStats = JsonSerializer.Deserialize<Dictionary<string, object>>(
|
||
entity.FailureReasonStats,
|
||
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
|
||
if (failureStats != null)
|
||
{
|
||
result.FailureReasonStats = failureStats;
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogWarning(ex, "解析失败原因统计失败: RecordId={RecordId}", entity.Id);
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 转换为任务详细信息列表
|
||
/// </summary>
|
||
private List<TaskDetailForRecord> ConvertToTaskDetails(List<WorkOrderEntity> tasks)
|
||
{
|
||
return tasks.Select(task => new TaskDetailForRecord
|
||
{
|
||
TaskId = task.Id,
|
||
TaskCode = task.WorkOrderCode ?? task.Code ?? $"TASK-{task.Id}",
|
||
ProjectNumber = task.ProjectNumber,
|
||
ProjectCategory = task.ProjectCategory,
|
||
ShiftId = task.ShiftId,
|
||
ShiftName = task.ShiftName,
|
||
ProcessId = task.ProcessId,
|
||
ProcessName = task.ProcessName,
|
||
WorkOrderDate = task.WorkOrderDate,
|
||
Priority = task.Priority,
|
||
Urgency = task.Urgency,
|
||
Complexity = task.Complexity,
|
||
EstimatedHours = task.EstimatedHours,
|
||
Status = task.Status,
|
||
AssignedPersonnelId = task.AssignedPersonnelId,
|
||
AssignedPersonnelName = task.AssignedPersonnelName ?? "",
|
||
AssignedEquipmentId = task.AssignedEquipmentId,
|
||
AssignedEquipmentName = task.AssignedEquipmentName ?? "",
|
||
WeightFactor = task.WeightFactor,
|
||
Remarks = task.Remarks ?? ""
|
||
}).ToList();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 查询所有整合记录列表
|
||
/// 深度业务思考:提供完整的记录列表查询,支持筛选和排序
|
||
/// </summary>
|
||
/// <param name="input">查询条件</param>
|
||
/// <returns>整合记录列表</returns>
|
||
[HttpGet]
|
||
public async Task<List<IntegrationRecordListOutput>> GetIntegrationRecordsAsync(IntegrationRecordGetListInput input)
|
||
{
|
||
try
|
||
{
|
||
// 构建查询条件
|
||
var query = _integrationRecordRepository.Select;
|
||
|
||
// 批次编码筛选
|
||
if (!string.IsNullOrWhiteSpace(input.IntegrationBatchCode))
|
||
{
|
||
query = query.Where(r => r.IntegrationBatchCode.Contains(input.IntegrationBatchCode));
|
||
}
|
||
|
||
// 项目编号筛选
|
||
if (!string.IsNullOrWhiteSpace(input.ProjectNumber))
|
||
{
|
||
query = query.Where(r => r.ProjectNumbers.Contains(input.ProjectNumber));
|
||
}
|
||
|
||
// 操作员用户名筛选
|
||
if (!string.IsNullOrWhiteSpace(input.OperatorUserName))
|
||
{
|
||
query = query.Where(r => r.OperatorUserName.Contains(input.OperatorUserName));
|
||
}
|
||
|
||
// 操作员真实姓名筛选
|
||
if (!string.IsNullOrWhiteSpace(input.OperatorRealName))
|
||
{
|
||
query = query.Where(r => r.OperatorRealName.Contains(input.OperatorRealName));
|
||
}
|
||
|
||
// 时间范围筛选
|
||
if (input.StartDate.HasValue)
|
||
{
|
||
query = query.Where(r => r.IntegrationTime >= input.StartDate.Value);
|
||
}
|
||
|
||
if (input.EndDate.HasValue)
|
||
{
|
||
query = query.Where(r => r.IntegrationTime <= input.EndDate.Value.AddDays(1).AddSeconds(-1));
|
||
}
|
||
|
||
// 按创建时间降序排序(最新的在前面)
|
||
query = query.OrderByDescending(r => r.CreatedTime);
|
||
|
||
// 执行查询并转换为列表
|
||
var entities = await query.ToListAsync();
|
||
var result = entities.Select(ConvertToIntegrationRecordListOutput).ToList();
|
||
|
||
_logger.LogInformation("成功查询整合记录列表: Count={Count}", result.Count);
|
||
|
||
return result;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogError(ex, "查询整合记录列表失败: {Message}", ex.Message);
|
||
throw new IntegrationRecordException($"查询整合记录列表失败: {ex.Message}", ex);
|
||
}
|
||
}
|
||
|
||
|
||
#region 发布管理接口实现
|
||
|
||
/// <summary>
|
||
/// 发布整合记录
|
||
/// 深度业务思考:执行完整的发布流程,包括验证、状态更新、任务发布和后处理
|
||
/// </summary>
|
||
[HttpPost]
|
||
public async Task<PublishIntegrationRecordResult> PublishIntegrationRecordAsync(PublishIntegrationRecordInput input)
|
||
{
|
||
var result = new PublishIntegrationRecordResult
|
||
{
|
||
IntegrationRecordId = input.IntegrationRecordId,
|
||
PublishedTime = DateTime.Now
|
||
};
|
||
|
||
try
|
||
{
|
||
// 第一步:获取整合记录并验证状态
|
||
var integrationRecord = await _integrationRecordRepository.GetAsync(input.IntegrationRecordId);
|
||
if (integrationRecord == null)
|
||
{
|
||
result.IsSuccess = false;
|
||
result.ErrorMessage = $"未找到ID为{input.IntegrationRecordId}的整合记录";
|
||
return result;
|
||
}
|
||
|
||
result.IntegrationBatchCode = integrationRecord.IntegrationBatchCode;
|
||
|
||
// 第二步:发布前验证
|
||
var validationResult = await ValidateBeforePublishAsync(integrationRecord, input);
|
||
result.ValidationResult = validationResult;
|
||
|
||
if (!validationResult.IsValid && !input.ForcePublish)
|
||
{
|
||
result.IsSuccess = false;
|
||
result.ErrorMessage = "发布前验证失败,存在阻塞性错误";
|
||
result.WarningMessages.AddRange(validationResult.BlockingErrors.Select(e => e.Message));
|
||
return result;
|
||
}
|
||
|
||
// 第三步:获取相关任务
|
||
var taskIds = integrationRecord.GetTaskIds();
|
||
if (!taskIds.Any())
|
||
{
|
||
result.IsSuccess = false;
|
||
result.ErrorMessage = "整合记录中没有关联的任务";
|
||
return result;
|
||
}
|
||
|
||
var taskEntities = await GetTaskEntitiesForRecordAsync(taskIds);
|
||
|
||
// 第四步:执行任务发布
|
||
var publishTasksResult = await ExecuteTaskPublishAsync(taskEntities, integrationRecord, input);
|
||
result.PublishedTasks = publishTasksResult.PublishedTasks;
|
||
result.FailedPublishTasks = publishTasksResult.FailedPublishTasks;
|
||
|
||
// 第五步:更新整合记录状态
|
||
await UpdateIntegrationRecordStatusInternalAsync(integrationRecord, "Published", input.PublishedByUserId, input.PublishedByUserName, input.PublishRemarks);
|
||
|
||
// 第六步:任务状态同步
|
||
result.TaskStatusSyncResult = await SynchronizeTaskStatusesAsync(taskEntities, integrationRecord);
|
||
|
||
// 第七步:发送通知(如果需要)
|
||
if (input.NotifyRelatedPersonnel)
|
||
{
|
||
result.NotificationResults = await SendPublishNotificationsAsync(integrationRecord, input);
|
||
}
|
||
|
||
// 第八步:生成统计信息
|
||
result.Statistics = GeneratePublishStatistics(result);
|
||
|
||
// 设置最终结果
|
||
result.IsSuccess = result.FailedPublishTasks.Count == 0;
|
||
result.SuccessMessage = result.IsSuccess ?
|
||
$"整合记录发布成功,共发布{result.PublishedTasks.Count}个任务" :
|
||
$"整合记录部分发布成功,{result.PublishedTasks.Count}个任务成功,{result.FailedPublishTasks.Count}个任务失败";
|
||
|
||
_logger.LogInformation("整合记录发布完成: RecordId={RecordId}, Success={IsSuccess}, PublishedCount={PublishedCount}",
|
||
input.IntegrationRecordId, result.IsSuccess, result.PublishedTasks.Count);
|
||
|
||
return result;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
result.IsSuccess = false;
|
||
result.ErrorMessage = $"发布过程中发生异常: {ex.Message}";
|
||
_logger.LogError(ex, "整合记录发布失败: RecordId={RecordId}, Error={Message}", input.IntegrationRecordId, ex.Message);
|
||
return result;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新整合记录状态
|
||
/// 深度业务思考:实现状态转换的完整业务逻辑,包括状态验证和审计
|
||
/// </summary>
|
||
[HttpPost]
|
||
public async Task<bool> UpdateIntegrationRecordStatusAsync(long recordId, string newStatus, long operatorUserId, string operatorName, string remarks = "")
|
||
{
|
||
try
|
||
{
|
||
var integrationRecord = await _integrationRecordRepository.GetAsync(recordId);
|
||
if (integrationRecord == null)
|
||
{
|
||
_logger.LogWarning("尝试更新不存在的整合记录状态: RecordId={RecordId}", recordId);
|
||
return false;
|
||
}
|
||
|
||
// 验证状态转换的合法性
|
||
if (!IsValidStatusTransition(integrationRecord.PublishStatus ?? "草稿", newStatus))
|
||
{
|
||
_logger.LogWarning("非法的状态转换: RecordId={RecordId}, From={OldStatus}, To={NewStatus}",
|
||
recordId, integrationRecord.PublishStatus, newStatus);
|
||
return false;
|
||
}
|
||
|
||
await UpdateIntegrationRecordStatusInternalAsync(integrationRecord, newStatus, operatorUserId, operatorName, remarks);
|
||
|
||
_logger.LogInformation("整合记录状态更新成功: RecordId={RecordId}, NewStatus={NewStatus}", recordId, newStatus);
|
||
return true;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogError(ex, "更新整合记录状态失败: RecordId={RecordId}, NewStatus={NewStatus}, Error={Message}",
|
||
recordId, newStatus, ex.Message);
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 发布修改后的任务
|
||
/// 深度业务思考:支持增量发布,只发布有变更的任务
|
||
/// </summary>
|
||
[HttpPost]
|
||
public async Task<PublishIntegrationRecordResult> PublishTaskModificationsAsync(long recordId, List<long> modifiedTaskIds, long operatorUserId, string operatorName, string publishRemarks = "")
|
||
{
|
||
var result = new PublishIntegrationRecordResult
|
||
{
|
||
IntegrationRecordId = recordId,
|
||
PublishedTime = DateTime.Now
|
||
};
|
||
|
||
try
|
||
{
|
||
// 获取整合记录
|
||
var integrationRecord = await _integrationRecordRepository.GetAsync(recordId);
|
||
if (integrationRecord == null)
|
||
{
|
||
result.IsSuccess = false;
|
||
result.ErrorMessage = $"未找到ID为{recordId}的整合记录";
|
||
return result;
|
||
}
|
||
|
||
result.IntegrationBatchCode = integrationRecord.IntegrationBatchCode;
|
||
|
||
// 获取修改的任务
|
||
var modifiedTasks = await GetTaskEntitiesForRecordAsync(modifiedTaskIds);
|
||
if (!modifiedTasks.Any())
|
||
{
|
||
result.IsSuccess = false;
|
||
result.ErrorMessage = "未找到需要发布的修改任务";
|
||
return result;
|
||
}
|
||
|
||
// 创建增量发布输入
|
||
var incrementalInput = new PublishIntegrationRecordInput
|
||
{
|
||
IntegrationRecordId = recordId,
|
||
PublishedByUserId = operatorUserId,
|
||
PublishedByUserName = operatorName,
|
||
PublishRemarks = publishRemarks ?? "增量任务修改发布",
|
||
ForcePublish = true, // 增量发布通常跳过完整验证
|
||
NotifyRelatedPersonnel = true
|
||
};
|
||
|
||
// 执行增量任务发布
|
||
var publishTasksResult = await ExecuteTaskPublishAsync(modifiedTasks, integrationRecord, incrementalInput);
|
||
result.PublishedTasks = publishTasksResult.PublishedTasks;
|
||
result.FailedPublishTasks = publishTasksResult.FailedPublishTasks;
|
||
|
||
// 更新记录备注
|
||
integrationRecord.Remarks = $"{integrationRecord.Remarks ?? ""}\n[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] 增量发布{modifiedTaskIds.Count}个任务修改";
|
||
await _integrationRecordRepository.UpdateAsync(integrationRecord);
|
||
|
||
// 生成统计信息
|
||
result.Statistics = GeneratePublishStatistics(result);
|
||
|
||
result.IsSuccess = result.FailedPublishTasks.Count == 0;
|
||
result.SuccessMessage = result.IsSuccess ?
|
||
$"任务修改发布成功,共发布{result.PublishedTasks.Count}个任务" :
|
||
$"任务修改部分发布成功,{result.PublishedTasks.Count}个成功,{result.FailedPublishTasks.Count}个失败";
|
||
|
||
_logger.LogInformation("增量任务发布完成: RecordId={RecordId}, ModifiedTaskCount={TaskCount}, Success={IsSuccess}",
|
||
recordId, modifiedTaskIds.Count, result.IsSuccess);
|
||
|
||
return result;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
result.IsSuccess = false;
|
||
result.ErrorMessage = $"发布任务修改时发生异常: {ex.Message}";
|
||
_logger.LogError(ex, "发布任务修改失败: RecordId={RecordId}, Error={Message}", recordId, ex.Message);
|
||
return result;
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 通知管理接口实现(预留)
|
||
|
||
/// <summary>
|
||
/// 发送发布通知(预留接口实现)
|
||
/// 深度业务思考:为未来的通知系统集成预留完整的接口结构
|
||
/// </summary>
|
||
[HttpPost]
|
||
public async Task<NotificationSendResult> SendPublishNotificationAsync(long recordId, string notificationType, List<long> targetPersonnelIds, string customMessage = "")
|
||
{
|
||
// 预留实现:当前返回模拟结果,未来集成真实通知服务
|
||
var result = new NotificationSendResult
|
||
{
|
||
NotificationType = notificationType,
|
||
IsSent = true, // 预留:假设发送成功
|
||
SentTime = DateTime.Now,
|
||
RecipientId = targetPersonnelIds.FirstOrDefault(),
|
||
RecipientName = "待集成通知服务", // 预留:需要从人员服务获取
|
||
FailureReason = ""
|
||
};
|
||
|
||
try
|
||
{
|
||
_logger.LogInformation("预留通知接口调用: RecordId={RecordId}, Type={NotificationType}, TargetCount={TargetCount}",
|
||
recordId, notificationType, targetPersonnelIds.Count);
|
||
|
||
// 预留:未来在此处集成实际的通知服务
|
||
// var notificationService = serviceProvider.GetService<INotificationService>();
|
||
// result = await notificationService.SendPublishNotificationAsync(...);
|
||
|
||
await Task.CompletedTask;
|
||
return result;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
result.IsSent = false;
|
||
result.FailureReason = $"通知发送异常: {ex.Message}";
|
||
_logger.LogError(ex, "发送发布通知失败: RecordId={RecordId}, Error={Message}", recordId, ex.Message);
|
||
return result;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建发布相关待办任务(预留接口实现)
|
||
/// 深度业务思考:为待办任务系统预留完整的集成接口
|
||
/// </summary>
|
||
[HttpPost]
|
||
public async Task<CreateTodoResult> CreatePublishRelatedTodoAsync(long recordId, string todoType, List<long> assigneeIds, string title, string description, DateTime? dueDate = null)
|
||
{
|
||
// 预留实现:当前返回模拟结果,未来集成真实待办服务
|
||
var result = new CreateTodoResult
|
||
{
|
||
IsSuccess = true, // 预留:假设创建成功
|
||
TodoType = todoType,
|
||
Title = title,
|
||
CreatedTime = DateTime.Now,
|
||
CreatedTodoCount = assigneeIds.Count,
|
||
DueDate = dueDate ?? DateTime.Now.AddDays(7),
|
||
ResultSummary = "待办任务创建成功(预留接口)"
|
||
};
|
||
|
||
// 模拟成功创建的待办ID
|
||
result.SuccessfulTodoIds = assigneeIds.Select(_ => (long)new Random().Next(10000, 99999)).ToList();
|
||
|
||
try
|
||
{
|
||
_logger.LogInformation("预留待办接口调用: RecordId={RecordId}, Type={TodoType}, AssigneeCount={AssigneeCount}",
|
||
recordId, todoType, assigneeIds.Count);
|
||
|
||
// 预留:未来在此处集成实际的待办任务服务
|
||
// var todoService = serviceProvider.GetService<ITodoTaskService>();
|
||
// result = await todoService.CreatePublishRelatedTodoAsync(...);
|
||
|
||
await Task.CompletedTask;
|
||
return result;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
result.IsSuccess = false;
|
||
result.ErrorMessages.Add($"创建待办任务异常: {ex.Message}");
|
||
result.ResultSummary = "创建待办任务失败";
|
||
_logger.LogError(ex, "创建发布相关待办失败: RecordId={RecordId}, Error={Message}", recordId, ex.Message);
|
||
return result;
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 私有辅助方法
|
||
|
||
/// <summary>
|
||
/// 发布前验证
|
||
/// </summary>
|
||
private async Task<PublishValidationResult> ValidateBeforePublishAsync(IntegrationRecordEntity record, PublishIntegrationRecordInput input)
|
||
{
|
||
var result = new PublishValidationResult
|
||
{
|
||
ValidationTime = DateTime.Now,
|
||
IsValid = true
|
||
};
|
||
|
||
// 状态验证
|
||
if (!string.IsNullOrEmpty(record.PublishStatus) && record.PublishStatus != "Draft")
|
||
{
|
||
result.BlockingErrors.Add(new IntegrationValidationError
|
||
{
|
||
ErrorType = "状态错误",
|
||
Message = $"记录状态为'{record.PublishStatus}',无法发布",
|
||
RelatedFieldName = "PublishStatus"
|
||
});
|
||
result.IsValid = false;
|
||
}
|
||
|
||
// 任务数量验证
|
||
var taskIds = record.GetTaskIds();
|
||
if (!taskIds.Any())
|
||
{
|
||
result.BlockingErrors.Add(new IntegrationValidationError
|
||
{
|
||
ErrorType = "数据错误",
|
||
Message = "记录中没有关联的任务",
|
||
RelatedFieldName = "TaskIds"
|
||
});
|
||
result.IsValid = false;
|
||
}
|
||
|
||
// 其他业务验证...
|
||
await Task.CompletedTask;
|
||
|
||
result.ValidationDetails = $"验证完成,发现{result.BlockingErrors.Count}个阻塞性错误,{result.Warnings.Count}个警告";
|
||
return result;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 执行任务发布
|
||
/// </summary>
|
||
private async Task<(List<PublishedTaskDetail> PublishedTasks, List<FailedPublishTaskDetail> FailedPublishTasks)> ExecuteTaskPublishAsync(
|
||
List<WorkOrderEntity> tasks,
|
||
IntegrationRecordEntity integrationRecord,
|
||
PublishIntegrationRecordInput input)
|
||
{
|
||
var publishedTasks = new List<PublishedTaskDetail>();
|
||
var failedTasks = new List<FailedPublishTaskDetail>();
|
||
|
||
foreach (var task in tasks)
|
||
{
|
||
try
|
||
{
|
||
// 记录发布前状态
|
||
var previousStatus = task.Status.ToString();
|
||
|
||
// 执行任务发布逻辑
|
||
var publishSuccess = await PublishSingleTaskAsync(task, integrationRecord, input);
|
||
|
||
if (publishSuccess)
|
||
{
|
||
publishedTasks.Add(new PublishedTaskDetail
|
||
{
|
||
TaskId = task.Id,
|
||
TaskCode = task.WorkOrderCode ?? $"TASK-{task.Id}",
|
||
AssignedPersonnelId = task.AssignedPersonnelId,
|
||
AssignedPersonnelName = task.AssignedPersonnelName ?? "",
|
||
AssignedEquipmentId = task.AssignedEquipmentId,
|
||
AssignedEquipmentName = task.AssignedEquipmentName ?? "",
|
||
PreviousStatus = previousStatus,
|
||
CurrentStatus = task.Status.ToString(),
|
||
PublishTime = DateTime.Now
|
||
});
|
||
}
|
||
else
|
||
{
|
||
failedTasks.Add(new FailedPublishTaskDetail
|
||
{
|
||
TaskId = task.Id,
|
||
TaskCode = task.WorkOrderCode ?? $"TASK-{task.Id}",
|
||
FailureReason = "任务发布失败",
|
||
DetailedErrors = new List<string> { "发布过程中遇到业务规则限制" }
|
||
});
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
failedTasks.Add(new FailedPublishTaskDetail
|
||
{
|
||
TaskId = task.Id,
|
||
TaskCode = task.WorkOrderCode ?? $"TASK-{task.Id}",
|
||
FailureReason = "发布异常",
|
||
DetailedErrors = new List<string> { ex.Message }
|
||
});
|
||
|
||
_logger.LogError(ex, "任务发布失败: TaskId={TaskId}, Error={Message}", task.Id, ex.Message);
|
||
}
|
||
}
|
||
|
||
return (publishedTasks, failedTasks);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 发布单个任务
|
||
/// </summary>
|
||
private async Task<bool> PublishSingleTaskAsync(WorkOrderEntity task, IntegrationRecordEntity integrationRecord, PublishIntegrationRecordInput input)
|
||
{
|
||
try
|
||
{
|
||
// 更新任务状态为已分配(发布后的任务状态)
|
||
task.Status = (int)WorkOrderStatusEnum.Assigned;
|
||
task.ModifiedTime = DateTime.Now;
|
||
task.ModifiedUserId = input.PublishedByUserId;
|
||
task.ModifiedUserName = input.PublishedByUserName;
|
||
|
||
// 保存任务更新
|
||
await _workOrderRepository.UpdateAsync(task);
|
||
|
||
return true;
|
||
}
|
||
catch
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 同步任务状态
|
||
/// </summary>
|
||
private async Task<TaskStatusSyncResult> SynchronizeTaskStatusesAsync(List<WorkOrderEntity> tasks, IntegrationRecordEntity integrationRecord)
|
||
{
|
||
var result = new TaskStatusSyncResult
|
||
{
|
||
SuccessfulSyncCount = tasks.Count,
|
||
FailedSyncCount = 0,
|
||
IsFullySuccessful = true,
|
||
SyncElapsedMilliseconds = 0
|
||
};
|
||
|
||
// 预留:未来可以在此处添加与外部系统的状态同步逻辑
|
||
|
||
await Task.CompletedTask;
|
||
return result;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 发送发布通知
|
||
/// </summary>
|
||
private async Task<List<NotificationSendResult>> SendPublishNotificationsAsync(IntegrationRecordEntity integrationRecord, PublishIntegrationRecordInput input)
|
||
{
|
||
var results = new List<NotificationSendResult>();
|
||
|
||
// 预留:根据发布规则确定通知对象和内容
|
||
var targetPersonnelIds = new List<long>(); // 从业务规则中获取
|
||
|
||
if (targetPersonnelIds.Any())
|
||
{
|
||
var notificationResult = await SendPublishNotificationAsync(
|
||
integrationRecord.Id,
|
||
"发布通知",
|
||
targetPersonnelIds,
|
||
$"整合记录 {integrationRecord.IntegrationBatchCode} 已发布生效");
|
||
|
||
results.Add(notificationResult);
|
||
}
|
||
|
||
return results;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 生成发布统计信息
|
||
/// </summary>
|
||
private PublishStatistics GeneratePublishStatistics(PublishIntegrationRecordResult result)
|
||
{
|
||
return new PublishStatistics
|
||
{
|
||
TotalTaskCount = result.PublishedTasks.Count + result.FailedPublishTasks.Count,
|
||
SuccessfulPublishCount = result.PublishedTasks.Count,
|
||
FailedPublishCount = result.FailedPublishTasks.Count,
|
||
PublishSuccessRate = result.PublishedTasks.Count + result.FailedPublishTasks.Count > 0 ?
|
||
(decimal)result.PublishedTasks.Count / (result.PublishedTasks.Count + result.FailedPublishTasks.Count) * 100 : 0,
|
||
InvolvedPersonnelCount = result.PublishedTasks.Select(t => t.AssignedPersonnelId).Where(id => id.HasValue).Distinct().Count(),
|
||
InvolvedEquipmentCount = result.PublishedTasks.Select(t => t.AssignedEquipmentId).Where(id => id.HasValue).Distinct().Count(),
|
||
TotalElapsedMilliseconds = 0 // 预留:记录实际执行时间
|
||
};
|
||
}
|
||
|
||
/// <summary>
|
||
/// 内部状态更新方法
|
||
/// </summary>
|
||
private async Task UpdateIntegrationRecordStatusInternalAsync(IntegrationRecordEntity integrationRecord, string newStatus, long operatorUserId, string operatorName, string remarks)
|
||
{
|
||
integrationRecord.PublishStatus = newStatus;
|
||
integrationRecord.PublishedTime = DateTime.Now;
|
||
integrationRecord.PublishedByUserId = operatorUserId;
|
||
integrationRecord.PublishedByUserName = operatorName;
|
||
|
||
if (!string.IsNullOrWhiteSpace(remarks))
|
||
{
|
||
integrationRecord.Remarks = $"{integrationRecord.Remarks ?? ""}\n[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] {remarks}";
|
||
}
|
||
|
||
integrationRecord.ModifiedTime = DateTime.Now;
|
||
integrationRecord.ModifiedUserId = operatorUserId;
|
||
integrationRecord.ModifiedUserName = operatorName;
|
||
|
||
await _integrationRecordRepository.UpdateAsync(integrationRecord);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证状态转换的合法性
|
||
/// </summary>
|
||
private bool IsValidStatusTransition(string currentStatus, string newStatus)
|
||
{
|
||
var validTransitions = new Dictionary<string, List<string>>
|
||
{
|
||
["草稿"] = new List<string> { "已发布", "已撤销" },
|
||
["已发布"] = new List<string> { "已完成", "已撤销" },
|
||
["已完成"] = new List<string> { "已归档" },
|
||
["已撤销"] = new List<string> { "草稿" }
|
||
};
|
||
|
||
return validTransitions.ContainsKey(currentStatus) && validTransitions[currentStatus].Contains(newStatus);
|
||
}
|
||
|
||
#endregion
|
||
|
||
|
||
/// <summary>
|
||
/// 转换为整合记录列表输出格式
|
||
/// </summary>
|
||
private IntegrationRecordListOutput ConvertToIntegrationRecordListOutput(IntegrationRecordEntity entity)
|
||
{
|
||
return new IntegrationRecordListOutput
|
||
{
|
||
Id = entity.Id,
|
||
IntegrationBatchCode = entity.IntegrationBatchCode,
|
||
IntegrationTime = entity.IntegrationTime,
|
||
ProjectNumbers = entity.ProjectNumbers ?? string.Empty,
|
||
OriginalTaskCount = entity.OriginalTaskCount,
|
||
SuccessTaskCount = entity.SuccessTaskCount,
|
||
FailedTaskCount = entity.FailedTaskCount,
|
||
ElapsedMilliseconds = entity.ElapsedMilliseconds,
|
||
PersonnelFairnessScore = entity.PersonnelFairnessScore,
|
||
EquipmentUtilizationRate = entity.EquipmentUtilizationRate,
|
||
OperatorUserId = entity.OperatorUserId,
|
||
OperatorUserName = entity.OperatorUserName ?? string.Empty,
|
||
OperatorRealName = entity.OperatorRealName ?? string.Empty,
|
||
Remarks = entity.Remarks ?? string.Empty,
|
||
PublishStatus = entity.PublishStatus ?? string.Empty,
|
||
CreatedTime = entity.CreatedTime ?? DateTime.Now
|
||
};
|
||
}
|
||
|
||
#region 辅助方法
|
||
|
||
/// <summary>
|
||
/// 整合记录异常类
|
||
/// </summary>
|
||
public class IntegrationRecordException : Exception
|
||
{
|
||
public IntegrationRecordException(string message) : base(message) { }
|
||
public IntegrationRecordException(string message, Exception innerException) : base(message, innerException) { }
|
||
}
|
||
|
||
#endregion
|
||
}
|
||
} |