示例#1
0
        public async Task <IActionResult> PutSesson(int sessionId, string reason, short userId)
        {
            var    result            = new Result <string>();
            var    awaitMakeUpLesson = new AwaitMakeUpLesson();
            Lesson lesson;

            try
            {
                lesson = await _ablemusicContext.Lesson.Where(x => x.LessonId == sessionId).FirstOrDefaultAsync();
            }
            catch (Exception ex)
            {
                result.IsSuccess    = false;
                result.ErrorMessage = ex.ToString();
                return(NotFound(result));
            }

            if (lesson == null)
            {
                result.IsSuccess    = false;
                result.ErrorMessage = "Session not found";
                return(NotFound(result));
            }
            if (lesson.IsCanceled == 1)
            {
                result.IsSuccess    = false;
                result.ErrorMessage = "This lesson has already been cancelled";
                return(BadRequest(result));
            }
            if (string.IsNullOrEmpty(reason))
            {
                result.IsSuccess    = false;
                result.ErrorMessage = "Reason is required";
                return(NotFound(result));
            }
            var user = await _ablemusicContext.User.Where(u => u.UserId == userId).FirstOrDefaultAsync();

            if (user == null)
            {
                result.IsSuccess    = false;
                result.ErrorMessage = "User id not found";
                return(NotFound(result));
            }

            lesson.IsCanceled = 1;
            lesson.Reason     = reason;
            //save to making up lessones to save
            awaitMakeUpLesson.MissedLessonId        = lesson.LessonId;
            awaitMakeUpLesson.LearnerId             = lesson.LearnerId;
            awaitMakeUpLesson.CourseInstanceId      = lesson.CourseInstanceId;
            awaitMakeUpLesson.GroupCourseInstanceId = lesson.GroupCourseInstanceId;
            awaitMakeUpLesson.CreateAt    = toNZTimezone(DateTime.UtcNow);
            awaitMakeUpLesson.IsActive    = 1;
            awaitMakeUpLesson.ExpiredDate = lesson.BeginTime.Value.Date.AddMonths(3);
            await _ablemusicContext.AwaitMakeUpLesson.AddAsync(awaitMakeUpLesson);


            bool           isGroupCourse = lesson.LearnerId == null;
            Teacher        teacher;
            Course         course;
            List <Holiday> holidays;

            try
            {
                teacher = await _ablemusicContext.Teacher.FirstOrDefaultAsync(t => t.TeacherId == lesson.TeacherId);

                if (lesson.IsTrial == 1)
                {
                    course = await _ablemusicContext.Course.Where(c => c.CourseId == lesson.TrialCourseId).FirstOrDefaultAsync();
                }
                else
                {
                    course = isGroupCourse ? await(from c in _ablemusicContext.Course
                                                   join gc in _ablemusicContext.GroupCourseInstance on c.CourseId equals gc.CourseId
                                                   where gc.GroupCourseInstanceId == lesson.GroupCourseInstanceId
                                                   select new Course
                    {
                        CourseId   = c.CourseId,
                        CourseName = c.CourseName
                    }).FirstOrDefaultAsync() :
                             await(from c in _ablemusicContext.Course
                                   join oto in _ablemusicContext.One2oneCourseInstance on c.CourseId equals oto.CourseId
                                   where oto.CourseInstanceId == lesson.CourseInstanceId
                                   select new Course
                    {
                        CourseId   = c.CourseId,
                        CourseName = c.CourseName
                    }).FirstOrDefaultAsync();
                }
                holidays = await _ablemusicContext.Holiday.ToListAsync();
            }
            catch (Exception e)
            {
                result.IsSuccess    = false;
                result.ErrorMessage = e.Message;
                return(NotFound(result));
            }

            if (course == null)
            {
                result.IsSuccess    = false;
                result.ErrorMessage = "Fail to found course name under this lesson";
                return(NotFound(result));
            }
            string courseName = course.CourseName;

            DateTime todoDate = lesson.BeginTime.Value.AddDays(-1);

            foreach (var holiday in holidays)
            {
                if (holiday.HolidayDate.Date == todoDate.Date)
                {
                    todoDate = todoDate.AddDays(-1);
                }
            }

            DateTime remindScheduleDate = todoDate;

            //string userConfirmUrlPrefix = "https://localhost:44304/api/session/sessioncancelconfirm/";
            string userConfirmUrlPrefix = _configuration.GetSection("UrlPrefix").Value;

            using (var dbContextTransaction = _ablemusicContext.Database.BeginTransaction())
            {
                if (!isGroupCourse)
                // Case of one to one course
                {
                    Learner learner;
                    try
                    {
                        learner = await _ablemusicContext.Learner.FirstOrDefaultAsync(l => l.LearnerId == lesson.LearnerId);
                    }
                    catch (Exception ex)
                    {
                        result.IsSuccess    = false;
                        result.ErrorMessage = ex.ToString();
                        return(NotFound(result));
                    }

                    TodoRepository todoRepository = new TodoRepository(_ablemusicContext);
                    todoRepository.AddSingleTodoList("Cancellation to Remind", TodoListContentGenerator.CancelSingleLessonForTeacher(teacher,
                                                                                                                                     lesson, reason), userId, todoDate, lesson.LessonId, null, teacher.TeacherId);
                    todoRepository.AddSingleTodoList("Cancellation to Remind", TodoListContentGenerator.CancelSingleLessonForLearner(learner,
                                                                                                                                     lesson, reason), userId, todoDate, lesson.LessonId, learner.LearnerId, null);
                    var saveTodoResult = await todoRepository.SaveTodoListsAsync();

                    if (!saveTodoResult.IsSuccess)
                    {
                        return(BadRequest(saveTodoResult));
                    }

                    RemindLogRepository remindLogRepository = new RemindLogRepository(_ablemusicContext);
                    remindLogRepository.AddSingleRemindLog(null, teacher.Email, RemindLogContentGenerator.CancelSingleLessonForTeacher(courseName,
                                                                                                                                       lesson, reason), teacher.TeacherId, "Lesson Cancellation Remind", lesson.LessonId, remindScheduleDate);
                    remindLogRepository.AddSingleRemindLog(learner.LearnerId, learner.Email, RemindLogContentGenerator.CancelSingleLessonForLearner(courseName,
                                                                                                                                                    lesson, reason), null, "Lesson Cancellation Remind", lesson.LessonId, remindScheduleDate);
                    var saveRemindLogResult = await remindLogRepository.SaveRemindLogAsync();

                    if (!saveRemindLogResult.IsSuccess)
                    {
                        return(BadRequest(saveRemindLogResult));
                    }

                    try
                    {
                        await _ablemusicContext.SaveChangesAsync();
                    }
                    catch (Exception e)
                    {
                        result.ErrorMessage = e.Message;
                        result.IsSuccess    = false;
                        return(BadRequest(result));
                    }

                    //sending Email
                    //List<NotificationEventArgs> notifications = new List<NotificationEventArgs>();
                    foreach (var todo in saveTodoResult.Data)
                    {
                        var    remind = saveRemindLogResult.Data.Find(r => r.LearnerId == todo.LearnerId && r.TeacherId == todo.TeacherId);
                        string currentPersonName;
                        if (todo.TeacherId == null)
                        {
                            currentPersonName = learner.FirstName + " " + learner.LastName;
                        }
                        else
                        {
                            currentPersonName = teacher.FirstName + " " + teacher.LastName;
                        }
                        string confirmURL  = userConfirmUrlPrefix + todo.ListId + "/" + remind.RemindId;
                        string mailContent = EmailContentGenerator.CancelLesson(currentPersonName, courseName, lesson, reason, confirmURL);
                        remindLogRepository.UpdateContent(remind.RemindId, mailContent);
                        //notifications.Add(new NotificationEventArgs(remind.Email, "Lesson Cancellation Confirm", mailContent, remind.RemindId));
                    }
                    var remindLogUpdateContentResult = await remindLogRepository.SaveUpdatedContentAsync();

                    if (!remindLogUpdateContentResult.IsSuccess)
                    {
                        result.IsSuccess    = false;
                        result.ErrorMessage = remindLogUpdateContentResult.ErrorMessage;
                        return(BadRequest(result));
                    }
                    //foreach (var mail in notifications)
                    //{
                    //    _notificationObservable.send(mail);
                    //}
                }
                else
                //Case of group course
                {
                    List <Learner> learners;
                    try
                    {
                        learners = (from lgc in _ablemusicContext.LearnerGroupCourse
                                    join l in _ablemusicContext.Learner on lgc.LearnerId equals l.LearnerId
                                    where lgc.GroupCourseInstanceId == lesson.GroupCourseInstanceId
                                    select new Learner()
                        {
                            LearnerId = l.LearnerId,
                            FirstName = l.FirstName,
                            LastName = l.LastName,
                            Email = l.Email
                        }).ToList();
                    }
                    catch (Exception ex)
                    {
                        result.IsSuccess    = false;
                        result.ErrorMessage = ex.ToString();
                        return(NotFound(result));
                    }

                    var todoForLearnersIdMapContent    = new Dictionary <int, string>();
                    var remindLogForLearnersMapContent = new Dictionary <Learner, string>();
                    foreach (var l in learners)
                    {
                        todoForLearnersIdMapContent.Add(l.LearnerId, TodoListContentGenerator.CancelSingleLessonForLearner(l, lesson, reason));
                        remindLogForLearnersMapContent.Add(l, RemindLogContentGenerator.CancelSingleLessonForLearner(courseName, lesson, reason));
                    }

                    TodoRepository todoRepository = new TodoRepository(_ablemusicContext);
                    todoRepository.AddSingleTodoList("Cancellation to Remind", TodoListContentGenerator.CancelSingleLessonForTeacher(teacher,
                                                                                                                                     lesson, reason), userId, todoDate, lesson.LessonId, null, teacher.TeacherId);
                    todoRepository.AddMutipleTodoLists("Cancellation to Remind", todoForLearnersIdMapContent, userId, todoDate, lesson.LessonId, null);
                    var saveTodoListsResult = await todoRepository.SaveTodoListsAsync();

                    if (!saveTodoListsResult.IsSuccess)
                    {
                        return(BadRequest(saveTodoListsResult));
                    }

                    RemindLogRepository remindLogRepository = new RemindLogRepository(_ablemusicContext);
                    remindLogRepository.AddSingleRemindLog(null, teacher.Email, RemindLogContentGenerator.CancelSingleLessonForTeacher(courseName,
                                                                                                                                       lesson, reason), teacher.TeacherId, "Lesson Cancellation Remind", lesson.LessonId, remindScheduleDate);
                    remindLogRepository.AddMultipleRemindLogs(remindLogForLearnersMapContent, null, "Lesson Cancellation Remind", lesson.LessonId, remindScheduleDate);
                    var saveRemindLogResult = await remindLogRepository.SaveRemindLogAsync();

                    if (!saveRemindLogResult.IsSuccess)
                    {
                        return(BadRequest(saveRemindLogResult));
                    }

                    try
                    {
                        await _ablemusicContext.SaveChangesAsync();
                    }
                    catch (Exception e)
                    {
                        result.ErrorMessage = e.Message;
                        result.IsSuccess    = false;
                        return(BadRequest(result));
                    }

                    //sending Email
                    //List<NotificationEventArgs> notifications = new List<NotificationEventArgs>();
                    foreach (var todo in saveTodoListsResult.Data)
                    {
                        var    remind = saveRemindLogResult.Data.Find(r => r.LearnerId == todo.LearnerId && r.TeacherId == todo.TeacherId);
                        string currentPersonName;
                        if (todo.TeacherId == null)
                        {
                            currentPersonName = learners.Find(l => l.LearnerId == todo.LearnerId).FirstName + " " + learners.Find(l => l.LearnerId == todo.LearnerId).LastName;
                        }
                        else
                        {
                            currentPersonName = teacher.FirstName + " " + teacher.LastName;
                        }
                        string confirmURL  = userConfirmUrlPrefix + todo.ListId + "/" + remind.RemindId;
                        string mailContent = EmailContentGenerator.CancelLesson(currentPersonName, courseName, lesson, reason, confirmURL);
                        remindLogRepository.UpdateContent(remind.RemindId, mailContent);
                        //notifications.Add(new NotificationEventArgs(remind.Email, "Lesson Cancellation Confirm", mailContent, remind.RemindId));
                    }
                    var remindLogUpdateContentResult = await remindLogRepository.SaveUpdatedContentAsync();

                    if (!remindLogUpdateContentResult.IsSuccess)
                    {
                        result.IsSuccess    = false;
                        result.ErrorMessage = remindLogUpdateContentResult.ErrorMessage;
                        return(BadRequest(result));
                    }
                    //foreach (var mail in notifications)
                    //{
                    //    _notificationObservable.send(mail);
                    //}
                }
                dbContextTransaction.Commit();
            }
            return(Ok(result));
        }
