feat(dal): Добавлен TemplateNameGeneratorService для генерации имени шаблонов по маске в Job

This commit is contained in:
Mikhail Kuznetsov
2025-06-18 09:58:23 +10:00
parent 38c9bb402e
commit 4b0ece1a2e
14 changed files with 4068 additions and 5 deletions

View File

@@ -0,0 +1,8 @@
namespace PARR.BLL.Domain
{
public class TemplateNameConstantPart
{
public required string Name { get; set; }
public required string Value { get; set; }
}
}

View File

@@ -7,14 +7,15 @@
new ShortcodeItem { ShortcodeEnum = ShortcodeEnum.EK, Name = "%ЭК%", Description = "Элемент конфигурации"}, new ShortcodeItem { ShortcodeEnum = ShortcodeEnum.EK, Name = "%ЭК%", Description = "Элемент конфигурации"},
new ShortcodeItem { ShortcodeEnum = ShortcodeEnum.ZO, Name = "%ЗО%", Description = "Зона ответственности"}, new ShortcodeItem { ShortcodeEnum = ShortcodeEnum.ZO, Name = "%ЗО%", Description = "Зона ответственности"},
new ShortcodeItem { ShortcodeEnum = ShortcodeEnum.Work, Name = "%РАБОТА%", Description = "Наименование работ"} new ShortcodeItem { ShortcodeEnum = ShortcodeEnum.Work, Name = "%РАБОТА%", Description = "Наименование работ"}
}; };
public static string GetShortcodeName(ShortcodeEnum shortcode) public static string GetShortcodeName(ShortcodeEnum shortcode)
{ {
return ShortcodesList.First(s => s.ShortcodeEnum == shortcode).Name; return ShortcodesList.First(s => s.ShortcodeEnum == shortcode).Name;
} }
public static List<ShortcodeItem> GetAll() public static List<ShortcodeItem> GetAll()
{ {
return ShortcodesList; return ShortcodesList;

View File

@@ -1,6 +1,8 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using PARR.BLL.Domain;
using PARR.Constants; using PARR.Constants;
using PARR.DAL.Contracts; using PARR.DAL.Contracts;
using PARR.DAL.Extensions;
using PARR.DAL.Models; using PARR.DAL.Models;
using PARR.DAL.Models.Job; using PARR.DAL.Models.Job;
using PARR.DAL.Models.Unit; using PARR.DAL.Models.Unit;
@@ -143,7 +145,17 @@ namespace PARR.DAL.Context
new { Name = nameof(SettingsFromDb.ScheduleRepeatRange), Description = "Расписание регламентной работы - Диапазн повторов", Value = "Отсутствует дата завершения" }, new { Name = nameof(SettingsFromDb.ScheduleRepeatRange), Description = "Расписание регламентной работы - Диапазн повторов", Value = "Отсутствует дата завершения" },
new { Name = nameof(SettingsFromDb.OrderSearchDeltaDate), Description = "Промежуток времени для поиска нарядов в ЕСПП", Value = new TimeSpan(1, 30, 0).ToString() }, new { Name = nameof(SettingsFromDb.OrderSearchDeltaDate), Description = "Промежуток времени для поиска нарядов в ЕСПП", Value = new TimeSpan(1, 30, 0).ToString() },
new { Name = nameof(SettingsFromDb.EsppRobotAccountTimeZoneHour), Description = "Таймзона УЗ роботов в ЕСПП, в часах (может быть положительная и отрицательная)", Value = "3" }, new { Name = nameof(SettingsFromDb.EsppRobotAccountTimeZoneHour), Description = "Таймзона УЗ роботов в ЕСПП, в часах (может быть положительная и отрицательная)", Value = "3" },
new { Name = nameof(SettingsFromDb.WeekendCacheTtl), Description = "Время хранения в кэше данных о выходных и рабочих днях", Value = new TimeSpan(1, 0, 0).ToString() } new { Name = nameof(SettingsFromDb.WeekendCacheTtl), Description = "Время хранения в кэше данных о выходных и рабочих днях", Value = new TimeSpan(1, 0, 0).ToString() },
new
{
Name = nameof(SettingsFromDb.TemplateNameConstantParts),
Description = "Список неизменных частей имени шаблона",
Value =
new List<TemplateNameConstantPart> {
new TemplateNameConstantPart { Name = "П-1", Value = "ЭИТИ" },
new TemplateNameConstantPart { Name = "П-2", Value = "ПАРР" }
}.ToJson()
}
); );
}); });
#endregion #endregion

View File

