2025-07-01 17:20:48 +10:00
using AutoMapper ;
using FluentValidation ;
using Microsoft.AspNetCore.Authorization ;
using Microsoft.AspNetCore.Mvc ;
using Microsoft.EntityFrameworkCore ;
using PARR.API.Contracts.V1 ;
using PARR.API.Contracts.V1.Requests ;
using PARR.API.Contracts.V1.Requests.Queries ;
using PARR.API.Contracts.V1.Responses ;
using PARR.API.Contracts.V1.Responses.Base ;
using PARR.API.Controllers.V1.Base ;
using PARR.API.Extensions ;
using PARR.API.Services.Interfaces ;
2026-02-27 16:37:52 +10:00
using PARR.API.Settings ;
using PARR.BLL.Domain.Mq ;
2026-02-02 09:24:39 +10:00
using PARR.BLL.Helpers ;
2026-02-27 16:37:52 +10:00
using PARR.BLL.Services.Interfaces ;
using PARR.Common.Domain ;
2025-07-01 17:20:48 +10:00
using PARR.Constants ;
2025-09-09 17:19:41 +10:00
using PARR.DAL.Contracts ;
2025-07-01 17:20:48 +10:00
using PARR.DAL.DomainModels ;
2026-01-16 11:04:26 +10:00
using PARR.DAL.DomainServices.Interfaces ;
2025-09-04 14:51:51 +10:00
using PARR.DAL.Models ;
2025-07-01 17:20:48 +10:00
using PARR.DAL.Models.Job ;
2025-09-09 17:19:41 +10:00
using PARR.DAL.Services.Interfaces ;
2025-07-01 17:20:48 +10:00
using PARR.DAL.Services.Interfaces.Job ;
2026-02-03 16:15:19 +10:00
using PARR.DAL.Services.Interfaces.Schedule ;
2025-07-01 17:20:48 +10:00
namespace PARR.API.Controllers.V1
{
/// <summary>
/// Управление группами работам
/// </summary>
[Authorize(Roles = ParrRoles.Administrator.Role)]
public class JobGroupController : BaseApiController
{
private readonly ILogger < JobController > logger ;
private readonly IMapper mapper ;
private readonly IUriService uriService ;
private readonly IJobGroupService groupService ;
2025-09-09 10:44:33 +10:00
private readonly IJobService jobService ;
2025-09-09 17:19:41 +10:00
private readonly IEsppSchTypeConfigService esppConfigService ;
2025-07-01 17:20:48 +10:00
private readonly IValidator < JobGroupRequest > validator ;
2025-12-19 10:48:41 +10:00
private readonly IJobGroupTypeService jobGroupTypeService ;
2026-01-16 11:04:26 +10:00
private readonly IMatchingStatusService matchingStatusService ;
2026-02-03 16:15:19 +10:00
private readonly IScheduleResponseAreaTimeOffsetService scheduleResponseAreaTimeOffsetService ;
2026-02-27 16:37:52 +10:00
private readonly IMqService mqService ;
private readonly MqSettings mqSettings ;
2025-07-01 17:20:48 +10:00
public JobGroupController (
ILogger < JobController > logger ,
IMapper mapper ,
IUriService uriService ,
IJobGroupService groupService ,
2025-09-09 10:44:33 +10:00
IJobService jobService ,
2025-09-09 17:19:41 +10:00
IEsppSchTypeConfigService esppConfigService ,
IValidator < JobGroupRequest > validator ,
2025-12-19 10:48:41 +10:00
IJobGroupTypeService jobGroupTypeService ,
2026-02-03 16:15:19 +10:00
IMatchingStatusService matchingStatusService ,
2026-02-27 16:37:52 +10:00
IScheduleResponseAreaTimeOffsetService scheduleResponseAreaTimeOffsetService ,
IMqService mqService ,
MqSettings mqSettings
2025-07-01 17:20:48 +10:00
)
{
this . logger = logger ;
this . mapper = mapper ;
this . uriService = uriService ;
this . groupService = groupService ;
2025-09-09 10:44:33 +10:00
this . jobService = jobService ;
2025-09-09 17:19:41 +10:00
this . esppConfigService = esppConfigService ;
2025-07-01 17:20:48 +10:00
this . validator = validator ;
2025-12-19 10:48:41 +10:00
this . jobGroupTypeService = jobGroupTypeService ;
2026-01-16 11:04:26 +10:00
this . matchingStatusService = matchingStatusService ;
2026-02-03 16:15:19 +10:00
this . scheduleResponseAreaTimeOffsetService = scheduleResponseAreaTimeOffsetService ;
2026-02-27 16:37:52 +10:00
this . mqService = mqService ;
this . mqSettings = mqSettings ;
2025-07-01 17:20:48 +10:00
}
/// <summary>
/// Получить список групп заданий на выполнение работ постранично
/// </summary>
/// <returns></returns>
[HttpGet(ApiRoutes.JobGroup.GetAll)]
public async Task < IActionResult > GetAll ( [ FromQuery ] PaginationQuery paginationQuery , [ FromQuery ] JobGroupQuery filter )
{
var paginationFilter = mapper . Map < PaginationFilter > ( paginationQuery ) ;
2025-12-19 10:48:41 +10:00
IQueryable < JobGroup > query = groupService . Get ( )
. Include ( t = > t . GroupType )
2025-12-26 11:21:45 +10:00
. Include ( t = > t . GroupingUnitField )
. Include ( t = > t . ScheduleExcludeType )
. Include ( t = > t . ScheduleExcludeTypeCalendar ) ;
2025-07-01 17:20:48 +10:00
query = query . OrderBy ( t = > t . GroupName ) ;
if ( ! string . IsNullOrEmpty ( filter . Name ) )
2026-02-02 09:24:39 +10:00
{
//query = query.Where(t => t.GroupName.ToLower().Contains(filter.Name.ToLower()));
query = query . Where ( t = > EF . Functions . Like ( t . GroupName . ToLower ( ) , SqlHelpers . RegexToLike ( filter . Name ) ) ) ;
}
2025-07-01 17:20:48 +10:00
2025-09-09 17:19:41 +10:00
if ( filter . IsFull )
2026-01-22 14:05:48 +10:00
query = query
. Include ( t = > t . Jobs ) . ThenInclude ( t = > t . Tnk )
. Include ( t = > t . DistributionConfig ) . ThenInclude ( t = > t . DistributionPeriod ) ;
2025-07-01 17:20:48 +10:00
2025-09-04 14:51:51 +10:00
var jobGroups = await groupService . GetPage ( query , paginationFilter ) . ToListAsync ( ) ;
2025-07-01 17:20:48 +10:00
2025-09-04 14:51:51 +10:00
if ( ! jobGroups . Any ( ) )
2025-07-01 17:20:48 +10:00
return NoContent ( ) ;
2025-09-04 16:03:30 +10:00
var response = mapper . Map < List < JobGroupResponse > > ( jobGroups ) ;
2025-07-01 17:20:48 +10:00
2025-09-09 17:19:41 +10:00
if ( filter . IsFull )
foreach ( var jobGroupResponse in response )
await AppendMissingDataAsync ( jobGroupResponse ) ;
2025-09-04 16:03:30 +10:00
var paginationResponse = new PagedResponse < JobGroupResponse > ( response , true ) . GetPaginatedProps ( paginationFilter , query ) ;
2025-07-01 17:20:48 +10:00
return Ok ( paginationResponse ) ;
}
/// <summary>
/// Получить группу заданий на выполнение работ по id
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[HttpGet(ApiRoutes.JobGroup.Get)]
public async Task < IActionResult > GetById ( [ FromRoute ] Guid id )
{
var jobGroup = await groupService . Get ( )
. Include ( t = > t . Jobs ) . ThenInclude ( t = > t . Tnk )
2025-11-17 12:06:33 +10:00
. Include ( t = > t . GroupType )
2025-12-19 10:48:41 +10:00
. Include ( t = > t . GroupingUnitField )
2025-12-26 11:21:45 +10:00
. Include ( t = > t . ScheduleExcludeType )
. Include ( t = > t . ScheduleExcludeTypeCalendar )
2026-01-22 14:05:48 +10:00
. Include ( t = > t . DistributionConfig ) . ThenInclude ( t = > t . DistributionPeriod )
2025-07-01 17:20:48 +10:00
. FirstOrDefaultAsync ( t = > t . Id = = id ) ;
if ( jobGroup = = null )
return NotFound ( ) ;
var response = mapper . Map < JobGroupResponse > ( jobGroup ) ;
2025-09-11 16:03:51 +10:00
await AppendMissingDataAsync ( response ) ;
2025-07-01 17:20:48 +10:00
return Ok ( new Response < JobGroupResponse > ( response , true ) ) ;
}
/// <summary>
/// Создать группу заданий на выполнение работ (JobGroup)
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
[HttpPost(ApiRoutes.JobGroup.Create)]
public async Task < IActionResult > Create ( [ FromBody ] JobGroupRequest request )
{
var resultValidate = await validator . ValidateAsync ( request ) ;
if ( ! resultValidate . IsValid )
return BadRequest ( new Response ( resultValidate . Errors ) ) ;
var jobGroup = new JobGroup
{
Id = Guid . NewGuid ( ) ,
GroupName = request . Name . Trim ( ) ,
2025-11-17 12:06:33 +10:00
//IsUmbrella = request.IsUmbrella,
GroupTypeId = request . GroupTypeId ,
2025-12-19 10:48:41 +10:00
GroupingUnitFieldId = await GetGroupingUnitFieldIdAsync ( request ) ,
2025-07-01 17:20:48 +10:00
ShortDescription = request . ShortDescription . Trim ( ) ,
FullDescription = request . FullDescription . Trim ( ) ,
Solution = request . Solution . Trim ( ) ,
TemplateDuration = request . TemplateDuration . Trim ( ) ,
ReferenceDate = request . ReferenceDate ,
2026-02-09 15:48:30 +10:00
UserTimeZoneOffsetMinutes = request . UserTimeZoneOffsetMinutes ,
2025-12-26 11:21:45 +10:00
ScheduleExcludeTypeId = request . ScheduleExcludeTypeId ,
2026-01-23 16:18:56 +10:00
ScheduleExcludeTypeCalendarId = request . ScheduleExcludeTypeCalendarId ,
IsAutoDistributionEnabled = request . IsAutoDistributionEnabled ,
2026-03-20 15:50:00 +10:00
IsResponseAreaTimezone = request . IsWorkGroupTimezone ,
IsGroupByResponsible = request . IsGroupByResponsible
2025-09-05 10:33:52 +10:00
//IsAgent = request.IsAgent,
//AgentName = request.AgentName,
//AgentTimeOutSec = request.AgentTimeOutSec,
//AgentScript = request.AgentScript
2025-07-01 17:20:48 +10:00
} ;
2026-01-23 16:18:56 +10:00
#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
2025-09-04 14:51:51 +10:00
//Добавляем настройки планировщика
request . Schedule . ForEach ( item = >
{
jobGroup . EsppSchValues . Add ( new EsppSchValue
{
JobGroupId = jobGroup . Id ,
TypeConfigId = item . TypeConfigId ,
TypeValueId = item . TypeValueId
} ) ;
} ) ;
2025-07-01 17:20:48 +10:00
if ( ! await groupService . CreateAsync ( jobGroup ) | | ! await groupService . CommitAsync ( ) )
return BadRequest ( new Response ( false , new List < ErrorModel > { new ErrorModel { Message = "Ошибка при создании группы заданий на выполнение работ" } } ) ) ;
logger . LogInformation ( $"Пользователь {User.Identity?.Name} добавил группу заданий на выполнение работ: {jobGroup.Id}, {jobGroup.GroupName}, {jobGroup.ShortDescription}" ) ;
2025-09-04 14:51:51 +10:00
var createdJobGroup = await groupService . Get ( ) . Include ( t = > t . Jobs ) . ThenInclude ( t = > t . Tnk )
2025-11-17 12:06:33 +10:00
. Include ( t = > t . GroupType )
2025-12-19 10:48:41 +10:00
. Include ( t = > t . GroupingUnitField )
2025-12-26 11:21:45 +10:00
. Include ( t = > t . ScheduleExcludeType )
. Include ( t = > t . ScheduleExcludeTypeCalendar )
2026-01-22 14:05:48 +10:00
. Include ( t = > t . DistributionConfig ) . ThenInclude ( t = > t . DistributionPeriod )
2025-07-01 17:20:48 +10:00
. FirstAsync ( t = > t . Id = = jobGroup . Id ) ;
var locationUri = uriService . GetUri ( ApiRoutes . JobGroup . Get , ApiRoutes . JobGroup . getParam , createdJobGroup . Id ) ;
var response = mapper . Map < JobGroupResponse > ( createdJobGroup ) ;
2025-12-26 13:50:30 +10:00
await AppendMissingDataAsync ( response ) ;
2025-07-01 17:20:48 +10:00
return Created ( locationUri , new Response < JobGroupResponse > ( response , true ) ) ;
}
/// <summary>
/// Обновить группу заданий на выполнение работ (JobGroup)
/// </summary>
/// <param name="id"></param>
/// <param name="request"></param>
/// <returns></returns>
[HttpPut(ApiRoutes.JobGroup.Update)]
public async Task < IActionResult > Update ( [ FromRoute ] Guid id , [ FromBody ] JobGroupRequest request )
{
var resultValidate = await validator . ValidateAsync ( request ) ;
if ( ! resultValidate . IsValid )
return BadRequest ( new Response ( resultValidate . Errors ) ) ;
var orig = await groupService . Get ( )
2025-09-04 14:51:51 +10:00
. Include ( t = > t . Jobs )
2025-07-01 17:20:48 +10:00
. ThenInclude ( t = > t . Tnk )
2025-09-04 14:51:51 +10:00
. Include ( t = > t . EsppSchValues )
2026-01-23 16:18:56 +10:00
. Include ( t = > t . DistributionConfig ) . ThenInclude ( t = > t . DistributionPeriod )
2025-07-01 17:20:48 +10:00
. FirstOrDefaultAsync ( t = > t . Id = = id ) ;
if ( orig = = null )
return BadRequest ( new Response ( false , new List < ErrorModel > { new ErrorModel { Message = $"Ошибка при изменении группы заданий на выполнение работ. Н е найдена группа с Id: {id}" } } ) ) ;
2026-02-27 16:37:52 +10:00
//Расписание было изменено, ниже добавим задание в очередь на обновление расписаний у связанных шаблонов
2025-09-04 14:51:51 +10:00
var isScheduleChanged = IsScheduleChanged ( orig , request ) ;
2025-07-01 17:20:48 +10:00
orig . GroupName = request . Name . Trim ( ) ;
2025-11-17 12:06:33 +10:00
//orig.IsUmbrella = request.IsUmbrella;
orig . GroupTypeId = request . GroupTypeId ;
2025-12-19 10:48:41 +10:00
orig . GroupingUnitFieldId = await GetGroupingUnitFieldIdAsync ( request ) ;
2025-07-01 17:20:48 +10:00
orig . ShortDescription = request . ShortDescription . Trim ( ) ;
orig . FullDescription = request . FullDescription . Trim ( ) ;
orig . Solution = request . Solution . Trim ( ) ;
orig . TemplateDuration = request . TemplateDuration . Trim ( ) ;
orig . ReferenceDate = request . ReferenceDate ;
2026-02-09 15:48:30 +10:00
orig . UserTimeZoneOffsetMinutes = request . UserTimeZoneOffsetMinutes ;
2025-12-26 11:21:45 +10:00
orig . ScheduleExcludeTypeId = request . ScheduleExcludeTypeId ;
orig . ScheduleExcludeTypeCalendarId = request . ScheduleExcludeTypeCalendarId ;
2026-01-23 16:18:56 +10:00
orig . IsAutoDistributionEnabled = request . IsAutoDistributionEnabled ;
2026-02-03 16:15:19 +10:00
orig . IsResponseAreaTimezone = request . IsWorkGroupTimezone ;
2026-03-20 15:50:00 +10:00
// IsGroupByResponsible - может быть значение, только если тип ГРУППОВОЙ
orig . IsGroupByResponsible = await GetIsGroupByResponsibleValue ( request ) ;
2025-09-05 10:33:52 +10:00
//orig.IsAgent = request.IsAgent;
//orig.AgentName = request.AgentName;
//orig.AgentTimeOutSec = request.AgentTimeOutSec;
//orig.AgentScript = request.AgentScript;
2026-01-23 16:18:56 +10:00
#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
2025-09-04 14:51:51 +10:00
//обновляем планировщик
orig . EsppSchValues . Clear ( ) ;
request . Schedule . ForEach ( item = >
{
orig . EsppSchValues . Add ( new EsppSchValue
{
JobGroupId = orig . Id ,
TypeConfigId = item . TypeConfigId ,
TypeValueId = item . TypeValueId
} ) ;
} ) ;
2025-07-01 17:20:48 +10:00
if ( ! await groupService . CommitAsync ( ) )
return BadRequest ( new Response ( false , new List < ErrorModel > { new ErrorModel { Message = "Ошибка при изменении группы заданий на выполнение работ." } } ) ) ;
logger . LogInformation ( $"Пользователь {User.Identity?.Name} обновил группу заданий на выполнение работ: {orig.Id}," +
2025-11-25 12:26:24 +10:00
$" {orig.GroupName}, {orig.ShortDescription}, {orig.FullDescription}," +
2025-07-01 17:20:48 +10:00
$" {orig.Solution}, {orig.TemplateDuration}, {orig.ReferenceDate}, {orig.IsAutoDistributionEnabled}" +
$", {orig.IsAgent}, {orig.AgentName}, {orig.AgentTimeOutSec}, {orig.AgentScript}" ) ;
2025-09-04 14:51:51 +10:00
2026-02-27 16:37:52 +10:00
#region р а с п и с а н и е б ы л о и з м е н е н о , о т п р а в и м з а д а н и е н а п е р е р а с ч е т nextRun
if ( isScheduleChanged )
{
// расписание было изменено, отправим задание на перерасчет nextRun
var requestToMq = new NextRunUpdateMq
{
JobGroupId = id ,
Initiator = new HistoryInitiator { InitiatorComment = "Изменилось расписание группы работ в ГУИ, отправлен запрос на перерасчет nextRun" , InitiatorParrComponentId = ParrComponentsEnum . Api }
} ;
var sendResult = await mqService . SendAsync ( mqSettings . NextRun , new List < object > { requestToMq } ) ;
2025-09-04 14:51:51 +10:00
2026-02-27 16:37:52 +10:00
if ( sendResult . IsSuccess )
logger . LogInformation ( "Задание на перерасчет NextRun успешно отправлено в очередь MQ {queueName}" , mqSettings . NextRun . QueueName ) ;
else
logger . LogError ( "Ошибка при отправке задания на перерасчет NextRun в очередь MQ {queueName}" , mqSettings . NextRun . QueueName ) ;
}
#endregion
2025-09-04 14:51:51 +10:00
2025-07-01 17:20:48 +10:00
var updatedJobGroup = await groupService . Get ( )
. Include ( t = > t . Jobs )
. ThenInclude ( t = > t . Tnk )
2025-11-17 12:06:33 +10:00
. Include ( t = > t . GroupType )
2025-12-19 10:48:41 +10:00
. Include ( t = > t . GroupingUnitField )
2025-12-26 11:21:45 +10:00
. Include ( t = > t . ScheduleExcludeType )
. Include ( t = > t . ScheduleExcludeTypeCalendar )
2026-01-22 14:05:48 +10:00
. Include ( t = > t . DistributionConfig ) . ThenInclude ( t = > t . DistributionPeriod )
2025-07-01 17:20:48 +10:00
. FirstAsync ( t = > t . Id = = orig . Id ) ;
2025-09-04 14:51:51 +10:00
var response = mapper . Map < JobGroupResponse > ( updatedJobGroup ) ;
2025-12-26 13:50:30 +10:00
await AppendMissingDataAsync ( response ) ;
2025-07-01 17:20:48 +10:00
2025-09-04 14:51:51 +10:00
return Ok ( new Response < JobGroupResponse > ( response , true ) ) ;
2025-07-01 17:20:48 +10:00
}
/// <summary>
2025-09-09 17:19:41 +10:00
/// Удалить группу заданий на выполнение работ (только если нет связанных заданий)
2025-07-01 17:20:48 +10:00
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
2025-09-09 10:44:33 +10:00
[HttpDelete(ApiRoutes.JobGroup.Delete)]
public async Task < IActionResult > Delete ( [ FromRoute ] Guid id )
{
var jobGroup = await groupService . Get ( )
. FirstOrDefaultAsync ( t = > t . Id = = id ) ;
if ( jobGroup = = null )
return BadRequest ( new Response ( false , new List < ErrorModel > { new ErrorModel {
Message = $"Ошибка при удалении группы заданий на выполнение работ. Н е найдена группа заданий на выполнение работ Id: {id}"
} } ) ) ;
var jobCount = await jobService . Get ( ) . CountAsync ( t = > t . GroupId = = id ) ;
if ( jobCount > 0 )
return BadRequest ( new Response ( false , new List < ErrorModel > { new ErrorModel {
Message = $"Ошибка при удалении группы заданий на выполнение работ. С данным группой связаны задания: {jobCount} шт."
} } ) ) ;
if ( ! groupService . Delete ( jobGroup ) | | ! await groupService . CommitAsync ( ) )
return BadRequest ( new Response ( false , new List < ErrorModel > { new ErrorModel {
Message = $"Ошибка при удалении группы заданий на выполнение работ"
} } ) ) ;
logger . LogInformation ( $"Пользователь {User.Identity?.Name} удалил группу заданий на выполнение работ: {jobGroup.Id},{jobGroup.GroupName}," +
2025-11-25 12:26:24 +10:00
$" {jobGroup.ShortDescription}, {jobGroup.FullDescription}," +
$" {jobGroup.Solution}, {jobGroup.TemplateDuration}, {jobGroup.ReferenceDate}," +
$" {jobGroup.IsAutoDistributionEnabled}, {jobGroup.IsAgent}, {jobGroup.AgentName}," +
$" {jobGroup.AgentTimeOutSec}, {jobGroup.AgentScript}" ) ;
2025-09-09 10:44:33 +10:00
return NoContent ( ) ;
}
2025-09-04 14:51:51 +10:00
/// <summary>
/// Проверка, были ли изменения в расписании
/// </summary>
/// <param name="orig"></param>
/// <param name="request"></param>
/// <returns></returns>
private bool IsScheduleChanged ( JobGroup orig , JobGroupRequest request )
2025-07-01 17:20:48 +10:00
{
2025-09-04 14:51:51 +10:00
var isScheduleChanged = false ;
2025-07-01 17:20:48 +10:00
2025-09-04 14:51:51 +10:00
if ( orig . ReferenceDate ! = request . ReferenceDate )
isScheduleChanged = true ;
if ( request . Schedule . Count ( ) ! = orig . EsppSchValues . Count ( ) )
isScheduleChanged = true ;
2026-02-27 16:37:52 +10:00
if ( request . IsAutoDistributionEnabled ! = orig . IsAutoDistributionEnabled )
isScheduleChanged = true ;
if ( request . DistributionConfig ? . DistributionPeriodId ! = orig . DistributionConfig ? . DistributionPeriodId )
isScheduleChanged = true ;
if ( request . DistributionConfig ? . IsExcludeWeekends ! = orig . DistributionConfig ? . IsExcludeWeekends )
isScheduleChanged = true ;
if ( request . DistributionConfig ? . IsGroupingByWorkGroup ! = orig . DistributionConfig ? . IsGroupingByWorkGroup )
isScheduleChanged = true ;
if ( request . ScheduleExcludeTypeId ! = orig . ScheduleExcludeTypeId )
isScheduleChanged = true ;
if ( request . ScheduleExcludeTypeCalendarId ! = orig . ScheduleExcludeTypeCalendarId )
isScheduleChanged = true ;
if ( request . IsWorkGroupTimezone ! = orig . IsResponseAreaTimezone )
isScheduleChanged = true ;
if ( request . UserTimeZoneOffsetMinutes ! = orig . UserTimeZoneOffsetMinutes )
isScheduleChanged = true ;
2025-09-04 14:51:51 +10:00
request . Schedule . ForEach ( requestSchedule = >
{
var schExist = orig . EsppSchValues . FirstOrDefault ( t = > t . JobGroupId = = orig . Id
& & t . TypeValueId = = requestSchedule . TypeValueId
& & t . TypeConfigId = = requestSchedule . TypeConfigId ) ;
if ( schExist = = null )
isScheduleChanged = true ;
} ) ;
return isScheduleChanged ;
2025-07-01 17:20:48 +10:00
}
2025-09-09 17:19:41 +10:00
2025-12-26 13:50:30 +10:00
/// <summary>
2026-01-16 11:04:26 +10:00
/// Заполнить обязательные поля
2025-12-26 13:50:30 +10:00
/// </summary>
/// <param name="jobGroupResponse"></param>
/// <returns></returns>
2025-09-09 17:19:41 +10:00
private async Task AppendMissingDataAsync ( JobGroupResponse jobGroupResponse )
{
var schedule = await esppConfigService . GetEsppScheduleDtoAsync ( jobGroupResponse . Id ) ;
if ( schedule = = null )
{
logger . LogError ( $"Н е смог замапить расписание, так как оно null. JobGroupId: {jobGroupResponse.Id}" ) ;
return ;
}
var scheduleResponse = new JobGroupScheduleResponse
{
2026-02-03 16:15:19 +10:00
//Timezone = settingsFromDb.ScheduleTimezone,
Timezone = scheduleResponseAreaTimeOffsetService . GetDefault . EsppValue ,
2025-09-09 17:19:41 +10:00
TypeSchedule = mapper . Map < EsppScheduleTypeScheduleResponse > ( schedule . TypeSchedule ) ,
Values = mapper . Map < List < EsppScheduleValResponse > > ( schedule . Values ) . OrderBy ( t = > t . Order ) . ToList ( )
} ;
jobGroupResponse . Schedule = scheduleResponse ;
jobGroupResponse . JobsCount = await jobService . Get ( ) . CountAsync ( t = > t . GroupId = = jobGroupResponse . Id ) ;
2026-01-16 11:04:26 +10:00
jobGroupResponse . MatchingStatus = await GetMatchingStatusAsync ( jobGroupResponse . Id ) ;
2025-12-19 10:48:41 +10:00
}
2026-03-20 15:50:00 +10:00
/// <summary>
/// Получить значение IsGroupByResponsible из реквеста
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
private async Task < bool? > GetIsGroupByResponsibleValue ( JobGroupRequest request )
{
// IsGroupByResponsible - может быть значение, только если тип ГРУППОВОЙ
if ( ! request . IsGroupByResponsible . HasValue )
return null ;
// Если есть значение, смотрим, групповой ли тип работ, и если нет, то вернем null
var groupingType = await jobGroupTypeService . Get ( ) . FirstAsync ( t = > t . Code = = JobGroupTypesEnum . Group ) ;
if ( request . GroupTypeId = = groupingType . Id )
{
// это групповой тип работ, все ок
return request . IsGroupByResponsible ;
}
else
{
// Это не сгруппированный тип, обнуляем IsGroupByResponsible
logger . LogInformation ( "При сохраненни JobGroup, был передан IsGroupByResponsible: {IsGroupByResponsible}, но при этом, тип группы не сгруппированный, а GroupTypeId: {GroupTypeId}, обнулил IsGroupByResponsible" ,
request . IsGroupByResponsible , request . GroupTypeId ) ;
return null ;
}
}
2025-12-19 10:48:41 +10:00
/// <summary>
/// Смотрим на тип Группы, и возвращаем GroupingUnitFieldId или обнуляем е г о
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
private async Task < Guid ? > GetGroupingUnitFieldIdAsync ( JobGroupRequest request )
{
// Если request.GroupingUnitFieldId == null, то ничего проверять не будем
if ( request . GroupingUnitFieldId = = null )
return request . GroupingUnitFieldId ;
2025-09-09 17:19:41 +10:00
2025-12-19 10:48:41 +10:00
var groupingType = await jobGroupTypeService . Get ( ) . FirstAsync ( t = > t . Code = = JobGroupTypesEnum . Group ) ;
if ( request . GroupTypeId = = groupingType . Id )
{
// Это сгруппированный тип, все ок
return request . GroupingUnitFieldId ;
}
else
{
// Это не сгруппированный тип, обнуляем GroupingUnitFieldId
2026-03-20 15:50:00 +10:00
logger . LogInformation ( "При сохраненни JobGroup, был передан GroupingUnitFieldId: {GroupingUnitFieldId}, но при этом, тип группы не сгруппированный, а GroupTypeId: {GroupTypeId}, обнулил GroupingUnitFieldId" ,
request . GroupingUnitFieldId , request . GroupTypeId ) ;
2025-12-19 10:48:41 +10:00
return null ;
}
2025-09-09 17:19:41 +10:00
}
2026-01-16 11:04:26 +10:00
/// <summary>
/// Получить статус matching`a
/// </summary>
/// <param name="jobGroupId"></param>
/// <returns></returns>
private async Task < MatchingStatusResponse ? > GetMatchingStatusAsync ( Guid jobGroupId )
{
var statusMatching = await matchingStatusService . GetStatusAsync ( jobGroupId , SyncTaskEntityTypeEnum . JobGroup ) ;
return mapper . Map < MatchingStatusResponse > ( statusMatching ) ;
}
2026-01-23 16:18:56 +10:00
/// <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
} ;
}
2025-07-01 17:20:48 +10:00
}
}