feat(dal): Реализован сервис UnitFilterService для получения Unit, для которых требуется создать или уже создан шаблон по Job.Id

This commit is contained in:
Mikhail Kuznetsov
2025-08-12 11:50:29 +10:00
parent 97af546654
commit 1272ce92ec
12 changed files with 189 additions and 114 deletions

View File

@@ -0,0 +1,139 @@
using Microsoft.EntityFrameworkCore;
using PARR.DAL.Contracts;
using PARR.DAL.DomainServices.Interfaces;
using PARR.DAL.Services.Interfaces.Job;
using PARR.DAL.Services.Interfaces.Unit;
using System.Text.RegularExpressions;
namespace PARR.DAL.DomainServices.Implementations
{
internal class ShortcodesService : IShortcodesService
{
private const string shortcodePattern = "%[^%\\s]+%";
private readonly SettingsFromDb settingsFromDb;
private readonly IJobService jobService;
private readonly IUnitService unitService;
public ShortcodesService(
SettingsFromDb settingsFromDb,
IJobService jobService,
IUnitService unitService
)
{
this.settingsFromDb = settingsFromDb;
this.jobService = jobService;
this.unitService = unitService;
}
public async Task<string> ApplyShortcodesAsync(string str, Guid unitId, Guid jobId)
{
//TODO удалить старый в GeneralExtesions, связанные с ним Enum и написать метод. делов...
var nameConstants = settingsFromDb.TemplateNameConstantPartsList;
var job = await jobService.Get().AsNoTracking().FirstOrDefaultAsync(t => t.Id == jobId);
var unit = await unitService.Get().AsNoTracking().FirstOrDefaultAsync(t => t.Id == unitId);
if (job != null && unit != null && job.TemplateNameMask != null)
{
var resultName = str;
var shortcodesInMask = GetShortCodes(resultName);
//Проверяем и меняем наличие статичных частей в маске имени шаблона
if (shortcodesInMask.Any(x => nameConstants.Select(x => "%" + x.Name + "%").ToList().Contains(x.Value)))
{
resultName = ReplaceConstants(nameConstants, resultName);
}
//Проверяем и меняем Shortcodes в маске имени шаблона
var shortCodes = GetShortcodesNames();
if (shortcodesInMask.Any(x => shortCodes.Select(x => x).ToList().Contains(x.Value)))
{
resultName = ReplaceShortcodes(job, unit, resultName, shortcodesInMask);
}
//Если остались %переменные% проверяем совпадение по имени поля
shortcodesInMask = GetShortCodes(resultName);
if (shortcodesInMask.Count > 0)
{
resultName = await ReplaceFieldValues(unitId, resultName, shortcodesInMask);
}
return resultName;
}
return "";
}
public bool isAnyShortcodes(string str)
{
return Regex.IsMatch(str, shortcodePattern);
}
private async Task<string> ReplaceFieldValues(Guid unitId, string resultName, List<Match> shortcodesInMask)
{
var unitWithFields = await unitService.Get()
.AsNoTracking()
.Include(u => u.UnitValues)
.ThenInclude(uv => uv.Field)
.Include(u => u.UnitValues)
.ThenInclude(uv => uv.Value)
.FirstOrDefaultAsync(t => t.Id == unitId);
foreach (var item in shortcodesInMask)
{
var fieldName = item.Value.Replace("%", "").ToUpper();
var value = unitWithFields!.UnitValues!.FirstOrDefault(t => t.Field!.AihitName!.ToUpper() == fieldName!);
if (value != null)
resultName = resultName.Replace(item.Value, value!.Value!.Value);
}
return resultName;
}
private static string ReplaceShortcodes(Models.Job.Job job, Models.Unit.Unit unit, string resultName, List<Match> shortcodesInMask)
{
if (shortcodesInMask.Any(x => x.Value == "%РАБОТА%"))
resultName = resultName.Replace("%РАБОТА%", job.WorkName);
if (shortcodesInMask.Any(x => x.Value == "%ЭК%"))
resultName = resultName.Replace("%ЭК%", unit.Name);
return resultName;
}
private static string ReplaceConstants(List<BLL.Domain.TemplateNameConstantPart> nameConstants, string resultName)
{
foreach (var item in nameConstants)
{
resultName = resultName.Replace($"%{item.Name}%", item.Value);
}
return resultName;
}
private static List<Match> GetShortCodes(string resultName)
{
var shortcodesInMask = Regex.Matches(resultName, shortcodePattern).ToList();
return shortcodesInMask;
}
private List<string> GetShortcodesNames()
{
var result = new List<string> {
"%ЭК%",
"%ЗО%",
"%РАБОТА%"
};
return result;
}
}
}

View File

