987 lines
47 KiB
C#
987 lines
47 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Text.Json;
|
||
using System.Threading.Tasks;
|
||
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.Models;
|
||
using NPP.SmartSchedue.Api.Contracts.Services.Integration.Output;
|
||
using NPP.SmartSchedue.Api.Contracts.Services.Work;
|
||
using NPP.SmartSchedue.Api.Services.Notification;
|
||
using NPP.SmartSchedue.Api.Contracts.Services.Work.Input;
|
||
using NPP.SmartSchedue.Api.Repositories.Work;
|
||
using NPP.SmartSchedue.Api.Repositories.Integration;
|
||
using ZhonTai.Admin.Services;
|
||
using ZhonTai.DynamicApi;
|
||
using ZhonTai.DynamicApi.Attributes;
|
||
|
||
namespace NPP.SmartSchedue.Api.Services.Integration
|
||
{
|
||
/// <summary>
|
||
/// 工作订单整合操作统一服务实现
|
||
/// </summary>
|
||
[DynamicApi(Area = "app")]
|
||
public class WorkOrderIntegrationOperationService : BaseService, IWorkOrderIntegrationOperationService, IDynamicApi
|
||
{
|
||
private readonly IWorkOrderService _workOrderService;
|
||
private readonly IIntegrationRecordService _integrationRecordService;
|
||
private readonly WorkOrderRepository _workOrderRepository;
|
||
private readonly IntegrationRecordRepository _integrationRecordRepository;
|
||
private readonly WorkOrderStatusValidator _statusValidator;
|
||
private readonly ILogger<WorkOrderIntegrationOperationService> _logger;
|
||
private readonly NotificationScheduledService _notificationScheduledService;
|
||
|
||
public WorkOrderIntegrationOperationService(
|
||
IWorkOrderService workOrderService,
|
||
IIntegrationRecordService integrationRecordService,
|
||
WorkOrderRepository workOrderRepository,
|
||
IntegrationRecordRepository integrationRecordRepository,
|
||
WorkOrderStatusValidator statusValidator,
|
||
ILogger<WorkOrderIntegrationOperationService> logger,
|
||
NotificationScheduledService notificationScheduledService)
|
||
{
|
||
_workOrderService = workOrderService;
|
||
_integrationRecordService = integrationRecordService;
|
||
_workOrderRepository = workOrderRepository;
|
||
_integrationRecordRepository = integrationRecordRepository;
|
||
_statusValidator = statusValidator;
|
||
_logger = logger;
|
||
_notificationScheduledService = notificationScheduledService;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 修改任务统一入口
|
||
/// </summary>
|
||
[HttpPost]
|
||
public async Task<WorkOrderOperationResult> ModifyWorkOrderAsync(WorkOrderModifyOperationInput input)
|
||
{
|
||
try
|
||
{
|
||
// 1. 参数验证
|
||
var paramValidation = ValidateModifyParameters(input);
|
||
if (!paramValidation.IsValid)
|
||
{
|
||
return CreateFailResult(paramValidation.ErrorMessage);
|
||
}
|
||
|
||
// 2. 一次性查询任务,获取所有需要的信息
|
||
var task = await _workOrderRepository.GetAsync(input.TaskId);
|
||
if (task == null)
|
||
{
|
||
return CreateFailResult("任务不存在");
|
||
}
|
||
|
||
// 3. 基于已查询的任务进行状态验证
|
||
var statusValidation = _statusValidator.ValidateModifyStatus(task);
|
||
if (!statusValidation.IsValid)
|
||
{
|
||
return CreateFailResult($"状态验证失败:{statusValidation.ErrorMessage}");
|
||
}
|
||
|
||
// 4. 业务规则检查
|
||
var businessValidation = await ValidateModifyBusinessRulesAsync(input);
|
||
if (!businessValidation.IsValid)
|
||
{
|
||
return CreateFailResult($"业务规则验证失败:{businessValidation.ErrorMessage}");
|
||
}
|
||
|
||
// 5. 保存原始任务信息,用于变更分析
|
||
var originalTask = new WorkOrderEntity
|
||
{
|
||
Id = task.Id,
|
||
WorkOrderDate = task.WorkOrderDate,
|
||
AssignedPersonnelId = task.AssignedPersonnelId,
|
||
AssignedEquipmentId = task.AssignedEquipmentId,
|
||
ProcessId = task.ProcessId,
|
||
ShiftId = task.ShiftId,
|
||
Priority = task.Priority,
|
||
Urgency = task.Urgency,
|
||
EstimatedHours = task.EstimatedHours,
|
||
Status = task.Status
|
||
};
|
||
|
||
// 6. 判断是否需要重新分配
|
||
bool needsReallocation = ShouldTriggerReallocation(originalTask, input.TaskModifyData);
|
||
|
||
if (needsReallocation)
|
||
{
|
||
_logger.LogInformation("任务{TaskId}修改触发重新分配条件", input.TaskId);
|
||
}
|
||
|
||
// 8. 更新整合记录(仅对已分配状态的任务)
|
||
long? affectedIntegrationRecordId = null;
|
||
bool reallocationTriggered = false;
|
||
|
||
if (originalTask.Status == (int)WorkOrderStatusEnum.Assigned && task.IntegrationRecordId.HasValue)
|
||
{
|
||
var integrationRecord = await _integrationRecordRepository.GetAsync(task.IntegrationRecordId.Value);
|
||
if (integrationRecord != null)
|
||
{
|
||
await UpdateIntegrationRecordAfterModifyAsync(integrationRecord, input, originalTask, needsReallocation);
|
||
affectedIntegrationRecordId = integrationRecord.Id;
|
||
}
|
||
}
|
||
|
||
Mapper.Map(input, task);
|
||
task.Status = (int)WorkOrderStatusEnum.PendingSubmit;
|
||
task.Remarks = "任务修改需重新智能整合";
|
||
|
||
await _workOrderRepository.UpdateAsync(task);
|
||
|
||
// 9. 发送通知
|
||
try
|
||
{
|
||
// 合并指定人员与任务FL人员
|
||
var designatedIds_Modify = new List<long>();
|
||
if (task.AssignedPersonnelId != null && task.AssignedPersonnelId.HasValue) designatedIds_Modify.AddRange(task.AssignedPersonnelId.Value);
|
||
if (task != null && task.WorkOrderFLPersonnels != null && task.WorkOrderFLPersonnels.Any()) designatedIds_Modify.AddRange(task.WorkOrderFLPersonnels.Select(x => x.FLPersonnelId));
|
||
designatedIds_Modify = designatedIds_Modify.Distinct().ToList();
|
||
|
||
await _notificationScheduledService.SendWorkOrderOperationNotificationAsync(
|
||
"Modify", input.TaskId, User.Id, User.Name, input.Remarks, designatedIds_Modify);
|
||
}
|
||
catch (Exception notifyEx)
|
||
{
|
||
_logger.LogWarning(notifyEx, "修改任务后发送通知失败,TaskId: {TaskId}", input.TaskId);
|
||
}
|
||
|
||
|
||
// 10. 返回结果
|
||
var resultMessage = needsReallocation ? "任务修改成功,已触发重新分配" : "任务修改成功";
|
||
|
||
return new WorkOrderOperationResult
|
||
{
|
||
IsSuccess = true,
|
||
Message = resultMessage,
|
||
AffectedIntegrationRecordId = affectedIntegrationRecordId,
|
||
Data = new {
|
||
TaskId = input.TaskId,
|
||
OperationType = "Modify",
|
||
NeedsReallocation = needsReallocation,
|
||
ReallocationTriggered = reallocationTriggered
|
||
}
|
||
};
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogError(ex, "修改任务时发生错误,TaskId: {TaskId}", input.TaskId);
|
||
return CreateFailResult($"修改任务失败:{ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 删除任务统一入口
|
||
/// </summary>
|
||
[HttpPost]
|
||
public async Task<WorkOrderOperationResult> DeleteWorkOrderAsync(WorkOrderDeleteOperationInput input)
|
||
{
|
||
try
|
||
{
|
||
// 1. 参数验证
|
||
var paramValidation = ValidateDeleteParameters(input);
|
||
if (!paramValidation.IsValid)
|
||
{
|
||
return CreateFailResult(paramValidation.ErrorMessage);
|
||
}
|
||
|
||
// 2. 一次性查询任务,获取所有需要的信息
|
||
var task = await _workOrderRepository.GetAsync(input.TaskId);
|
||
if (task == null)
|
||
{
|
||
return CreateFailResult("任务不存在");
|
||
}
|
||
|
||
// 3. 基于已查询的任务进行状态验证
|
||
var statusValidation = _statusValidator.ValidateDeleteStatus(task);
|
||
if (!statusValidation.IsValid)
|
||
{
|
||
return CreateFailResult($"状态验证失败:{statusValidation.ErrorMessage}");
|
||
}
|
||
|
||
// 4. 业务规则检查
|
||
var businessValidation = await ValidateDeleteBusinessRulesAsync(input);
|
||
if (!businessValidation.IsValid)
|
||
{
|
||
return CreateFailResult($"业务规则验证失败:{businessValidation.ErrorMessage}");
|
||
}
|
||
|
||
// 5. 获取整合记录信息(仅对已分配任务且有关联记录的情况)
|
||
IntegrationRecordEntity integrationRecord = null;
|
||
if (task.Status == (int)WorkOrderStatusEnum.Assigned && task.IntegrationRecordId.HasValue)
|
||
{
|
||
integrationRecord = await _integrationRecordRepository.GetAsync(task.IntegrationRecordId.Value);
|
||
}
|
||
|
||
// 6. 执行任务操作
|
||
await _workOrderService.SoftDeleteAsync(input.TaskId);
|
||
|
||
// 7. 更新整合记录(仅对已分配状态的任务)
|
||
if (integrationRecord != null)
|
||
{
|
||
await UpdateIntegrationRecordAfterDeleteAsync(integrationRecord, input);
|
||
}
|
||
|
||
// 8. 发送通知
|
||
try
|
||
{
|
||
// 合并指定人员与任务FL人员
|
||
// 合并指定人员与任务FL人员
|
||
var designatedIds_Delete = new List<long>();
|
||
if (task.AssignedPersonnelId != null && task.AssignedPersonnelId.HasValue) designatedIds_Delete.AddRange(task.AssignedPersonnelId.Value);
|
||
if (task != null && task.WorkOrderFLPersonnels != null && task.WorkOrderFLPersonnels.Any()) designatedIds_Delete.AddRange(task.WorkOrderFLPersonnels.Select(x => x.FLPersonnelId));
|
||
designatedIds_Delete = designatedIds_Delete.Distinct().ToList();
|
||
|
||
await _notificationScheduledService.SendWorkOrderOperationNotificationAsync(
|
||
"Delete", input.TaskId, User.Id, User.Name, input.DeleteReason, designatedIds_Delete);
|
||
}
|
||
catch (Exception notifyEx)
|
||
{
|
||
_logger.LogWarning(notifyEx, "删除任务后发送通知失败,TaskId: {TaskId}", input.TaskId);
|
||
}
|
||
|
||
// 9. 返回结果
|
||
return new WorkOrderOperationResult
|
||
{
|
||
IsSuccess = true,
|
||
Message = input.IsSoftDelete ? "任务软删除成功" : "任务删除成功",
|
||
AffectedIntegrationRecordId = integrationRecord?.Id,
|
||
Data = new { TaskId = input.TaskId, OperationType = "Delete", IsSoftDelete = input.IsSoftDelete }
|
||
};
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogError(ex, "删除任务时发生错误,TaskId: {TaskId}", input.TaskId);
|
||
return CreateFailResult($"删除任务失败:{ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 取消任务统一入口
|
||
/// </summary>
|
||
[HttpPost]
|
||
public async Task<WorkOrderOperationResult> CancelWorkOrderAsync(WorkOrderCancelOperationInput input)
|
||
{
|
||
try
|
||
{
|
||
// 1. 参数验证
|
||
var paramValidation = ValidateCancelParameters(input);
|
||
if (!paramValidation.IsValid)
|
||
{
|
||
return CreateFailResult(paramValidation.ErrorMessage);
|
||
}
|
||
|
||
// 2. 一次性查询任务,获取所有需要的信息
|
||
var task = await _workOrderRepository.GetAsync(input.TaskId);
|
||
if (task == null)
|
||
{
|
||
return CreateFailResult("任务不存在");
|
||
}
|
||
|
||
// 3. 基于已查询的任务进行状态验证
|
||
var statusValidation = _statusValidator.ValidateCancelStatus(task);
|
||
if (!statusValidation.IsValid)
|
||
{
|
||
return CreateFailResult($"状态验证失败:{statusValidation.ErrorMessage}");
|
||
}
|
||
|
||
// 4. 业务规则检查
|
||
var businessValidation = await ValidateCancelBusinessRulesAsync(input);
|
||
if (!businessValidation.IsValid)
|
||
{
|
||
return CreateFailResult($"业务规则验证失败:{businessValidation.ErrorMessage}");
|
||
}
|
||
|
||
// 5. 获取整合记录信息(仅对已分配任务且有关联记录的情况)
|
||
IntegrationRecordEntity integrationRecord = null;
|
||
if (task.Status == (int)WorkOrderStatusEnum.Assigned && task.IntegrationRecordId.HasValue)
|
||
{
|
||
integrationRecord = await _integrationRecordRepository.GetAsync(task.IntegrationRecordId.Value);
|
||
}
|
||
|
||
// 6. 执行任务操作 - 更新状态为取消
|
||
task.Status = (int)WorkOrderStatusEnum.Cancelled;
|
||
task.Remarks = "任务已取消";
|
||
await _workOrderRepository.UpdateAsync(task);
|
||
|
||
// 7. 更新整合记录(仅对已分配状态的任务)
|
||
if (integrationRecord != null)
|
||
{
|
||
await UpdateIntegrationRecordAfterCancelAsync(integrationRecord, input);
|
||
}
|
||
|
||
// 8. 发送通知
|
||
try
|
||
{
|
||
// 合并指定人员与任务FL人员
|
||
var designatedIds_Cancel = new List<long>();
|
||
if (task.AssignedPersonnelId != null && task.AssignedPersonnelId.HasValue) designatedIds_Cancel.AddRange(task.AssignedPersonnelId.Value);
|
||
if (task != null && task.WorkOrderFLPersonnels != null && task.WorkOrderFLPersonnels.Any()) designatedIds_Cancel.AddRange(task.WorkOrderFLPersonnels.Select(x => x.FLPersonnelId));
|
||
designatedIds_Cancel = designatedIds_Cancel.Distinct().ToList();
|
||
|
||
await _notificationScheduledService.SendWorkOrderOperationNotificationAsync(
|
||
"Cancel", input.TaskId, User.Id, User.Name, input.CancelReason, designatedIds_Cancel);
|
||
}
|
||
catch (Exception notifyEx)
|
||
{
|
||
_logger.LogWarning(notifyEx, "取消任务后发送通知失败,TaskId: {TaskId}", input.TaskId);
|
||
}
|
||
|
||
// 9. 返回结果
|
||
return new WorkOrderOperationResult
|
||
{
|
||
IsSuccess = true,
|
||
Message = "任务取消成功",
|
||
AffectedIntegrationRecordId = integrationRecord?.Id,
|
||
Data = new { TaskId = input.TaskId, OperationType = "Cancel" }
|
||
};
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogError(ex, "取消任务时发生错误,TaskId: {TaskId}", input.TaskId);
|
||
return CreateFailResult($"取消任务失败:{ex.Message}");
|
||
}
|
||
}
|
||
|
||
|
||
#region 私有辅助方法
|
||
|
||
/// <summary>
|
||
/// 判断任务修改是否需要触发重新分配
|
||
/// 基于业务关键字段分析,确保分配策略的准确性
|
||
/// </summary>
|
||
private bool ShouldTriggerReallocation(WorkOrderEntity originalTask, WorkOrderUpdateInput modifyData)
|
||
{
|
||
// 1. 时间相关变更(高优先级)
|
||
// WorkOrderDate 变更直接影响班次安排和资源可用性
|
||
if (originalTask.WorkOrderDate.Date != modifyData.WorkOrderDate.Date)
|
||
{
|
||
_logger.LogInformation("任务{TaskId}日期从{OriginalDate}变更为{NewDate},触发重新分配",
|
||
originalTask.Id, originalTask.WorkOrderDate.ToString("yyyy-MM-dd"),
|
||
modifyData.WorkOrderDate.ToString("yyyy-MM-dd"));
|
||
return true;
|
||
}
|
||
|
||
// 2. 人员设备约束变更(直接影响资源分配)
|
||
if (originalTask.AssignedPersonnelId != modifyData.AssignedPersonnelId ||
|
||
originalTask.AssignedEquipmentId != modifyData.AssignedEquipmentId)
|
||
{
|
||
_logger.LogInformation("任务{TaskId}资源分配变更,人员:{OriginalPersonnel}->{NewPersonnel},设备:{OriginalEquipment}->{NewEquipment},触发重新分配",
|
||
originalTask.Id,
|
||
originalTask.AssignedPersonnelId, modifyData.AssignedPersonnelId,
|
||
originalTask.AssignedEquipmentId, modifyData.AssignedEquipmentId);
|
||
return true;
|
||
}
|
||
|
||
// 3. 工序或班次变更(影响分配策略和资源池)
|
||
if (originalTask.ProcessId != modifyData.ProcessId ||
|
||
originalTask.ShiftId != modifyData.ShiftId)
|
||
{
|
||
_logger.LogInformation("任务{TaskId}工序或班次变更,工序:{OriginalProcess}->{NewProcess},班次:{OriginalShift}->{NewShift},触发重新分配",
|
||
originalTask.Id,
|
||
originalTask.ProcessId, modifyData.ProcessId,
|
||
originalTask.ShiftId, modifyData.ShiftId);
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 修改任务后更新整合记录(仅对已分配任务生效)
|
||
/// </summary>
|
||
private async Task UpdateIntegrationRecordAfterModifyAsync(IntegrationRecordEntity record, WorkOrderModifyOperationInput input, WorkOrderEntity originalTask, bool needsReallocation)
|
||
{
|
||
if (record == null) return;
|
||
|
||
try
|
||
{
|
||
var modifyData = input.TaskModifyData;
|
||
|
||
// === 1. 版本管理字段(每次修改都更新) ===
|
||
record.CurrentVersion += 1;
|
||
record.ChangeTriggerSource = "TaskModification";
|
||
|
||
// === 2. 根据变更类型更新对应字段 ===
|
||
var changeTypes = new List<string>();
|
||
|
||
// 2.1 日期变更处理
|
||
if (originalTask.WorkOrderDate.Date != modifyData.WorkOrderDate.Date)
|
||
{
|
||
changeTypes.Add("WorkOrderDateChanged");
|
||
// 日期变更影响所有基于时间的分配,需要标记为需要重新分配
|
||
await UpdateAllocationResultsForDateChange(record, input.TaskId, originalTask, modifyData);
|
||
}
|
||
|
||
// 2.2 人员分配变更处理
|
||
if (originalTask.AssignedPersonnelId != modifyData.AssignedPersonnelId)
|
||
{
|
||
changeTypes.Add("PersonnelAssignmentChanged");
|
||
await UpdatePersonnelAllocationResultAfterTaskCancel(record, input.TaskId, "Task AssignmentChanged");
|
||
await RecalculatePersonnelFairnessScore(record);
|
||
}
|
||
|
||
// 2.3 设备分配变更处理
|
||
if (originalTask.AssignedEquipmentId != modifyData.AssignedEquipmentId)
|
||
{
|
||
changeTypes.Add("EquipmentAssignmentChanged");
|
||
await UpdateEquipmentAllocationResultAfterTaskCancel(record, input.TaskId, "Task AssignmentChanged");
|
||
await RecalculateEquipmentUtilizationRate(record);
|
||
}
|
||
|
||
// 2.4 工序/班次变更处理
|
||
if (originalTask.ProcessId != modifyData.ProcessId || originalTask.ShiftId != modifyData.ShiftId)
|
||
{
|
||
changeTypes.Add("ProcessOrShiftChanged");
|
||
// 工序班次变更可能需要更新分配策略配置
|
||
await UpdateStrategyConfigForProcessShiftChange(record, originalTask, modifyData);
|
||
// 重新评估所有分配结果
|
||
await ReEvaluateAllAllocationResults(record, input.TaskId);
|
||
}
|
||
|
||
// === 3. 统计信息更新 ===
|
||
if (needsReallocation)
|
||
{
|
||
// 如果需要重新分配,可能会影响成功失败统计
|
||
// 这里可以标记状态,等待重新分配完成后再更新统计
|
||
record.AllowAutoReallocation = true;
|
||
record.ChangeImpactScore = CalculateChangeImpact(changeTypes, originalTask, modifyData);
|
||
}
|
||
|
||
// === 4. 变更详情记录 ===
|
||
var changeDetails = record.GetChangeDetails();
|
||
if (!changeDetails.ChangedTaskIds.Contains(input.TaskId))
|
||
{
|
||
changeDetails.ChangedTaskIds.Add(input.TaskId);
|
||
}
|
||
changeDetails.ChangeTypes.AddRange(changeTypes);
|
||
changeDetails.DetectedTime = DateTime.Now;
|
||
|
||
// 记录具体变更内容到TaskModifications
|
||
if (originalTask.WorkOrderDate.Date != modifyData.WorkOrderDate.Date)
|
||
{
|
||
changeDetails.TaskModifications.Add(new TaskChangeDetail
|
||
{
|
||
TaskId = input.TaskId,
|
||
ModificationType = "TimeChanged",
|
||
BeforeValue = System.Text.Json.JsonSerializer.Serialize(new { WorkOrderDate = originalTask.WorkOrderDate }),
|
||
AfterValue = System.Text.Json.JsonSerializer.Serialize(new { WorkOrderDate = modifyData.WorkOrderDate }),
|
||
Description = "任务日期变更"
|
||
});
|
||
}
|
||
|
||
if (originalTask.AssignedPersonnelId != modifyData.AssignedPersonnelId)
|
||
{
|
||
changeDetails.PersonnelChanges.Add(new PersonnelAssignmentChange
|
||
{
|
||
TaskId = input.TaskId,
|
||
PreviousPersonnelId = originalTask.AssignedPersonnelId,
|
||
NewPersonnelId = modifyData.AssignedPersonnelId,
|
||
ChangeReason = "任务修改导致人员分配变更"
|
||
});
|
||
}
|
||
|
||
if (originalTask.AssignedEquipmentId != modifyData.AssignedEquipmentId)
|
||
{
|
||
changeDetails.EquipmentChanges.Add(new EquipmentAssignmentChange
|
||
{
|
||
TaskId = input.TaskId,
|
||
PreviousEquipmentId = originalTask.AssignedEquipmentId,
|
||
NewEquipmentId = modifyData.AssignedEquipmentId,
|
||
ChangeReason = "任务修改导致设备分配变更"
|
||
});
|
||
}
|
||
|
||
if (originalTask.ProcessId != modifyData.ProcessId)
|
||
{
|
||
changeDetails.TaskModifications.Add(new TaskChangeDetail
|
||
{
|
||
TaskId = input.TaskId,
|
||
ModificationType = "ProcessChanged",
|
||
BeforeValue = System.Text.Json.JsonSerializer.Serialize(new { ProcessId = originalTask.ProcessId }),
|
||
AfterValue = System.Text.Json.JsonSerializer.Serialize(new { ProcessId = modifyData.ProcessId }),
|
||
Description = "工序变更"
|
||
});
|
||
}
|
||
|
||
if (originalTask.ShiftId != modifyData.ShiftId)
|
||
{
|
||
changeDetails.TaskModifications.Add(new TaskChangeDetail
|
||
{
|
||
TaskId = input.TaskId,
|
||
ModificationType = "ShiftChanged",
|
||
BeforeValue = System.Text.Json.JsonSerializer.Serialize(new { ShiftId = originalTask.ShiftId }),
|
||
AfterValue = System.Text.Json.JsonSerializer.Serialize(new { ShiftId = modifyData.ShiftId }),
|
||
Description = "班次变更"
|
||
});
|
||
}
|
||
record.SetChangeDetails(changeDetails);
|
||
|
||
// === 5. 更新结果摘要 ===
|
||
var reallocationNote = needsReallocation ? " (需要重新分配)" : "";
|
||
record.ResultSummary = $"总任务数: {record.TotalTaskCount}, 成功: {record.SuccessTaskCount}, 失败: {record.FailedTaskCount}, 成功率: {record.SuccessRate}%{reallocationNote}";
|
||
|
||
// === 6. 操作日志 ===
|
||
var changeTypeStr = string.Join(", ", changeTypes);
|
||
record.Remarks = $"{record.Remarks}\n[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] 任务{input.TaskId}修改({changeTypeStr}){reallocationNote}: {input.Remarks}";
|
||
|
||
await _integrationRecordRepository.UpdateAsync(record);
|
||
|
||
_logger.LogInformation("任务{TaskId}修改后,整合记录{IntegrationRecordId}已更新,变更类型:{ChangeTypes},需要重新分配:{NeedsReallocation}",
|
||
input.TaskId, record.Id, changeTypeStr, needsReallocation);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogError(ex, "更新整合记录时发生错误,TaskId: {TaskId}, IntegrationRecordId: {IntegrationRecordId}",
|
||
input.TaskId, record.Id);
|
||
throw;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 删除任务后更新整合记录(仅对已分配任务生效)
|
||
/// </summary>
|
||
private async Task UpdateIntegrationRecordAfterDeleteAsync(IntegrationRecordEntity record, WorkOrderDeleteOperationInput input)
|
||
{
|
||
if (record == null) return;
|
||
|
||
try
|
||
{
|
||
// 1. 从 TaskIdsJson 中移除被删除的任务ID
|
||
var taskIds = record.GetTaskIds();
|
||
if (taskIds.Contains(input.TaskId))
|
||
{
|
||
taskIds.Remove(input.TaskId);
|
||
record.SetTaskIds(taskIds);
|
||
}
|
||
|
||
// 2. 更新任务计数统计(删除的任务直接减少成功数,不增加失败数)
|
||
record.SuccessTaskCount = Math.Max(0, record.SuccessTaskCount - 1);
|
||
|
||
// 3. 更新人员分配结果(从JSON中移除该任务的分配信息)
|
||
await UpdatePersonnelAllocationResultAfterTaskRemoval(record, input.TaskId);
|
||
|
||
// 4. 更新设备分配结果(从JSON中移除该任务的分配信息)
|
||
await UpdateEquipmentAllocationResultAfterTaskRemoval(record, input.TaskId);
|
||
|
||
// 5. 更新结果摘要
|
||
record.ResultSummary = $"总任务数: {record.TotalTaskCount}, 成功: {record.SuccessTaskCount}, 失败: {record.FailedTaskCount}, 成功率: {record.SuccessRate}%";
|
||
|
||
// 6. 记录操作日志
|
||
var deleteType = input.IsSoftDelete ? "软删除" : "物理删除";
|
||
record.Remarks = $"{record.Remarks}\n[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] 任务{input.TaskId}被{input.OperatorName}{deleteType}: {input.DeleteReason}";
|
||
|
||
await _integrationRecordRepository.UpdateAsync(record);
|
||
|
||
_logger.LogInformation("已分配任务{TaskId}{DeleteType}后,整合记录{IntegrationRecordId}已更新(包含TaskIds、分配结果等)",
|
||
input.TaskId, deleteType, record.Id);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogError(ex, "删除任务后更新整合记录时发生错误,TaskId: {TaskId}, IntegrationRecordId: {IntegrationRecordId}",
|
||
input.TaskId, record.Id);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 取消任务后更新整合记录(仅对已分配任务生效)
|
||
/// </summary>
|
||
private async Task UpdateIntegrationRecordAfterCancelAsync(IntegrationRecordEntity record, WorkOrderCancelOperationInput input)
|
||
{
|
||
if (record == null) return;
|
||
|
||
try
|
||
{
|
||
// 1. 任务取消后不从TaskIdsJson中移除(取消的任务仍然是原始整合的一部分)
|
||
// 2. 更新任务计数统计
|
||
record.SuccessTaskCount = Math.Max(0, record.SuccessTaskCount - 1);
|
||
|
||
// 3. 更新人员分配结果(将该任务标记为取消状态)
|
||
await UpdatePersonnelAllocationResultAfterTaskCancel(record, input.TaskId, "Task Cancelled");
|
||
|
||
// 4. 更新设备分配结果(将该任务标记为取消状态)
|
||
await UpdateEquipmentAllocationResultAfterTaskCancel(record, input.TaskId, "Task Cancelled");
|
||
|
||
// 5. 更新结果摘要
|
||
record.ResultSummary = $"总任务数: {record.TotalTaskCount}, 成功: {record.SuccessTaskCount}, 失败: {record.FailedTaskCount}, 成功率: {record.SuccessRate}%";
|
||
|
||
// 6. 记录操作日志
|
||
record.Remarks = $"{record.Remarks}\n[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] 任务{input.TaskId}被{input.OperatorName}取消: {input.CancelReason}";
|
||
|
||
await _integrationRecordRepository.UpdateAsync(record);
|
||
|
||
_logger.LogInformation("已分配任务{TaskId}取消后,整合记录{IntegrationRecordId}已更新(包含分配结果状态等)", input.TaskId, record.Id);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogError(ex, "取消任务后更新整合记录时发生错误,TaskId: {TaskId}, IntegrationRecordId: {IntegrationRecordId}",
|
||
input.TaskId, record.Id);
|
||
}
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 创建失败结果
|
||
/// </summary>
|
||
private WorkOrderOperationResult CreateFailResult(string message)
|
||
{
|
||
return new WorkOrderOperationResult
|
||
{
|
||
IsSuccess = false,
|
||
Message = message,
|
||
ErrorDetails = { message }
|
||
};
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证修改操作参数
|
||
/// </summary>
|
||
private WorkOrderValidationResult ValidateModifyParameters(WorkOrderModifyOperationInput input)
|
||
{
|
||
if (input == null)
|
||
return WorkOrderValidationResult.Fail("输入参数不能为空");
|
||
|
||
if (input.TaskId <= 0)
|
||
return WorkOrderValidationResult.Fail("任务ID必须大于0");
|
||
|
||
if (input.TaskModifyData == null)
|
||
return WorkOrderValidationResult.Fail("修改数据不能为空");
|
||
|
||
return WorkOrderValidationResult.Success();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证删除操作参数
|
||
/// </summary>
|
||
private WorkOrderValidationResult ValidateDeleteParameters(WorkOrderDeleteOperationInput input)
|
||
{
|
||
if (input == null)
|
||
return WorkOrderValidationResult.Fail("输入参数不能为空");
|
||
|
||
if (input.TaskId <= 0)
|
||
return WorkOrderValidationResult.Fail("任务ID必须大于0");
|
||
|
||
return WorkOrderValidationResult.Success();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证取消操作参数
|
||
/// </summary>
|
||
private WorkOrderValidationResult ValidateCancelParameters(WorkOrderCancelOperationInput input)
|
||
{
|
||
if (input == null)
|
||
return WorkOrderValidationResult.Fail("输入参数不能为空");
|
||
|
||
if (input.TaskId <= 0)
|
||
return WorkOrderValidationResult.Fail("任务ID必须大于0");
|
||
|
||
return WorkOrderValidationResult.Success();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证修改操作的业务规则
|
||
/// </summary>
|
||
private Task<WorkOrderValidationResult> ValidateModifyBusinessRulesAsync(WorkOrderModifyOperationInput input)
|
||
{
|
||
// 这里可以添加具体的业务规则验证
|
||
// 例如:检查任务是否与其他任务有依赖关系等
|
||
return Task.FromResult(WorkOrderValidationResult.Success());
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证删除操作的业务规则
|
||
/// </summary>
|
||
private Task<WorkOrderValidationResult> ValidateDeleteBusinessRulesAsync(WorkOrderDeleteOperationInput input)
|
||
{
|
||
// 这里可以添加具体的业务规则验证
|
||
// 例如:检查任务是否与其他任务有依赖关系等
|
||
return Task.FromResult(WorkOrderValidationResult.Success());
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证取消操作的业务规则
|
||
/// </summary>
|
||
private Task<WorkOrderValidationResult> ValidateCancelBusinessRulesAsync(WorkOrderCancelOperationInput input)
|
||
{
|
||
// 这里可以添加具体的业务规则验证
|
||
// 例如:检查任务是否与其他任务有依赖关系等
|
||
return Task.FromResult(WorkOrderValidationResult.Success());
|
||
}
|
||
|
||
/// <summary>
|
||
/// 任务删除后更新人员分配结果
|
||
/// </summary>
|
||
private async Task UpdatePersonnelAllocationResultAfterTaskRemoval(IntegrationRecordEntity record, long taskId)
|
||
{
|
||
try
|
||
{
|
||
if (string.IsNullOrWhiteSpace(record.PersonnelAllocationResultJson) || record.PersonnelAllocationResultJson == "{}")
|
||
return;
|
||
|
||
// 解析人员分配结果
|
||
var allocationResult = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, object>>(record.PersonnelAllocationResultJson);
|
||
if (allocationResult == null) return;
|
||
|
||
// 从成功分配列表中移除该任务
|
||
if (allocationResult.ContainsKey("successfulAllocations"))
|
||
{
|
||
var successfulAllocations = allocationResult["successfulAllocations"] as JsonElement?;
|
||
if (successfulAllocations.HasValue && successfulAllocations.Value.ValueKind == JsonValueKind.Array)
|
||
{
|
||
var updatedAllocations = new List<object>();
|
||
foreach (var allocation in successfulAllocations.Value.EnumerateArray())
|
||
{
|
||
if (allocation.TryGetProperty("TaskId", out var taskIdElement) &&
|
||
taskIdElement.GetInt64() != taskId)
|
||
{
|
||
updatedAllocations.Add(System.Text.Json.JsonSerializer.Deserialize<object>(allocation.GetRawText()));
|
||
}
|
||
}
|
||
allocationResult["successfulAllocations"] = updatedAllocations;
|
||
}
|
||
}
|
||
|
||
// 添加到失败列表
|
||
if (!allocationResult.ContainsKey("failedAllocations"))
|
||
allocationResult["failedAllocations"] = new List<object>();
|
||
|
||
var failedList = allocationResult["failedAllocations"] as List<object> ?? new List<object>();
|
||
failedList.Add(new { TaskId = taskId, Reason = "Task deleted", Timestamp = DateTime.Now });
|
||
allocationResult["failedAllocations"] = failedList;
|
||
|
||
// 更新JSON
|
||
record.PersonnelAllocationResultJson = System.Text.Json.JsonSerializer.Serialize(allocationResult);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogError(ex, "更新人员分配结果时发生错误,TaskId: {TaskId}", taskId);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 任务删除后更新设备分配结果
|
||
/// </summary>
|
||
private async Task UpdateEquipmentAllocationResultAfterTaskRemoval(IntegrationRecordEntity record, long taskId)
|
||
{
|
||
try
|
||
{
|
||
if (string.IsNullOrWhiteSpace(record.EquipmentAllocationResultJson) || record.EquipmentAllocationResultJson == "{}")
|
||
return;
|
||
|
||
// 解析设备分配结果
|
||
var allocationResult = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, object>>(record.EquipmentAllocationResultJson);
|
||
if (allocationResult == null) return;
|
||
|
||
// 从成功分配列表中移除该任务
|
||
if (allocationResult.ContainsKey("successfulAllocations"))
|
||
{
|
||
var successfulAllocations = allocationResult["successfulAllocations"] as JsonElement?;
|
||
if (successfulAllocations.HasValue && successfulAllocations.Value.ValueKind == JsonValueKind.Array)
|
||
{
|
||
var updatedAllocations = new List<object>();
|
||
foreach (var allocation in successfulAllocations.Value.EnumerateArray())
|
||
{
|
||
if (allocation.TryGetProperty("TaskId", out var taskIdElement) &&
|
||
taskIdElement.GetInt64() != taskId)
|
||
{
|
||
updatedAllocations.Add(System.Text.Json.JsonSerializer.Deserialize<object>(allocation.GetRawText()));
|
||
}
|
||
}
|
||
allocationResult["successfulAllocations"] = updatedAllocations;
|
||
}
|
||
}
|
||
|
||
// 添加到失败列表
|
||
if (!allocationResult.ContainsKey("failedAllocations"))
|
||
allocationResult["failedAllocations"] = new List<object>();
|
||
|
||
var failedList = allocationResult["failedAllocations"] as List<object> ?? new List<object>();
|
||
failedList.Add(new { TaskId = taskId, Reason = "Task deleted", Timestamp = DateTime.Now });
|
||
allocationResult["failedAllocations"] = failedList;
|
||
|
||
// 更新JSON
|
||
record.EquipmentAllocationResultJson = System.Text.Json.JsonSerializer.Serialize(allocationResult);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogError(ex, "更新设备分配结果时发生错误,TaskId: {TaskId}", taskId);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 任务取消后更新人员分配结果
|
||
/// </summary>
|
||
private async Task UpdatePersonnelAllocationResultAfterTaskCancel(IntegrationRecordEntity record, long taskId, string reason = "")
|
||
{
|
||
try
|
||
{
|
||
if (string.IsNullOrWhiteSpace(record.PersonnelAllocationResultJson) || record.PersonnelAllocationResultJson == "{}")
|
||
return;
|
||
|
||
// 解析人员分配结果
|
||
var allocationResult = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, object>>(record.PersonnelAllocationResultJson);
|
||
if (allocationResult == null) return;
|
||
|
||
// 从成功分配列表中移除该任务
|
||
if (allocationResult.ContainsKey("successfulAllocations"))
|
||
{
|
||
var successfulAllocations = allocationResult["successfulAllocations"] as JsonElement?;
|
||
if (successfulAllocations.HasValue && successfulAllocations.Value.ValueKind == JsonValueKind.Array)
|
||
{
|
||
var updatedAllocations = new List<object>();
|
||
foreach (var allocation in successfulAllocations.Value.EnumerateArray())
|
||
{
|
||
if (allocation.TryGetProperty("TaskId", out var taskIdElement) &&
|
||
taskIdElement.GetInt64() != taskId)
|
||
{
|
||
updatedAllocations.Add(System.Text.Json.JsonSerializer.Deserialize<object>(allocation.GetRawText()));
|
||
}
|
||
}
|
||
allocationResult["successfulAllocations"] = updatedAllocations;
|
||
}
|
||
}
|
||
|
||
// 添加到失败列表
|
||
if (!allocationResult.ContainsKey("failedAllocations"))
|
||
allocationResult["failedAllocations"] = new List<object>();
|
||
|
||
var failedList = allocationResult["failedAllocations"] as List<object> ?? new List<object>();
|
||
failedList.Add(new { TaskId = taskId, Reason = reason, Timestamp = DateTime.Now });
|
||
allocationResult["failedAllocations"] = failedList;
|
||
|
||
// 更新JSON
|
||
record.PersonnelAllocationResultJson = System.Text.Json.JsonSerializer.Serialize(allocationResult);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogError(ex, "更新人员分配结果时发生错误,TaskId: {TaskId}", taskId);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 任务取消后更新设备分配结果
|
||
/// </summary>
|
||
private async Task UpdateEquipmentAllocationResultAfterTaskCancel(IntegrationRecordEntity record, long taskId,string reason = "")
|
||
{
|
||
try
|
||
{
|
||
if (string.IsNullOrWhiteSpace(record.EquipmentAllocationResultJson) || record.EquipmentAllocationResultJson == "{}")
|
||
return;
|
||
|
||
// 解析设备分配结果
|
||
var allocationResult = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, object>>(record.EquipmentAllocationResultJson);
|
||
if (allocationResult == null) return;
|
||
|
||
// 从成功分配列表中移除该任务
|
||
if (allocationResult.ContainsKey("successfulAllocations"))
|
||
{
|
||
var successfulAllocations = allocationResult["successfulAllocations"] as JsonElement?;
|
||
if (successfulAllocations.HasValue && successfulAllocations.Value.ValueKind == JsonValueKind.Array)
|
||
{
|
||
var updatedAllocations = new List<object>();
|
||
foreach (var allocation in successfulAllocations.Value.EnumerateArray())
|
||
{
|
||
if (allocation.TryGetProperty("TaskId", out var taskIdElement) &&
|
||
taskIdElement.GetInt64() != taskId)
|
||
{
|
||
updatedAllocations.Add(System.Text.Json.JsonSerializer.Deserialize<object>(allocation.GetRawText()));
|
||
}
|
||
}
|
||
allocationResult["successfulAllocations"] = updatedAllocations;
|
||
}
|
||
}
|
||
|
||
// 添加到失败列表
|
||
if (!allocationResult.ContainsKey("failedAllocations"))
|
||
allocationResult["failedAllocations"] = new List<object>();
|
||
|
||
var failedList = allocationResult["failedAllocations"] as List<object> ?? new List<object>();
|
||
failedList.Add(new { TaskId = taskId, Reason = reason, Timestamp = DateTime.Now });
|
||
allocationResult["failedAllocations"] = failedList;
|
||
|
||
// 更新JSON
|
||
record.EquipmentAllocationResultJson = System.Text.Json.JsonSerializer.Serialize(allocationResult);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogError(ex, "更新设备分配结果时发生错误,TaskId: {TaskId}", taskId);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 计算变更影响评分
|
||
/// </summary>
|
||
private int CalculateChangeImpact(List<string> changeTypes, WorkOrderEntity originalTask, WorkOrderUpdateInput modifyData)
|
||
{
|
||
int score = 0;
|
||
|
||
if (changeTypes.Contains("WorkOrderDateChanged")) score += 40;
|
||
if (changeTypes.Contains("PersonnelAssignmentChanged")) score += 30;
|
||
if (changeTypes.Contains("EquipmentAssignmentChanged")) score += 25;
|
||
if (changeTypes.Contains("ProcessOrShiftChanged")) score += 35;
|
||
|
||
return Math.Min(100, score);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 日期变更时更新分配结果
|
||
/// </summary>
|
||
private async Task UpdateAllocationResultsForDateChange(IntegrationRecordEntity record, long taskId, WorkOrderEntity originalTask, WorkOrderUpdateInput modifyData)
|
||
{
|
||
// 日期变更可能需要重新评估所有分配结果
|
||
// 这里可以实现具体的日期变更处理逻辑
|
||
_logger.LogInformation("任务{TaskId}日期变更,正在更新分配结果", taskId);
|
||
await Task.CompletedTask; // 占位实现
|
||
}
|
||
|
||
/// <summary>
|
||
/// 重新计算人员公平性评分
|
||
/// </summary>
|
||
private async Task RecalculatePersonnelFairnessScore(IntegrationRecordEntity record)
|
||
{
|
||
// 这里可以实现人员公平性评分的重新计算逻辑
|
||
// 暂时保持原有分数
|
||
_logger.LogInformation("正在重新计算人员公平性评分,整合记录ID: {IntegrationRecordId}", record.Id);
|
||
await Task.CompletedTask; // 占位实现
|
||
}
|
||
|
||
/// <summary>
|
||
/// 重新计算设备利用率
|
||
/// </summary>
|
||
private async Task RecalculateEquipmentUtilizationRate(IntegrationRecordEntity record)
|
||
{
|
||
// 这里可以实现设备利用率的重新计算逻辑
|
||
// 暂时保持原有数值
|
||
_logger.LogInformation("正在重新计算设备利用率,整合记录ID: {IntegrationRecordId}", record.Id);
|
||
await Task.CompletedTask; // 占位实现
|
||
}
|
||
|
||
/// <summary>
|
||
/// 工序班次变更时更新策略配置
|
||
/// </summary>
|
||
private async Task UpdateStrategyConfigForProcessShiftChange(IntegrationRecordEntity record, WorkOrderEntity originalTask, WorkOrderUpdateInput modifyData)
|
||
{
|
||
// 工序班次变更可能需要更新分配策略
|
||
_logger.LogInformation("工序班次变更,正在更新策略配置,整合记录ID: {IntegrationRecordId}", record.Id);
|
||
await Task.CompletedTask; // 占位实现
|
||
}
|
||
|
||
/// <summary>
|
||
/// 重新评估所有分配结果
|
||
/// </summary>
|
||
private async Task ReEvaluateAllAllocationResults(IntegrationRecordEntity record, long taskId)
|
||
{
|
||
// 重新评估所有分配结果的逻辑
|
||
_logger.LogInformation("正在重新评估所有分配结果,任务ID: {TaskId},整合记录ID: {IntegrationRecordId}", taskId, record.Id);
|
||
await Task.CompletedTask; // 占位实现
|
||
}
|
||
|
||
#endregion
|
||
}
|
||
} |