示例#2
0
        public async Task <IActionResult> Post(int userId, [FromBody] LessonViewModel lessonViewModel)
        {
            var    result               = new Result <Lesson>();
            var    lesson               = _mapper.Map(lessonViewModel, new Lesson());
            var    lessonRemains        = new List <LessonRemain>();
            var    course               = new Course();
            var    awaitMakeUpLessons   = new List <AwaitMakeUpLesson>();
            string userConfirmUrlPrefix = _configuration.GetSection("UrlPrefix").Value;

            try
            {
                lessonRemains = await _ablemusicContext.LessonRemain.Where(lr => lr.CourseInstanceId == lesson.CourseInstanceId &&
                                                                           lr.LearnerId == lesson.LearnerId).ToListAsync();

                course = await(from oto in _ablemusicContext.One2oneCourseInstance
                               join c in _ablemusicContext.Course on oto.CourseId equals c.CourseId
                               where oto.CourseInstanceId == lesson.CourseInstanceId
                               select new Course
                {
                    CourseId   = c.CourseId,
                    CourseName = c.CourseName,
                    Duration   = c.Duration,
                }).FirstOrDefaultAsync();
                awaitMakeUpLessons = await _ablemusicContext.AwaitMakeUpLesson.Where(a => a.IsActive == 1 && a.LearnerId == lesson.LearnerId &&
                                                                                     (a.CourseInstanceId.HasValue && lesson.CourseInstanceId == a.CourseInstanceId) ||
                                                                                     (a.GroupCourseInstanceId.HasValue && lesson.GroupCourseInstanceId == a.GroupCourseInstanceId))
                                     .OrderBy(a => a.ExpiredDate).ToListAsync();
            }
            catch (Exception ex)
            {
                LogErrorToFile(ex.Message);
                result.IsSuccess    = false;
                result.ErrorMessage = ex.Message;
                return(BadRequest(result));
            }
            if (lessonRemains.Count <= 0)
            {
                result.IsSuccess    = false;
                result.ErrorMessage = "Lesson Remain not found";
                return(BadRequest(result));
            }
            if (course == null)
            {
                result.IsSuccess    = false;
                result.ErrorMessage = "Course not found";
                return(BadRequest(result));
            }
            if (awaitMakeUpLessons.Count <= 0)
            {
                result.IsSuccess    = false;
                result.ErrorMessage = "AwaitMakeUpLesson not found";
                return(BadRequest(result));
            }
            AwaitMakeUpLesson validMakeUpLesson = null;

            foreach (var makeUpLesson in awaitMakeUpLessons)
            {
                if (makeUpLesson.ExpiredDate.Value.Date >= lesson.BeginTime.Value.Date)
                {
                    validMakeUpLesson = makeUpLesson;
                    break;
                }
            }
            if (validMakeUpLesson == null)
            {
                result.IsSuccess    = false;
                result.ErrorMessage = "Your lesson all expired";
                return(BadRequest(result));
            }

            TimeSpan duration;

            switch (course.Duration)
            {
            case 1: duration = TimeSpan.FromMinutes(30);
                break;

            case 2: duration = TimeSpan.FromMinutes(45);
                break;

            case 3: duration = TimeSpan.FromMinutes(60);
                break;

            default: duration = TimeSpan.FromMinutes(0);
                break;
            }
            lesson.EndTime = lesson.BeginTime.Value.Add(duration);
            int termId = 0;

            foreach (var lr in lessonRemains)
            {
                if (lr.Quantity > 0)
                {
                    termId = (int)lr.TermId;
                }
            }
            if (termId == 0)
            {
                result.IsSuccess    = false;
                result.ErrorMessage = "Lesson Remain not found";
                return(BadRequest(result));
            }

            Teacher teacher  = new Teacher();
            var     invoice  = new Invoice();
            var     holidays = new List <Holiday>();
            var     org      = new pegasusContext.Org();
            var     room     = new Room();
            var     learner  = new Learner();

            try
            {
                invoice = await _ablemusicContext.Invoice.Where(i => i.TermId == termId && i.LearnerId == lesson.LearnerId &&
                                                                i.CourseInstanceId == lesson.CourseInstanceId).FirstOrDefaultAsync();

                teacher = await _ablemusicContext.Teacher.Where(t => t.TeacherId == lesson.TeacherId).FirstOrDefaultAsync();

                org = await _ablemusicContext.Org.Where(o => o.OrgId == lesson.OrgId).FirstOrDefaultAsync();

                room = await _ablemusicContext.Room.Where(r => r.RoomId == lesson.RoomId).FirstOrDefaultAsync();

                learner = await _ablemusicContext.Learner.Where(l => l.LearnerId == lesson.LearnerId).FirstOrDefaultAsync();

                holidays = await _ablemusicContext.Holiday.ToListAsync();
            }
            catch (Exception ex)
            {
                result.IsSuccess    = false;
                result.ErrorMessage = ex.Message;
                return(BadRequest(result));
            }
            if (learner == null)
            {
                result.IsSuccess    = false;
                result.ErrorMessage = "Learner not found";
                return(BadRequest(result));
            }
            if (room == null)
            {
                result.IsSuccess    = false;
                result.ErrorMessage = "Room not found";
                return(BadRequest(result));
            }
            if (org == null)
            {
                result.IsSuccess    = false;
                result.ErrorMessage = "Org not found";
                return(BadRequest(result));
            }
            if (teacher == null)
            {
                result.IsSuccess    = false;
                result.ErrorMessage = "Teacher not found";
                return(BadRequest(result));
            }
            if (invoice == null)
            {
                result.IsSuccess    = false;
                result.ErrorMessage = "Lesson Remain not found";
                return(BadRequest(result));
            }

            var lessonConflictCheckerService = new LessonConflictCheckerService(_ablemusicContext, lesson);
            Result <List <object> > lessonConflictCheckResult;

            try
            {
                lessonConflictCheckResult = await lessonConflictCheckerService.CheckBothRoomAndTeacher();
            }
            catch (Exception ex)
            {
                result.IsSuccess    = false;
                result.ErrorMessage = ex.Message;
                return(BadRequest(result));
            }
            if (!lessonConflictCheckResult.IsSuccess)
            {
                return(BadRequest(lessonConflictCheckResult));
            }

            DateTime todoDate = lesson.BeginTime.Value.AddDays(-1);

            foreach (var holiday in holidays)
            {
                if (holiday.HolidayDate.Date == todoDate.Date)
                {
                    todoDate = todoDate.AddDays(-1);
                }
            }
            DateTime remindScheduleDate = todoDate;

            lesson.LessonId              = 0;
            lesson.IsCanceled            = 0;
            lesson.Reason                = null;
            lesson.CreatedAt             = toNZTimezone(DateTime.UtcNow);
            lesson.GroupCourseInstanceId = null;
            lesson.IsTrial               = 0;
            lesson.InvoiceNum            = invoice.InvoiceNum;
            lesson.IsConfirm             = 0;
            lesson.IsPaid                = 1;
            lesson.TrialCourseId         = null;
            lesson.IsChanged             = 0;

            validMakeUpLesson.IsActive = 0;

            using (var dbContextTransaction = _ablemusicContext.Database.BeginTransaction())
            {
                try
                {
                    await _ablemusicContext.Lesson.AddAsync(lesson);

                    await _ablemusicContext.SaveChangesAsync();

                    validMakeUpLesson.NewLessonId = lesson.LessonId;
                    await _ablemusicContext.SaveChangesAsync();
                }
                catch (Exception ex)
                {
                    result.IsSuccess    = false;
                    result.ErrorMessage = ex.Message;
                    return(BadRequest(result));
                }

                TodoRepository todoRepository = new TodoRepository(_ablemusicContext);
                todoRepository.AddSingleTodoList("Lesson Rearranged", TodoListContentGenerator.RearrangedSingleLessonWithoutOldLessonForLearner(
                                                     learner, lesson, org, room, teacher), (short)userId, todoDate, lesson.LessonId, lesson.LearnerId, null);
                todoRepository.AddSingleTodoList("Lesson Rearranged", TodoListContentGenerator.RearrangedSingleLessonWithoutOldLessonForTeacher(
                                                     learner, lesson, org, room, teacher), (short)userId, todoDate, lesson.LessonId, null, teacher.TeacherId);
                var saveTodoResult = await todoRepository.SaveTodoListsAsync();

                if (!saveTodoResult.IsSuccess)
                {
                    try
                    {
                        _ablemusicContext.Lesson.Remove(lesson);
                    }
                    catch (Exception ex)
                    {
                        result.IsSuccess    = false;
                        result.ErrorMessage = ex.Message + "\n" + saveTodoResult.ErrorMessage;
                        return(BadRequest(result));
                    }
                    return(BadRequest(saveTodoResult));
                }

                RemindLogRepository remindLogRepository = new RemindLogRepository(_ablemusicContext);
                remindLogRepository.AddSingleRemindLog(learner.LearnerId, learner.Email, RemindLogContentGenerator.RearrangedSingleLessonWithoutOldLessonForLearner(
                                                           learner, lesson, org, room, teacher), null, "Lesson Rearranged", lesson.LessonId, remindScheduleDate);
                remindLogRepository.AddSingleRemindLog(null, teacher.Email, RemindLogContentGenerator.RearrangedSingleLessonWithoutOldLessonForTeacher(
                                                           learner, lesson, org, room, teacher), teacher.TeacherId, "Lesson Rearranged", lesson.LessonId, remindScheduleDate);

                var saveRemindResult = await remindLogRepository.SaveRemindLogAsync();

                if (!saveRemindResult.IsSuccess)
                {
                    try
                    {
                        _ablemusicContext.Lesson.Remove(lesson);
                    }
                    catch (Exception ex)
                    {
                        result.IsSuccess    = false;
                        result.ErrorMessage = ex.Message + "\n" + saveRemindResult.ErrorMessage;
                        return(BadRequest(result));
                    }
                    return(BadRequest(saveRemindResult));
                }

                //sending Email
                //List<NotificationEventArgs> notifications = new List<NotificationEventArgs>();
                foreach (var todo in saveTodoResult.Data)
                {
                    var    remind = saveRemindResult.Data.Find(r => r.LearnerId == todo.LearnerId && r.TeacherId == todo.TeacherId);
                    string currentPersonName;
                    if (todo.TeacherId == null)
                    {
                        currentPersonName = learner.FirstName + " " + learner.LastName;
                    }
                    else
                    {
                        currentPersonName = teacher.FirstName + " " + teacher.LastName;
                    }
                    string confirmURL  = userConfirmUrlPrefix + todo.ListId + "/" + remind.RemindId;
                    string mailContent = EmailContentGenerator.RearrangeLesson(currentPersonName, course.CourseName, lesson, confirmURL, org, room);
                    remindLogRepository.UpdateContent(remind.RemindId, mailContent);
                    //notifications.Add(new NotificationEventArgs(remind.Email, "Lesson Rearrange Confirm", mailContent, remind.RemindId));
                }

                var remindLogUpdateContentResult = await remindLogRepository.SaveUpdatedContentAsync();

                if (!remindLogUpdateContentResult.IsSuccess)
                {
                    result.IsSuccess    = false;
                    result.ErrorMessage = remindLogUpdateContentResult.ErrorMessage;
                    return(BadRequest(result));
                }
                dbContextTransaction.Commit();

                //foreach (var mail in notifications)
                //{
                //    _notificationObservable.send(mail);
                //}
            }
            result.Data         = lesson;
            result.Data.Learner = null;
            result.Data.Org     = null;
            result.Data.Room    = null;
            result.Data.Teacher = null;
            return(Ok(result));
        }