@@ -0,0 +1,128 @@
using Microsoft.EntityFrameworkCore;
using PARR.DAL.Contracts;
using PARR.DAL.DomainServices.Interfaces;
using PARR.DAL.Services.Interfaces.Job;
using PARR.DAL.Services.Interfaces.Unit;
using System.Text.RegularExpressions;
namespace PARR.DAL.DomainServices.Implementations
{
internal class TemplateNameGeneratorService : ITemplateNameGeneratorService
{
private readonly SettingsFromDb settingsFromDb;
private readonly IJobService jobService;
private readonly IUnitService unitService;
public TemplateNameGeneratorService(
SettingsFromDb settingsFromDb,
IJobService jobService,
IUnitService unitService
)
{
this.settingsFromDb = settingsFromDb;
this.jobService = jobService;
this.unitService = unitService;
}
public async Task<string> GetTemplateNameAsync(Guid jobId, Guid unitId)
{
var nameConstants = settingsFromDb.TemplateNameConstantPartsList;
var job = await jobService.Get().AsNoTracking().FirstOrDefaultAsync(t => t.Id == jobId);
var unit = await unitService.Get().AsNoTracking().FirstOrDefaultAsync(t => t.Id == unitId);
if (job != null && unit != null && job.TemplateNameMask != null)
{
var resultName = job.TemplateNameMask;
var shortcodesInMask = GetShortCodes(resultName);
//Проверяем и меняем наличие статичных частей в маске имени шаблона
if (shortcodesInMask.Any(x => nameConstants.Select(x => "%" + x.Name + "%").ToList().Contains(x.Value)))
{
resultName = ReplaceConstants(nameConstants, resultName);
}
//Проверяем и меняем Shortcodes в маске имени шаблона
var shortCodes = GetShortcodesNames();
if (shortcodesInMask.Any(x => shortCodes.Select(x => x).ToList().Contains(x.Value)))
{
resultName = ReplaceShortcodes(job, unit, resultName, shortcodesInMask);
}
//Если остались %переменные% проверяем совпадение по имени поля
shortcodesInMask = GetShortCodes(resultName);
if (shortcodesInMask.Count > 0)
{
resultName = await ReplaceFieldValues(unitId, resultName, shortcodesInMask);
}
return resultName;
}
return "";
}
private async Task<string> ReplaceFieldValues(Guid unitId, string resultName, List<Match> shortcodesInMask)
{
var unitWithFields = await unitService.Get()
.AsNoTracking()
.Include(u => u.UnitValues)
.ThenInclude(uv => uv.Field)
.Include(u => u.UnitValues)
.ThenInclude(uv => uv.Value)
.FirstOrDefaultAsync(t => t.Id == unitId);
foreach (var item in shortcodesInMask)
{
var fieldName = item.Value.Replace("%", "").ToUpper();
var value = unitWithFields!.UnitValues!.FirstOrDefault(t => t.Field!.AihitName!.ToUpper() == fieldName!);
if (value != null)
resultName = resultName.Replace(item.Value, value!.Value!.Value);
}
return resultName;
}
private static string ReplaceShortcodes(Models.Job.Job job, Models.Unit.Unit unit, string resultName, List<Match> shortcodesInMask)
{
if (shortcodesInMask.Any(x => x.Value == "%РАБОТА%"))
resultName = resultName.Replace("%РАБОТА%", job.WorkName);
if (shortcodesInMask.Any(x => x.Value == "%ЭК%"))
resultName = resultName.Replace("%ЭК%", unit.Name);
return resultName;
}
private static string ReplaceConstants(List<BLL.Domain.TemplateNameConstantPart> nameConstants, string resultName)
{
foreach (var item in nameConstants)
{
resultName = resultName.Replace($"%{item.Name}%", item.Value);
}
return resultName;
}
private static List<Match> GetShortCodes(string resultName)
{
var shortcodePattern = "%[^%\\s]+%";
var shortcodesInMask = Regex.Matches(resultName, shortcodePattern).ToList();
return shortcodesInMask;
}
private List<string> GetShortcodesNames()
{
var result = new List<string> {
"%ЭК%",
"%ЗО%",
"%РАБОТА%"
};
return result;
}
}
}

View File

