diff --git a/PARR.API/Contracts/V1/Requests/JobRequest.cs b/PARR.API/Contracts/V1/Requests/JobRequest.cs
index ce741c01..c688e996 100644
--- a/PARR.API/Contracts/V1/Requests/JobRequest.cs
+++ b/PARR.API/Contracts/V1/Requests/JobRequest.cs
@@ -2,6 +2,7 @@
{
public class JobRequest
{
+
public required Guid TnkId { get; set; }
public required Guid GroupId { get; set; }
@@ -26,6 +27,11 @@
public class UnitFilterRequest
{
+ ///
+ /// Id = null в методе Create, в Update обязателен
+ ///
+ public Guid? Id { get; set; }
+
public required string UnitFilterMask { get; set; }
public List? FieldFilters { get; set; }
@@ -36,6 +42,7 @@
public class FieldFilterRequest
{
+
public Guid FieldId { get; set; }
public string? ValueMask { get; set; }
diff --git a/PARR.API/Controllers/V1/JobController.cs b/PARR.API/Controllers/V1/JobController.cs
index 67be7b86..58447fc6 100644
--- a/PARR.API/Controllers/V1/JobController.cs
+++ b/PARR.API/Controllers/V1/JobController.cs
@@ -160,6 +160,20 @@ namespace PARR.API.Controllers.V1
return BadRequest(new Response(jobValidateResult.Errors));
#endregion
+
+ #region Проверка существования работы с такими же параметрами
+ var isExistTheSameLinks = await jobService.Get()
+ .CountAsync(t =>
+ t.Group!.IsUmbrella == true &&
+ t.GroupId == request.GroupId &&
+ (t.MinValueRelationships == request.MinValueRelationships ||
+ t.MaxValueRelationships == request.MaxValueRelationships)
+ );
+ if (isExistTheSameLinks > 0)
+ return BadRequest(new Response(false, new List { new ErrorModel { FieldName = nameof(request.Name), Message = $"Работа с указанным диапазоном связей пересекается с уже имеющейся в базе данных({request.MinValueRelationships}-{request.MaxValueRelationships})" } }));
+ #endregion
+
+
var job = mapper.Map(request);
if (!await jobService.CreateAsync(job) || !await jobService.CommitAsync())
@@ -200,21 +214,84 @@ namespace PARR.API.Controllers.V1
if (!resultValidate.IsValid)
return BadRequest(new Response(resultValidate.Errors));
- var orig = await jobService.Get().Include(t => t.Tnk)
+ var orig = await jobService.Get()
+ .Include(t => t.Tnk)
+ .Include(t => t.Group)
+ .Include(t => t.UnitFilters)
+ .ThenInclude(t => t.FieldFilters)
+ .Include(t => t.UnitFilters)
+ .ThenInclude(t => t.RelationshipFilters)
+ .AsSingleQuery()
.FirstOrDefaultAsync(t => t.Id == id);
if (orig == null)
return BadRequest(new Response(false, new List { new ErrorModel { Message = $"Ошибка при изменении задания на выполнение работ. Не найдено задание с Id: {id}" } }));
- orig.Name = request.Name.Trim();
- orig.WorkName = request.WorkName.Trim();
- orig.MinValueRelationships = request.MinValueRelationships;
- orig.MaxValueRelationships = request.MaxValueRelationships;
- orig.isParentRelationships = request.isParentRelationships;
- orig.TemplateNameMask = request.TemplateNameMask.Trim();
- orig.WorkGroupMask = request.WorkGroupMask.Trim();
- orig.TnkId = request.TnkId;
- orig.GroupId = request.GroupId;
+ #region обновление полей задания на работу
+ var changed = false;
+
+ if (orig.Name != request.Name.Trim())
+ {
+ orig.Name = request.Name.Trim();
+ changed = true;
+ }
+
+ if (orig.WorkName != request.WorkName.Trim())
+ {
+ orig.WorkName = request.WorkName.Trim();
+ changed = true;
+ }
+
+ if (orig.MinValueRelationships != request.MinValueRelationships)
+ {
+ orig.MinValueRelationships = request.MinValueRelationships;
+ changed = true;
+ }
+
+ if (orig.MaxValueRelationships != request.MaxValueRelationships)
+ {
+ orig.MaxValueRelationships = request.MaxValueRelationships;
+ changed = true;
+ }
+
+ if (orig.isParentRelationships != request.isParentRelationships)
+ {
+ orig.isParentRelationships = request.isParentRelationships;
+ changed = true;
+ }
+
+ if (orig.TemplateNameMask != request.TemplateNameMask.Trim())
+ {
+ orig.TemplateNameMask = request.TemplateNameMask.Trim();
+ changed = true;
+ }
+
+ if (orig.WorkGroupMask != request.WorkGroupMask.Trim())
+ {
+ orig.WorkGroupMask = request.WorkGroupMask.Trim();
+ changed = true;
+ }
+
+ if (orig.TnkId != request.TnkId)
+ {
+ orig.TnkId = request.TnkId;
+ changed = true;
+ }
+
+ if (orig.GroupId != request.GroupId)
+ {
+ orig.GroupId = request.GroupId;
+ changed = true;
+ }
+
+ if (changed)
+ orig.DateModified = DateTimeOffset.UtcNow;
+ #endregion
+
+ var job = mapper.Map(request);
+ job.Id = id;//На всякий. Пусть будет для чистоты
+
+ UpdateUnitFilters(orig, job);//Обновление вложенных дочерних элементов-фильтров
if (!await jobService.CommitAsync())
return BadRequest(new Response(false, new List { new ErrorModel { Message = "Ошибка при изменении задания на выполнение работ." } }));
@@ -224,17 +301,164 @@ namespace PARR.API.Controllers.V1
$" {orig.TemplateNameMask}, {orig.TnkId}, {nameof(orig.GroupId)}");
- var updatedApplicationInWork = await jobService.Get().Include(t => t.Tnk)
+ var updatedJob = await jobService.Get()
+ .Include(t => t.Tnk)
+ .Include(t => t.Group)
+ .Include(t => t.UnitFilters)
+ .ThenInclude(t => t.FieldFilters)
+ .ThenInclude(t => t.Field)
+ .Include(t => t.UnitFilters)
+ .ThenInclude(t => t.RelationshipFilters)
.FirstAsync(t => t.Id == orig.Id);
- var response = mapper.Map(updatedApplicationInWork);
+ var response = mapper.Map(updatedJob);
response.TemplatesCount = await templateService.Get().CountAsync(t => t.JobId == id);
var statistics = await GetStatisticsAsync(response.Id);
BindStatistics(response, statistics);
return Ok(new Response(response, true));
+ }
+
+ private void UpdateUnitFilters(Job orig, Job mappedRequest)
+ {
+ //Сразу удаляем UnitFilter которых нет
+ var toDelete = orig.UnitFilters.Where(t => !mappedRequest.UnitFilters.Any(e => e.Id == t.Id));
+ foreach (var item in toDelete)
+ orig.UnitFilters.Remove(item);
+
+ foreach (var mappedUnitFilter in mappedRequest.UnitFilters)
+ {
+ var origUnitFilter = orig.UnitFilters.FirstOrDefault(t => t.Id == mappedUnitFilter.Id);
+
+ if (origUnitFilter == null)
+ {
+ var newUnitFilter = new JobUnitFilter
+ {
+ UnitFilter = mappedUnitFilter.UnitFilter,
+ DateCreated = DateTimeOffset.UtcNow,
+ JobId = orig.Id
+ };
+
+ foreach (var newRequestFieldFilter in mappedUnitFilter.FieldFilters)
+ {
+ var newFieldFilter = CreateFieldFilter(newUnitFilter.Id, newRequestFieldFilter.FieldId, newRequestFieldFilter.ValueMask);
+
+ newUnitFilter.FieldFilters.Add(newFieldFilter);
+ }
+
+ foreach (var newRequestRelationshipFilter in mappedUnitFilter.RelationshipFilters)
+ {
+ var newRelationshipFilter = CreateRelationshipFilter(newRequestRelationshipFilter.FieldId,
+ newRequestRelationshipFilter.IsParent,
+ newRequestRelationshipFilter.IsFullMatch,
+ newRequestRelationshipFilter.IsInverse,
+ newRequestRelationshipFilter.ValueMask);
+ newUnitFilter.RelationshipFilters.Add(newRelationshipFilter);
+ }
+
+ orig.UnitFilters.Add(newUnitFilter);
+ }
+ else
+ {
+ #region Непосредственно UnitFilter
+ if (origUnitFilter.UnitFilter != mappedUnitFilter.UnitFilter)
+ {
+ origUnitFilter.UnitFilter = mappedUnitFilter.UnitFilter;
+ origUnitFilter.DateModified = DateTimeOffset.UtcNow;
+ }
+ #endregion
+
+ #region FieldFilters
+ //Сразу удаляем неактуальные
+ var fieldFiltersToDelete = origUnitFilter.FieldFilters.Where(t => !mappedUnitFilter.FieldFilters.Any(m => m.FieldId == t.FieldId));
+ foreach (var item in fieldFiltersToDelete)
+ origUnitFilter.FieldFilters.Remove(item);
+
+ //Перебираем FieldFilter
+ foreach (var mappedFieldFilter in mappedUnitFilter.FieldFilters)
+ {
+ var origFieldFilter = origUnitFilter.FieldFilters.FirstOrDefault(t => t.FieldId == mappedFieldFilter.FieldId);
+
+ if (origFieldFilter == null)//Нет в БД? не проблема - создадим
+ {
+ var newFieldFilter = CreateFieldFilter(origUnitFilter.Id, mappedFieldFilter.FieldId, mappedFieldFilter.ValueMask);
+ origUnitFilter.FieldFilters.Add(newFieldFilter);
+ }
+ else
+ {
+ if (origFieldFilter.ValueMask != mappedFieldFilter.ValueMask)
+ {
+ origFieldFilter.ValueMask = mappedFieldFilter.ValueMask;
+ origFieldFilter.DateModified = DateTimeOffset.UtcNow;
+ }
+ }
+ }
+ #endregion
+
+ #region RelationshipFilters
+ //Сразу удаляем неактуальные
+ var relationshipFiltersToDelete = origUnitFilter.RelationshipFilters.Where(t => !mappedUnitFilter.RelationshipFilters.Any(m => m.FieldId == t.FieldId));
+ foreach (var item in relationshipFiltersToDelete)
+ origUnitFilter.RelationshipFilters.Remove(item);
+
+ //Перебираем RelationshipFilters
+ foreach (var mappedRelationshipFilter in mappedUnitFilter.RelationshipFilters)
+ {
+ var origRelationshipFilter = origUnitFilter.RelationshipFilters.FirstOrDefault(t => t.FieldId == mappedRelationshipFilter.FieldId);
+
+ if (origRelationshipFilter == null)//Нет в БД? не проблема - создадим
+ {
+ var newRelationshipFilter = CreateRelationshipFilter(mappedRelationshipFilter.FieldId,
+ mappedRelationshipFilter.IsParent,
+ mappedRelationshipFilter.IsFullMatch,
+ mappedRelationshipFilter.IsInverse,
+ mappedRelationshipFilter.ValueMask);
+
+ origUnitFilter.RelationshipFilters.Add(newRelationshipFilter);
+ }
+ else
+ {
+ if (origRelationshipFilter.IsParent != mappedRelationshipFilter.IsParent)
+ origRelationshipFilter.IsParent = mappedRelationshipFilter.IsParent;
+
+ if (origRelationshipFilter.ValueMask != mappedRelationshipFilter.ValueMask)
+ origRelationshipFilter.ValueMask = mappedRelationshipFilter.ValueMask;
+
+ if (origRelationshipFilter.IsFullMatch != mappedRelationshipFilter.IsFullMatch)
+ origRelationshipFilter.IsFullMatch = mappedRelationshipFilter.IsFullMatch;
+
+ if (origRelationshipFilter.IsInverse != mappedRelationshipFilter.IsInverse)
+ origRelationshipFilter.IsInverse = mappedRelationshipFilter.IsInverse;
+ }
+ }
+ #endregion
+ }
+ }
+ }
+
+ private static JobRelationshipFilter CreateRelationshipFilter(Guid fieldId, bool isParent, bool isFullMatch, bool isInverse, string valueMask)
+ {
+ return new JobRelationshipFilter
+ {
+ FieldId = fieldId,
+ IsParent = isParent,
+ IsFullMatch = isFullMatch,
+ IsInverse = isInverse,
+ ValueMask = valueMask
+ };
+ }
+
+ private static FieldFilter CreateFieldFilter(Guid unitFilterId, Guid fieldId, string valueMask)
+ {
+ return new FieldFilter
+ {
+ UnitFilterId = unitFilterId,
+ DateCreated = DateTimeOffset.UtcNow,
+ FieldId = fieldId,
+ ValueMask = valueMask
+ };
}
@@ -350,4 +574,6 @@ namespace PARR.API.Controllers.V1
public required ScheduleStats ScheduleStatistics { get; set; }
}
+
+
}
diff --git a/PARR.API/MappingProfiles/RequestToDomainProfile.cs b/PARR.API/MappingProfiles/RequestToDomainProfile.cs
index 4a699077..cb31f956 100644
--- a/PARR.API/MappingProfiles/RequestToDomainProfile.cs
+++ b/PARR.API/MappingProfiles/RequestToDomainProfile.cs
@@ -12,6 +12,7 @@ namespace PARR.API.MappingProfiles
{
CreateMap();
+ #region Job
CreateMap()
.ForMember(d => d.Id, o => o.MapFrom(s => Guid.NewGuid()))
.ForMember(d => d.DateCreated, o => o.MapFrom(s => DateTimeOffset.UtcNow))
@@ -23,7 +24,7 @@ namespace PARR.API.MappingProfiles
});
CreateMap()
- .ForMember(d => d.Id, o => o.MapFrom(s => Guid.NewGuid()))
+ .ForMember(d => d.Id, o => o.MapFrom(s => (s.Id == null) ? Guid.NewGuid() : s.Id))
.ForMember(d => d.DateCreated, o => o.MapFrom(s => DateTimeOffset.UtcNow))
.ForMember(d => d.UnitFilter, o => o.MapFrom(s => s.UnitFilterMask))
.AfterMap((s, d) =>
@@ -42,6 +43,7 @@ namespace PARR.API.MappingProfiles
.ForMember(d => d.DateCreated, o => o.MapFrom(s => DateTimeOffset.UtcNow));
CreateMap();
+ #endregion
}
}
}
diff --git a/PARR.API/Validators/JobRequestValidator.cs b/PARR.API/Validators/JobRequestValidator.cs
index f206ed31..b8d3915d 100644
--- a/PARR.API/Validators/JobRequestValidator.cs
+++ b/PARR.API/Validators/JobRequestValidator.cs
@@ -1,5 +1,4 @@
using FluentValidation;
-using Microsoft.EntityFrameworkCore;
using PARR.API.Contracts.V1.Requests;
using PARR.DAL.Models.Job;
using PARR.DAL.Services.Interfaces;
@@ -27,6 +26,7 @@ namespace PARR.API.Validators
this.jobGroupService = jobGroupService;
this.jobService = jobService;
this.unitFieldService = unitFieldService;
+
RuleFor(t => t.Name)
.NotNull().NotEmpty();
@@ -49,17 +49,10 @@ namespace PARR.API.Validators
.WithMessage("Неверно заданы параметры фильтров. Внимательнее, пожалуйста!");
RuleFor(t => t.MinValueRelationships)
- .MustAsync(async (entity, value, c) => await IsMinValueRelationShipsExist(entity))
- .WithMessage("Работа с таким минимальным количеством связей уже существует");
+ .GreaterThanOrEqualTo(0);
RuleFor(t => t.MaxValueRelationships)
.GreaterThanOrEqualTo(t => t.MinValueRelationships);
-
- RuleFor(t => t.MaxValueRelationships)
- .MustAsync(async (entity, value, c) => await IsMaxValueRelationShipsExist(entity))
- .WithMessage("Работа с таким максимальным количеством связей уже существует");
-
-
}
private async Task IsUnitFiltersCorrect(JobRequest entity)
@@ -103,21 +96,5 @@ namespace PARR.API.Validators
{
return await tnkService.GetAsync(entity.TnkId) != null;
}
-
- private async Task IsMinValueRelationShipsExist(JobRequest entity)
- {
- if (!jobGroup?.IsUmbrella == true)
- return true;
-
- return await jobService.Get().CountAsync(t => t.GroupId == entity.GroupId && t.MinValueRelationships == entity.MinValueRelationships) == 0;
- }
-
- private async Task IsMaxValueRelationShipsExist(JobRequest entity)
- {
- if (!jobGroup?.IsUmbrella == true)
- return true;
-
- return await jobService.Get().CountAsync(t => t.GroupId == entity.GroupId && t.MaxValueRelationships == entity.MaxValueRelationships) == 0;
- }
}
}
\ No newline at end of file