示例#3
0
        public async Task <IActionResult> Put(int lessonId, short userId, string reason)
        {
            var            result = new Result <List <object> >();
            Lesson         lesson;
            Invoice        invoice;
            Learner        learner;
            List <Course>  courses;
            List <Lesson>  remainLessons;
            List <Holiday> holidays;
            LessonRemain   lessonRemain;

            try
            {
                lesson = await _ablemusicContext.Lesson.Where(l => l.LessonId == lessonId).FirstOrDefaultAsync();

                if (lesson == null)
                {
                    throw new Exception("Lesson not found");
                }
                invoice = await _ablemusicContext.Invoice.Where(iv => iv.InvoiceNum == lesson.InvoiceNum && iv.IsActive == 1).FirstOrDefaultAsync();

                if (invoice == null)
                {
                    throw new Exception("This session may is a group session or Trial session, this session is not allowed to reschedule");
                }
                courses = await(from c in _ablemusicContext.Course
                                join oto in _ablemusicContext.One2oneCourseInstance on c.CourseId equals oto.CourseId
                                where oto.CourseInstanceId == lesson.CourseInstanceId
                                select new Course
                {
                    CourseId   = c.CourseId,
                    CourseName = c.CourseName,
                    Duration   = c.Duration,
                }).ToListAsync();
                remainLessons = await(from l in _ablemusicContext.Lesson
                                      where l.LearnerId == lesson.LearnerId && l.CourseInstanceId == lesson.CourseInstanceId &&
                                      l.BeginTime > lesson.BeginTime && l.IsCanceled != 1
                                      select new Lesson
                {
                    LessonId              = l.LessonId,
                    LearnerId             = l.LearnerId,
                    RoomId                = l.RoomId,
                    TeacherId             = l.TeacherId,
                    OrgId                 = l.OrgId,
                    IsCanceled            = l.IsCanceled,
                    Reason                = l.Reason,
                    CreatedAt             = l.CreatedAt,
                    CourseInstanceId      = l.CourseInstanceId,
                    GroupCourseInstanceId = l.GroupCourseInstanceId,
                    IsTrial               = l.IsTrial,
                    BeginTime             = l.BeginTime,
                    EndTime               = l.EndTime,
                    InvoiceNum            = l.InvoiceNum,
                    Learner               = null,
                    Teacher               = new Teacher
                    {
                        TeacherId             = l.Teacher.TeacherId,
                        FirstName             = l.Teacher.FirstName,
                        LastName              = l.Teacher.LastName,
                        Email                 = l.Teacher.Email,
                        User                  = null,
                        AvailableDays         = null,
                        GroupCourseInstance   = null,
                        Lesson                = null,
                        One2oneCourseInstance = null,
                    },
                    CourseInstance      = null,
                    GroupCourseInstance = null,
                    Org  = null,
                    Room = null,
                }).ToListAsync();
                learner = await _ablemusicContext.Learner.Where(l => l.LearnerId == lesson.LearnerId).FirstOrDefaultAsync();

                holidays = await _ablemusicContext.Holiday.ToListAsync();

                lessonRemain = await _ablemusicContext.LessonRemain.Where(lr => lr.TermId == invoice.TermId &&
                                                                          lr.CourseInstanceId == lesson.CourseInstanceId && lr.LearnerId == lesson.LearnerId).FirstOrDefaultAsync();
            }
            catch (Exception ex)
            {
                result.IsSuccess    = false;
                result.IsFound      = false;
                result.ErrorMessage = ex.Message;
                return(NotFound(result));
            }
            if (lesson.GroupCourseInstanceId != null)
            {
                result.IsSuccess    = false;
                result.ErrorMessage = "Group course is not allowed to reschedule";
                return(BadRequest(result));
            }
            if (lesson.IsCanceled == 1)
            {
                result.IsSuccess    = false;
                result.ErrorMessage = "This lesson has been already canelled";
                return(BadRequest(result));
            }
            if (courses.Count <= 0)
            {
                result.IsSuccess    = false;
                result.ErrorMessage = "Fail to found course name under this lesson";
                return(NotFound(result));
            }
            int numOfSchedulesToBeAdd = courses[0].Duration.Value + 1;

            if (remainLessons.Count < numOfSchedulesToBeAdd)
            {
                result.IsSuccess    = false;
                result.ErrorMessage = "Not enough remain lessons to do reschedule\n" + "Remain lessons found:" +
                                      remainLessons.Count + "\nRemain lessons need:" + numOfSchedulesToBeAdd;
                result.Data = new List <object>();
                foreach (var rl in remainLessons)
                {
                    result.Data.Add(new { RemainLesson = rl });
                }
                return(BadRequest(result));
            }
            string courseName = courses[0].CourseName;

            DateTime min = remainLessons[0].BeginTime.Value;
            DateTime max = remainLessons[0].BeginTime.Value;

            foreach (var remainLesson in remainLessons)
            {
                min = remainLesson.BeginTime.Value > min ? min : remainLesson.BeginTime.Value;
                max = remainLesson.BeginTime.Value > max ? remainLesson.BeginTime.Value : max;
            }
            List <Lesson> lessonsToBeAppend = new List <Lesson>();
            int           i = numOfSchedulesToBeAdd;
            var           lessonConflictCheckerService = new LessonConflictCheckerService(_ablemusicContext, min, max);

            try
            {
                await lessonConflictCheckerService.LoadAllProtentialConflictLessonsToMemoryAsync();
            }
            catch (Exception ex)
            {
                result.IsSuccess    = false;
                result.ErrorMessage = ex.Message;
                return(BadRequest(result));
            }

            Dictionary <int, object> lessonIdMapConflictCheckResult = new Dictionary <int, object>();

            foreach (var remainLesson in remainLessons)
            {
                if (i <= 0)
                {
                    break;
                }
                remainLesson.EndTime = remainLesson.EndTime.Value.AddMinutes(15);
                lessonConflictCheckerService.ConfigureLessonToCheck(remainLesson);
                Result <List <object> > lessonConflictCheckResult   = lessonConflictCheckerService.CheckBothRoomAndTeacherInMemory();
                Result <List <object> > lessonConflictRecheckResult = new Result <List <object> >();
                if (lessonConflictCheckResult.IsSuccess)
                {
                    lessonsToBeAppend.Add(remainLesson);
                    i--;
                }
                else
                {
                    remainLesson.EndTime   = remainLesson.EndTime.Value.AddMinutes(-15);
                    remainLesson.BeginTime = remainLesson.BeginTime.Value.AddMinutes(-15);
                    lessonConflictCheckerService.ConfigureLessonToCheck(remainLesson);
                    lessonConflictRecheckResult = lessonConflictCheckerService.CheckBothRoomAndTeacherInMemory();
                    if (lessonConflictRecheckResult.IsSuccess)
                    {
                        lessonsToBeAppend.Add(remainLesson);
                        i--;
                    }
                    else
                    {
                        remainLesson.BeginTime = remainLesson.BeginTime.Value.AddMinutes(15);
                        lessonIdMapConflictCheckResult.Add(remainLesson.LessonId, new
                        {
                            TimeBeforeConflict = lessonConflictRecheckResult,
                            TimeAfterConflict  = lessonConflictCheckResult
                        });
                    }
                }
            }

            if (lessonsToBeAppend.Count < numOfSchedulesToBeAdd)
            {
                result.IsSuccess    = false;
                result.ErrorMessage = "Not enough valid remain lessons to do reschedule.\n" +
                                      "Valid lessons found: " + lessonsToBeAppend.Count +
                                      "\nRemain Lessons Found:" + remainLessons.Count +
                                      "\nRemain Lessons with Conflict:" + (remainLessons.Count - lessonsToBeAppend.Count) +
                                      "\n Number of valid lessons need: " + numOfSchedulesToBeAdd;
                result.Data = new List <object>();
                foreach (var l in lessonsToBeAppend)
                {
                    result.Data.Add(new { ValidLesson = l });
                }
                foreach (var map in lessonIdMapConflictCheckResult)
                {
                    result.Data.Add(new
                    {
                        RemainLessonIdWithConflict = map.Key,
                        ConflictDetail             = map.Value
                    });
                }
                return(BadRequest(result));
            }

            DateTime todoDate = lesson.BeginTime.Value;

            foreach (var holiday in holidays)
            {
                if (holiday.HolidayDate.Date == todoDate.Date)
                {
                    todoDate = todoDate.AddDays(-1);
                }
            }
            DateTime remindScheduledDate = todoDate;

            List <Teacher> effectedTeachers = new List <Teacher>();

            foreach (var lessonAppend in lessonsToBeAppend)
            {
                if (effectedTeachers.Find(et => et.TeacherId == lessonAppend.Teacher.TeacherId) == null)
                {
                    effectedTeachers.Add(lessonAppend.Teacher);
                }
            }

            var teacherIdMapTodoContent    = new Dictionary <short, string>();
            var teacherMapRemindLogContent = new Dictionary <Teacher, string>();

            foreach (var teacher in effectedTeachers)
            {
                teacherIdMapTodoContent.Add(teacher.TeacherId, TodoListContentGenerator.LessonRescheduleForTeacher(lesson, lessonsToBeAppend, teacher, courseName));
                teacherMapRemindLogContent.Add(teacher, RemindLogContentGenerator.LessonRescheduleForTeacher(lesson, lessonsToBeAppend, teacher, courseName));
            }

            using (var dbContextTransaction = _ablemusicContext.Database.BeginTransaction())
            {
                TodoRepository todoRepository = new TodoRepository(_ablemusicContext);
                todoRepository.AddSingleTodoList("Lesson Reschedule Remind", TodoListContentGenerator.LessonRescheduleForLearner(lesson, learner,
                                                                                                                                 lessonsToBeAppend, courseName), userId, todoDate, lesson.LessonId, learner.LearnerId, null);
                todoRepository.AddMutipleTodoLists("Lesson Reschedule Remind", teacherIdMapTodoContent, userId, todoDate, lesson.LessonId, null);
                var saveTodoResult = await todoRepository.SaveTodoListsAsync();

                if (!saveTodoResult.IsSuccess)
                {
                    return(BadRequest(saveTodoResult));
                }

                RemindLogRepository remindLogRepository = new RemindLogRepository(_ablemusicContext);
                remindLogRepository.AddSingleRemindLog(learner.LearnerId, learner.Email, RemindLogContentGenerator.LessonRescheduleForLearner(lesson, learner,
                                                                                                                                              lessonsToBeAppend, courseName), null, "Lesson Reschedule Remind", lesson.LessonId, remindScheduledDate);
                remindLogRepository.AddMultipleRemindLogs(teacherMapRemindLogContent, null, "Lesson Reschedule Remind", lesson.LessonId, remindScheduledDate);
                var saveRemindLogResult = await remindLogRepository.SaveRemindLogAsync();

                if (!saveRemindLogResult.IsSuccess)
                {
                    return(BadRequest(saveRemindLogResult));
                }

                result.Data = new List <object>();
                foreach (var lessonAppend in lessonsToBeAppend)
                {
                    result.Data.Add(new Lesson
                    {
                        LessonId              = lessonAppend.LessonId,
                        LearnerId             = lessonAppend.LearnerId,
                        RoomId                = lessonAppend.RoomId,
                        TeacherId             = lessonAppend.TeacherId,
                        OrgId                 = lessonAppend.OrgId,
                        IsCanceled            = lessonAppend.IsCanceled,
                        Reason                = lessonAppend.Reason,
                        CreatedAt             = lessonAppend.CreatedAt,
                        CourseInstanceId      = lessonAppend.CourseInstanceId,
                        GroupCourseInstanceId = lessonAppend.GroupCourseInstanceId,
                        IsTrial               = lessonAppend.IsTrial,
                        IsPaid                = lessonAppend.IsPaid,
                        IsChanged             = lessonAppend.IsChanged,
                        IsConfirm             = lessonAppend.IsConfirm,
                        BeginTime             = lessonAppend.BeginTime,
                        EndTime               = lessonAppend.EndTime,
                        InvoiceNum            = lessonAppend.InvoiceNum,
                    });
                    _ablemusicContext.Update(lessonAppend);
                }

                lesson.IsCanceled      = 1;
                lesson.Reason          = reason;
                lessonRemain.Quantity -= 1;

                try
                {
                    await _ablemusicContext.SaveChangesAsync();
                }
                catch (Exception ex)
                {
                    result.IsSuccess    = false;
                    result.ErrorMessage = ex.Message;
                    return(BadRequest(result));
                }

                string userConfirmUrlPrefix = _configuration.GetSection("UrlPrefix").Value;
                //sending Email
                //List<NotificationEventArgs> notifications = new List<NotificationEventArgs>();
                foreach (var todo in saveTodoResult.Data)
                {
                    var    remind = saveRemindLogResult.Data.Find(r => r.LearnerId == todo.LearnerId && r.TeacherId == todo.TeacherId);
                    string currentPersonName;
                    if (todo.TeacherId == null)
                    {
                        currentPersonName = learner.FirstName + " " + learner.LastName;
                    }
                    else
                    {
                        var currentTeacher = effectedTeachers.Find(t => t.TeacherId == todo.TeacherId);
                        currentPersonName = currentTeacher.FirstName + " " + currentTeacher.LastName;
                    }
                    string confirmURL  = userConfirmUrlPrefix + todo.ListId + "/" + remind.RemindId;
                    string mailContent = EmailContentGenerator.LessonReschedule(currentPersonName, courseName, lesson, reason, confirmURL, lessonsToBeAppend);
                    remindLogRepository.UpdateContent(remind.RemindId, mailContent);
                    //notifications.Add(new NotificationEventArgs(remind.Email, "Lesson Reschedule Confirm", mailContent, remind.RemindId));
                }
                //foreach (var mail in notifications)
                //{
                //    _notificationObservable.send(mail);
                //}
                var remindLogUpdateContentResult = await remindLogRepository.SaveUpdatedContentAsync();

                if (!remindLogUpdateContentResult.IsSuccess)
                {
                    result.IsSuccess    = false;
                    result.ErrorMessage = remindLogUpdateContentResult.ErrorMessage;
                    return(BadRequest(result));
                }
                dbContextTransaction.Commit();
            }
            return(Ok(result));
        }
        public async Task <IActionResult> PutLesson(short userId, [FromBody] LessonViewModel lessonViewmodel)
        {
            var    result = new Result <Lesson>();
            string userConfirmUrlPrefix = _configuration.GetSection("UrlPrefix").Value;
            Lesson newLesson            = new Lesson();
            Lesson oldLesson            = new Lesson();

            _mapper.Map(lessonViewmodel, newLesson);
            try
            {
                oldLesson = await _ablemusicContext.Lesson.Where(l => l.LessonId == newLesson.LessonId).FirstOrDefaultAsync();
            }
            catch (Exception ex)
            {
                result.IsFound      = false;
                result.IsSuccess    = false;
                result.ErrorMessage = ex.ToString();
                return(NotFound(result));
            }
            if (oldLesson == null)
            {
                result.IsFound      = false;
                result.IsSuccess    = false;
                result.ErrorMessage = "Lesson id not found";
                return(NotFound(result));
            }

            TimeSpan lessonDuration = oldLesson.EndTime.Value.Subtract(oldLesson.BeginTime.Value);

            newLesson.EndTime = newLesson.BeginTime.Value.Add(lessonDuration);

            var lessonConflictCheckerService = new LessonConflictCheckerService(_ablemusicContext, newLesson.BeginTime.Value,
                                                                                newLesson.EndTime.Value, newLesson.RoomId.Value, newLesson.OrgId, (int)newLesson.TeacherId, oldLesson.LessonId);
            Result <List <object> > lessonConflictCheckResult;

            try
            {
                lessonConflictCheckResult = await lessonConflictCheckerService.CheckBothRoomAndTeacher();
            }
            catch (Exception ex)
            {
                result.IsSuccess    = false;
                result.ErrorMessage = ex.Message;
                return(BadRequest(result));
            }
            if (!lessonConflictCheckResult.IsSuccess)
            {
                return(BadRequest(lessonConflictCheckResult));
            }

            Learner        learner  = new Learner();
            List <Learner> learners = new List <Learner>();
            Teacher        newTeacher;
            Teacher        oldTeacher;

            pegasusContext.Org oldOrg;
            pegasusContext.Org newOrg;
            Room           oldRoom;
            Room           newRoom;
            Course         course;
            List <Holiday> holidays;

            try
            {
                if (oldLesson.CourseInstanceId != null)
                {
                    learner = await _ablemusicContext.Learner.FirstOrDefaultAsync(l => l.LearnerId == oldLesson.LearnerId);

                    course = await(from c in _ablemusicContext.Course
                                   join oto in _ablemusicContext.One2oneCourseInstance on c.CourseId equals oto.CourseId
                                   join l in _ablemusicContext.Lesson on oto.CourseInstanceId equals l.CourseInstanceId
                                   where l.LessonId == newLesson.LessonId
                                   select new Course
                    {
                        CourseId   = c.CourseId,
                        CourseName = c.CourseName
                    }).FirstOrDefaultAsync();
                }
                else
                {
                    learners = await(from gc in _ablemusicContext.GroupCourseInstance
                                     join lgc in _ablemusicContext.LearnerGroupCourse on gc.GroupCourseInstanceId equals lgc.GroupCourseInstanceId
                                     join l in _ablemusicContext.Learner on lgc.LearnerId equals l.LearnerId
                                     where gc.GroupCourseInstanceId == oldLesson.GroupCourseInstanceId
                                     select l
                                     ).ToListAsync();
                    course = await(from c in _ablemusicContext.Course
                                   join gc in _ablemusicContext.GroupCourseInstance on c.CourseId equals gc.CourseId
                                   join l in _ablemusicContext.Lesson on gc.GroupCourseInstanceId equals l.GroupCourseInstanceId
                                   where l.LessonId == newLesson.LessonId
                                   select new Course
                    {
                        CourseId   = c.CourseId,
                        CourseName = c.CourseName
                    }).FirstOrDefaultAsync();
                }
                newTeacher = await _ablemusicContext.Teacher.FirstOrDefaultAsync(t => t.TeacherId == newLesson.TeacherId);

                oldTeacher = newLesson.TeacherId == oldLesson.TeacherId ? newTeacher :
                             await _ablemusicContext.Teacher.FirstOrDefaultAsync(t => t.TeacherId == oldLesson.TeacherId);

                if (oldLesson.IsTrial == 1)
                {
                    course = await _ablemusicContext.Course.Where(c => c.CourseId == oldLesson.TrialCourseId).FirstOrDefaultAsync();
                }
                holidays = await _ablemusicContext.Holiday.ToListAsync();

                oldOrg = await _ablemusicContext.Org.Where(o => o.OrgId == oldLesson.OrgId).FirstOrDefaultAsync();

                newOrg = newLesson.OrgId == oldLesson.OrgId ? oldOrg :
                         await _ablemusicContext.Org.Where(o => o.OrgId == newLesson.OrgId).FirstOrDefaultAsync();

                oldRoom = await _ablemusicContext.Room.Where(r => r.RoomId == oldLesson.RoomId).FirstOrDefaultAsync();

                newRoom = newLesson.RoomId == oldLesson.RoomId ? oldRoom :
                          await _ablemusicContext.Room.Where(r => r.RoomId == newLesson.RoomId).FirstOrDefaultAsync();
            }
            catch (Exception e)
            {
                result.IsSuccess    = false;
                result.ErrorMessage = e.Message;
                return(NotFound(result));
            }
            if (course == null)
            {
                result.IsSuccess    = false;
                result.ErrorMessage = "Fail to found course name under this lesson";
                return(NotFound(result));
            }
            string courseName = course.CourseName;

            DateTime oldTodoDate = oldLesson.BeginTime.Value.AddDays(-1);
            DateTime newTodoDate = newLesson.BeginTime.Value.AddDays(-1);

            foreach (var holiday in holidays)
            {
                if (holiday.HolidayDate.Date == oldTodoDate.Date)
                {
                    oldTodoDate = oldTodoDate.AddDays(-1);
                }
                if (holiday.HolidayDate.Date == newTodoDate.Date)
                {
                    newTodoDate = newTodoDate.AddDays(-1);
                }
            }

            DateTime oldRemindScheduledDate = oldTodoDate;
            DateTime newRemindScheduledDate = newTodoDate;

            oldLesson.IsCanceled  = 1;
            oldLesson.IsChanged   = 1;
            oldLesson.NewLessonId = 1;
            oldLesson.Reason      = newLesson.Reason;

            newLesson.LessonId              = 0;
            newLesson.LearnerId             = oldLesson.LearnerId;
            newLesson.IsCanceled            = 0;
            newLesson.Reason                = "";
            newLesson.CreatedAt             = toNZTimezone(DateTime.UtcNow);
            newLesson.CourseInstanceId      = oldLesson.CourseInstanceId;
            newLesson.GroupCourseInstanceId = oldLesson.GroupCourseInstanceId;
            newLesson.IsTrial               = oldLesson.IsTrial;
            newLesson.TrialCourseId         = oldLesson.TrialCourseId;
            newLesson.InvoiceNum            = oldLesson.InvoiceNum;
            newLesson.IsPaid                = oldLesson.IsPaid;
            //newLesson.NewLessonId = oldLesson.NewLessonId;
            newLesson.IsChanged = 0;

            using (var dbContextTransaction = _ablemusicContext.Database.BeginTransaction())
            {
                try
                {
                    await _ablemusicContext.Lesson.AddAsync(newLesson);

                    oldLesson.NewLessonId = newLesson.LessonId;
                    await _ablemusicContext.SaveChangesAsync();
                }
                catch (Exception ex)
                {
                    result.IsSuccess    = false;
                    result.ErrorMessage = ex.ToString();
                    return(BadRequest(result));
                }

                TodoRepository todoRepository = new TodoRepository(_ablemusicContext);
                if (oldLesson.CourseInstanceId != null)
                {
                    todoRepository.AddSingleTodoList("Lesson Rearrangement to Remind", TodoListContentGenerator.RearrangedSingleLessonWithOldLessonForLearner(
                                                         oldLesson, newLesson, learner, oldTeacher, newTeacher, oldOrg, newOrg, oldRoom, newRoom), userId, newTodoDate, newLesson.LessonId, learner.LearnerId, null);
                    todoRepository.AddSingleTodoList("Lesson Rearrangement to Remind", TodoListContentGenerator.RearrangedSingleLessonWithOldLessonForLearner(
                                                         oldLesson, newLesson, learner, oldTeacher, newTeacher, oldOrg, newOrg, oldRoom, newRoom), userId, oldTodoDate, oldLesson.LessonId, learner.LearnerId, null);
                }
                else
                {
                    Dictionary <int, string> learnerIdMapContent = new Dictionary <int, string>();
                    foreach (var l in learners)
                    {
                        learnerIdMapContent.Add(l.LearnerId, TodoListContentGenerator.RearrangedSingleLessonWithOldLessonForLearner(oldLesson, newLesson, l, oldTeacher, newTeacher, oldOrg, newOrg, oldRoom, newRoom));
                    }
                    todoRepository.AddMutipleTodoLists("Lesson Rearrangement to Remind", learnerIdMapContent, userId, newTodoDate, newLesson.LessonId, null);
                    todoRepository.AddMutipleTodoLists("Lesson Rearrangement to Remind", learnerIdMapContent, userId, oldTodoDate, newLesson.LessonId, null);
                }
                todoRepository.AddSingleTodoList("Lesson Rearrangement to Remind", TodoListContentGenerator.RearrangedSingleLessonWithOldLessonForOldTeacher(
                                                     oldLesson, newLesson, oldTeacher, newTeacher, oldOrg, newOrg, oldRoom, newRoom), userId, newTodoDate, newLesson.LessonId, null, oldTeacher.TeacherId);
                todoRepository.AddSingleTodoList("Lesson Rearrangement to Remind", TodoListContentGenerator.RearrangedSingleLessonWithOldLessonForNewTeacher(
                                                     oldLesson, newLesson, oldTeacher, newTeacher, oldOrg, newOrg, oldRoom, newRoom), userId, newTodoDate, newLesson.LessonId, null, newTeacher.TeacherId);

                todoRepository.AddSingleTodoList("Lesson Rearrangement to Remind", TodoListContentGenerator.RearrangedSingleLessonWithOldLessonForOldTeacher(
                                                     oldLesson, newLesson, oldTeacher, newTeacher, oldOrg, newOrg, oldRoom, newRoom), userId, oldTodoDate, oldLesson.LessonId, null, oldTeacher.TeacherId);
                todoRepository.AddSingleTodoList("Lesson Rearrangement to Remind", TodoListContentGenerator.RearrangedSingleLessonWithOldLessonForNewTeacher(
                                                     oldLesson, newLesson, oldTeacher, newTeacher, oldOrg, newOrg, oldRoom, newRoom), userId, oldTodoDate, oldLesson.LessonId, null, newTeacher.TeacherId);
                var saveTodoResult = await todoRepository.SaveTodoListsAsync();

                if (!saveTodoResult.IsSuccess)
                {
                    return(BadRequest(saveTodoResult));
                }

                RemindLogRepository remindLogRepository       = new RemindLogRepository(_ablemusicContext);
                DateTime            earlyDate                 = newRemindScheduledDate >= oldRemindScheduledDate ? oldRemindScheduledDate : newRemindScheduledDate;
                DateTime            laterDate                 = newRemindScheduledDate >= oldRemindScheduledDate ? newRemindScheduledDate : oldRemindScheduledDate;
                DateTime            laterDateNoticeWeekBefore = laterDate.AddDays(-7);
                int dateDifferentBetweenNowAndEarlyDate       = (int)(earlyDate - DateTime.UtcNow.ToNZTimezone()).TotalDays;
                int dateDifferentBetweenEarlyDateAndLaterDate = (int)(laterDate - earlyDate).TotalDays;
                if (dateDifferentBetweenNowAndEarlyDate < 7 & dateDifferentBetweenNowAndEarlyDate > 1)
                {
                    earlyDate = DateTime.UtcNow.ToNZTimezone().AddDays(1);
                }
                List <DateTime> remindScheduledDates = new List <DateTime>
                {
                    earlyDate,
                    laterDate
                };
                foreach (var remindScheduleDate in remindScheduledDates)
                {
                    if (oldLesson.CourseInstanceId != null)
                    {
                        remindLogRepository.AddSingleRemindLog(learner.LearnerId, learner.Email, RemindLogContentGenerator.RearrangedSingleLessonWithOldLessonForLearner(
                                                                   oldLesson, newLesson, oldTeacher, newTeacher, oldOrg, newOrg, oldRoom, newRoom, courseName), null, "Lesson Rearrangement Remind", newLesson.LessonId, remindScheduleDate);
                    }
                    else
                    {
                        Dictionary <Learner, string> learnerMapContent = new Dictionary <Learner, string>();
                        foreach (var l in learners)
                        {
                            learnerMapContent.Add(l, RemindLogContentGenerator.RearrangedSingleLessonWithOldLessonForLearner(oldLesson, newLesson, oldTeacher, newTeacher, oldOrg, newOrg, oldRoom, newRoom, courseName));
                        }
                        remindLogRepository.AddMultipleRemindLogs(learnerMapContent, null, "Lesson rearrangement Remind", newLesson.LessonId, remindScheduleDate);
                    }
                    remindLogRepository.AddSingleRemindLog(null, oldTeacher.Email, RemindLogContentGenerator.RearrangedSingleLessonWithOldLessonForOldTeacher(
                                                               oldLesson, newLesson, oldTeacher, newTeacher, oldOrg, newOrg, oldRoom, newRoom, courseName), oldTeacher.TeacherId, "Lesson Rearrangement Remind", oldLesson.LessonId, remindScheduleDate);
                    remindLogRepository.AddSingleRemindLog(null, newTeacher.Email, RemindLogContentGenerator.RearrangedSingleLessonWithOldLessonForNewTeacher(
                                                               oldLesson, newLesson, oldTeacher, newTeacher, oldOrg, newOrg, oldRoom, newRoom, courseName), newTeacher.TeacherId, "Lesson Rearrangement Remind", newLesson.LessonId, remindScheduleDate);
                }

                foreach (var remindlog in remindLogRepository._remindLogs.Reverse <RemindLog>())
                {
                    if (remindlog.ScheduledDate <= DateTime.UtcNow.ToNZTimezone())
                    {
                        remindLogRepository._remindLogs.Remove(remindlog);
                    }
                    if (dateDifferentBetweenEarlyDateAndLaterDate <= 7)
                    {
                        if (remindlog.ScheduledDate.Value.Date == laterDateNoticeWeekBefore.Date)
                        {
                            remindLogRepository._remindLogs.Remove(remindlog);
                        }
                    }
                }

                var saveRemindLogResult = await remindLogRepository.SaveRemindLogAsync();

                if (!saveRemindLogResult.IsSuccess)
                {
                    try
                    {
                        oldLesson.IsCanceled = 0;
                        oldLesson.Reason     = "";
                        _ablemusicContext.Lesson.Remove(newLesson);
                        await _ablemusicContext.SaveChangesAsync();
                    }
                    catch (Exception ex)
                    {
                        result.IsSuccess    = false;
                        result.ErrorMessage = ex.Message + "\n" + saveTodoResult.ErrorMessage;
                        return(BadRequest(result));
                    }
                    return(BadRequest(saveRemindLogResult));
                }

                //sending Email
                //List<NotificationEventArgs> notifications = new List<NotificationEventArgs>();
                foreach (var remind in saveRemindLogResult.Data)
                {
                    var    todo = saveTodoResult.Data.Find(t => t.LearnerId == remind.LearnerId && t.TeacherId == remind.TeacherId && t.TodoDate == newTodoDate);
                    string currentPersonName;
                    if (remind.TeacherId == null)
                    {
                        currentPersonName = learner.FirstName + " " + learner.LastName;
                    }
                    else
                    {
                        currentPersonName = remind.TeacherId == newTeacher.TeacherId ? newTeacher.FirstName + " " + newTeacher.LastName : oldTeacher.FirstName + " " + oldTeacher.LastName;
                    }
                    string confirmURL  = userConfirmUrlPrefix + todo.ListId + "/" + remind.RemindId;
                    string mailContent = EmailContentGenerator.RearrangeLessonWithOld(currentPersonName, courseName, confirmURL, oldLesson, oldTeacher,
                                                                                      newTeacher, oldOrg, newOrg, oldRoom, newRoom);
                    remindLogRepository.UpdateContent(remind.RemindId, mailContent);
                    //notifications.Add(new NotificationEventArgs(remind.Email, "Lesson Rearrange Confirm", mailContent, remind.RemindId));
                }
                var remindLogUpdateContentResult = await remindLogRepository.SaveUpdatedContentAsync();

                if (!remindLogUpdateContentResult.IsSuccess)
                {
                    result.IsSuccess    = false;
                    result.ErrorMessage = remindLogUpdateContentResult.ErrorMessage;
                    return(BadRequest(result));
                }
                //foreach (var mail in notifications)
                //{
                //    _notificationObservable.send(mail);
                //}
                dbContextTransaction.Commit();
            }

            result.IsSuccess = true;
            //result.Data = newLesson;
            return(Ok(result));
        }
