using _0_Framework.Application; using AccountManagement.Application.Contracts.Task; using AccountManagement.Application.Contracts.TaskSchedule; using AccountManagement.Domain.TaskScheduleAgg; using System; using System.IO; using System.Linq; using System.Threading.Tasks; using System.Transactions; using AccountManagement.Domain.TaskAgg; using Company.Domain.HolidayItemAgg; namespace AccountManagement.Application; public class TaskScheduleApplication : ITaskScheduleApplication { private readonly ITaskApplication _taskApplication; private readonly ITaskScheduleRepository _taskScheduleRepository; private readonly IHolidayItemRepository _holidayItemRepository; private readonly ITaskRepository _taskRepository; public TaskScheduleApplication(ITaskApplication taskApplication, ITaskScheduleRepository taskScheduleRepository, IHolidayItemRepository holidayItemRepository, ITaskRepository taskRepository) { _taskApplication = taskApplication; _taskScheduleRepository = taskScheduleRepository; _holidayItemRepository = holidayItemRepository; _taskRepository = taskRepository; } public OperationResult Create(CreateTask command) { OperationResult operation = new OperationResult(); if (command.HasSchedule) { switch (command.ScheduleType) { case TaskScheduleType.Limited: if (Convert.ToInt32(command.ScheduleCount) > 60) { return operation.Failed("تعداد وارد شده بیشتر از حد مجاز است"); } return CreateLimitedTasks(command); break; case TaskScheduleType.Unlimited: return CreateUnlimitedTasks(command); break; default: return operation.Failed("نوع وظیفه محول شده مشخص نمیباشد"); } } else { return operation.Failed("این تسک بصورت دوره ای نمیباشد"); } } public async Task GetDetails(long id) { return await _taskScheduleRepository.GetDetails(id); } public OperationResult Remove(long taskScheduleId) { var op = new OperationResult(); var taskSchedule = _taskScheduleRepository.Get(taskScheduleId); if (taskSchedule == null) return op.Failed("وظیفه مورد نظر یافت نشد"); var tasks = _taskRepository.GetTasksByTaskScheduleId(taskScheduleId); var assigns = tasks.SelectMany(x => x.Assigns); if (assigns.Any(x => x.IsCanceledRequest || x.IsDone || x.IsCancel || x.TimeRequest || x.AcceptedTimeRequest > 0)) { taskSchedule.DeActive(); var removableTask = tasks.Where(x=>x.Assigns.All(a=>a.IsDone==false && a.IsCancel == false)).ToList(); _taskRepository.RemoveRange(removableTask); } else { _taskScheduleRepository.Remove(taskSchedule); _taskRepository.RemoveRange(tasks); } _taskRepository.SaveChanges(); return op.Succcedded(); } private OperationResult CreateLimitedTasks(CreateTask command) { OperationResult operation = new OperationResult(); if (Convert.ToInt32(command.ScheduleCount) < 1 || string.IsNullOrWhiteSpace(command.ScheduleCount)) { return operation.Failed("تعداد وارد شده باید بیشتر از 2 باشد"); } if (string.IsNullOrWhiteSpace(command.ScheduleUnitNumber)) { return operation.Failed("لطفا تعداد بازه خود را مشخص کنید"); } switch (command.ScheduleUnitType) { case TaskScheduleUnitType.Year: if (Convert.ToInt32(command.ScheduleCount) != 1) { return operation.Failed("دوره نمیتواند بیشتر از 1 سال باشد"); } break; case TaskScheduleUnitType.Month: if (Convert.ToInt32(command.ScheduleUnitNumber) is > 12 or < 1) { return operation.Failed("بازه وارد شده نا معتبر است"); } if (Convert.ToInt32(command.ScheduleCount) is > 60 or < 1) { return operation.Failed("تعداد دفعات وارد شده نامعتبر است"); } break; case TaskScheduleUnitType.Week: if (command.ScheduleUnitNumber != "first" && command.ScheduleUnitNumber != "last") { return operation.Failed("بازه وارد شده نا معتبر است"); } break; case TaskScheduleUnitType.Day: if (Convert.ToInt32(command.ScheduleUnitNumber) is > 29 or < 1) { return operation.Failed("بازه وارد شده نا معتبر است"); } break; default: return operation.Failed("نوع بازه مشخص نمیباشد"); break; } try { //using var transaction = new TransactionScope(); DateTime previousDateRaw = command.EndTaskDate.ToEndDayOfGeorgianDateTime(); DateTime previousDateEdited = command.EndTaskDate.ToEndDayOfGeorgianDateTime(); var day = Convert.ToInt32(command.EndTaskDate.Substring(8, 2)); var month = Convert.ToInt32(command.EndTaskDate.Substring(5, 2)); var year = Convert.ToInt32(command.EndTaskDate.Substring(0, 4)); int count = Convert.ToInt32(command.ScheduleCount); bool isInt = int.TryParse(command.ScheduleUnitNumber, out int unitNumber); string kindOfWeekUnit = isInt ? "" : command.ScheduleUnitNumber; var taskSchedule = new TaskSchedule(command.ScheduleCount, command.ScheduleType, command.ScheduleUnitType, command.ScheduleUnitNumber, previousDateEdited); _taskScheduleRepository.Create(taskSchedule); _taskScheduleRepository.SaveChanges(); command.TaskScheduleId = taskSchedule.id; switch (command.ScheduleUnitType) { case TaskScheduleUnitType.Year: for (int i = 1; i <= count; i++) { command.EndTaskDate = previousDateEdited.ToFarsi(); operation = _taskApplication.CreateTask(command); taskSchedule.SetLastEndTaskDate(previousDateEdited); bool isHoliday = _holidayItemRepository.GetHoliday(previousDateRaw); while (isHoliday || previousDateEdited.DayOfWeek == DayOfWeek.Friday) { previousDateEdited = previousDateRaw.AddDays(1); isHoliday = _holidayItemRepository.GetHoliday(previousDateEdited); } previousDateRaw = previousDateRaw.AddYears(unitNumber); previousDateEdited = previousDateRaw; } break; case TaskScheduleUnitType.Month: bool endOfMonth = day == 31; if (endOfMonth) { for (int i = 1; i <= count; i++) { command.EndTaskDate = previousDateEdited.ToFarsi(); operation = _taskApplication.CreateTask(command); taskSchedule.SetLastEndTaskDate(previousDateEdited); if (month >= 12) { var extra = month - 12; year++; month = extra + unitNumber; } else { month = unitNumber + month; } previousDateRaw = $"{year:0000}/{month:00}/01".FindeEndOfMonth().ToGeorgianDateTime(); bool isHoliday = _holidayItemRepository.GetHoliday(previousDateRaw); while (isHoliday || previousDateEdited.DayOfWeek == DayOfWeek.Friday) { previousDateEdited = previousDateRaw.AddDays(1); isHoliday = _holidayItemRepository.GetHoliday(previousDateEdited); } previousDateEdited = previousDateRaw; } } else { for (int i = 1; i < count; i++) { command.EndTaskDate = previousDateEdited.ToFarsi(); operation = _taskApplication.CreateTask(command); taskSchedule.SetLastEndTaskDate(previousDateEdited); var endDay = 0; if (month >= 12) { var extra = month - 12; year++; month = extra + unitNumber; } else { month = unitNumber + month; } if (day == 30) { if (month == 12) { var lastYearDay = Convert.ToInt32($"{year:0000}/{month:00}/1".FindeEndOfMonth() .Substring(8, 2)); endDay = lastYearDay == 30 ? lastYearDay : 29; } } previousDateEdited = endDay == 0 ? $"{year:0000}/{month:00}/{day:00}".ToGeorgianDateTime() : $"{year:0000}/{month:00}/{endDay:00}".ToGeorgianDateTime(); } //for (int i = 1; i <= count; i++) //{ // command.EndTaskDate = previousDateEdited.ToFarsi(); // operation = _taskApplication.CreateTask(command); // taskSchedule.SetLastEndTaskDate(previousDateEdited); // previousDateRaw = $"{year:0000}/{month:00}/01".FindeEndOfMonth().ToGeorgianDateTime(); // bool isHoliday = _holidayItemRepository.GetHoliday(previousDateRaw); // while (isHoliday || previousDateEdited.DayOfWeek == DayOfWeek.Friday) // { // previousDateEdited = previousDateRaw.AddDays(1); // isHoliday = _holidayItemRepository.GetHoliday(previousDateEdited); // } // previousDateEdited = previousDateRaw; //} } break; case TaskScheduleUnitType.Week: for (int i = 1; i <= count; i++) { if (string.IsNullOrWhiteSpace(kindOfWeekUnit)) { throw new InvalidDataException(); } command.EndTaskDate = kindOfWeekUnit switch { "first" => previousDateRaw.GetNextDayOfWeek(DayOfWeek.Saturday).ToFarsi(), "last" => previousDateRaw.GetNextDayOfWeek(DayOfWeek.Thursday).ToFarsi(), _ => throw new InvalidDataException() }; operation = _taskApplication.CreateTask(command); taskSchedule.SetLastEndTaskDate(previousDateEdited); bool isHoliday = _holidayItemRepository.GetHoliday(previousDateRaw); while (isHoliday || previousDateEdited.DayOfWeek == DayOfWeek.Friday) { previousDateEdited = previousDateRaw.AddDays(1); isHoliday = _holidayItemRepository.GetHoliday(previousDateEdited); } previousDateRaw = command.EndTaskDate.ToGeorgianDateTime(); previousDateEdited = previousDateRaw; } break; case TaskScheduleUnitType.Day: for (int i = 1; i <= count; i++) { command.EndTaskDate = previousDateEdited.ToFarsi(); operation = _taskApplication.CreateTask(command); taskSchedule.SetLastEndTaskDate(previousDateEdited); previousDateRaw = previousDateRaw.AddDays(unitNumber); bool isHoliday = _holidayItemRepository.GetHoliday(previousDateRaw); while (isHoliday || previousDateEdited.DayOfWeek == DayOfWeek.Friday) { previousDateEdited = previousDateRaw.AddDays(1); isHoliday = _holidayItemRepository.GetHoliday(previousDateEdited); } previousDateEdited = previousDateRaw; } break; } _taskScheduleRepository.SaveChanges(); //transaction.Complete(); operation = operation.Succcedded(); return operation; } catch (Exception e) { return operation.Failed(e.ToString()); } } private OperationResult CreateUnlimitedTasks(CreateTask command) { using var transaction = new TransactionScope(); var lastDate = command.EndTaskDate.ToGeorgianDateTime(); var taskSchedule = new TaskSchedule(command.ScheduleCount, command.ScheduleType, command.ScheduleUnitType, command.ScheduleUnitNumber, lastDate); _taskScheduleRepository.Create(taskSchedule); _taskScheduleRepository.SaveChanges(); command.TaskScheduleId = taskSchedule.id; var operation = _taskApplication.CreateTask(command); if (!operation.IsSuccedded) return operation; _taskScheduleRepository.SaveChanges(); transaction.Complete(); return operation.Succcedded(); } }