2023-10-17 09:42:18 +10:00
|
|
|
|
using Microsoft.Extensions.Logging;
|
2023-10-18 10:09:51 +10:00
|
|
|
|
using PARR.DAL.Contracts;
|
2023-10-17 09:42:18 +10:00
|
|
|
|
using PARR.DAL.DomainModels;
|
2023-10-23 13:45:43 +10:00
|
|
|
|
using PARR.DAL.Extensions;
|
2023-10-17 09:42:18 +10:00
|
|
|
|
using PARR.DAL.Services.Interfaces;
|
|
|
|
|
|
|
|
|
|
|
|
namespace PARR.DAL.TransformServices
|
|
|
|
|
|
{
|
|
|
|
|
|
internal class EsppScheduleTransformService : IEsppScheduleTransformService
|
|
|
|
|
|
{
|
|
|
|
|
|
private readonly IEsppSchTypeConfigService esppSchTypeConfigService;
|
|
|
|
|
|
private readonly ILogger<EsppScheduleTransformService> logger;
|
|
|
|
|
|
|
2023-10-19 09:14:19 +10:00
|
|
|
|
private readonly Dictionary<string, int> monthDict = new Dictionary<string, int>()
|
|
|
|
|
|
{
|
|
|
|
|
|
{ "Январь", 1 },
|
|
|
|
|
|
{ "Февраль", 2 },
|
|
|
|
|
|
{ "Март", 3 },
|
|
|
|
|
|
{ "Апрель", 4 },
|
|
|
|
|
|
{ "Май", 5 },
|
|
|
|
|
|
{ "Июнь", 6 },
|
|
|
|
|
|
{ "Июль", 7 },
|
|
|
|
|
|
{ "Август", 8 },
|
|
|
|
|
|
{ "Сентябрь", 9 },
|
|
|
|
|
|
{ "Октябрь", 10 },
|
|
|
|
|
|
{ "Ноябрь", 11 },
|
|
|
|
|
|
{ "Декабрь", 12 }
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
private readonly Dictionary<string, int> orderDict = new Dictionary<string, int>()
|
|
|
|
|
|
{
|
|
|
|
|
|
{ "Первый", 1 },
|
|
|
|
|
|
{ "Второй", 2 },
|
|
|
|
|
|
{ "Третий", 3 },
|
|
|
|
|
|
{ "Четвертый", 4 },
|
|
|
|
|
|
{ "Последний", 5 }
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
private readonly Dictionary<string, int> dwDict = new Dictionary<string, int>()
|
|
|
|
|
|
{
|
|
|
|
|
|
{"Понедельник", 1 },
|
|
|
|
|
|
{"Вторник", 2 },
|
|
|
|
|
|
{"Среда", 3 },
|
|
|
|
|
|
{"Четверг", 4 },
|
|
|
|
|
|
{"Пятница", 5 },
|
|
|
|
|
|
{"Суббота", 6 },
|
|
|
|
|
|
{"Воскресенье", 0 }
|
|
|
|
|
|
};
|
2024-02-05 16:05:02 +10:00
|
|
|
|
|
|
|
|
|
|
public EsppScheduleTransformService(
|
|
|
|
|
|
IEsppSchTypeConfigService esppSchTypeConfigService,
|
|
|
|
|
|
ILogger<EsppScheduleTransformService> logger
|
|
|
|
|
|
)
|
2023-10-17 09:42:18 +10:00
|
|
|
|
{
|
|
|
|
|
|
this.esppSchTypeConfigService = esppSchTypeConfigService;
|
|
|
|
|
|
this.logger = logger;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public DateTimeOffset GetNextDate(EsppScheduleDto esppSchedule, DateTimeOffset lastRun)
|
|
|
|
|
|
{
|
|
|
|
|
|
//todo:
|
2023-10-18 10:09:51 +10:00
|
|
|
|
//если больше текущего вернуть lastRun. Это и есть следующая дата
|
|
|
|
|
|
if (lastRun > DateTimeOffset.UtcNow)
|
|
|
|
|
|
return lastRun;
|
2023-10-23 13:45:43 +10:00
|
|
|
|
|
2023-10-18 10:09:51 +10:00
|
|
|
|
switch (esppSchedule.TypeSchedule.Id)
|
|
|
|
|
|
{
|
2023-10-23 11:04:12 +10:00
|
|
|
|
case (int)EsppSchTypeScheduleEnum.Regularly:
|
|
|
|
|
|
return GetNextDateRegularly(esppSchedule.Values, lastRun);
|
2023-10-19 09:14:19 +10:00
|
|
|
|
case (int)EsppSchTypeScheduleEnum.Weekly:
|
|
|
|
|
|
return GetNextDateWeekly(esppSchedule.Values, lastRun);
|
|
|
|
|
|
case (int)EsppSchTypeScheduleEnum.Monthly:
|
|
|
|
|
|
return GetNextDateMonthly(esppSchedule.Values, lastRun);
|
|
|
|
|
|
case (int)EsppSchTypeScheduleEnum.Monthly2:
|
|
|
|
|
|
return GetNextDateMonthly2(esppSchedule.Values, lastRun);
|
|
|
|
|
|
case (int)EsppSchTypeScheduleEnum.Annually:
|
|
|
|
|
|
return GetNextDateAnnually(esppSchedule.Values, lastRun);
|
2023-10-18 10:09:51 +10:00
|
|
|
|
case (int)EsppSchTypeScheduleEnum.Annually2:
|
|
|
|
|
|
return GetNextDateAnnually2(esppSchedule.Values, lastRun);
|
|
|
|
|
|
}
|
|
|
|
|
|
return lastRun;//todo убрать lastrun должен возвращать реальный результат
|
2023-10-17 09:42:18 +10:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public List<DateTimeOffset> GetNextSchedule(EsppScheduleDto esppSchedule, DateTimeOffset lastRun)
|
|
|
|
|
|
{
|
2023-10-18 10:09:51 +10:00
|
|
|
|
// расписание на оставшееся на сегодня время. его так мало...
|
2023-11-28 11:59:26 +10:00
|
|
|
|
lastRun = lastRun.UtcDateTime;
|
2023-10-17 09:42:18 +10:00
|
|
|
|
var schedules = new List<DateTimeOffset>();
|
2023-10-23 13:45:43 +10:00
|
|
|
|
var curTime = lastRun;
|
2023-11-28 11:59:26 +10:00
|
|
|
|
|
|
|
|
|
|
//Если ещё не произошло то добавляем расписание, возможно это новое AiW и он ещё ниразу не запускался.
|
|
|
|
|
|
//lastRun это будущее
|
|
|
|
|
|
if (lastRun >= DateTimeOffset.UtcNow && lastRun <= DateTimeOffset.UtcNow.EndOfDay())
|
|
|
|
|
|
schedules.Add(lastRun);
|
|
|
|
|
|
|
2023-10-23 13:45:43 +10:00
|
|
|
|
while (curTime < DateTimeOffset.UtcNow.EndOfDay())
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (esppSchedule.TypeSchedule.Id)
|
|
|
|
|
|
{
|
|
|
|
|
|
case (int)EsppSchTypeScheduleEnum.Regularly:
|
|
|
|
|
|
curTime = GetNextDateRegularly(esppSchedule.Values, curTime);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case (int)EsppSchTypeScheduleEnum.Weekly:
|
|
|
|
|
|
curTime = GetNextDateWeekly(esppSchedule.Values, curTime);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case (int)EsppSchTypeScheduleEnum.Monthly:
|
|
|
|
|
|
curTime = GetNextDateMonthly(esppSchedule.Values, curTime);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case (int)EsppSchTypeScheduleEnum.Monthly2:
|
|
|
|
|
|
curTime = GetNextDateMonthly2(esppSchedule.Values, curTime);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case (int)EsppSchTypeScheduleEnum.Annually:
|
|
|
|
|
|
curTime = GetNextDateAnnually(esppSchedule.Values, curTime);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case (int)EsppSchTypeScheduleEnum.Annually2:
|
|
|
|
|
|
curTime = GetNextDateAnnually2(esppSchedule.Values, curTime);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
schedules.Add(curTime);
|
|
|
|
|
|
}
|
|
|
|
|
|
schedules.RemoveAll(s => s > DateTimeOffset.UtcNow.EndOfDay());
|
2023-10-17 09:42:18 +10:00
|
|
|
|
|
|
|
|
|
|
return schedules.OrderBy(t => t).ToList();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public async Task<DateTimeOffset> GetNextDateAsync(Guid applicationInWorkId, DateTimeOffset lastRun)
|
|
|
|
|
|
{
|
2023-11-28 11:59:26 +10:00
|
|
|
|
return GetNextDate(await GetEsppScheduleAsync(applicationInWorkId), lastRun);
|
2023-10-17 09:42:18 +10:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public async Task<List<DateTimeOffset>> GetNextScheduleAsync(Guid applicationInWorkId, DateTimeOffset lastRun)
|
|
|
|
|
|
{
|
2023-11-28 11:59:26 +10:00
|
|
|
|
var esppSchedule = await GetEsppScheduleAsync(applicationInWorkId);
|
2023-11-27 16:42:15 +10:00
|
|
|
|
var nextSchedule = GetNextSchedule(esppSchedule, lastRun);
|
|
|
|
|
|
|
|
|
|
|
|
return nextSchedule;
|
2023-10-17 09:42:18 +10:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-11-28 11:59:26 +10:00
|
|
|
|
private async Task<EsppScheduleDto> GetEsppScheduleAsync(Guid applicationInWorkId)
|
2023-10-17 09:42:18 +10:00
|
|
|
|
{
|
|
|
|
|
|
var esppSchedule = await esppSchTypeConfigService.GetEsppScheduleDtoAsync(applicationInWorkId);
|
|
|
|
|
|
if (esppSchedule == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
logger.LogError($"Не найдено расписание в БД, applicationInWorkId: {applicationInWorkId}");
|
|
|
|
|
|
throw new Exception($"Не найдено расписание в БД, applicationInWorkId: {applicationInWorkId}");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return esppSchedule;
|
|
|
|
|
|
}
|
2023-10-18 10:09:51 +10:00
|
|
|
|
|
2023-10-23 11:04:12 +10:00
|
|
|
|
private DateTimeOffset GetNextDateRegularly(List<EsppScheduleValDto> values, DateTimeOffset lastRun)
|
|
|
|
|
|
{
|
|
|
|
|
|
var regDict = new Dictionary<string, int>
|
|
|
|
|
|
{
|
2023-10-23 13:45:43 +10:00
|
|
|
|
{"Каждый час",1},
|
2023-10-23 11:04:12 +10:00
|
|
|
|
{"Каждые 2 часа",2},
|
|
|
|
|
|
{"Каждые 3 часа", 3},
|
|
|
|
|
|
{"Каждые 4 часа", 4},
|
|
|
|
|
|
{"Каждые 6 часов", 6},
|
|
|
|
|
|
{"Каждые 12 часов", 12},
|
|
|
|
|
|
{"Ежедневно", 24},
|
|
|
|
|
|
{"Каждые 72 часа", 72},
|
|
|
|
|
|
{"Каждые 96 часов", 96},
|
|
|
|
|
|
{"Каждые 2 недели", 336},
|
|
|
|
|
|
{"Каждые 60 дней", 1440},
|
|
|
|
|
|
{"Каждые 80 дней", 1920},
|
|
|
|
|
|
{"Каждые 90 дней", 2160},
|
|
|
|
|
|
{"Каждые полгода", 4380},
|
|
|
|
|
|
{"Каждые 1,5 года", 13140},
|
|
|
|
|
|
{"Каждые 3 года", 26280},
|
|
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
var regNum = regDict[values[0].Value.Value];
|
|
|
|
|
|
|
2023-10-23 13:45:43 +10:00
|
|
|
|
var calcDay = lastRun.AddHours(regNum);
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-10-23 11:04:12 +10:00
|
|
|
|
//TODO: вот это повторяется от метода к методу
|
|
|
|
|
|
//Если итоговая дата указывает на прошлое, то повторяем расчёт и ухоим в рекурсию
|
|
|
|
|
|
if (calcDay < DateTimeOffset.UtcNow)
|
|
|
|
|
|
calcDay = GetNextDateRegularly(values, calcDay);
|
2023-10-23 13:45:43 +10:00
|
|
|
|
|
2023-10-23 11:04:12 +10:00
|
|
|
|
|
|
|
|
|
|
return calcDay;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-10-19 09:14:19 +10:00
|
|
|
|
private DateTimeOffset GetNextDateWeekly(List<EsppScheduleValDto> values, DateTimeOffset lastRun)
|
|
|
|
|
|
{
|
|
|
|
|
|
var dwNum = dwDict[values[0].Value.Value];
|
|
|
|
|
|
|
|
|
|
|
|
var calcDay = new DateTimeOffset(DateTimeOffset.UtcNow.Year, DateTimeOffset.UtcNow.Month, DateTimeOffset.UtcNow.Day, lastRun.Hour, lastRun.Minute, lastRun.Second, lastRun.Offset);
|
|
|
|
|
|
|
|
|
|
|
|
if (((int)calcDay.DayOfWeek) != dwNum)
|
|
|
|
|
|
OffsetToDayOfWeek(dwNum, ref calcDay);
|
|
|
|
|
|
|
|
|
|
|
|
//TODO: вот это повторяется от метода к методу
|
|
|
|
|
|
//Если итоговая дата указывает на прошлое, то повторяем расчёт и ухоим в рекурсию
|
|
|
|
|
|
if (calcDay < DateTimeOffset.UtcNow)
|
|
|
|
|
|
calcDay = calcDay.AddDays(7);//а вот тут что-то новенькое
|
|
|
|
|
|
|
|
|
|
|
|
return calcDay;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private DateTimeOffset GetNextDateMonthly(List<EsppScheduleValDto> values, DateTimeOffset lastRun)
|
|
|
|
|
|
{
|
2024-03-22 12:06:19 +10:00
|
|
|
|
int.TryParse(values[0].Value.Value, out int dayNum);
|
2023-10-19 09:14:19 +10:00
|
|
|
|
|
|
|
|
|
|
var calcDay = new DateTimeOffset(DateTimeOffset.UtcNow.Year, DateTimeOffset.UtcNow.Month, dayNum, lastRun.Hour, lastRun.Minute, lastRun.Second, lastRun.Offset);
|
|
|
|
|
|
|
|
|
|
|
|
//TODO: вот это повторяется от метода к методу
|
|
|
|
|
|
//Если итоговая дата указывает на прошлое, то повторяем расчёт и ухоим в рекурсию
|
|
|
|
|
|
if (calcDay < DateTimeOffset.UtcNow)
|
|
|
|
|
|
calcDay = calcDay.AddMonths(1);//и вот тут что-то новенькое
|
|
|
|
|
|
|
|
|
|
|
|
return calcDay;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private DateTimeOffset GetNextDateMonthly2(List<EsppScheduleValDto> values, DateTimeOffset lastRun)
|
|
|
|
|
|
{
|
|
|
|
|
|
var orderNum = orderDict[values[0].Value.Value];
|
|
|
|
|
|
var dwNum = dwDict[values[1].Value.Value];
|
|
|
|
|
|
|
|
|
|
|
|
var calcDay = new DateTimeOffset(DateTimeOffset.UtcNow.Year, DateTimeOffset.UtcNow.Month, 1, lastRun.Hour, lastRun.Minute, lastRun.Second, lastRun.Offset);
|
|
|
|
|
|
|
|
|
|
|
|
List<DateTimeOffset> daysList = FindAllDaysInMonth(dwNum, ref calcDay);
|
|
|
|
|
|
|
|
|
|
|
|
if (orderNum == 5)//5-последний
|
|
|
|
|
|
calcDay = daysList.Last();
|
|
|
|
|
|
else
|
|
|
|
|
|
calcDay = daysList[orderNum - 1];
|
|
|
|
|
|
|
|
|
|
|
|
//TODO: вот это повторяется от метода к методу
|
|
|
|
|
|
//Если итоговая дата указывает на прошлое, то повторяем расчёт и ухоим в рекурсию
|
|
|
|
|
|
if (calcDay < DateTimeOffset.UtcNow)
|
|
|
|
|
|
calcDay = GetNextDateAnnually2(values, calcDay);
|
|
|
|
|
|
|
|
|
|
|
|
return calcDay;
|
|
|
|
|
|
}
|
|
|
|
|
|
private DateTimeOffset GetNextDateAnnually(List<EsppScheduleValDto> values, DateTimeOffset lastRun)
|
|
|
|
|
|
{
|
|
|
|
|
|
var monthNum = monthDict[values[0].Value.Value];
|
|
|
|
|
|
int.TryParse(values[1].Value.Value, out int dayNum);
|
|
|
|
|
|
|
|
|
|
|
|
var calcDay = new DateTimeOffset(lastRun.Year + 1, monthNum, dayNum, lastRun.Hour, lastRun.Minute, lastRun.Second, lastRun.Offset);
|
|
|
|
|
|
|
|
|
|
|
|
//TODO: вот это повторяется от метода к методу
|
|
|
|
|
|
//Если итоговая дата указывает на прошлое, то повторяем расчёт и ухоим в рекурсию
|
|
|
|
|
|
if (calcDay < DateTimeOffset.UtcNow)
|
|
|
|
|
|
calcDay = GetNextDateAnnually(values, calcDay);
|
|
|
|
|
|
|
|
|
|
|
|
return calcDay;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-10-18 10:09:51 +10:00
|
|
|
|
private DateTimeOffset GetNextDateAnnually2(List<EsppScheduleValDto> values, DateTimeOffset lastRun)
|
|
|
|
|
|
{
|
2023-10-19 09:14:19 +10:00
|
|
|
|
var monthADict = new Dictionary<string, int>
|
|
|
|
|
|
{
|
|
|
|
|
|
{ "Января", 1 },
|
|
|
|
|
|
{ "Февраля", 2 },
|
|
|
|
|
|
{ "Марта", 3 },
|
|
|
|
|
|
{ "Апреля", 4 },
|
|
|
|
|
|
{ "Мая", 5 },
|
|
|
|
|
|
{ "Июня", 6 },
|
|
|
|
|
|
{ "Июля", 7 },
|
|
|
|
|
|
{ "Августа", 8 },
|
|
|
|
|
|
{ "Сентября", 9 },
|
|
|
|
|
|
{ "Октября", 10 },
|
|
|
|
|
|
{ "Ноября", 11 },
|
|
|
|
|
|
{ "Декабря", 12 }
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
var monthNum = monthADict[values[2].Value.Value];
|
2023-10-18 10:09:51 +10:00
|
|
|
|
var orderNum = orderDict[values[0].Value.Value];
|
|
|
|
|
|
var dwNum = dwDict[values[1].Value.Value];
|
|
|
|
|
|
|
|
|
|
|
|
var calcDay = new DateTimeOffset(lastRun.Year + 1, monthNum, 1, lastRun.Hour, lastRun.Minute, lastRun.Second, lastRun.Offset);
|
|
|
|
|
|
|
2023-10-19 09:14:19 +10:00
|
|
|
|
List<DateTimeOffset> daysList = FindAllDaysInMonth(dwNum, ref calcDay);
|
2023-10-18 10:09:51 +10:00
|
|
|
|
|
2023-10-19 09:14:19 +10:00
|
|
|
|
if (orderNum == 5)//5-последний
|
|
|
|
|
|
calcDay = daysList.Last();
|
|
|
|
|
|
else
|
|
|
|
|
|
calcDay = daysList[orderNum];
|
2023-10-18 10:09:51 +10:00
|
|
|
|
|
2023-10-19 09:14:19 +10:00
|
|
|
|
//TODO: вот это повторяется от метода к методу
|
|
|
|
|
|
//Если итоговая дата указывает на прошлое, то повторяем расчёт и ухоим в рекурсию
|
|
|
|
|
|
if (calcDay < DateTimeOffset.UtcNow)
|
|
|
|
|
|
calcDay = GetNextDateAnnually2(values, calcDay);
|
|
|
|
|
|
|
|
|
|
|
|
return calcDay;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private List<DateTimeOffset> FindAllDaysInMonth(int dwNum, ref DateTimeOffset calcDay)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (((int)calcDay.DayOfWeek) != dwNum)
|
|
|
|
|
|
OffsetToDayOfWeek(dwNum, ref calcDay);
|
2023-10-18 10:09:51 +10:00
|
|
|
|
|
|
|
|
|
|
var daysList = new List<DateTimeOffset>();
|
2023-10-19 09:14:19 +10:00
|
|
|
|
var monthNum = calcDay.Month;
|
2023-10-18 10:09:51 +10:00
|
|
|
|
while (calcDay.Month == monthNum)
|
|
|
|
|
|
{
|
|
|
|
|
|
daysList.Add(calcDay);
|
|
|
|
|
|
calcDay = calcDay.AddDays(7);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-10-19 09:14:19 +10:00
|
|
|
|
return daysList;
|
2023-10-18 10:09:51 +10:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-10-23 11:04:12 +10:00
|
|
|
|
private void OffsetToDayOfWeek(int dwNum, ref DateTimeOffset calcDay)
|
2023-10-19 09:14:19 +10:00
|
|
|
|
{
|
|
|
|
|
|
var daysOffset = dwNum - ((int)calcDay.DayOfWeek);
|
|
|
|
|
|
|
|
|
|
|
|
if (daysOffset < 0)
|
|
|
|
|
|
daysOffset = 7 + daysOffset;
|
|
|
|
|
|
|
|
|
|
|
|
calcDay = calcDay.AddDays(daysOffset);
|
|
|
|
|
|
}
|
2023-10-17 09:42:18 +10:00
|
|
|
|
}
|
|
|
|
|
|
}
|