feat(api): переписан метод Update для JobController

This commit is contained in:
Mikhail Kuznetsov
2025-09-16 15:27:26 +10:00
parent 691a256d9c
commit e094db168f
4 changed files with 250 additions and 38 deletions

View File

@@ -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
{
/// <summary>
/// Id = null в методе Create, в Update обязателен
/// </summary>
public Guid? Id { get; set; }
public required string UnitFilterMask { get; set; }
public List<FieldFilterRequest>? FieldFilters { get; set; }
@@ -36,6 +42,7 @@
public class FieldFilterRequest
{
public Guid FieldId { get; set; }
public string? ValueMask { get; set; }

View File

@@ -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<ErrorModel> { new ErrorModel { FieldName = nameof(request.Name), Message = $"Работа с указанным диапазоном связей пересекается с уже имеющейся в базе данных({request.MinValueRelationships}-{request.MaxValueRelationships})" } }));
#endregion
var job = mapper.Map<Job>(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<ErrorModel> { 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<Job>(request);
job.Id = id;//На всякий. Пусть будет для чистоты
UpdateUnitFilters(orig, job);//Обновление вложенных дочерних элементов-фильтров
if (!await jobService.CommitAsync())
return BadRequest(new Response(false, new List<ErrorModel> { 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<JobResponse>(updatedApplicationInWork);
var response = mapper.Map<JobResponse>(updatedJob);
response.TemplatesCount = await templateService.Get().CountAsync(t => t.JobId == id);
var statistics = await GetStatisticsAsync(response.Id);
BindStatistics(response, statistics);
return Ok(new Response<JobResponse>(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; }
}
}

View File

@@ -12,6 +12,7 @@ namespace PARR.API.MappingProfiles
{
CreateMap<PaginationQuery, PaginationFilter>();
#region Job
CreateMap<JobRequest, Job>()
.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<UnitFilterRequest, JobUnitFilter>()
.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<RelationshipFilterRequest, JobRelationshipFilter>();
#endregion
}
}
}

View File

@@ -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<bool> IsUnitFiltersCorrect(JobRequest entity)
@@ -103,21 +96,5 @@ namespace PARR.API.Validators
{
return await tnkService.GetAsync(entity.TnkId) != null;
}
private async Task<bool> 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<bool> IsMaxValueRelationShipsExist(JobRequest entity)
{
if (!jobGroup?.IsUmbrella == true)
return true;
return await jobService.Get().CountAsync(t => t.GroupId == entity.GroupId && t.MaxValueRelationships == entity.MaxValueRelationships) == 0;
}
}
}