示例#5
0
        public async Task <IActionResult> PostPeriodCourseChange([FromBody] PeriodCourseChangeViewModel inputObj)
        {
            var              result = new Result <List <object> >();
            List <Lesson>    exsitingLessons;
            Learner          learner;
            List <Holiday>   holidays;
            List <Amendment> exsitingAmendments;
            Amendment        amendment     = new Amendment();
            DateTime?        todoDateEnd   = null;
            DateTime         todoDateBegin = inputObj.BeginDate;
            List <Term>      terms;
            dynamic          courseInfo;
            dynamic          newCourseInfo;
            AvailableDays    availableDay;

            try
            {
                if (inputObj.EndDate.HasValue)
                {
                    exsitingLessons = await _ablemusicContext.Lesson.Where(l => l.LearnerId == inputObj.LearnerId && l.IsCanceled != 1 &&
                                                                           l.BeginTime.Value.Date <= inputObj.EndDate.Value.Date && l.BeginTime.Value.Date >= inputObj.BeginDate.Date &&
                                                                           l.CourseInstanceId == inputObj.InstanceId).ToListAsync();
                }
                else
                {
                    exsitingLessons = await _ablemusicContext.Lesson.Where(l => l.LearnerId == inputObj.LearnerId && l.IsCanceled != 1 &&
                                                                           l.BeginTime.Value.Date >= inputObj.BeginDate.Date).ToListAsync();
                }
                terms = await _ablemusicContext.Term.ToListAsync();

                courseInfo = await(from i in _ablemusicContext.One2oneCourseInstance
                                   join cs in _ablemusicContext.CourseSchedule on i.CourseInstanceId equals cs.CourseInstanceId
                                   join l in _ablemusicContext.Learner on i.LearnerId equals l.LearnerId
                                   join t in _ablemusicContext.Teacher on i.TeacherId equals t.TeacherId
                                   join c in _ablemusicContext.Course on i.CourseId equals c.CourseId
                                   join o in _ablemusicContext.Org on i.OrgId equals o.OrgId
                                   join r in _ablemusicContext.Room on i.RoomId equals r.RoomId
                                   where i.CourseInstanceId == inputObj.InstanceId && inputObj.CourseScheduleId == cs.CourseScheduleId
                                   select new
                {
                    OrgId      = i.OrgId,
                    OrgName    = o.OrgName,
                    RoomId     = i.RoomId,
                    RoomName   = r.RoomName,
                    CourseId   = i.CourseId,
                    CourseName = c.CourseName,
                    c.Duration,
                    TeacherId        = i.TeacherId,
                    TeacherFirstName = t.FirstName,
                    TeacherLastName  = t.LastName,
                    TeacherEmail     = t.Email,
                    LearnerId        = i.LearnerId,
                    LearnerFirstName = l.FirstName,
                    LearnerLastName  = l.LastName,
                    LearnerEmail     = l.Email,
                    DayOfWeek        = cs.DayOfWeek,
                    BeginTime        = cs.BeginTime,
                    EndTime          = cs.EndTime,
                }).FirstOrDefaultAsync();
                availableDay = await _ablemusicContext.AvailableDays.Where(ad => ad.TeacherId == inputObj.TeacherId && ad.DayOfWeek == inputObj.DayOfWeek && ad.OrgId == inputObj.OrgId).FirstOrDefaultAsync();
            }
            catch (Exception ex)
            {
                result.IsSuccess    = false;
                result.ErrorMessage = ex.Message;
                return(BadRequest(result));
            }
            if (courseInfo == null)
            {
                result.IsSuccess    = false;
                result.ErrorMessage = "Course schedule or course instance not found";
                return(BadRequest(result));
            }
            if (availableDay == null || availableDay.RoomId == null)
            {
                result.IsSuccess    = false;
                result.ErrorMessage = "Room Id not found";
                return(BadRequest(result));
            }

            try
            {
                newCourseInfo = new
                {
                    newOrg  = await _ablemusicContext.Org.Where(o => o.OrgId == inputObj.OrgId).FirstOrDefaultAsync(),
                    newRoom = await _ablemusicContext.Room.Where(r => r.RoomId == availableDay.RoomId).FirstOrDefaultAsync(),
                };
                learner = await _ablemusicContext.Learner.Where(l => l.LearnerId == inputObj.LearnerId).FirstOrDefaultAsync();

                holidays = await _ablemusicContext.Holiday.ToListAsync();

                exsitingAmendments = await _ablemusicContext.Amendment.Where(a => a.LearnerId == inputObj.LearnerId && a.AmendType == 2 &&
                                                                             a.BeginDate == inputObj.BeginDate && a.EndDate == inputObj.EndDate && inputObj.OrgId == a.OrgId &&
                                                                             inputObj.BeginTime == a.BeginTime && inputObj.DayOfWeek == a.DayOfWeek && inputObj.InstanceId == a.CourseInstanceId &&
                                                                             availableDay.RoomId == a.RoomId && inputObj.IsTemporary == a.IsTemporary
                                                                             ).ToListAsync();
            }
            catch (Exception ex)
            {
                result.IsSuccess    = false;
                result.ErrorMessage = ex.Message;
                return(BadRequest(result));
            }
            if (newCourseInfo == null)
            {
                result.IsSuccess    = false;
                result.ErrorMessage = "Org id or room id not found";
                return(BadRequest(result));
            }
            if (exsitingAmendments.Count > 0)
            {
                result.IsSuccess    = false;
                result.ErrorMessage = "The same change has already being made";
                return(BadRequest(result));
            }
            if (!inputObj.EndDate.HasValue && inputObj.IsTemporary == 1)
            {
                result.IsSuccess    = false;
                result.ErrorMessage = "EndDate is required when type is temporary";
                return(BadRequest(result));
            }

            switch ((short)courseInfo.Duration)
            {
            case 1: inputObj.EndTime = inputObj.BeginTime.Add(TimeSpan.FromMinutes(30));
                break;

            case 2:
                inputObj.EndTime = inputObj.BeginTime.Add(TimeSpan.FromMinutes(45));
                break;

            case 3:
                inputObj.EndTime = inputObj.BeginTime.Add(TimeSpan.FromMinutes(60));
                break;
            }

            foreach (var lesson in exsitingLessons.Reverse <Lesson>())
            {
                if (courseInfo.DayOfWeek != lesson.BeginTime.Value.ToDayOfWeek() || lesson.IsChanged == 1 ||
                    lesson.BeginTime.Value.TimeOfDay != courseInfo.BeginTime)
                {
                    exsitingLessons.Remove(lesson);
                }
            }

            var newLessonsMapOldLesson = new Dictionary <Lesson, Lesson>();

            foreach (var lesson in exsitingLessons)
            {
                DateTime beginTime = lesson.BeginTime.Value;
                DateTime endTime   = lesson.EndTime.Value;
                if (inputObj.DayOfWeek != courseInfo.DayOfWeek)
                {
                    beginTime = beginTime.SetDateByDayOfWeekInWeek(inputObj.DayOfWeek);
                    endTime   = endTime.SetDateByDayOfWeekInWeek(inputObj.DayOfWeek);
                }
                beginTime = beginTime.Date + inputObj.BeginTime;
                endTime   = endTime.Date + inputObj.EndTime;
                newLessonsMapOldLesson.Add(new Lesson
                {
                    LearnerId             = lesson.LearnerId,
                    RoomId                = availableDay.RoomId,
                    TeacherId             = inputObj.TeacherId,
                    OrgId                 = Convert.ToInt16(inputObj.OrgId),
                    IsCanceled            = 0,
                    Reason                = null,
                    CreatedAt             = DateTime.UtcNow.ToNZTimezone(),
                    CourseInstanceId      = lesson.CourseInstanceId,
                    GroupCourseInstanceId = lesson.GroupCourseInstanceId,
                    IsTrial               = lesson.IsTrial,
                    BeginTime             = beginTime,
                    EndTime               = endTime,
                    InvoiceNum            = lesson.InvoiceNum,
                    IsConfirm             = lesson.IsConfirm,
                    TrialCourseId         = lesson.TrialCourseId,
                    IsChanged             = lesson.IsChanged,
                    IsPaid                = lesson.IsPaid,
                    NewLessonId           = lesson.NewLessonId,
                }, lesson);
                lesson.IsCanceled = 1;
            }

            amendment.CourseInstanceId = inputObj.InstanceId;
            amendment.OrgId            = Convert.ToInt16(inputObj.OrgId);
            amendment.DayOfWeek        = inputObj.DayOfWeek;
            amendment.BeginTime        = inputObj.BeginTime;
            amendment.EndTime          = inputObj.EndTime;
            amendment.LearnerId        = inputObj.LearnerId;
            amendment.RoomId           = availableDay.RoomId;
            amendment.BeginDate        = inputObj.BeginDate;
            amendment.EndDate          = inputObj.IsTemporary == 1 ? inputObj.EndDate : null;
            amendment.CreatedAt        = toNZTimezone(DateTime.UtcNow);
            amendment.Reason           = inputObj.Reason;
            amendment.IsTemporary      = inputObj.IsTemporary;
            amendment.AmendType        = 2;
            amendment.TeacherId        = inputObj.TeacherId;
            amendment.CourseScheduleId = inputObj.CourseScheduleId;

            DateTime endDate;

            if (inputObj.IsTemporary == 1)
            {
                endDate = inputObj.EndDate.Value;
            }
            else
            {
                Term     currentTerm        = null;
                Term     nextTerm           = null;
                DateTime lastDateInAllTerms = inputObj.BeginDate;
                foreach (var t in terms)
                {
                    lastDateInAllTerms = lastDateInAllTerms >= t.EndDate.Value ? lastDateInAllTerms : t.EndDate.Value;
                    if (amendment.BeginDate.Value > t.BeginDate.Value && amendment.BeginDate.Value < t.EndDate.Value)
                    {
                        currentTerm = t;
                    }
                }
                if (currentTerm == null)
                {
                    result.IsSuccess    = false;
                    result.ErrorMessage = "Term not found";
                    return(BadRequest(result));
                }
                DateTime currentDay = currentTerm.EndDate.Value.AddDays(1);
                while (currentDay < lastDateInAllTerms)
                {
                    nextTerm = terms.Find(t => t.BeginDate.Value <currentDay && t.EndDate.Value> currentDay);
                    if (nextTerm != null)
                    {
                        break;
                    }
                    else
                    {
                        currentDay = currentDay.AddDays(1);
                    }
                }
                if (nextTerm == null)
                {
                    endDate = currentTerm.EndDate.Value;
                }
                else
                {
                    endDate = nextTerm.EndDate.Value;
                }
            }

            var visualLessonsForCheckingConflict = new List <Lesson>();

            DateTime currentDate      = amendment.BeginDate.Value;
            int      currentDayOfWeek = currentDate.DayOfWeek == 0 ? 7 : (int)currentDate.DayOfWeek;

            while (currentDayOfWeek != amendment.DayOfWeek)
            {
                currentDate      = currentDate.AddDays(1);
                currentDayOfWeek = currentDate.DayOfWeek == 0 ? 7 : (int)currentDate.DayOfWeek;
            }
            while (currentDate <= endDate)
            {
                visualLessonsForCheckingConflict.Add(new Lesson
                {
                    RoomId    = amendment.RoomId,
                    TeacherId = amendment.TeacherId,
                    OrgId     = amendment.OrgId.Value,
                    BeginTime = currentDate.Add(amendment.BeginTime.Value),
                    EndTime   = currentDate.Add(amendment.EndTime.Value),
                });
                currentDate      = currentDate.AddDays(7);
                currentDayOfWeek = currentDate.DayOfWeek == 0 ? 7 : (int)currentDate.DayOfWeek;
            }

            var lessonConflictCheckerService = new LessonConflictCheckerService(_ablemusicContext, inputObj.BeginDate, endDate);

            try
            {
                await lessonConflictCheckerService.LoadAllProtentialConflictLessonsToMemoryAsync();
            }
            catch (Exception ex)
            {
                result.IsSuccess    = false;
                result.ErrorMessage = ex.Message;
                return(BadRequest(result));
            }

            Dictionary <Lesson, object> lessonIdMapConflictCheckResult = new Dictionary <Lesson, object>();

            foreach (var lesson in visualLessonsForCheckingConflict)
            {
                lessonConflictCheckerService.ConfigureLessonToCheck(lesson);
                Result <List <object> > lessonConflictCheckResult = lessonConflictCheckerService.CheckBothRoomAndTeacherInMemory();
                if (!lessonConflictCheckResult.IsSuccess)
                {
                    lessonIdMapConflictCheckResult.Add(lesson, lessonConflictCheckResult);
                }
            }

            if (lessonIdMapConflictCheckResult.Count > 0)
            {
                result.IsSuccess    = false;
                result.ErrorMessage = "Conflict Found";
                result.Data         = new List <object>
                {
                    new { ArrangedLessonFound = exsitingLessons.Count }
                };
                foreach (var conflictResult in lessonIdMapConflictCheckResult)
                {
                    result.Data.Add(new
                    {
                        LessonWithConflict = conflictResult.Key,
                        ConflictDetail     = conflictResult.Value
                    });
                }
                return(BadRequest(result));
            }

            foreach (var holiday in holidays)
            {
                if (holiday.HolidayDate.Date == todoDateBegin.Date)
                {
                    todoDateBegin = todoDateBegin.AddDays(-1);
                }
            }

            if (inputObj.EndDate.HasValue)
            {
                todoDateEnd = inputObj.EndDate.Value;
                foreach (var holiday in holidays)
                {
                    if (holiday.HolidayDate.Date == todoDateEnd.Value.Date)
                    {
                        todoDateEnd = todoDateEnd.Value.AddDays(-1);
                    }
                }
            }

            DateTime remindScheduleDateBegin = todoDateBegin;

            using (var dbContextTransaction = _ablemusicContext.Database.BeginTransaction())
            {
                TodoRepository todoRepository = new TodoRepository(_ablemusicContext);
                todoRepository.AddSingleTodoList("Period Course Change Remind", TodoListContentGenerator.PeriodCourseChangeForLearner(courseInfo,
                                                                                                                                      newCourseInfo, inputObj, todoDateBegin), inputObj.UserId, todoDateBegin, null, inputObj.LearnerId, null);
                todoRepository.AddSingleTodoList("Period Course Change Remind", TodoListContentGenerator.PeriodCourseChangeForTeacher(courseInfo,
                                                                                                                                      newCourseInfo, inputObj, todoDateBegin), inputObj.UserId, todoDateBegin, null, null, courseInfo.TeacherId);
                if (inputObj.EndDate.HasValue && inputObj.IsTemporary == 1)
                {
                    todoRepository.AddSingleTodoList("Period Course Change Remind", TodoListContentGenerator.PeriodCourseChangeForLearner(courseInfo,
                                                                                                                                          newCourseInfo, inputObj, todoDateEnd.Value), inputObj.UserId, todoDateEnd.Value, null, inputObj.LearnerId, null);
                    todoRepository.AddSingleTodoList("Period Course Change Remind", TodoListContentGenerator.PeriodCourseChangeForTeacher(courseInfo,
                                                                                                                                          newCourseInfo, inputObj, todoDateEnd.Value), inputObj.UserId, todoDateEnd.Value, null, null, courseInfo.TeacherId);
                }
                var saveTodoResult = await todoRepository.SaveTodoListsAsync();

                if (!saveTodoResult.IsSuccess)
                {
                    return(BadRequest(saveTodoResult));
                }

                RemindLogRepository remindLogRepository = new RemindLogRepository(_ablemusicContext);
                remindLogRepository.AddSingleRemindLog(courseInfo.LearnerId, courseInfo.LearnerEmail, RemindLogContentGenerator.PeriodCourseChangeForLearner(
                                                           courseInfo, newCourseInfo, inputObj), null, "Period Course Change Remind", null, remindScheduleDateBegin);
                remindLogRepository.AddSingleRemindLog(null, courseInfo.TeacherEmail, RemindLogContentGenerator.PeriodCourseChangeForTeacher(courseInfo,
                                                                                                                                             newCourseInfo, inputObj), courseInfo.TeacherId, "Period Course Change Remind", null, remindScheduleDateBegin);

                var saveRemindLogResult = await remindLogRepository.SaveRemindLogAsync();

                if (!saveRemindLogResult.IsSuccess)
                {
                    return(BadRequest(saveRemindLogResult));
                }

                try
                {
                    foreach (var lesson in newLessonsMapOldLesson)
                    {
                        await _ablemusicContext.Lesson.AddAsync(lesson.Key);
                    }
                    await _ablemusicContext.Amendment.AddAsync(amendment);

                    await _ablemusicContext.SaveChangesAsync();

                    foreach (var lesson in exsitingLessons)
                    {
                        foreach (var m in newLessonsMapOldLesson)
                        {
                            if (m.Value.LessonId == lesson.LessonId)
                            {
                                lesson.NewLessonId = m.Key.LessonId;
                            }
                        }
                    }
                    await _ablemusicContext.SaveChangesAsync();
                }
                catch (Exception ex)
                {
                    result.IsSuccess    = false;
                    result.ErrorMessage = ex.Message;
                    return(BadRequest(result));
                }

                //sending Email
                //List<NotificationEventArgs> notifications = new List<NotificationEventArgs>();
                foreach (var remind in saveRemindLogResult.Data)
                {
                    string currentPersonName;
                    if (remind.TeacherId == null)
                    {
                        currentPersonName = courseInfo.LearnerFirstName + " " + courseInfo.LearnerLastName;
                    }
                    else
                    {
                        currentPersonName = courseInfo.TeacherFirstName + " " + courseInfo.TeacherLastName;
                    }
                    string mailContent = EmailContentGenerator.PeriodCourseChange(currentPersonName, courseInfo, newCourseInfo, inputObj);
                    remindLogRepository.UpdateContent(remind.RemindId, mailContent);
                    //notifications.Add(new NotificationEventArgs(remind.Email, "Period Course Change Remind", mailContent, remind.RemindId));
                }
                var remindLogUpdateContentResult = await remindLogRepository.SaveUpdatedContentAsync();

                if (!remindLogUpdateContentResult.IsSuccess)
                {
                    result.IsSuccess    = false;
                    result.ErrorMessage = remindLogUpdateContentResult.ErrorMessage;
                    return(BadRequest(result));
                }
                //foreach (var mail in notifications)
                //{
                //    _notificationObservable.send(mail);
                //}
                dbContextTransaction.Commit();
            }

            result.Data = new List <object>
            {
                new { ArrangedLessonFound = exsitingLessons.Count },
                new { ArrangedLessonChanged = newLessonsMapOldLesson.Count }
            };

            return(Ok(result));
        }
