feat(core): ShortcodeService в классы реализации шорткодов добавлены требования по загрузке таблиц
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using PARR.Core.Services.Shortcodes.Models;
|
||||
using PARR.Core.Services.Shortcodes.Enums;
|
||||
using PARR.Core.Services.Shortcodes.Models;
|
||||
using PARR.Domain.Settings;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
@@ -8,11 +9,15 @@ internal class ConstantsShortcodeHandler : IShortcodeHandler
|
||||
{
|
||||
private readonly SettingsFromDb settings;
|
||||
public int Order => 5;
|
||||
public Regex Pattern => new(@"%[А-ЯA-Z0-9_\-]+%", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
|
||||
private static readonly Regex _pattern = new(@"%[А-ЯA-Z0-9_\-]+%", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
public Regex Pattern => _pattern;
|
||||
|
||||
public ShortcodeDataRequirementsEnum Requirements => ShortcodeDataRequirementsEnum.None;
|
||||
|
||||
public ConstantsShortcodeHandler(SettingsFromDb settings) => this.settings = settings;
|
||||
|
||||
public Task<string> ResolveAsync(string input, TemplateForShortcode data, string caller, CancellationToken ct = default)
|
||||
public Task<string> ResolveAsync(string input, TemplateForShortcode template, string caller, CancellationToken ct = default)
|
||||
{
|
||||
var result = input;
|
||||
foreach (var constant in settings.TemplateNameConstantPartsList)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using PARR.Core.Repositories.Interfaces.Unit;
|
||||
using PARR.Core.Services.Shortcodes.Enums;
|
||||
using PARR.Core.Services.Shortcodes.Models;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
@@ -10,7 +11,11 @@ internal class FieldShortcodeHandler : IShortcodeHandler
|
||||
private readonly IUnitInValueRepository unitInValueRepository;
|
||||
private readonly ILogger<FieldShortcodeHandler> logger;
|
||||
public int Order => 90; // Всегда последним
|
||||
public Regex Pattern => new(@"%[^%]+%", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
|
||||
private static readonly Regex _pattern = new(@"%[^%]+%", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
public Regex Pattern => _pattern;
|
||||
|
||||
public ShortcodeDataRequirementsEnum Requirements => ShortcodeDataRequirementsEnum.None;
|
||||
|
||||
public FieldShortcodeHandler(IUnitInValueRepository unitInValueRepository, ILogger<FieldShortcodeHandler> logger)
|
||||
{
|
||||
@@ -18,7 +23,7 @@ internal class FieldShortcodeHandler : IShortcodeHandler
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
public async Task<string> ResolveAsync(string input, TemplateForShortcode data, string caller, CancellationToken ct = default)
|
||||
public async Task<string> ResolveAsync(string input, TemplateForShortcode template, string caller, CancellationToken ct = default)
|
||||
{
|
||||
var matches = Pattern.Matches(input);
|
||||
if (matches.Count == 0) return input;
|
||||
@@ -30,7 +35,7 @@ internal class FieldShortcodeHandler : IShortcodeHandler
|
||||
|
||||
if (fieldNames.Count == 0) return input;
|
||||
|
||||
var fieldValues = await unitInValueRepository.GetFieldValuesAsync(data.UnitId, fieldNames, ct).ConfigureAwait(false);
|
||||
var fieldValues = await unitInValueRepository.GetFieldValuesAsync(template.UnitId, fieldNames, ct).ConfigureAwait(false);
|
||||
|
||||
var valuesMap = fieldValues
|
||||
.GroupBy(x => x.FieldName, StringComparer.OrdinalIgnoreCase)
|
||||
@@ -49,7 +54,7 @@ internal class FieldShortcodeHandler : IShortcodeHandler
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.LogDebug("[{Caller}] Поле '{FieldName}' не найдено для UnitId={UnitId}. Шорткод пропущен.", caller, fieldName, data.UnitId);
|
||||
logger.LogDebug("[{Caller}] Поле '{FieldName}' не найдено для UnitId={UnitId}. Шорткод пропущен.", caller, fieldName, template.UnitId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using PARR.Core.Repositories.Interfaces;
|
||||
using PARR.Core.Repositories.Interfaces.Unit;
|
||||
using PARR.Core.Services.Shortcodes.Enums;
|
||||
using PARR.Core.Services.Shortcodes.Models;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
@@ -15,7 +16,14 @@ internal class GroupedFieldShortcodeHandler : IShortcodeHandler
|
||||
private readonly ILogger<GroupedFieldShortcodeHandler> logger;
|
||||
|
||||
public int Order => 30;
|
||||
public Regex Pattern => new(@"%ГР_ПОЛЕ-ПН%", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
|
||||
private static readonly Regex _pattern = new(@"%ГР_ПОЛЕ-ПН%", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
public Regex Pattern => _pattern;
|
||||
|
||||
public ShortcodeDataRequirementsEnum Requirements =>
|
||||
ShortcodeDataRequirementsEnum.Job |
|
||||
ShortcodeDataRequirementsEnum.JobGroup |
|
||||
ShortcodeDataRequirementsEnum.UnitsInTemplate;
|
||||
|
||||
public GroupedFieldShortcodeHandler(
|
||||
IUnitRepository unitRepo,
|
||||
@@ -29,32 +37,22 @@ internal class GroupedFieldShortcodeHandler : IShortcodeHandler
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
public async Task<string> ResolveAsync(string input, TemplateForShortcode data, string caller, CancellationToken ct = default)
|
||||
public async Task<string> ResolveAsync(string input, TemplateForShortcode template, string caller, CancellationToken ct = default)
|
||||
{
|
||||
if (!input.Contains("%ГР_ПОЛЕ-ПН%", StringComparison.OrdinalIgnoreCase)) return input;
|
||||
|
||||
if (data.Job?.Group == null)
|
||||
if (template.Job?.Group == null)
|
||||
{
|
||||
logger.LogWarning("[{Caller}] Job не содержит Group, необходимый для %ГР_ПОЛЕ-ПН%. Шорткод пропущен.", caller);
|
||||
return input.Replace("%ГР_ПОЛЕ-ПН%", string.Empty, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
var unitsList = data.UnitsInTemplate;
|
||||
var unitsList = template.UnitsInTemplate;
|
||||
if (unitsList.Count == 0)
|
||||
{
|
||||
logger.LogWarning("[{Caller}] Template {TemplateId} не содержит UnitsInTemplate. Данные догружаются из БД.", caller, data.Id);
|
||||
var fullTemplate = await templateRepo.Get()
|
||||
.AsNoTracking()
|
||||
.Include(t => t.UnitsInTemplate)
|
||||
.FirstOrDefaultAsync(t => t.Id == data.Id, ct);
|
||||
|
||||
unitsList = fullTemplate?.UnitsInTemplate
|
||||
?.Select(uit => new UnitInTemplateForShortcode(uit.UnitId, uit.UnitFieldValueId))
|
||||
.ToList() ?? new List<UnitInTemplateForShortcode>();
|
||||
}
|
||||
|
||||
if (unitsList.Count == 0)
|
||||
// Данные должны быть загружены оркестратором. Если пусто — значит в БД действительно нет связей.
|
||||
return input.Replace("%ГР_ПОЛЕ-ПН%", string.Empty, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
var unitIds = unitsList.Select(u => u.UnitId).Distinct().ToList();
|
||||
var fieldValueIds = unitsList.Select(u => u.UnitFieldValueId).Distinct().ToList();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using PARR.Core.Services.Shortcodes.Models;
|
||||
using PARR.Core.Services.Shortcodes.Enums;
|
||||
using PARR.Core.Services.Shortcodes.Models;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace PARR.Core.Services.Shortcodes.Handlers
|
||||
@@ -16,6 +17,11 @@ namespace PARR.Core.Services.Shortcodes.Handlers
|
||||
/// </summary>
|
||||
Regex Pattern { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Декларация данных, необходимых хендлеру для работы.
|
||||
/// </summary>
|
||||
ShortcodeDataRequirementsEnum Requirements { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Заменяет все найденные шорткоды в строке на вычисленные значения.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using PARR.Core.Services.Shortcodes.Models;
|
||||
using PARR.Core.Services.Shortcodes.Enums;
|
||||
using PARR.Core.Services.Shortcodes.Models;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace PARR.Core.Services.Shortcodes.Handlers;
|
||||
@@ -6,13 +7,18 @@ namespace PARR.Core.Services.Shortcodes.Handlers;
|
||||
internal class IndexShortcodeHandler : IShortcodeHandler
|
||||
{
|
||||
public int Order => 15;
|
||||
public Regex Pattern => new(@"%ИНДЕКС%", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
|
||||
public Task<string> ResolveAsync(string input, TemplateForShortcode data, string caller, CancellationToken ct = default)
|
||||
private static readonly Regex _pattern = new(@"%ИНДЕКС%", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
|
||||
public Regex Pattern => _pattern;
|
||||
|
||||
public ShortcodeDataRequirementsEnum Requirements => ShortcodeDataRequirementsEnum.None;
|
||||
|
||||
public Task<string> ResolveAsync(string input, TemplateForShortcode template, string caller, CancellationToken ct = default)
|
||||
{
|
||||
if (data.Index.HasValue && input.Contains("%ИНДЕКС%", StringComparison.OrdinalIgnoreCase))
|
||||
if (template.Index.HasValue && input.Contains("%ИНДЕКС%", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return Task.FromResult(input.Replace("%ИНДЕКС%", data.Index.Value.ToString(), StringComparison.OrdinalIgnoreCase));
|
||||
return Task.FromResult(input.Replace("%ИНДЕКС%", template.Index.Value.ToString(), StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
return Task.FromResult(input);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using PARR.Core.Repositories.Interfaces.Unit;
|
||||
using PARR.Core.Services.Shortcodes.Enums;
|
||||
using PARR.Core.Services.Shortcodes.Models;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
@@ -11,7 +12,11 @@ internal class LettersShortcodeHandler : IShortcodeHandler
|
||||
private readonly ILogger<LettersShortcodeHandler> logger;
|
||||
|
||||
public int Order => 60;
|
||||
public Regex Pattern => new(@"%БУКВЫ:([^%]+)%", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
|
||||
private static readonly Regex _pattern = new(@"%БУКВЫ:([^%]+)%", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
public Regex Pattern => _pattern;
|
||||
|
||||
public ShortcodeDataRequirementsEnum Requirements => ShortcodeDataRequirementsEnum.None;
|
||||
|
||||
public LettersShortcodeHandler(IUnitInValueRepository unitInValueRepo, ILogger<LettersShortcodeHandler> logger)
|
||||
{
|
||||
@@ -19,7 +24,7 @@ internal class LettersShortcodeHandler : IShortcodeHandler
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
public async Task<string> ResolveAsync(string input, TemplateForShortcode data, string caller, CancellationToken ct = default)
|
||||
public async Task<string> ResolveAsync(string input, TemplateForShortcode template, string caller, CancellationToken ct = default)
|
||||
{
|
||||
var matches = Pattern.Matches(input);
|
||||
if (matches.Count == 0) return input;
|
||||
@@ -32,7 +37,7 @@ internal class LettersShortcodeHandler : IShortcodeHandler
|
||||
var resolved = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
foreach (var field in uniqueFields)
|
||||
{
|
||||
var values = await unitInValueRepo.GetFieldValuesAsync(data.UnitId, new List<string> { field }, ct);
|
||||
var values = await unitInValueRepo.GetFieldValuesAsync(template.UnitId, new List<string> { field }, ct);
|
||||
var rawValue = values.FirstOrDefault().Value;
|
||||
var letters = string.IsNullOrEmpty(rawValue) ? string.Empty : new string(rawValue.Where(char.IsLetter).ToArray());
|
||||
resolved[$"%БУКВЫ:{field}%"] = letters;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using PARR.Core.Common.Interfaces;
|
||||
using PARR.Core.Repositories.Interfaces.Unit;
|
||||
using PARR.Core.Services.Shortcodes.Enums;
|
||||
using PARR.Core.Services.Shortcodes.Models;
|
||||
using PARR.Domain.Cache.Models;
|
||||
using System.Text.RegularExpressions;
|
||||
@@ -14,7 +15,13 @@ internal class MaxShortcodeHandler : IShortcodeHandler
|
||||
private readonly ILogger<MaxShortcodeHandler> logger;
|
||||
|
||||
public int Order => 40;
|
||||
public Regex Pattern => new(@"%МАКС:([^%]+)%", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
private static readonly Regex _pattern = new(@"%МАКС:([^%]+)%", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
public Regex Pattern => _pattern;
|
||||
|
||||
public ShortcodeDataRequirementsEnum Requirements =>
|
||||
ShortcodeDataRequirementsEnum.Job |
|
||||
ShortcodeDataRequirementsEnum.JobGroup |
|
||||
ShortcodeDataRequirementsEnum.UnitsInTemplate;
|
||||
|
||||
public MaxShortcodeHandler(
|
||||
IUnitInValueRepository unitInValueRepo,
|
||||
@@ -26,11 +33,12 @@ internal class MaxShortcodeHandler : IShortcodeHandler
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
public async Task<string> ResolveAsync(string input, TemplateForShortcode data, string caller, CancellationToken ct = default)
|
||||
public async Task<string> ResolveAsync(string input, TemplateForShortcode template, string caller, CancellationToken ct = default)
|
||||
{
|
||||
var matches = Pattern.Matches(input);
|
||||
if (matches.Count == 0) return input;
|
||||
|
||||
// Извлекаем уникальные имена полей, чтобы не ходить в кэш/БД дважды для одинаковых шорткодов
|
||||
var uniqueFields = matches.Cast<Match>()
|
||||
.Select(m => m.Value.Trim('%').Split(':', 2)[1].Trim())
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
@@ -39,7 +47,7 @@ internal class MaxShortcodeHandler : IShortcodeHandler
|
||||
var resolved = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
foreach (var field in uniqueFields)
|
||||
{
|
||||
resolved[$"%МАКС:{field}%"] = await GetMaxValueAsync(data, field, caller, ct);
|
||||
resolved[$"%МАКС:{field}%"] = await GetMaxValueAsync(template, field, caller, ct);
|
||||
}
|
||||
|
||||
var result = input;
|
||||
@@ -48,21 +56,30 @@ internal class MaxShortcodeHandler : IShortcodeHandler
|
||||
if (resolved.TryGetValue(m.Value, out var val))
|
||||
result = result.Replace(m.Value, val, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private async Task<string> GetMaxValueAsync(TemplateForShortcode data, string fieldName, string caller, CancellationToken ct = default)
|
||||
private async Task<string> GetMaxValueAsync(TemplateForShortcode template, string fieldName, string caller, CancellationToken ct)
|
||||
{
|
||||
if (data.Job?.Group?.Id == Guid.Empty || data.UnitId == Guid.Empty) return "Нет данных";
|
||||
// Guard: данные должны быть подготовлены оркестратором согласно Requirements
|
||||
if (template.Job?.Group == null || template.UnitId == Guid.Empty)
|
||||
return "Нет данных";
|
||||
|
||||
if (template.UnitsInTemplate.Count == 0)
|
||||
{
|
||||
logger.LogDebug("[{Caller}] %МАКС:{Field}% пропущен: UnitsInTemplate пуст для шаблона {TemplateId}.", caller, fieldName, template.Id);
|
||||
return "Нет данных";
|
||||
}
|
||||
|
||||
var cacheKey = cacheService.GetKey(
|
||||
new[] { "grouped", "shortcode", $"{data.Job.Group.Id:N}", $"{data.UnitId:N}" },
|
||||
new[] { "grouped", "shortcode", $"{template.Job.Group.Id:N}", $"{template.UnitId:N}" },
|
||||
new[] { $"%МАКС:{fieldName}%" });
|
||||
|
||||
var cached = await cacheService.GetCachedDataAsync<GroupedShortcode>(cacheKey);
|
||||
if (cached != null) return cached.Data.Value;
|
||||
|
||||
var unitIds = data.UnitsInTemplate.Select(u => u.UnitId).Distinct().ToList();
|
||||
var unitIds = template.UnitsInTemplate.Select(u => u.UnitId).Distinct().ToList();
|
||||
var value = await unitInValueRepo.GetMostFrequentValueForFieldAsync(unitIds, fieldName, ct);
|
||||
|
||||
if (!string.IsNullOrEmpty(value))
|
||||
|
||||
@@ -1,32 +1,33 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using PARR.Core.Repositories.Interfaces;
|
||||
using PARR.Core.Repositories.Interfaces.Unit;
|
||||
using PARR.Core.Services.Shortcodes.Enums;
|
||||
using PARR.Core.Services.Shortcodes.Models;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace PARR.Core.Services.Shortcodes.Handlers;
|
||||
|
||||
internal class RelShortcodeHandler : IShortcodeHandler
|
||||
internal class RelationshipUnitShortcodeHandler : IShortcodeHandler
|
||||
{
|
||||
private readonly IUnitInValueRepository unitInValueRepo;
|
||||
private readonly ITemplateRepository templateRepo;
|
||||
private readonly ILogger<RelShortcodeHandler> logger;
|
||||
private readonly ILogger<RelationshipUnitShortcodeHandler> logger;
|
||||
|
||||
public int Order => 50;
|
||||
public Regex Pattern => new(@"%СВЯЗЬ:([^%]+)%", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
|
||||
public RelShortcodeHandler(
|
||||
private static readonly Regex _pattern = new(@"%СВЯЗЬ:([^%]+)%", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
public Regex Pattern => _pattern;
|
||||
|
||||
public ShortcodeDataRequirementsEnum Requirements => ShortcodeDataRequirementsEnum.UnitsInTemplate;
|
||||
|
||||
public RelationshipUnitShortcodeHandler(
|
||||
IUnitInValueRepository unitInValueRepo,
|
||||
ITemplateRepository templateRepo,
|
||||
ILogger<RelShortcodeHandler> logger)
|
||||
ILogger<RelationshipUnitShortcodeHandler> logger)
|
||||
{
|
||||
this.unitInValueRepo = unitInValueRepo;
|
||||
this.templateRepo = templateRepo;
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
public async Task<string> ResolveAsync(string input, TemplateForShortcode data, string caller, CancellationToken ct = default)
|
||||
public async Task<string> ResolveAsync(string input, TemplateForShortcode template, string caller, CancellationToken ct = default)
|
||||
{
|
||||
var matches = Pattern.Matches(input);
|
||||
if (matches.Count == 0) return input;
|
||||
@@ -39,7 +40,7 @@ internal class RelShortcodeHandler : IShortcodeHandler
|
||||
var resolved = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
foreach (var field in uniqueFields)
|
||||
{
|
||||
resolved[$"%СВЯЗЬ:{field}%"] = await GetRelValueAsync(data, field, caller, ct);
|
||||
resolved[$"%СВЯЗЬ:{field}%"] = await GetRelValueAsync(template, field, caller, ct);
|
||||
}
|
||||
|
||||
var result = input;
|
||||
@@ -51,24 +52,16 @@ internal class RelShortcodeHandler : IShortcodeHandler
|
||||
return result;
|
||||
}
|
||||
|
||||
private async Task<string> GetRelValueAsync(TemplateForShortcode data, string fieldName, string caller, CancellationToken ct)
|
||||
private async Task<string> GetRelValueAsync(TemplateForShortcode template, string fieldName, string caller, CancellationToken ct)
|
||||
{
|
||||
var unitsList = data.UnitsInTemplate;
|
||||
if (unitsList.Count == 0)
|
||||
// Оркестратор гарантирует наличие данных согласно Requirements
|
||||
if (template.UnitsInTemplate.Count == 0)
|
||||
{
|
||||
var fullTemplate = await templateRepo.Get()
|
||||
.AsNoTracking()
|
||||
.Include(t => t.UnitsInTemplate)
|
||||
.FirstOrDefaultAsync(t => t.Id == data.Id, ct);
|
||||
|
||||
unitsList = fullTemplate?.UnitsInTemplate
|
||||
?.Select(uit => new UnitInTemplateForShortcode(uit.UnitId, uit.UnitFieldValueId))
|
||||
.ToList() ?? new List<UnitInTemplateForShortcode>();
|
||||
logger.LogDebug("[{Caller}] %СВЯЗЬ:{Field}% пропущен: UnitsInTemplate пуст.", caller, fieldName);
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
if (unitsList.Count == 0) return string.Empty;
|
||||
|
||||
var unitIds = unitsList.Select(u => u.UnitId).Distinct().ToList();
|
||||
var unitIds = template.UnitsInTemplate.Select(u => u.UnitId).Distinct().ToList();
|
||||
|
||||
// Пакетный запрос вместо N+1
|
||||
var allValues = await unitInValueRepo.Get()
|
||||
@@ -86,7 +79,10 @@ internal class RelShortcodeHandler : IShortcodeHandler
|
||||
if (distinctSorted.Count == 0) return string.Empty;
|
||||
|
||||
if (distinctSorted.Count > 1)
|
||||
logger.LogWarning("[{Caller}] %СВЯЗЬ:{Field}% нашёл {Count} значений. Используется первое: '{First}'", caller, fieldName, distinctSorted.Count, distinctSorted[0]);
|
||||
{
|
||||
logger.LogWarning("[{Caller}] %СВЯЗЬ:{Field}% нашёл {Count} значений. Используется первое: '{First}'",
|
||||
caller, fieldName, distinctSorted.Count, distinctSorted[0]);
|
||||
}
|
||||
|
||||
return distinctSorted[0]!;
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using PARR.Core.Services.Shortcodes.Models;
|
||||
using PARR.Core.Services.Shortcodes.Enums;
|
||||
using PARR.Core.Services.Shortcodes.Models;
|
||||
using PARR.Core.Services.UnitFilterService;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
@@ -9,19 +10,23 @@ internal class RelationshipsShortcodeHandler : IShortcodeHandler
|
||||
private readonly IUnitFilterService unitFilterService;
|
||||
|
||||
public int Order => 70;
|
||||
public Regex Pattern => new(@"%СВЯЗИ(-ПН)?%", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
|
||||
private static readonly Regex _pattern = new(@"%СВЯЗИ(-ПН)?%", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
public Regex Pattern => _pattern;
|
||||
|
||||
public ShortcodeDataRequirementsEnum Requirements => ShortcodeDataRequirementsEnum.Job;
|
||||
|
||||
public RelationshipsShortcodeHandler(IUnitFilterService unitFilterService) => this.unitFilterService = unitFilterService;
|
||||
|
||||
public async Task<string> ResolveAsync(string input, TemplateForShortcode data, string caller, CancellationToken ct = default)
|
||||
public async Task<string> ResolveAsync(string input, TemplateForShortcode template, string caller, CancellationToken ct = default)
|
||||
{
|
||||
if (data.Job == null) return input;
|
||||
if (template.Job == null) return input;
|
||||
|
||||
var hasPlain = input.Contains("%СВЯЗИ%", StringComparison.OrdinalIgnoreCase);
|
||||
var hasNumbered = input.Contains("%СВЯЗИ-ПН%", StringComparison.OrdinalIgnoreCase);
|
||||
if (!hasPlain && !hasNumbered) return input;
|
||||
|
||||
var relatedNames = await unitFilterService.GetRelatedUnitNamesAsync(data.JobId, data.UnitId, ct);
|
||||
var relatedNames = await unitFilterService.GetRelatedUnitNamesAsync(template.JobId, template.UnitId, ct);
|
||||
var result = input;
|
||||
|
||||
if (hasPlain)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using PARR.Core.Services.Shortcodes.Enums;
|
||||
using PARR.Core.Services.Shortcodes.Models;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
@@ -8,23 +9,31 @@ internal class StandardShortcodeHandler : IShortcodeHandler
|
||||
{
|
||||
private readonly ILogger<StandardShortcodeHandler> logger;
|
||||
public int Order => 10;
|
||||
public Regex Pattern => new(@"%(?:ЭК|ТИКТАК|РАБОТА|ГРУППА_РАБОТ|ТНК|ТНК-КРАТКО|ИД)%", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
|
||||
private static readonly Regex _pattern = new(@"%(?:ЭК|ТИКТАК|РАБОТА|ГРУППА_РАБОТ|ТНК|ТНК-КРАТКО|ИД)%", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
public Regex Pattern => _pattern;
|
||||
|
||||
public ShortcodeDataRequirementsEnum Requirements =>
|
||||
ShortcodeDataRequirementsEnum.Job |
|
||||
ShortcodeDataRequirementsEnum.JobGroup |
|
||||
ShortcodeDataRequirementsEnum.JobTnk |
|
||||
ShortcodeDataRequirementsEnum.UnitName;
|
||||
|
||||
public StandardShortcodeHandler(ILogger<StandardShortcodeHandler> logger) => this.logger = logger;
|
||||
|
||||
public Task<string> ResolveAsync(string input, TemplateForShortcode data, string caller, CancellationToken ct = default)
|
||||
public Task<string> ResolveAsync(string input, TemplateForShortcode template, string caller, CancellationToken ct = default)
|
||||
{
|
||||
var result = input;
|
||||
result = Replace(result, "%ЭК%", data.UnitName);
|
||||
result = Replace(result, "%ЭК%", template.UnitName);
|
||||
result = Replace(result, "%ТИКТАК%", DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString());
|
||||
result = Replace(result, "%ИД%", data.Id.ToString("N"));
|
||||
result = Replace(result, "%ИД%", template.Id.ToString("N"));
|
||||
|
||||
if (data.Job != null)
|
||||
if (template.Job != null)
|
||||
{
|
||||
result = Replace(result, "%РАБОТА%", data.Job.WorkName);
|
||||
result = Replace(result, "%ГРУППА_РАБОТ%", data.Job.Group?.GroupName);
|
||||
result = Replace(result, "%ТНК%", data.Job.Tnk?.Name);
|
||||
result = Replace(result, "%ТНК-КРАТКО%", data.Job.Tnk?.ShortName);
|
||||
result = Replace(result, "%РАБОТА%", template.Job.WorkName);
|
||||
result = Replace(result, "%ГРУППА_РАБОТ%", template.Job.Group?.GroupName);
|
||||
result = Replace(result, "%ТНК%", template.Job.Tnk?.Name);
|
||||
result = Replace(result, "%ТНК-КРАТКО%", template.Job.Tnk?.ShortName);
|
||||
}
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user