@@ -1,4 +1,9 @@
namespace PARR.DAL.Contracts using PARR.BLL.Domain;
using PARR.DAL.Extensions;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json;
namespace PARR.DAL.Contracts
{ {
/// <summary> /// <summary>
/// Настройки из БД /// Настройки из БД
@@ -33,6 +38,35 @@
/// </summary> /// </summary>
public string TemplatePrefixWithoutVariable => TemplatePrefixName.Replace("%PREFIX%-", ""); public string TemplatePrefixWithoutVariable => TemplatePrefixName.Replace("%PREFIX%-", "");
public string TemplateNameConstantParts { get; set; } = string.Empty;
[NotMapped]
public List<TemplateNameConstantPart> TemplateNameConstantPartsList
{
get
{
if (!string.IsNullOrEmpty(TemplateNameConstantParts))
{
try
{
return JsonSerializer.Deserialize<List<TemplateNameConstantPart>>(TemplateNameConstantParts) ?? new List<TemplateNameConstantPart>();
}
catch
{
return new List<TemplateNameConstantPart>();
}
}
return new List<TemplateNameConstantPart>();
}
set
{
if (value != null)
TemplateNameConstantParts = value.ToJson() ?? string.Empty;
}
}
/// <summary> /// <summary>
/// Количество попыток выполнения задания роботом /// Количество попыток выполнения задания роботом
/// </summary> /// </summary>

View File

@@ -0,0 +1,15 @@
using PARR.DAL.Models.Job;
using PARR.DAL.Models.Unit;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PARR.DAL.DomainServices
{
public interface ITemplateNameGeneratorService
{
Task<string> GetTemplateNameAsync(Guid jobId, Guid unitId);
}
}

View File

@@ -0,0 +1,128 @@
using Microsoft.EntityFrameworkCore;
using PARR.Constants.Shortcodes;
using PARR.DAL.Contracts;
using PARR.DAL.Services.Interfaces.Job;
using PARR.DAL.Services.Interfaces.Unit;
using System.Text.RegularExpressions;
namespace PARR.DAL.DomainServices
{
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().FirstOrDefaultAsync(t => t.Id == jobId);
var unit = await unitService.Get().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()
.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 == Shortcodes.GetShortcodeName(ShortcodeEnum.Work)))
resultName = resultName.Replace(Shortcodes.GetShortcodeName(ShortcodeEnum.Work), job.WorkName);
if (shortcodesInMask.Any(x => x.Value == Shortcodes.GetShortcodeName(ShortcodeEnum.EK)))
resultName = resultName.Replace(Shortcodes.GetShortcodeName(ShortcodeEnum.EK), 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>();
var shortcodes = Enum.GetValues(typeof(ShortcodeEnum)).Cast<ShortcodeEnum>();
foreach (var item in shortcodes)
{
result.Add(Shortcodes.GetShortcodeName(item).ToUpper());
}
return result;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,28 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace PARR.DAL.Migrations
{
/// <inheritdoc />
public partial class tblSettingsAddParamTemplateNameConstantParts : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.InsertData(
table: "Settings",
columns: new[] { "Name", "Description", "Value" },
values: new object[] { "TemplateNameConstantParts", "Список неизменных частей имени шаблона", "[{\"Name\":\"П-1\",\"Value\":\"ЭИТИ\"},{\"Name\":\"П-2\",\"Value\":\"ПАРР\"}]" });
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "Settings",
keyColumn: "Name",
keyValue: "TemplateNameConstantParts");
}
}
}

View File

@@ -2471,6 +2471,12 @@ namespace PARR.DAL.Migrations
Name = "WeekendCacheTtl", Name = "WeekendCacheTtl",
Description = "Время хранения в кэше данных о выходных и рабочих днях", Description = "Время хранения в кэше данных о выходных и рабочих днях",
Value = "01:00:00" Value = "01:00:00"
},
new
{
Name = "TemplateNameConstantParts",
Description = "Список неизменных частей имени шаблона",
Value = "[{\"Name\":\"П-1\",\"Value\":\"ЭИТИ\"},{\"Name\":\"П-2\",\"Value\":\"ПАРР\"}]"
}); });
}); });

View File

@@ -20,6 +20,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\PARR.BLL\PARR.BLL.csproj" />
<ProjectReference Include="..\PARR.Common\PARR.Common.csproj" /> <ProjectReference Include="..\PARR.Common\PARR.Common.csproj" />
<ProjectReference Include="..\PARR.Constants\PARR.Constants.csproj" /> <ProjectReference Include="..\PARR.Constants\PARR.Constants.csproj" />
</ItemGroup> </ItemGroup>

View File