@@ -0,0 +1,133 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using PARR.DAL.DomainServices.Interfaces;
using PARR.DAL.Services.Interfaces;
using PARR.DAL.Services.Interfaces.Job;
using PARR.DAL.Services.Interfaces.Unit;
namespace PARR.DAL.DomainServices.Implementations
{
internal class UnitFilterService : IUnitFilterService
{
private readonly ILogger<UnitFilterService> logger;
private readonly IJobService jobService;
private readonly IUnitService unitService;
private readonly ITemplateService templateService;
public UnitFilterService(
ILogger<UnitFilterService> logger,
IJobService jobService,
IUnitService unitService,
ITemplateService templateService
)
{
this.logger = logger;
this.jobService = jobService;
this.unitService = unitService;
this.templateService = templateService;
}
public async Task<IEnumerable<Guid>?> GetUnitsIdByJobFilterAsync(Guid jobId)
{
var result = new List<Guid>();
var job = await jobService
.Get().AsNoTracking()
.Include(t => t.UnitFilters)
.ThenInclude(t => t.FieldFilters)
.Include(t => t.UnitFilters)
.ThenInclude(t => t.RelationshipFilters)
.FirstOrDefaultAsync(t => t.Id == jobId);
if (job == null)
return null;
var baseQuery = unitService
.Get().AsNoTracking()
.Include(t => t.UnitValues)
.ThenInclude(t => t.Field)
.Include(t => t.UnitValues)
.ThenInclude(t => t.Value)
.Include(t => t.ParentUnits)
.ThenInclude(t => t.ParentUnit)
.ThenInclude(t => t.UnitValues)
.ThenInclude(t => t.Field)
.Include(t => t.ParentUnits)
.ThenInclude(t => t.ParentUnit)
.ThenInclude(t => t.UnitValues)
.ThenInclude(t => t.Value)
.Include(t => t.ChildUnits)
.ThenInclude(t => t.ChildUnit)
.ThenInclude(t => t.UnitValues)
.ThenInclude(t => t.Field)
.Include(t => t.ChildUnits)
.ThenInclude(t => t.ChildUnit)
.ThenInclude(t => t.UnitValues)
.ThenInclude(t => t.Value);
logger.LogInformation($"В baseQuery записей {await baseQuery.CountAsync()}");
foreach (var unitFilter in job.UnitFilters)
{
var query = baseQuery.Where(t => EF.Functions.ILike(t.Name, unitFilter.UnitFilter));
foreach (var fieldFilter in unitFilter.FieldFilters)
query = query.Where(t => t.UnitValues.Any(x => x.FieldId == fieldFilter.FieldId && (x.Value!.Value != null && EF.Functions.ILike(x.Value!.Value, fieldFilter.ValueMask))));
if (unitFilter.RelationshipFilters.Any())
{
var parentFilters = unitFilter.RelationshipFilters.Where(t => t.IsParent == true).ToList();
foreach (var parentFilter in parentFilters)
{
if (parentFilter.IsInverse == false)
{
if (parentFilter.IsFullMatch)
query = query.Where(t => !t.ParentUnits.Any() || t.ParentUnits.All(p => p.ParentUnit!.UnitValues.Any(pf => pf.FieldId == parentFilter.FieldId && (pf.Value!.Value != null && EF.Functions.ILike(pf.Value.Value, parentFilter.ValueMask)))));
else
query = query.Where(t => !t.ParentUnits.Any() || t.ParentUnits.Any(p => p.ParentUnit!.UnitValues.Any(pf => pf.FieldId == parentFilter.FieldId && (pf.Value!.Value != null && EF.Functions.ILike(pf.Value.Value, parentFilter.ValueMask)))));
}
else
{
if (parentFilter.IsFullMatch)
query = query.Where(t => !t.ParentUnits.Any() || !t.ParentUnits.All(p => p.ParentUnit!.UnitValues.Any(pf => pf.FieldId == parentFilter.FieldId && (pf.Value!.Value != null && EF.Functions.ILike(pf.Value.Value, parentFilter.ValueMask)))));
else
query = query.Where(t => !t.ParentUnits.Any() || !t.ParentUnits.Any(p => p.ParentUnit!.UnitValues.Any(pf => pf.FieldId == parentFilter.FieldId && (pf.Value!.Value != null && EF.Functions.ILike(pf.Value.Value, parentFilter.ValueMask)))));
}
logger.LogInformation($"!В query записей {await query.CountAsync()}");
}
}
var newUnits = await query.Select(t => t.Id).ToListAsync();
result.AddRange(newUnits);
}
return result;
}
public async Task<IEnumerable<Guid>?> GetUnitsIdForExistTemplatesByJobFilterAsync(Guid jobId)
{
var unitIdsMustBeCreated = await GetUnitsIdByJobFilterAsync(jobId);
if (unitIdsMustBeCreated == null || !unitIdsMustBeCreated.Any())
return null;
var unitWithTemplates = await templateService.Get().AsNoTracking().Where(t => t.JobId == jobId && unitIdsMustBeCreated.Any(x => x == t.UnitId)).Select(t => t.UnitId).ToListAsync();
return unitWithTemplates;
}
public async Task<IEnumerable<Guid>?> GetUnitsIdForNotExistTemplatesByJobFilterAsync(Guid jobId)
{
var unitIdsMustBeCreated = await GetUnitsIdByJobFilterAsync(jobId);
if (unitIdsMustBeCreated == null || !unitIdsMustBeCreated.Any())
return null;
var unitIdsWithTemplate = await templateService.Get().AsNoTracking().Where(t => t.JobId == jobId).Select(t => t.UnitId).ToListAsync();
var unitsIdToCreateTemplate = unitIdsMustBeCreated.Where(t => !unitIdsWithTemplate.Any(x => x == t));
return unitsIdToCreateTemplate;
}
}
}