diff --git a/PARR.API.sln b/PARR.API.sln
index 547d9e78..2abc5c3e 100644
--- a/PARR.API.sln
+++ b/PARR.API.sln
@@ -51,7 +51,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PARR.EsppApi", "PARR.EsppAp
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PARR.Test", "PARR.Test\PARR.Test.csproj", "{CFE2A198-67BF-4828-8E8D-31A01858FDA7}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PARR.Constants", "PARR.Constants\PARR.Constants.csproj", "{46B09885-C9FB-449C-ACAA-24C671194C4D}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PARR.Constants", "PARR.Constants\PARR.Constants.csproj", "{46B09885-C9FB-449C-ACAA-24C671194C4D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PARR.EsppSync", "PARR.EsppSync\PARR.EsppSync.csproj", "{71121EF7-D4C1-43A4-9243-EF5C4C82030F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -141,6 +143,10 @@ Global
{46B09885-C9FB-449C-ACAA-24C671194C4D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{46B09885-C9FB-449C-ACAA-24C671194C4D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{46B09885-C9FB-449C-ACAA-24C671194C4D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {71121EF7-D4C1-43A4-9243-EF5C4C82030F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {71121EF7-D4C1-43A4-9243-EF5C4C82030F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {71121EF7-D4C1-43A4-9243-EF5C4C82030F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {71121EF7-D4C1-43A4-9243-EF5C4C82030F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/PARR.EsppSync/IEsppObject.cs b/PARR.EsppSync/IEsppObject.cs
new file mode 100644
index 00000000..c1f410fc
--- /dev/null
+++ b/PARR.EsppSync/IEsppObject.cs
@@ -0,0 +1,7 @@
+namespace PARR.EsppSync
+{
+ public interface IEsppObject
+ {
+ public string TemplateName { get; set; }
+ }
+}
diff --git a/PARR.EsppSync/ISyncService.cs b/PARR.EsppSync/ISyncService.cs
new file mode 100644
index 00000000..f8a092a7
--- /dev/null
+++ b/PARR.EsppSync/ISyncService.cs
@@ -0,0 +1,26 @@
+using PARR.DAL.Contracts;
+using PARR.DAL.Models;
+
+namespace PARR.EsppSync
+{
+ ///
+ /// Делегат парсинга из строки в модель EsppObject
+ ///
+ ///
+ ///
+ ///
+ public delegate EsppObject ParserHandlerDelegate(string str) where EsppObject : class, IEsppObject;
+
+ ///
+ /// Конвертирует Template в модель для сравнения
+ ///
+ ///
+ ///
+ ///
+ public delegate EsppObject ConvertDbObjToComparisonObjHandlerDelegate(Template template) where EsppObject : class, IEsppObject;
+
+ public interface ISyncService where EsppObject : class, IEsppObject
+ {
+ Task SyncEsppObjectAsync(string str, ParserHandlerDelegate parser, ConvertDbObjToComparisonObjHandlerDelegate converterToEsppObject, RobotsEnum robot);
+ }
+}
\ No newline at end of file
diff --git a/PARR.EsppSync/PARR.EsppSync.csproj b/PARR.EsppSync/PARR.EsppSync.csproj
new file mode 100644
index 00000000..52abd3ef
--- /dev/null
+++ b/PARR.EsppSync/PARR.EsppSync.csproj
@@ -0,0 +1,17 @@
+
+
+
+ net7.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
diff --git a/PARR.EsppSync/SyncService.cs b/PARR.EsppSync/SyncService.cs
new file mode 100644
index 00000000..f2986e87
--- /dev/null
+++ b/PARR.EsppSync/SyncService.cs
@@ -0,0 +1,140 @@
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using PARR.DAL.Contracts;
+using PARR.DAL.Models;
+using PARR.DAL.Services.Interfaces;
+
+namespace PARR.EsppSync
+{
+ internal class SyncService : ISyncService where EsppObject : class, IEsppObject
+ {
+ private readonly ILogger> logger;
+ private readonly IServiceProvider serviceProvider;
+
+ public SyncService(
+ ILogger> logger,
+ IServiceProvider serviceProvider
+ )
+ {
+ this.logger = logger;
+ this.serviceProvider = serviceProvider;
+ }
+
+
+ public async Task SyncEsppObjectAsync(
+ string str,
+ ParserHandlerDelegate parser,
+ ConvertDbObjToComparisonObjHandlerDelegate converterToEsppObject,
+ RobotsEnum robot
+ )
+ {
+ logger.LogDebug($"Получил строку. Начинаю работать. Строка: {str}");
+
+ if (string.IsNullOrEmpty(str))
+ {
+ logger.LogWarning("Получил пустую строку, ничего не делаю.");
+ return;
+ }
+
+ var esppObject = parser.Invoke(str);
+
+ if (esppObject == null)
+ {
+ logger.LogWarning("После парсинга строки, esppObject = null. Дальше ничего не буду делать.");
+ return;
+ }
+
+ using (var scope = serviceProvider.CreateScope())
+ {
+ var templateService = GetServiceInScope(scope);
+ var robotConfigurationService = GetServiceInScope(scope);
+
+ var template = await templateService.GetTemplateByNameAsync(esppObject.TemplateName);
+
+ //todo: существует в ЕСПП но отсутствует в ПАРР. Может его деактивировать или еще что-то сделать. Пока просто пропустим
+ if (template == null)
+ {
+ logger.LogWarning($"Найден объект в ЕСПП с именем шаблона {esppObject.TemplateName} незарегистрированный в ПАРР.");
+
+ return;
+ }
+ else
+ {
+ var dbObjectInEsppObject = converterToEsppObject.Invoke(template);
+ var isChanged = IsChanged(esppObject, dbObjectInEsppObject);
+
+ if (isChanged)
+ {
+ SetUpdateStatus(ref template, robotConfigurationService, robot);
+
+ if (!await templateService.CommitAsync())
+ logger.LogError($"Не удалось изменить запись Template {template.Name}, Robot: {robot}");
+ else
+ logger.LogInformation($"Установлен принудительный статус {TaskStatusEnum.Updating}, Template {template.Name}, Robot: {robot}");
+ }//надо ли проверять если не изменился, но был статус Updating не понятно. Доверяем роботу пока, что после окончания работ он точно сообщит
+ else
+ {
+ //если все поля совпали
+ //проверяем, какой был статус предыдущий статус в БД, если он был не Ок, то ставим ему ОК
+ var robotConfig = robotConfigurationService.GetFromTemplateByRobotCode(robot, ref template);
+ if (robotConfig.TaskStatusCode != (int)TaskStatusEnum.Ok)
+ {
+ robotConfigurationService.ChangeTaskStatus(TaskStatusEnum.Ok, ref robotConfig);
+ if (!await templateService.CommitAsync())
+ logger.LogError($"Не удалось изменить запись Template {template.Name}, Robot: {robot}");
+ else
+ logger.LogInformation($"Установлен принудительный статус {TaskStatusEnum.Ok}, Template {template.Name}, Robot: {robot}");
+ }
+ }
+ }
+ }
+ }
+
+
+ private void SetUpdateStatus(ref Template template, IRobotConfigurationService robotConfigurationService, RobotsEnum robot)
+ {
+ var robotConfig = robotConfigurationService.GetFromTemplateByRobotCode(robot, ref template);
+ robotConfigurationService.ChangeTaskStatus(TaskStatusEnum.Updating, ref robotConfig);
+ }
+
+
+ private Service GetServiceInScope(IServiceScope scope)
+ {
+ var service = scope.ServiceProvider.GetService();
+ if (service == null)
+ throw new Exception($"Не найден сервис: {nameof(Service)}");
+
+ return service;
+ }
+
+
+ private bool IsChanged(EsppObject esppObj, EsppObject dbObj)
+ {
+ foreach (var prop in dbObj.GetType().GetProperties())
+ {
+ if (prop == null)
+ continue;
+
+ var dbValue = dbObj.GetType().GetProperty(prop.Name)?.GetValue(dbObj, null);
+ var esppValue = esppObj.GetType().GetProperty(prop.Name)?.GetValue(esppObj, null);
+
+ if (dbValue == null || esppValue == null)
+ continue;
+
+ //Replace("\r","").Replace("\n","") - в подробном описании могут быть переносы строк, в Rabbit прилетает без переносов. Убираем переносы для стравнения
+ var dbValueStr = dbValue!.ToString()!.ToLower().Replace("\r", "").Replace("\n", "");
+ var esppValueStr = esppValue!.ToString()!.ToLower();
+
+ if (dbValueStr != esppValueStr)
+ {
+ logger.LogDebug($"Не совпадают поля. dbValueStr: {dbValueStr}, esppValueStr: {esppValueStr}");
+
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ }
+}
diff --git a/PARR.EsppTemplateSync/Services/Manager.cs b/PARR.EsppTemplateSync/Services/Manager.cs
index 83f2f6f5..4dc4b864 100644
--- a/PARR.EsppTemplateSync/Services/Manager.cs
+++ b/PARR.EsppTemplateSync/Services/Manager.cs
@@ -116,9 +116,9 @@ namespace PARR.EsppTemplateSync.Services
if (!await templateService.CommitAsync())
logger.LogError($"Не удалось изменить запись Template {template.Name}");
else
- logger.LogInformation($"----- Установлен принудительный статус {TaskStatusEnum.Updating.ToString()} Template {template.Name} -----");
+ logger.LogInformation($"----- Установлен принудительный статус {TaskStatusEnum.Updating} Template {template.Name} -----");
- } //надо ли проверять если не изменился, но был статус Updating не понятно. Доверяем роботу пока, что после окончания работ от точно сообщит
+ } //надо ли проверять если не изменился, но был статус Updating не понятно. Доверяем роботу пока, что после окончания работ он точно сообщит
else
{
//если все поля совпали
@@ -151,9 +151,11 @@ namespace PARR.EsppTemplateSync.Services
{
foreach (var prop in template.GetType().GetProperties())
{
- if (prop == null) continue;
+ if (prop == null)
+ continue;
- if (globalSettings.IgnoreTemplateFields != null && globalSettings.IgnoreTemplateFields.Contains(prop.Name)) continue;
+ if (globalSettings.IgnoreTemplateFields != null && globalSettings.IgnoreTemplateFields.Contains(prop.Name))
+ continue;
var parrValue = template.GetType().GetProperty(prop.Name)?.GetValue(template, null);
var esppValue = esppTemplate.GetType().GetProperty(prop.Name)?.GetValue(esppTemplate, null);
diff --git a/PARR.EsppTemplateSync/Services/ParserService.cs b/PARR.EsppTemplateSync/Services/ParserService.cs
index 226bae23..43635045 100644
--- a/PARR.EsppTemplateSync/Services/ParserService.cs
+++ b/PARR.EsppTemplateSync/Services/ParserService.cs
@@ -119,7 +119,7 @@ namespace PARR.EsppTemplateSync.Services
}
- // dll
+ //// dll
//public delegate Dt CustomParserHandlerDelegate(string str);
@@ -135,7 +135,7 @@ namespace PARR.EsppTemplateSync.Services
//public class RunConverter
//{
- // public void Run(CustomParserHandlerDelegate customParser)
+ // public void Run(CustomParserHandlerDelegate customParser)
// {
// var conv = new Converter();
// //var obj = conv.ParseString("sdfsdfsdf", SuperParser);
diff --git a/README.md b/README.md
index f299d19b..90a2cca7 100644
--- a/README.md
+++ b/README.md
@@ -16,6 +16,7 @@
- PARR.EsppOrderLoaderWorker
- PARR.EsppOrderManager - управление нарядами в ЕСПП (в работу, выполнить, и т.п.)
- PARR.EsppOrderManagerWorker
+- PARR.EsppSync - общая логика синхронизации шаблонов и расписаний ЕСПП с БД PARR
- PARR.EsppTemplateSync - логика синхронизации шаблонов ESPP с БД PARR
- PARR.EsppTemplateSyncWorker - worker для PARR.EsppTemplateSync
- PARR.GeneratorTemplates - логика генерации шаблонов в ПАРР