feat(api): jobGroup - управление автораспределением
This commit is contained in:
@@ -489,6 +489,11 @@
|
||||
public const string Distribute = Base + "/distributor/";
|
||||
}
|
||||
|
||||
public static class DistributionPeriod
|
||||
{
|
||||
public const string GetAll = Base + "/distribution-periods/";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region SyncTask
|
||||
|
||||
@@ -27,7 +27,12 @@
|
||||
|
||||
public Guid? ScheduleExcludeTypeCalendarId { get; set; }
|
||||
|
||||
//public bool IsAutoDistributionEnabled { get; set; }
|
||||
public bool IsAutoDistributionEnabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Настройки автораспределения
|
||||
/// </summary>
|
||||
public DistributionConfigRequest? DistributionConfig { get; set; }
|
||||
|
||||
//public bool IsAgent { get; set; }
|
||||
|
||||
@@ -46,4 +51,19 @@
|
||||
|
||||
public Guid TypeConfigId { get; set; }
|
||||
}
|
||||
|
||||
public class DistributionConfigRequest
|
||||
{
|
||||
public Guid DistributionPeriodId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Исключать выходные и праздники
|
||||
/// </summary>
|
||||
public bool IsExcludeWeekends { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Группировать по рабочей группе
|
||||
/// </summary>
|
||||
public bool IsGroupingByWorkGroup { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
52
PARR.API/Controllers/V1/DistributionPeriodController.cs
Normal file
52
PARR.API/Controllers/V1/DistributionPeriodController.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using AutoMapper;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using PARR.API.Contracts.V1;
|
||||
using PARR.API.Contracts.V1.Responses;
|
||||
using PARR.API.Contracts.V1.Responses.Base;
|
||||
using PARR.API.Controllers.V1.Base;
|
||||
using PARR.Constants;
|
||||
using PARR.DAL.Services.Interfaces;
|
||||
|
||||
namespace PARR.API.Controllers.V1
|
||||
{
|
||||
/// <summary>
|
||||
/// Периоды распределения РР
|
||||
/// </summary>
|
||||
[Authorize(Roles = ParrRoles.Administrator.Role)]
|
||||
public class DistributionPeriodController : BaseApiController
|
||||
{
|
||||
private readonly IDistributionPeriodService distributionPeriodService;
|
||||
private readonly IMapper mapper;
|
||||
|
||||
public DistributionPeriodController(
|
||||
IDistributionPeriodService distributionPeriodService,
|
||||
IMapper mapper
|
||||
)
|
||||
{
|
||||
this.distributionPeriodService = distributionPeriodService;
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Список периодов распределения
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet(ApiRoutes.DistributionPeriod.GetAll)]
|
||||
public async Task<IActionResult> GetAll()
|
||||
{
|
||||
var periods = await distributionPeriodService.Get()
|
||||
.OrderBy(t => t.Name)
|
||||
.ToListAsync();
|
||||
|
||||
if (!periods.Any())
|
||||
return NoContent();
|
||||
|
||||
var response = mapper.Map<List<DistributionPeriodResponse>>(periods);
|
||||
|
||||
return Ok(new Response<List<DistributionPeriodResponse>>(response, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -160,14 +160,28 @@ namespace PARR.API.Controllers.V1
|
||||
TemplateDuration = request.TemplateDuration.Trim(),
|
||||
ReferenceDate = request.ReferenceDate,
|
||||
ScheduleExcludeTypeId = request.ScheduleExcludeTypeId,
|
||||
ScheduleExcludeTypeCalendarId = request.ScheduleExcludeTypeCalendarId
|
||||
//IsAutoDistributionEnabled = request.IsAutoDistributionEnabled,
|
||||
ScheduleExcludeTypeCalendarId = request.ScheduleExcludeTypeCalendarId,
|
||||
IsAutoDistributionEnabled = request.IsAutoDistributionEnabled,
|
||||
//IsAgent = request.IsAgent,
|
||||
//AgentName = request.AgentName,
|
||||
//AgentTimeOutSec = request.AgentTimeOutSec,
|
||||
//AgentScript = request.AgentScript
|
||||
};
|
||||
|
||||
#region Если включено автораспределение, добавляем настройки
|
||||
if (request.IsAutoDistributionEnabled)
|
||||
{
|
||||
// на всякий проверим, но вообще это проверяется в валидаторе
|
||||
if (request.DistributionConfig == null)
|
||||
{
|
||||
logger.LogError("Ошибка при создании группы работ '{name}', отсутствуют настройки автораспределения", request.Name);
|
||||
return BadRequest(new Response(false, new List<ErrorModel> { new ErrorModel { Message = "Ошибка при создании группы заданий на выполнение работ" } }));
|
||||
}
|
||||
|
||||
jobGroup.DistributionConfig = CreateDistributionConfig(request.DistributionConfig, jobGroup.Id);
|
||||
}
|
||||
#endregion
|
||||
|
||||
//Добавляем настройки планировщика
|
||||
request.Schedule.ForEach(item =>
|
||||
{
|
||||
@@ -220,6 +234,7 @@ namespace PARR.API.Controllers.V1
|
||||
.Include(t => t.Jobs)
|
||||
.ThenInclude(t => t.Tnk)
|
||||
.Include(t => t.EsppSchValues)
|
||||
.Include(t => t.DistributionConfig).ThenInclude(t => t.DistributionPeriod)
|
||||
.FirstOrDefaultAsync(t => t.Id == id);
|
||||
|
||||
if (orig == null)
|
||||
@@ -239,12 +254,45 @@ namespace PARR.API.Controllers.V1
|
||||
orig.ReferenceDate = request.ReferenceDate;
|
||||
orig.ScheduleExcludeTypeId = request.ScheduleExcludeTypeId;
|
||||
orig.ScheduleExcludeTypeCalendarId = request.ScheduleExcludeTypeCalendarId;
|
||||
//orig.IsAutoDistributionEnabled = request.IsAutoDistributionEnabled;
|
||||
orig.IsAutoDistributionEnabled = request.IsAutoDistributionEnabled;
|
||||
//orig.IsAgent = request.IsAgent;
|
||||
//orig.AgentName = request.AgentName;
|
||||
//orig.AgentTimeOutSec = request.AgentTimeOutSec;
|
||||
//orig.AgentScript = request.AgentScript;
|
||||
orig.DateModified = DateTimeOffset.UtcNow;
|
||||
|
||||
#region Обновляем настройки автораспределения
|
||||
|
||||
if (request.IsAutoDistributionEnabled)
|
||||
{
|
||||
if (request.DistributionConfig == null)
|
||||
{
|
||||
logger.LogError("Ошибка при изменении группы работ '{name}', отсутствуют настройки автораспределения", request.Name);
|
||||
return BadRequest(new Response(false, new List<ErrorModel> { new ErrorModel { Message = "Ошибка при изменении группы заданий на выполнение работ" } }));
|
||||
}
|
||||
|
||||
// если настройки были, меняем, если не было, создаем
|
||||
if (orig.DistributionConfig != null)
|
||||
{
|
||||
orig.DistributionConfig.DistributionPeriodId = request.DistributionConfig.DistributionPeriodId;
|
||||
orig.DistributionConfig.IsExcludeWeekends = request.DistributionConfig.IsExcludeWeekends;
|
||||
orig.DistributionConfig.IsGroupingByWorkGroup = request.DistributionConfig.IsGroupingByWorkGroup;
|
||||
}
|
||||
else
|
||||
{
|
||||
//создаем
|
||||
orig.DistributionConfig = CreateDistributionConfig(request.DistributionConfig, orig.Id);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// удаляем настройки распределения если они были
|
||||
if (orig.DistributionConfig != null)
|
||||
{
|
||||
groupService.DeleteDistributionConfig(orig.DistributionConfig);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
//обновляем планировщик
|
||||
orig.EsppSchValues.Clear();
|
||||
@@ -443,5 +491,23 @@ namespace PARR.API.Controllers.V1
|
||||
|
||||
return mapper.Map<MatchingStatusResponse>(statusMatching);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Создать конфиг распределения
|
||||
/// </summary>
|
||||
/// <param name="distributionConfigRequest"></param>
|
||||
/// <param name="jobGroupId"></param>
|
||||
/// <returns></returns>
|
||||
private JobGroupDistributionConfig CreateDistributionConfig(DistributionConfigRequest distributionConfigRequest, Guid jobGroupId)
|
||||
{
|
||||
return new JobGroupDistributionConfig
|
||||
{
|
||||
GroupId = jobGroupId,
|
||||
DistributionPeriodId = distributionConfigRequest.DistributionPeriodId,
|
||||
IsExcludeWeekends = distributionConfigRequest.IsExcludeWeekends,
|
||||
IsGroupingByWorkGroup = distributionConfigRequest.IsGroupingByWorkGroup
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using PARR.API.Contracts.V1.Requests;
|
||||
using PARR.DAL.Contracts;
|
||||
using PARR.DAL.Services.Interfaces;
|
||||
using PARR.DAL.Services.Interfaces.Job;
|
||||
using PARR.DAL.Services.Interfaces.Schedule;
|
||||
using PARR.DAL.Services.Interfaces.Unit;
|
||||
@@ -14,7 +15,8 @@ namespace PARR.API.Validators
|
||||
IJobGroupTypeService jobGroupTypeService,
|
||||
IUnitFieldService unitFieldService,
|
||||
IScheduleExcludeTypeService scheduleExcludeTypeService,
|
||||
IScheduleExcludeTypeCalendarService scheduleExcludeTypeCalendarService
|
||||
IScheduleExcludeTypeCalendarService scheduleExcludeTypeCalendarService,
|
||||
IDistributionPeriodService distributionPeriodService
|
||||
)
|
||||
{
|
||||
RuleFor(t => t.Name)
|
||||
@@ -91,6 +93,35 @@ namespace PARR.API.Validators
|
||||
})
|
||||
.WithMessage("Некорректное значение");
|
||||
|
||||
RuleFor(t => t.DistributionConfig)
|
||||
.Must((entity, value, c) =>
|
||||
{
|
||||
// если включено автораспределение, должны быть настройки
|
||||
if (entity.IsAutoDistributionEnabled && value != null)
|
||||
return true;
|
||||
|
||||
// если выкл автораспределение, то валидно
|
||||
if (!entity.IsAutoDistributionEnabled)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}).WithMessage("Отсутствуют настройки автораспределения");
|
||||
|
||||
RuleFor(t => t.DistributionConfig)
|
||||
.MustAsync(async (entity, value, c) =>
|
||||
{
|
||||
// если есть настройка периода, проверить что она валидна
|
||||
var periodId = value?.DistributionPeriodId;
|
||||
|
||||
if (periodId.HasValue)
|
||||
{
|
||||
var exist = await distributionPeriodService.GetAsync(periodId.Value);
|
||||
|
||||
return exist != null;
|
||||
}
|
||||
|
||||
return true;
|
||||
}).WithMessage("Некорректное значение периода распределения");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,15 +3,15 @@ using Moq;
|
||||
using PARR.DAL.Contracts;
|
||||
using PARR.DAL.DomainModels;
|
||||
using PARR.DAL.Models;
|
||||
using PARR.DAL.NextRunServices.Subservices;
|
||||
using PARR.DAL.Services.Interfaces;
|
||||
using PARR.DAL.TransformServices;
|
||||
|
||||
namespace PARR.DAL.Tests.TransformServices
|
||||
{
|
||||
public class EsppScheduleTransformServiceTests
|
||||
{
|
||||
private Mock<IEsppSchTypeConfigService> esppSchTypeConfigServiceMock;
|
||||
private Mock<INextRunModifierService> nextRunModifierServiceMock;
|
||||
//private Mock<INextRunModifierService> nextRunModifierServiceMock;
|
||||
|
||||
private ILogger<EsppScheduleTransformService> logger;
|
||||
private EsppScheduleTransformService service;
|
||||
@@ -19,7 +19,7 @@ namespace PARR.DAL.Tests.TransformServices
|
||||
public EsppScheduleTransformServiceTests()
|
||||
{
|
||||
esppSchTypeConfigServiceMock = new Mock<IEsppSchTypeConfigService>();
|
||||
nextRunModifierServiceMock = new Mock<INextRunModifierService>();
|
||||
//nextRunModifierServiceMock = new Mock<INextRunModifierService>();
|
||||
|
||||
var loggerFactory = new LoggerFactory();
|
||||
logger = loggerFactory.CreateLogger<EsppScheduleTransformService>();
|
||||
@@ -27,8 +27,8 @@ namespace PARR.DAL.Tests.TransformServices
|
||||
|
||||
service = new EsppScheduleTransformService(
|
||||
logger,
|
||||
esppSchTypeConfigServiceMock.Object,
|
||||
nextRunModifierServiceMock.Object
|
||||
esppSchTypeConfigServiceMock.Object
|
||||
//nextRunModifierServiceMock.Object
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ using PARR.DAL.NextRunServices.Models;
|
||||
using PARR.DAL.NextRunServices.Subservices;
|
||||
using PARR.DAL.Services.Interfaces;
|
||||
using PARR.DAL.Services.Interfaces.Job;
|
||||
using PARR.DAL.TransformServices;
|
||||
|
||||
namespace PARR.DAL.NextRunServices
|
||||
{
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using PARR.Constants;
|
||||
using PARR.DAL.Contracts;
|
||||
using PARR.DAL.DomainModels;
|
||||
using PARR.DAL.Extensions;
|
||||
using PARR.DAL.Services.Interfaces;
|
||||
using PARR.DAL.TransformServices;
|
||||
|
||||
namespace PARR.DAL.TransformServices
|
||||
namespace PARR.DAL.NextRunServices.Subservices
|
||||
{
|
||||
internal class EsppScheduleTransformService : IEsppScheduleTransformService
|
||||
{
|
||||
private readonly IEsppSchTypeConfigService esppSchTypeConfigService;
|
||||
private readonly INextRunModifierService nextRunModifierService;
|
||||
//private readonly INextRunModifierService nextRunModifierService;
|
||||
private readonly ILogger<EsppScheduleTransformService> logger;
|
||||
|
||||
private static readonly Dictionary<string, int> monthDict = new Dictionary<string, int>()
|
||||
@@ -52,12 +51,12 @@ namespace PARR.DAL.TransformServices
|
||||
|
||||
public EsppScheduleTransformService(
|
||||
ILogger<EsppScheduleTransformService> logger,
|
||||
IEsppSchTypeConfigService esppSchTypeConfigService,
|
||||
INextRunModifierService nextRunModifierService
|
||||
IEsppSchTypeConfigService esppSchTypeConfigService
|
||||
//INextRunModifierService nextRunModifierService
|
||||
)
|
||||
{
|
||||
this.esppSchTypeConfigService = esppSchTypeConfigService;
|
||||
this.nextRunModifierService = nextRunModifierService;
|
||||
//this.nextRunModifierService = nextRunModifierService;
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
@@ -493,18 +492,18 @@ namespace PARR.DAL.TransformServices
|
||||
//}
|
||||
|
||||
|
||||
private int ParseInt(string value)
|
||||
{
|
||||
try
|
||||
{
|
||||
return int.Parse(value);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogError(ex, $"{nameof(this.GetType)}, получение конца периода. Не смог распарсить string в int для значения {value}.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
//private int ParseInt(string value)
|
||||
//{
|
||||
// try
|
||||
// {
|
||||
// return int.Parse(value);
|
||||
// }
|
||||
// catch (Exception ex)
|
||||
// {
|
||||
// logger.LogError(ex, $"{nameof(this.GetType)}, получение конца периода. Не смог распарсить string в int для значения {value}.");
|
||||
// return 0;
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
//private DistributionPeriodTypeEnum ParseDistributionPeriodType(string value)
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace PARR.DAL.TransformServices
|
||||
namespace PARR.DAL.NextRunServices.Subservices
|
||||
{
|
||||
/// <summary>
|
||||
/// Сервис трансформации расписания ЕСПП в дату/расписание
|
||||
@@ -2,8 +2,7 @@
|
||||
|
||||
namespace PARR.DAL.NextRunServices.Subservices
|
||||
{
|
||||
//todo: public -> internal!!!
|
||||
public interface ITemplateDistributor
|
||||
internal interface ITemplateDistributor
|
||||
{
|
||||
/// <summary>
|
||||
/// Распределяет все шаблоны на указанный период, учитывая план нагрузки.
|
||||
|
||||
@@ -18,5 +18,11 @@ namespace PARR.DAL.Services.Implementations.Job
|
||||
protected override DbSet<JobGroup> EntitySet => dataContext.JobGroups;
|
||||
|
||||
protected override DataContext EntitiContext => dataContext;
|
||||
|
||||
|
||||
public void DeleteDistributionConfig(JobGroupDistributionConfig distributionConfig)
|
||||
{
|
||||
EntitiContext.JobGroupDistributionConfigs.Remove(distributionConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
using PARR.DAL.Services.Interfaces.Base;
|
||||
using PARR.DAL.Models.Job;
|
||||
using PARR.DAL.Services.Interfaces.Base;
|
||||
|
||||
namespace PARR.DAL.Services.Interfaces.Job
|
||||
{
|
||||
public interface IJobGroupService : IBaseService<Models.Job.JobGroup>
|
||||
{
|
||||
/// <summary>
|
||||
/// Удалить настройки автораспределения
|
||||
/// </summary>
|
||||
/// <param name="distributionConfig"></param>
|
||||
void DeleteDistributionConfig(JobGroupDistributionConfig distributionConfig);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,12 +6,12 @@ namespace PARR.Test.NextRun
|
||||
{
|
||||
internal class NextRunTest
|
||||
{
|
||||
private readonly ITemplateDistributor templateDistributor;
|
||||
//private readonly ITemplateDistributor templateDistributor;
|
||||
private readonly INextRunService nextRunService;
|
||||
|
||||
public NextRunTest(ITemplateDistributor templateDistributor, INextRunService nextRunService)
|
||||
public NextRunTest(/*ITemplateDistributor templateDistributor,*/ INextRunService nextRunService)
|
||||
{
|
||||
this.templateDistributor = templateDistributor;
|
||||
//this.templateDistributor = templateDistributor;
|
||||
this.nextRunService = nextRunService;
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace PARR.Test.NextRun
|
||||
NextRun: null
|
||||
);
|
||||
|
||||
var template = await templateDistributor.GetValidNextRunForTemplateAsync(GetDateStart(), periodDays, referenceDate, targetTemplate, new List<TemplateNextRunDto>(), excludeWeekends, isNew);
|
||||
//var template = await templateDistributor.GetValidNextRunForTemplateAsync(GetDateStart(), periodDays, referenceDate, targetTemplate, new List<TemplateNextRunDto>(), excludeWeekends, isNew);
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace PARR.Test.NextRun
|
||||
// исключать выходные и праздники
|
||||
var excludeWeekends = true;
|
||||
|
||||
var templates = await templateDistributor.DistributeTemplatesAsync(GetDateStart(), periodDays, referenceDate, GetTemplates(), excludeWeekends);
|
||||
// var templates = await templateDistributor.DistributeTemplatesAsync(GetDateStart(), periodDays, referenceDate, GetTemplates(), excludeWeekends);
|
||||
|
||||
//await GetValidNextRunForTemplateAsync(templates);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user