fix(esppSync, dal, api): Исправление после удаления старых ShortCodes

This commit is contained in:
Mikhail Kuznetsov
2025-08-01 14:45:36 +10:00
parent 5e2df418e7
commit e3b9392d84
14 changed files with 216 additions and 118 deletions

View File

@@ -3,9 +3,7 @@ using PARR.API.Authentication.Models;
using PARR.API.Contracts.V1.Responses;
using PARR.API.MappingProfiles.Resolvers;
using PARR.Common.Domain;
using PARR.Constants.Shortcodes;
using PARR.DAL.DomainModels;
using PARR.DAL.Extensions;
using PARR.DAL.Models;
using PARR.DAL.Models.Job;
using PARR.DAL.Models.Unit;
@@ -158,11 +156,11 @@ namespace PARR.API.MappingProfiles
.ForMember(d => d.IsActive, o => o.MapFrom(s => s.Template!.IsActiveTemplate))
.ForMember(d => d.ClosingCode, o => o.MapFrom<RobotTaskTemplateClosingCodeResolver>())
.ForMember(d => d.FullDescription, o => o.MapFrom(s => s.Template!.Job!.Group!.FullDescription))
.ForMember(d => d.ShortDescription, o => o.MapFrom(s => s.Template!.Job!.Group!.ShortDescription.ApplyShortcode(ShortcodeEnum.EK, s.Template!.Unit!.Name)))
.ForMember(d => d.ShortDescription, o => o.MapFrom(s => s.Template!.Job!.Group!.ShortDescription))
.ForMember(d => d.Solution, o => o.MapFrom(s => s.Template!.Job!.Group!.Solution))
//.ForMember(d => d.ResponseArea, o => o.MapFrom(s => s.Template!.Host!.ResponseArea!.Name))
//ЗО берем у группы а не у хоста
.ForMember(d => d.ResponseArea, o => o.MapFrom(s => s.Template!.Unit.BaseFields.ResponseArea))
.ForMember(d => d.ResponseArea, o => o.MapFrom(s => s.Template!.Unit.BaseFields!.ResponseArea))
.ForMember(d => d.TemplateDuration, o => o.MapFrom(s => s.Template!.Job!.Group!.TemplateDuration))
.ForMember(d => d.Initiator, o => o.MapFrom<RobotTaskTemplateInitiatorResolver>())
.ForMember(d => d.Category, o => o.MapFrom<RobotTaskTemplateCategoryResolver>())
@@ -173,9 +171,9 @@ namespace PARR.API.MappingProfiles
.ForMember(d => d.ProcessEsppId, o => o.MapFrom(s => s.Template!.Job!.Tnk!.Subprocess!.Process!.EsppId))
.ForMember(d => d.SubprocessName, o => o.MapFrom(s => s.Template!.Job!.Tnk!.Subprocess!.Name))
.ForMember(d => d.SubprocessEsppId, o => o.MapFrom(s => s.Template!.Job!.Tnk!.Subprocess!.EsppId))
.ForMember(d => d.TnkName, o => o.MapFrom(s => s.Template!.Job!.Tnk!.Name.ApplyShortcode(ShortcodeEnum.EK, s.Template!.Unit!.Name)))
.ForMember(d => d.TnkName, o => o.MapFrom(s => s.Template!.Job!.Tnk!.Name))
.ForMember(d => d.TnkEsppId, o => o.MapFrom(s => s.Template!.Job!.Tnk!.EsppId))
.ForMember(d => d.WorkName, o => o.MapFrom(s => s.Template!.Job!.WorkName.ApplyShortcode(ShortcodeEnum.EK, s.Template!.Unit!.Name)))
.ForMember(d => d.WorkName, o => o.MapFrom(s => s.Template!.Job!.WorkName))
//.ForMember(d => d.WorkEsppId, o => o.MapFrom(s => s.Template!.Job!.EsppId))
.ForMember(d => d.ScheduleEsppId, o => o.MapFrom(s => s.Template!.ScheduleEsppId));

View File

@@ -0,0 +1,23 @@
using AutoMapper;
using PARR.API.Contracts.V1.Responses;
using PARR.DAL.DomainServices;
using PARR.DAL.Models;
namespace PARR.API.MappingProfiles.Resolvers
{
public class RobotTaskTemplateShortCodeResolver : IValueResolver<RobotConfiguration, RobotTaskTemplateResponse, string>
{
private readonly IShortcodesService shortcodesService;
public RobotTaskTemplateShortCodeResolver(
IShortcodesService shortcodesService
)
{
this.shortcodesService = shortcodesService;
}
public string Resolve(RobotConfiguration source, RobotTaskTemplateResponse destination, string destMember, ResolutionContext context)
{
throw new NotImplementedException();
}
}
}