@@ -5,6 +5,7 @@ using PARR.DAL.CacheServices;
using PARR.DAL.Configurations.DbSettings; using PARR.DAL.Configurations.DbSettings;
using PARR.DAL.Context; using PARR.DAL.Context;
using PARR.DAL.Contracts; using PARR.DAL.Contracts;
using PARR.DAL.DomainServices;
using PARR.DAL.InfluxDbServices; using PARR.DAL.InfluxDbServices;
using PARR.DAL.Services.Implementation; using PARR.DAL.Services.Implementation;
using PARR.DAL.Services.Implementations; using PARR.DAL.Services.Implementations;
@@ -112,6 +113,10 @@ namespace PARR.DAL
// TransformServices // TransformServices
services.AddTransient<IEsppScheduleTransformService, EsppScheduleTransformService>(); services.AddTransient<IEsppScheduleTransformService, EsppScheduleTransformService>();
services.AddTransient<INextRunModifierService, NextRunModifierService>(); services.AddTransient<INextRunModifierService, NextRunModifierService>();
#region DomainServces
services.AddTransient<ITemplateNameGeneratorService, TemplateNameGeneratorService>();
#endregion
} }
/// <summary> /// <summary>

View File

@@ -8,6 +8,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Elastic.CommonSchema.Serilog" Version="8.6.1" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
<PackageReference Include="Serilog.Extensions.Hosting" Version="7.0.0" /> <PackageReference Include="Serilog.Extensions.Hosting" Version="7.0.0" />
<PackageReference Include="Serilog.Settings.Configuration" Version="7.0.1" /> <PackageReference Include="Serilog.Settings.Configuration" Version="7.0.1" />

View File

@@ -4,8 +4,9 @@ using PARR.DAL;
using PARR.Test; using PARR.Test;
using Serilog; using Serilog;
using PARR.TemplateDistributor; using PARR.TemplateDistributor;
using Elastic.CommonSchema.Serilog;
IHost host = Host.CreateDefaultBuilder(args) /*IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) => .ConfigureServices((hostContext, services) =>
{ {
//services.InstallEsppApiServices(hostContext.Configuration); //services.InstallEsppApiServices(hostContext.Configuration);
@@ -21,6 +22,34 @@ IHost host = Host.CreateDefaultBuilder(args)
.WriteTo.Console() .WriteTo.Console()
.ReadFrom.Configuration(hostContext.Configuration); .ReadFrom.Configuration(hostContext.Configuration);
}) })
.Build(); .Build();*/
var builder = Host.CreateApplicationBuilder();
builder.Services.AddLogging(config =>
{
config.ClearProviders();
var logger = new LoggerConfiguration();
if (builder.Environment.IsProduction())
logger.WriteTo.Console(new EcsTextFormatter());
else
logger.WriteTo.Console();
logger.ReadFrom.Configuration(builder.Configuration);
config.AddSerilog(logger.CreateLogger());
});
builder.Services.InstallDalServices(builder.Configuration);
builder.Services.InstallEsppApiServices(builder.Configuration);
builder.Services.InstallBllServices(builder.Configuration);
builder.Configuration.AddDalConfigurations(builder.Services);
builder.Services.AddDallSettings(builder.Configuration);
builder.Services.AddHostedService<Worker>();
var host = builder.Build();
host.Run(); host.Run();

View File

@@ -1,6 +1,8 @@
using Elastic.CommonSchema;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using PARR.BLL.Services.Interfaces; using PARR.BLL.Services.Interfaces;
using PARR.Constants; using PARR.Constants;
using PARR.DAL.DomainServices;
using PARR.DAL.Services.Interfaces; using PARR.DAL.Services.Interfaces;
using PARR.DAL.Services.Interfaces.Unit; using PARR.DAL.Services.Interfaces.Unit;
using PARR.EsppApi; using PARR.EsppApi;
@@ -36,6 +38,13 @@ namespace PARR.Test
protected override async Task ExecuteAsync(CancellationToken stoppingToken) protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{ {
#region test #region test
using (var scope = serviceProvider.CreateScope())
{
var service = scope.ServiceProvider.GetService<ITemplateNameGeneratorService>();
var ttt = await service.GetTemplateNameAsync(Guid.Parse("ba05948b-b040-48cc-ab77-0accc9c223a0"), Guid.Parse("d4a86f24-6975-4614-98ab-431f26e3eb69"));
}
//var tName = "ДВС-ЭИТИ-ПТК-ПАРР__ВРТ-VCD-02-ДВС__ПРОЧЕЕ(РАБОТЫ)"; //var tName = "ДВС-ЭИТИ-ПТК-ПАРР__ВРТ-VCD-02-ДВС__ПРОЧЕЕ(РАБОТЫ)";
//var prefix = "ЭИТИ-ПТК-ПАРР"; //var prefix = "ЭИТИ-ПТК-ПАРР";
////templateName.Contains(settingsFromDb.TemplatePrefixWithoutVariable, StringComparison.CurrentCultureIgnoreCase) ////templateName.Contains(settingsFromDb.TemplatePrefixWithoutVariable, StringComparison.CurrentCultureIgnoreCase)