Files
parr_api/PARR.Core/Common/Helpers/JobGroupCloneHelper.cs

180 lines
6.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using PARR.Core.Repositories.Interfaces.JobGroupRepositories;
using PARR.Domain.Entities.Base.History;
using PARR.Domain.Entities.JobEntities;
using PARR.Domain.Entities.JobGroupEntities;
using PARR.Domain.Entities.Schedule;
namespace PARR.Core.Common.Helpers;
/// <summary>
/// Сервис для полного клонирования JobGroup со всеми вложенными Job, фильтрами, AutoControl и EsppSchValues.
/// Шаблоны (Template) не клонируются. Идентификаторы генерируются стратегией EF Core.
/// </summary>
public class JobGroupCloneHelper
{
private readonly IJobGroupRepository groupRepository;
private readonly ILogger<JobGroupCloneHelper> logger;
public JobGroupCloneHelper(
IJobGroupRepository groupRepository,
ILogger<JobGroupCloneHelper> logger)
{
this.groupRepository = groupRepository;
this.logger = logger;
}
public async Task<Guid> CloneAsync(
Guid sourceJobGroupId,
string? newGroupName,
HistoryInitiator initiator,
CancellationToken ct = default)
{
var sourceGroup = await groupRepository.Get()
.AsNoTracking()
.Include(g => g.Jobs)
.ThenInclude(j => j.UnitFilters)
.ThenInclude(uf => uf.FieldFilters)
.Include(g => g.Jobs)
.ThenInclude(j => j.UnitFilters)
.ThenInclude(uf => uf.RelationshipFilters)
.Include(g => g.Jobs)
.ThenInclude(j => j.AutoControl)
.Include(g => g.EsppSchValues)
.FirstOrDefaultAsync(g => g.Id == sourceJobGroupId, ct);
if (sourceGroup == null)
{
throw new InvalidOperationException($"JobGroup {sourceJobGroupId} not found.");
}
logger.LogInformation("Начало клонирования JobGroup {JobGroupId}.", sourceJobGroupId);
var newGroup = MapJobGroup(sourceGroup, newGroupName);
foreach (var sourceJob in sourceGroup.Jobs ?? Enumerable.Empty<Job>())
{
var newJob = MapJob(sourceJob);
newGroup.Jobs.Add(newJob);
CloneJobFilters(sourceJob.UnitFilters, newJob);
if (sourceJob.AutoControl != null)
{
newJob.AutoControl = MapAutoControl(sourceJob.AutoControl);
}
}
// Клонирование значений расписания
foreach (var sourceSchValue in sourceGroup.EsppSchValues ?? Enumerable.Empty<EsppSchValue>())
{
newGroup.EsppSchValues.Add(new EsppSchValue
{
TypeValueId = sourceSchValue.TypeValueId,
TypeConfigId = sourceSchValue.TypeConfigId
});
}
var isSuccess = await groupRepository.CreateAsync(newGroup);
if (!isSuccess)
{
throw new InvalidOperationException("Не удалось сохранить клон JobGroup в базу данных.");
}
await groupRepository.CommitAsync(initiator);
logger.LogInformation("JobGroup успешно клонирована. Новый ID: {NewGroupId}.", newGroup.Id);
return newGroup.Id;
}
private JobGroup MapJobGroup(JobGroup source, string? newName)
{
string finalName = string.IsNullOrWhiteSpace(newName)
? $"{source.GroupName?.TrimEnd()} КЛОН"
: newName.Trim();
return new JobGroup
{
GroupName = finalName,
ShortDescription = source.ShortDescription,
FullDescription = source.FullDescription,
Solution = source.Solution,
TemplateDuration = source.TemplateDuration,
ReferenceDate = source.ReferenceDate,
UserTimeZoneOffsetMinutes = source.UserTimeZoneOffsetMinutes,
IsResponseAreaTimezone = source.IsResponseAreaTimezone,
IsAutoDistributionEnabled = source.IsAutoDistributionEnabled,
IsAgent = source.IsAgent,
AgentName = source.AgentName,
AgentTimeOutSec = source.AgentTimeOutSec,
AgentScript = source.AgentScript,
GroupTypeId = source.GroupTypeId,
GroupingUnitFieldId = source.GroupingUnitFieldId,
IsGroupByResponsible = source.IsGroupByResponsible,
ScheduleExcludeTypeId = source.ScheduleExcludeTypeId,
ScheduleExcludeTypeCalendarId = source.ScheduleExcludeTypeCalendarId,
DateCreated = DateTimeOffset.UtcNow,
Jobs = new HashSet<Job>(),
EsppSchValues = new HashSet<EsppSchValue>()
};
}
private Job MapJob(Job source)
{
return new Job
{
Name = source.Name,
WorkName = source.WorkName,
MinValueRelationships = source.MinValueRelationships,
MaxValueRelationships = source.MaxValueRelationships,
IsParentRelationships = source.IsParentRelationships,
TemplateNameMask = source.TemplateNameMask,
WorkGroupMask = source.WorkGroupMask,
ResponseAreaMask = source.ResponseAreaMask,
TnkId = source.TnkId,
DateCreated = DateTimeOffset.UtcNow,
UnitFilters = new HashSet<JobUnitFilter>()
};
}
private JobAutoControl MapAutoControl(JobAutoControl source)
{
return new JobAutoControl
{
InitUsedTemplateState = source.InitUsedTemplateState,
InitUsedScheduleState = source.InitUsedScheduleState
};
}
private void CloneJobFilters(IEnumerable<JobUnitFilter>? sourceFilters, Job targetJob)
{
if (sourceFilters == null) return;
foreach (var sourceFilter in sourceFilters)
{
var newFilter = new JobUnitFilter
{
UnitFilter = sourceFilter.UnitFilter,
DateCreated = DateTimeOffset.UtcNow,
FieldFilters = sourceFilter.FieldFilters?.Select(f => new JobFieldFilter
{
FieldId = f.FieldId,
ValueMask = f.ValueMask,
IsInverse = f.IsInverse,
DateCreated = DateTimeOffset.UtcNow
}).ToList() ?? new List<JobFieldFilter>(),
RelationshipFilters = sourceFilter.RelationshipFilters?.Select(r => new JobRelationshipFilter
{
FieldId = r.FieldId,
ValueMask = r.ValueMask,
IsInverse = r.IsInverse,
IsParent = r.IsParent,
IsFullMatch = r.IsFullMatch
}).ToList() ?? new List<JobRelationshipFilter>()
};
targetJob.UnitFilters.Add(newFilter);
}
}
}