View File

@@ -1,7 +1,6 @@
using FluentValidation;
using PARR.API.Contracts.V1.Requests;
using PARR.BLL.Services.Interfaces;
using PARR.Constants.Shortcodes;
using PARR.DAL.Services.Interfaces;
namespace PARR.API.Validators
@@ -24,15 +23,16 @@ namespace PARR.API.Validators
RuleFor(t => t.TemplateNameMask)
.NotEmpty()
.NotNull();
RuleFor(t => t.TemplateNameMask)
.Must((entity, value, c) => templateMaskValidator
.IsValid(entity.TemplateNameMask))
.WithMessage($"Неверно указана маска имени шаблонов. Обязательными условиями являются" +
$" наличие кодового слова \"ПАРР\" и обязательное использование динамической составляющей" +
$" %ЭК%. Доступные значения динамических составляющих:" +
$" {string.Join(", ", Shortcodes.GetAll().Select(sc => sc.Name + " - " + sc.Description))}"
);
//TODO Сделать проверку по шорткодам и возможным полям
//RuleFor(t => t.TemplateNameMask)
// .Must((entity, value, c) => templateMaskValidator
// .IsValid(entity.TemplateNameMask))
// .WithMessage($"Неверно указана маска имени шаблонов. Обязательными условиями являются" +
// $" наличие кодового слова \"ПАРР\" и обязательное использование динамической составляющей" +
// $" %ЭК%. Доступные значения динамических составляющих:" +
// $" {string.Join(", ", Shortcodes.GetAll().Select(sc => sc.Name + " - " + sc.Description))}"
// );
RuleFor(t => t.EsppId).NotEmpty().NotNull().WithMessage("EsppId не может быть пустым");

View File

@@ -1,5 +1,4 @@
using PARR.BLL.Services.Interfaces;
using PARR.Constants.Shortcodes;
using System.Text.RegularExpressions;
namespace PARR.BLL.Services.Implementations
@@ -28,14 +27,13 @@ namespace PARR.BLL.Services.Implementations
return true;
}
private List<string> GetShortcodesNames()
private List<string> GetShortcodesNames()//TODO Ну ты опять этот метод дублируешь?!
{
var result = new List<string>();
var shortcodes = Enum.GetValues(typeof(ShortcodeEnum)).Cast<ShortcodeEnum>();
foreach (var item in shortcodes)
{
result.Add(Shortcodes.GetShortcodeName(item).ToUpper());
}
var result = new List<string> {
"%ЭК%",
"%ЗО%",
"%РАБОТА%"
};
return result;
}

View File

@@ -1,10 +0,0 @@
namespace PARR.Constants.Shortcodes
{
public enum ShortcodeEnum
{
EK,
ZO,
Work
//!!!Не забыть добавить в справочник имен (ShortcodeName) строковое значение
}
}

View File

@@ -1,15 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PARR.Constants.Shortcodes
{
public class ShortcodeItem
{
public ShortcodeEnum ShortcodeEnum { get; set; }
public required string Name { get; set; }
public required string Description { get; set; }
}
}

View File

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

View File

@@ -1,17 +1,139 @@
using System;
using Microsoft.EntityFrameworkCore;
using PARR.DAL.Contracts;
using PARR.DAL.Services.Implementations.Job;
using PARR.DAL.Services.Implementations.Unit;
using PARR.DAL.Services.Interfaces.Job;
using PARR.DAL.Services.Interfaces.Unit;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace PARR.DAL.DomainServices
{
internal class ShortcodesService : IShortcodesService
{
public Task<string> ApplyShortcodesAsync(string str, Guid unitId, Guid jobId)
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 и написать метод. делов...
throw new NotImplementedException();
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

@@ -1,5 +1,4 @@
using Microsoft.EntityFrameworkCore;
using PARR.Constants.Shortcodes;
using PARR.DAL.Contracts;
using PARR.DAL.Services.Interfaces.Job;
using PARR.DAL.Services.Interfaces.Unit;
@@ -89,11 +88,11 @@ namespace PARR.DAL.DomainServices
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 == "%РАБОТА%"))
resultName = resultName.Replace("%РАБОТА%", job.WorkName);
if (shortcodesInMask.Any(x => x.Value == Shortcodes.GetShortcodeName(ShortcodeEnum.EK)))
resultName = resultName.Replace(Shortcodes.GetShortcodeName(ShortcodeEnum.EK), unit.Name);
if (shortcodesInMask.Any(x => x.Value == "%ЭК%"))
resultName = resultName.Replace("%ЭК%", unit.Name);
return resultName;
}
@@ -116,12 +115,11 @@ namespace PARR.DAL.DomainServices
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());
}
var result = new List<string> {
"%ЭК%",
"%ЗО%",
"%РАБОТА%"
};
return result;
}