示例#6
0
        public async Task <IActionResult> PostDayoff([FromBody] LearnerDayoffViewModel inputObj)
        {
            var              result = new Result <object>();
            List <Lesson>    lessons;
            List <Amendment> amendments = new List <Amendment>();
            List <Amendment> exsitsAmendment;
            Learner          learner;
            dynamic          courseSchedules;
            List <Holiday>   holidays;

            try
            {
                lessons = await _ablemusicContext.Lesson.Where(l => l.LearnerId == inputObj.LearnerId && l.IsCanceled != 1 && l.CourseInstanceId.HasValue && inputObj.InstanceIds.Contains(l.CourseInstanceId.Value) &&
                                                               l.BeginTime.Value.Date >= inputObj.BeginDate.Date && l.BeginTime.Value.Date <= inputObj.EndDate.Date).OrderBy(l => l.CourseInstanceId).ToListAsync();

                courseSchedules = await(from i in _ablemusicContext.One2oneCourseInstance
                                        join cs in _ablemusicContext.CourseSchedule on i.CourseInstanceId equals cs.CourseInstanceId
                                        join l in _ablemusicContext.Learner on i.LearnerId equals l.LearnerId
                                        join t in _ablemusicContext.Teacher on i.TeacherId equals t.TeacherId
                                        join c in _ablemusicContext.Course on i.CourseId equals c.CourseId
                                        join o in _ablemusicContext.Org on i.OrgId equals o.OrgId
                                        join r in _ablemusicContext.Room on i.RoomId equals r.RoomId
                                        where inputObj.InstanceIds.Contains(cs.CourseInstanceId.Value)
                                        select new
                {
                    cs.CourseScheduleId,
                    cs.CourseInstanceId,
                    i.OrgId,
                    o.OrgName,
                    i.RoomId,
                    r.RoomName,
                    i.CourseId,
                    c.CourseName,
                    i.TeacherId,
                    TeacherFirstName = t.FirstName,
                    TeacherLastName  = t.LastName,
                    TeacherEmail     = t.Email,
                    cs.DayOfWeek,
                    i.LearnerId,
                    LearnerFirstName = l.FirstName,
                    LearnerLastName  = l.LastName,
                    LearnerEmail     = l.Email,
                }).ToListAsync();
                learner = await _ablemusicContext.Learner.Where(l => l.LearnerId == inputObj.LearnerId).FirstOrDefaultAsync();

                holidays = await _ablemusicContext.Holiday.ToListAsync();

                exsitsAmendment = await _ablemusicContext.Amendment.Where(a => a.LearnerId == inputObj.LearnerId && a.AmendType == 1 &&
                                                                          a.CourseInstanceId.HasValue && inputObj.InstanceIds.Contains(a.CourseInstanceId.Value) &&
                                                                          ((inputObj.BeginDate >= a.BeginDate && inputObj.BeginDate <= a.EndDate) ||
                                                                           (inputObj.EndDate >= a.BeginDate && inputObj.EndDate <= a.EndDate) ||
                                                                           (inputObj.BeginDate <= a.BeginDate && inputObj.EndDate >= a.EndDate))).ToListAsync();
            }
            catch (Exception ex)
            {
                result.IsSuccess    = false;
                result.ErrorMessage = ex.ToString();
                return(BadRequest(result));
            }
            if (courseSchedules.Count < 1)
            {
                result.IsSuccess    = false;
                result.ErrorMessage = "Course schedule not found";
                return(BadRequest(result));
            }
            if (learner == null)
            {
                result.IsSuccess    = false;
                result.ErrorMessage = "Learner not found";
                return(BadRequest(result));
            }
            if (exsitsAmendment.Count > 0)
            {
                result.IsSuccess    = false;
                result.ErrorMessage = "There is a conflict of date on your previous asking leave";
                return(BadRequest(result));
            }
            byte remaining = 0;

            if (lessons.Count() > 0)
            {
                remaining = GetSplitCount(lessons[0].BeginTime.Value, lessons[0].EndTime.Value);
            }
            Dictionary <string, int> invoiceNumsMapLessonQuantity = new Dictionary <string, int>();

            foreach (var lesson in lessons)
            {
                if (inputObj.IsInvoiceChange && lesson.InvoiceNum != null)
                {
                    if (!invoiceNumsMapLessonQuantity.ContainsKey(lesson.InvoiceNum))
                    {
                        invoiceNumsMapLessonQuantity.Add(lesson.InvoiceNum, 1);
                    }
                    else
                    {
                        invoiceNumsMapLessonQuantity[lesson.InvoiceNum]++;
                    }
                }
                lesson.IsCanceled = 1;
                lesson.Reason     = inputObj.Reason;
            }

            var invoices = new List <Invoice>();
            var invoiceWaitingConfirms   = new List <InvoiceWaitingConfirm>();
            var invoiceNumMapCoursePrice = new Dictionary <string, decimal>();
            var awaitMakeUpLessons       = new List <AwaitMakeUpLesson>();

            if (inputObj.IsInvoiceChange)
            {
                try
                {
                    invoices = await _ablemusicContext.Invoice.Where(i => i.IsActive == 1 && invoiceNumsMapLessonQuantity.Keys.Contains(i.InvoiceNum)).ToListAsync();

                    invoiceWaitingConfirms = await _ablemusicContext.InvoiceWaitingConfirm.Where(iw => iw.IsActivate == 1 && invoiceNumsMapLessonQuantity.Keys.Contains(iw.InvoiceNum)).ToListAsync();

                    foreach (var i in invoiceWaitingConfirms)
                    {
                        var coursePrice = (await _ablemusicContext.One2oneCourseInstance.Where(oto => oto.CourseInstanceId == i.CourseInstanceId).Include(oto => oto.Course).FirstOrDefaultAsync()).Course.Price;
                        invoiceNumMapCoursePrice.Add(i.InvoiceNum, coursePrice.Value);
                    }
                }
                catch (Exception ex)
                {
                    result.IsSuccess    = false;
                    result.ErrorMessage = ex.Message;
                    return(BadRequest(result));
                }
                if (invoiceWaitingConfirms.Count <= 0 || invoiceWaitingConfirms.Count < invoiceNumsMapLessonQuantity.Count)
                {
                    result.IsSuccess    = false;
                    result.ErrorMessage = "Invoce not found, try to request without apply to invoce";
                    return(BadRequest(result));
                }
                foreach (var i in invoices)
                {
                    if (i.PaidFee > 0)
                    {
                        result.IsSuccess    = false;
                        result.ErrorMessage = "Paid invoce found, try to request without apply to invoce";
                        result.Data         = new List <object>
                        {
                            i
                        };
                        return(BadRequest(result));
                    }
                    else
                    {
                        var fee = invoiceNumMapCoursePrice[i.InvoiceNum] * invoiceNumsMapLessonQuantity[i.InvoiceNum];
                        i.LessonFee      -= fee;
                        i.TotalFee       -= fee;
                        i.OwingFee       -= fee;
                        i.LessonQuantity += invoiceNumsMapLessonQuantity[i.InvoiceNum];
                    }
                }
                foreach (var iw in invoiceWaitingConfirms)
                {
                    if (iw.PaidFee > 0)
                    {
                        result.IsSuccess    = false;
                        result.ErrorMessage = "Paid invoce found, try to request without apply to invoce";
                        result.Data         = new List <object>
                        {
                            iw
                        };
                        return(BadRequest(result));
                    }
                    else
                    {
                        var fee = invoiceNumMapCoursePrice[iw.InvoiceNum] * invoiceNumsMapLessonQuantity[iw.InvoiceNum];
                        iw.LessonFee      -= fee;
                        iw.TotalFee       -= fee;
                        iw.OwingFee       -= fee;
                        iw.LessonQuantity -= invoiceNumsMapLessonQuantity[iw.InvoiceNum];
                    }
                }
            }
            else
            {
                foreach (var l in lessons)
                {
                    awaitMakeUpLessons.Add(new AwaitMakeUpLesson()
                    {
                        CreateAt              = DateTime.UtcNow.ToNZTimezone(),
                        SchduledAt            = null,
                        ExpiredDate           = l.BeginTime.Value.AddMonths(3).Date,
                        MissedLessonId        = l.LessonId,
                        NewLessonId           = null,
                        IsActive              = 1,
                        LearnerId             = l.LearnerId,
                        CourseInstanceId      = l.CourseInstanceId,
                        GroupCourseInstanceId = null,
                        Remaining             = remaining
                    });
                }
            }

            foreach (var cs in courseSchedules)
            {
                if (cs.LearnerId != inputObj.LearnerId)
                {
                    result.IsSuccess    = false;
                    result.ErrorMessage = "InstanceId not match learnerId";
                    return(BadRequest(result));
                }
                Amendment amendment = new Amendment
                {
                    CourseInstanceId = cs.CourseInstanceId,
                    OrgId            = cs.OrgId,
                    DayOfWeek        = cs.DayOfWeek,
                    BeginTime        = null,
                    EndTime          = null,
                    LearnerId        = cs.LearnerId,
                    RoomId           = cs.RoomId,
                    BeginDate        = inputObj.BeginDate,
                    EndDate          = inputObj.EndDate,
                    CreatedAt        = toNZTimezone(DateTime.UtcNow),
                    Reason           = inputObj.Reason,
                    IsTemporary      = null,
                    AmendType        = 1,
                    CourseScheduleId = cs.CourseScheduleId
                };
                amendments.Add(amendment);
            }

            DateTime todoDate = inputObj.EndDate;

            foreach (var holiday in holidays)
            {
                if (holiday.HolidayDate.Date == todoDate.Date)
                {
                    todoDate = todoDate.AddDays(-1);
                }
            }

            DateTime remindScheduledDate = todoDate;

            var teacherIdMapTodoContent    = new Dictionary <short, string>();
            var teacherMapRemindLogContent = new Dictionary <Teacher, string>();

            foreach (var cs in courseSchedules)
            {
                if (!teacherIdMapTodoContent.ContainsKey(cs.TeacherId))
                {
                    teacherIdMapTodoContent.Add(cs.TeacherId, TodoListContentGenerator.DayOffForTeacher(cs, inputObj.EndDate.ToString()));
                }

                teacherMapRemindLogContent.Add(new Teacher
                {
                    TeacherId = cs.TeacherId,
                    Email     = cs.TeacherEmail
                }, RemindLogContentGenerator.DayOffForTeacher(cs, inputObj.EndDate.ToString()));
            }

            using (var dbContextTransaction = _ablemusicContext.Database.BeginTransaction())
            {
                TodoRepository todoRepository = new TodoRepository(_ablemusicContext);
                todoRepository.AddSingleTodoList("Student Leaving Lesson Reminder", TodoListContentGenerator.DayOffForLearner(courseSchedules[0],
                                                                                                                              inputObj.EndDate.ToString()), inputObj.UserId, todoDate, null, courseSchedules[0].LearnerId, null);
                todoRepository.AddMutipleTodoLists("Student Leaving Lesson Reminder", teacherIdMapTodoContent, inputObj.UserId, todoDate, null, null);
                var saveTodoResult = await todoRepository.SaveTodoListsAsync();

                if (!saveTodoResult.IsSuccess)
                {
                    return(BadRequest(saveTodoResult));
                }

                RemindLogRepository remindLogRepository = new RemindLogRepository(_ablemusicContext);
                remindLogRepository.AddSingleRemindLog(courseSchedules[0].LearnerId, courseSchedules[0].LearnerEmail,
                                                       RemindLogContentGenerator.DayOffForLearner(courseSchedules[0], inputObj.EndDate.ToString()), null, "Student Ask Leave Reminder", null, remindScheduledDate);
                remindLogRepository.AddMultipleRemindLogs(teacherMapRemindLogContent, null, "Student Leaving Lesson Reminder", null, remindScheduledDate);
                var saveRemindLogResult = await remindLogRepository.SaveRemindLogAsync();

                if (!saveRemindLogResult.IsSuccess)
                {
                    return(BadRequest(saveRemindLogResult));
                }

                try
                {
                    foreach (var amendment in amendments)
                    {
                        await _ablemusicContext.Amendment.AddAsync(amendment);
                    }
                    if (!inputObj.IsInvoiceChange)
                    {
                        foreach (var makeUpLesson in awaitMakeUpLessons)
                        {
                            await _ablemusicContext.AwaitMakeUpLesson.AddAsync(makeUpLesson);
                        }
                    }
                    await _ablemusicContext.SaveChangesAsync();
                }
                catch (Exception ex)
                {
                    result.IsSuccess    = false;
                    result.ErrorMessage = ex.ToString();
                    return(BadRequest(result));
                }

                string userConfirmUrlPrefix = _configuration.GetSection("UrlPrefix").Value;
                //sending Email
                //List<NotificationEventArgs> notifications = new List<NotificationEventArgs>();
                foreach (var todo in saveTodoResult.Data)
                {
                    var     remind                = saveRemindLogResult.Data.Find(r => r.LearnerId == todo.LearnerId && r.TeacherId == todo.TeacherId);
                    string  currentPersonName     = "";
                    dynamic currentCourseSchedule = null;
                    if (todo.TeacherId == null)
                    {
                        foreach (var cs in courseSchedules)
                        {
                            if (todo.LearnerId == cs.LearnerId)
                            {
                                currentPersonName     = cs.LearnerFirstName + " " + cs.LearnerLastName;
                                currentCourseSchedule = cs;
                            }
                        }
                    }
                    else
                    {
                        foreach (var cs in courseSchedules)
                        {
                            if (todo.TeacherId == cs.TeacherId)
                            {
                                currentPersonName     = cs.TeacherFirstName + " " + cs.TeacherLastName;
                                currentCourseSchedule = cs;
                            }
                        }
                    }
                    string confirmURL  = userConfirmUrlPrefix + todo.ListId + "/" + remind.RemindId;
                    string mailContent = EmailContentGenerator.Dayoff(currentPersonName, currentCourseSchedule, inputObj, confirmURL);
                    remindLogRepository.UpdateContent(remind.RemindId, mailContent);
                    //notifications.Add(new NotificationEventArgs(remind.Email, "Dayoff is expired", mailContent, remind.RemindId));
                }
                var remindLogUpdateContentResult = await remindLogRepository.SaveUpdatedContentAsync();

                if (!remindLogUpdateContentResult.IsSuccess)
                {
                    result.IsSuccess    = false;
                    result.ErrorMessage = remindLogUpdateContentResult.ErrorMessage;
                    return(BadRequest(result));
                }
                //foreach (var mail in notifications)
                //{
                //    _notificationObservable.send(mail);
                //}
                dbContextTransaction.Commit();
            }

            foreach (var amendment in amendments)
            {
                amendment.Learner = null;
            }
            result.Data = new
            {
                EffectedAmendmentCount             = amendments.Count,
                EffectedLessonsCount               = lessons.Count,
                EffectedAwaitMakeUpLessonCount     = awaitMakeUpLessons.Count,
                EffectedInvoiceWaitingConfirmCount = invoiceWaitingConfirms.Count,
                EffectedInvoiceCount               = invoices.Count,
                EffectedAmendments            = amendments,
                EffectedLessons               = lessons,
                EffectedAwaitMakeUpLessons    = awaitMakeUpLessons,
                EffectedInvoiceWaitingConfirm = invoiceWaitingConfirms,
                EffectedInvoices              = invoices,
            };
            return(Ok(result));
        }