View File

@@ -1,5 +1,4 @@
using PARR.Constants.Shortcodes;
using System.Text.Encodings.Web;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Unicode;
@@ -46,11 +45,11 @@ namespace PARR.DAL.Extensions
/// <param name="shortcode">Код шаблона из PARR.Constants.ShortcodeEnum.ShortcodeEnum</param>
/// <param name="shortcodeValue">Итоговое строковое значение</param>
/// <returns></returns>
public static string ApplyShortcode(this string sourceString, ShortcodeEnum shortcode, string shortcodeValue)
{
var shortcodeName = Shortcodes.GetShortcodeName(shortcode);
//public static string ApplyShortcode(this string sourceString, ShortcodeEnum shortcode, string shortcodeValue)
//{
// var shortcodeName = Shortcodes.GetShortcodeName(shortcode);
return sourceString.Replace(shortcodeName, shortcodeValue);
}
// return sourceString.Replace(shortcodeName, shortcodeValue);
//}
}
}

View File

@@ -16,7 +16,7 @@ namespace PARR.EsppSync
/// <typeparam name="EsppObject"></typeparam>
/// <param name="templateName"></param>
/// <returns></returns>
public delegate EsppObject ConvertDbObjToComparisonObjHandlerDelegate<EsppObject>(Template template) where EsppObject : class, IEsppObject;
public delegate Task<EsppObject> ConvertDbObjToComparisonObjHandlerDelegate<EsppObject>(Template template) where EsppObject : class, IEsppObject;
public interface ISyncService<EsppObject> where EsppObject : class, IEsppObject
{

View File

@@ -62,22 +62,25 @@ namespace PARR.EsppSync
{
var dbObjectInEsppObject = converterToEsppObject.Invoke(template);
bool isChanged;
bool isChanged = false;
//TODO: FIX ME Please, BRO
//bool isChanged;
// если в БД isActive == false, то синхронизировать только по полям из IEsppObject
if (dbObjectInEsppObject.IsActive == false)
{
logger.LogDebug($"Объект деактивирован в ПАРР. Сравниваем только обязательные поля. {esppObject.TemplateName}");
var lightDbObj = new EsppLightObject(dbObjectInEsppObject);
var lightEsppObject = new EsppLightObject(esppObject);
isChanged = IsChanged(lightEsppObject, lightDbObj);
}
else
{
logger.LogDebug($"Объект активирован в ПАРР. Сравниваем все поля. {esppObject.TemplateName}");
isChanged = IsChanged(esppObject, dbObjectInEsppObject);
}
//if (dbObjectInEsppObject.IsActive == false)
//{
// logger.LogDebug($"Объект деактивирован в ПАРР. Сравниваем только обязательные поля. {esppObject.TemplateName}");
// var lightDbObj = new EsppLightObject(dbObjectInEsppObject);
// var lightEsppObject = new EsppLightObject(esppObject);
// isChanged = IsChanged(lightEsppObject, lightDbObj);
//}
//else
//{
// logger.LogDebug($"Объект активирован в ПАРР. Сравниваем все поля. {esppObject.TemplateName}");
// isChanged = IsChanged(esppObject, dbObjectInEsppObject);
//}
if (isChanged)

View File

@@ -1,11 +1,13 @@
using Microsoft.Extensions.Logging;
using PARR.BLL.Services.Interfaces;
using PARR.DAL.Contracts;
using PARR.DAL.DomainServices;
using PARR.DAL.Extensions;
using PARR.DAL.Models;
using PARR.EsppSync;
using PARR.EsppTemplateSync.Domain;
using PARR.EsppTemplateSync.Settings;
using System.Threading.Tasks;
namespace PARR.EsppTemplateSync
{
@@ -16,13 +18,15 @@ namespace PARR.EsppTemplateSync
private readonly IMqService mqService;
private readonly ISyncService<EsppObjectTemplate> syncService;
private readonly SettingsFromDb settingsFromDb;
private readonly IShortcodesService shortcodesService;
public TemplateMQSyncer(
ILogger<TemplateMQSyncer> logger,
GlobalSettings globalSettings,
IMqService mqService,
ISyncService<EsppObjectTemplate> syncService,
SettingsFromDb settingsFromDb
SettingsFromDb settingsFromDb,
IShortcodesService shortcodesService
)
{
this.logger = logger;
@@ -30,7 +34,7 @@ namespace PARR.EsppTemplateSync
this.mqService = mqService;
this.syncService = syncService;
this.settingsFromDb = settingsFromDb;
this.shortcodesService = shortcodesService;
if (globalSettings.MqSettings == null)
{
logger.LogError("Нет секции настроек хранилища. MqSettings, EsppTemplates");
@@ -58,16 +62,16 @@ namespace PARR.EsppTemplateSync
private async Task SyncTemplateAsync(string str)
{
await syncService.SyncEsppObjectAsync(str, ParseStrToEsppObject, ConvertDbObjToEsppObj);
await syncService.SyncEsppObjectAsync(str, ParseStrToEsppObject, ConvertDbObjToEsppObjAsync);
}
/// <summary>
/// Преобразование модели БД в модель для сравнения
/// </summary>
/// <param name="template"></param>
/// <param name="template">template должен обязательно содержать в себе информацию о Job+Group и Unit+BaseFields</param>
/// <returns></returns>
private EsppObjectTemplate ConvertDbObjToEsppObj(Template template)
private async Task<EsppObjectTemplate> ConvertDbObjToEsppObjAsync(Template template)
{
var templateFromDb = new EsppObjectTemplate
{
@@ -75,18 +79,20 @@ namespace PARR.EsppTemplateSync
IsActive = template.IsActiveTemplate,
//WorkGroup = template.Host!.WorkGroup!,
WorkGroup = template.Unit!.BaseFields!.WorkGroup!,
ShortDescription = Normalize(template.Job.Group.ShortDescription.ApplyShortcode(Constants.Shortcodes.ShortcodeEnum.EK,template.Unit.Name)),
//ShortDescription = Normalize(template.Job.Group.ShortDescription.ApplyShortcode(Constants.Shortcodes.ShortcodeEnum.EK,template.Unit.Name)),
ShortDescription = Normalize(await shortcodesService.ApplyShortcodesAsync(template.Job!.Group!.ShortDescription,template.UnitId,template.JobId)),//TODO Вынести в переменную
//ResponseArea = template.Host!.ResponseArea!.Name,
//ЗО берем РГ а не хоста
ResponseArea = template.Unit.BaseFields.ResponseArea,
ResponseArea = template.Unit.BaseFields.ResponseArea!,
Duration = template.Job.Group.TemplateDuration,
EK = template.Unit.Name,
FullDescription = Normalize(template.Job.Group.FullDescription),
Solution = Normalize(template.Job.Group.Solution),
Process = template.Job.Tnk!.Subprocess!.Process!.Name,
SubProcess = template.Job.Tnk.Subprocess.Name,
TNK = template.Job.Tnk.Name.ApplyShortcode(Constants.Shortcodes.ShortcodeEnum.EK, template.Unit.Name),
Work = template.Job.WorkName.ApplyShortcode(Constants.Shortcodes.ShortcodeEnum.EK, template.Unit.Name),
//TNK = template.Job.Tnk.Name.ApplyShortcode(Constants.Shortcodes.ShortcodeEnum.EK, template.Unit.Name),
TNK = Normalize(await shortcodesService.ApplyShortcodesAsync(template.Job.Tnk.Name, template.UnitId, template.JobId)),
Work = Normalize(await shortcodesService.ApplyShortcodesAsync(template.Job.WorkName, template.UnitId, template.JobId)),
Initiator = settingsFromDb.Initiator
};

View File

@@ -228,7 +228,7 @@ namespace PARR.GeneratorTemplates.Services
host.ResponseArea!.Name,
settingsFromDb.TemplatePrefixName,
host.Ek,
appInWork.Work!.TemplateSuffix ?? appInWork.Work!.Name.ApplyShortcode(Constants.Shortcodes.ShortcodeEnum.EK, host.Ek)
appInWork.Work!.TemplateSuffix ?? appInWork.Work!.Name
),
IsActiveTemplate = query.IsActiveTemplate ?? false,
IsActiveSchedule = query.IsActiveSchedule ?? false,