public async Task AddAppointmentShouldReturnNull(string clientId, string trainerId)
        {
            var options = new DbContextOptionsBuilder <ApplicationDbContext>()
                          .UseInMemoryDatabase(Guid.NewGuid().ToString()).Options;
            var db = new ApplicationDbContext(options);
            var appointmentsRepository = new EfDeletableEntityRepository <Appointment>(db);
            var usersRepository        = new EfDeletableEntityRepository <ApplicationUser>(db);
            var notificationsService   = new Mock <INotificationsService>();

            var service = new AppointmentsService(
                appointmentsRepository,
                usersRepository,
                notificationsService.Object);

            var inputModel = new AddAppointmentInputModel()
            {
                StartTime  = DateTime.UtcNow,
                EndTime    = DateTime.UtcNow.AddDays(2),
                ClientId   = clientId,
                TrainerId  = trainerId,
                IsApproved = true,
                Notes      = null,
                Type       = AppointmentType.Consultation,
            };

            var result = await service.AddAppoinmentAsync(inputModel);

            Assert.Null(result);
        }
        public async Task <IActionResult> Request()
        {
            var userId    = this.HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value;
            var viewModel = new AddAppointmentInputModel()
            {
                TrainersOptions = await this.trainersService
                                  .GetAllTrainersAsync <TrainerOptionsViewModel>(userId),
            };

            viewModel.ClientId = userId;

            return(this.View(viewModel));
        }
        public async Task GetAppointmentRequestsForTrainerShouldNotThrow()
        {
            var options = new DbContextOptionsBuilder <ApplicationDbContext>()
                          .UseInMemoryDatabase(Guid.NewGuid().ToString()).Options;
            var db = new ApplicationDbContext(options);
            var appointmentsRepository = new EfDeletableEntityRepository <Appointment>(db);
            var usersRepository        = new EfDeletableEntityRepository <ApplicationUser>(db);
            var notificationsService   = new Mock <INotificationsService>();

            var service = new AppointmentsService(
                appointmentsRepository,
                usersRepository,
                notificationsService.Object);

            var client       = new ApplicationUser();
            var trainer      = new ApplicationUser();
            var role         = new ApplicationRole(GlobalConstants.TrainerRoleName);
            var identityRole = new IdentityUserRole <string>()
            {
                RoleId = role.Id,
                UserId = trainer.Id,
            };

            trainer.Roles.Add(identityRole);

            await usersRepository.AddAsync(trainer);

            await usersRepository.AddAsync(client);

            await usersRepository.SaveChangesAsync();

            var inputModel = new AddAppointmentInputModel()
            {
                StartTime  = DateTime.UtcNow,
                EndTime    = DateTime.UtcNow.AddDays(2),
                ClientId   = client.Id,
                TrainerId  = trainer.Id,
                IsApproved = true,
                Notes      = "Plamen",
                Type       = AppointmentType.Consultation,
            };

            var appointment = await service.AddAppoinmentAsync(inputModel);

            var result = await service.GetAppointmentRequestsForTrainer <TestAppointmentModel>(trainer.Id);

            Assert.Empty(result);
        }
        public async Task <IActionResult> Add()
        {
            var trainer = await this.userManager.GetUserAsync(this.User);

            string trainerId = await this.userManager.GetUserIdAsync(trainer);

            var viewModel = new AddAppointmentInputModel()
            {
                ClientsOptions = await this.usersService
                                 .GetAllUsersAsync <ClientOptionsViewModel>(trainerId),
            };

            viewModel.TrainerId = trainerId;

            return(this.View(viewModel));
        }
        public async Task ApproveAppointmentShouldThrow(string clientId, string trainerId, int appointmentId)
        {
            var options = new DbContextOptionsBuilder <ApplicationDbContext>()
                          .UseInMemoryDatabase(Guid.NewGuid().ToString()).Options;
            var db = new ApplicationDbContext(options);
            var appointmentsRepository = new EfDeletableEntityRepository <Appointment>(db);
            var usersRepository        = new EfDeletableEntityRepository <ApplicationUser>(db);
            var notificationsService   = new Mock <INotificationsService>();

            var service = new AppointmentsService(
                appointmentsRepository,
                usersRepository,
                notificationsService.Object);

            var client       = new ApplicationUser();
            var trainer      = new ApplicationUser();
            var role         = new ApplicationRole(GlobalConstants.TrainerRoleName);
            var identityRole = new IdentityUserRole <string>()
            {
                RoleId = role.Id,
                UserId = trainer.Id,
            };

            trainer.Roles.Add(identityRole);

            await usersRepository.AddAsync(trainer);

            await usersRepository.AddAsync(client);

            await usersRepository.SaveChangesAsync();

            var inputModel = new AddAppointmentInputModel()
            {
                StartTime  = DateTime.UtcNow,
                EndTime    = DateTime.UtcNow.AddDays(3),
                ClientId   = client.Id,
                TrainerId  = trainer.Id,
                IsApproved = true,
                Notes      = null,
                Type       = AppointmentType.Consultation,
            };

            var appointment = await service.AddAppoinmentAsync(inputModel);

            await Assert.ThrowsAnyAsync <InvalidOperationException>(async() =>
                                                                    await service.ApproveAppointment(appointmentId, trainerId, clientId));
        }
        public async Task <IActionResult> Request(AddAppointmentInputModel inputModel)
        {
            var userId = this.HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value;

            if (!this.ModelState.IsValid)
            {
                inputModel.TrainersOptions = await this.trainersService
                                             .GetAllTrainersAsync <TrainerOptionsViewModel>(userId);

                return(this.View(inputModel));
            }

            if (this.appointmentsService.IsEndTimeSoonerThanStartTime(inputModel.StartTime.Value, inputModel.EndTime.Value))
            {
                this.ModelState.AddModelError("StartTime", "End time should be later than start time!");

                inputModel.TrainersOptions = await this.trainersService
                                             .GetAllTrainersAsync <TrainerOptionsViewModel>(userId);

                return(this.View(inputModel));
            }

            if (this.appointmentsService.IsStartTimePast(inputModel.StartTime.Value))
            {
                this.ModelState.AddModelError("StartTime", "Appointment cannot be in the past!");

                inputModel.TrainersOptions = await this.trainersService
                                             .GetAllTrainersAsync <TrainerOptionsViewModel>(userId);

                return(this.View(inputModel));
            }

            inputModel.IsApproved = false;
            var result = await this.appointmentsService.AddAppoinmentAsync(inputModel);

            if (result == null)
            {
                return(this.BadRequest());
            }

            return(this.Redirect("/Appointments/MyAppointments"));
        }
        public async Task <IActionResult> Add(AddAppointmentInputModel inputModel)
        {
            if (!this.ModelState.IsValid)
            {
                inputModel.ClientsOptions = await this.usersService
                                            .GetAllUsersAsync <ClientOptionsViewModel>(inputModel.TrainerId);

                return(this.View(inputModel));
            }

            if (this.appointmentsService.IsEndTimeSoonerThanStartTime(inputModel.StartTime.Value, inputModel.EndTime.Value))
            {
                this.ModelState.AddModelError("StartTime", "End time should be later than start time!");

                inputModel.ClientsOptions = await this.usersService
                                            .GetAllUsersAsync <ClientOptionsViewModel>(inputModel.TrainerId);

                return(this.View(inputModel));
            }

            if (this.appointmentsService.IsStartTimePast(inputModel.StartTime.Value))
            {
                this.ModelState.AddModelError("StartTime", "Appointment cannot be in the past!");

                inputModel.ClientsOptions = await this.usersService
                                            .GetAllUsersAsync <ClientOptionsViewModel>(inputModel.TrainerId);

                return(this.View(inputModel));
            }

            inputModel.IsApproved = true;
            var result = await this.appointmentsService.AddAppoinmentAsync(inputModel);

            if (result == null)
            {
                return(this.BadRequest());
            }

            return(this.Redirect("/Trainers/Dashboard/Index"));
        }
        public async Task <Appointment> AddAppoinmentAsync(AddAppointmentInputModel inputModel)
        {
            var trainer = await this.usersRepository
                          .All()
                          .FirstOrDefaultAsync(x => x.Id == inputModel.TrainerId && x.Roles.Any());

            var client = await this.usersRepository
                         .All()
                         .FirstOrDefaultAsync(x => x.Id == inputModel.ClientId && !x.Roles.Any());

            if (trainer == null || client == null)
            {
                return(null);
            }

            var appointment = new Appointment()
            {
                Client     = client,
                ClientId   = inputModel.ClientId,
                Trainer    = trainer,
                TrainerId  = inputModel.TrainerId,
                StartTime  = inputModel.StartTime.Value,
                EndTime    = inputModel.EndTime.Value,
                Type       = inputModel.Type,
                Notes      = inputModel.Notes,
                IsApproved = inputModel.IsApproved,
            };

            trainer.TrainerAppointments.Add(appointment);
            client.ClientAppointments.Add(appointment);

            await this.appointmentsRepository.AddAsync(appointment);

            await this.appointmentsRepository.SaveChangesAsync();

            if (inputModel.IsApproved)
            {
                await this.notificationsService.CreateNotificationAsync(
                    $"You have new appointment with {trainer.FirstName} {trainer.LastName} for " +
                    $"{appointment.StartTime.Hour.ToString("d2")}:{appointment.StartTime.Minute.ToString("d2")} " +
                    $"o'clock on {appointment.StartTime.Date.DayOfWeek}",
                    $"/Appointments/MyAppointments",
                    client.Id);

                await this.notificationsService.CreateNotificationAsync(
                    $"You have new appointment with {client.FirstName} {client.LastName} for " +
                    $"{appointment.StartTime.Hour.ToString("d2")}:{appointment.StartTime.Minute.ToString("d2")} " +
                    $"o'clock on {appointment.StartTime.Date.DayOfWeek}",
                    $"/Trainers/Appointments/",
                    trainer.Id);
            }
            else
            {
                await this.notificationsService.CreateNotificationAsync(
                    $"You have sent an appointment request for {appointment.Type.ToString()} " +
                    $"with {trainer.FirstName} {trainer.LastName} for " +
                    $"{appointment.StartTime.Hour.ToString("d2")}:{appointment.StartTime.Minute.ToString("d2")} " +
                    $"o'clock on {appointment.StartTime.Date.DayOfWeek}",
                    $"/Appointments/MyAppointments",
                    client.Id);

                await this.notificationsService.CreateNotificationAsync(
                    $"You have recieved an appointment request for {appointment.Type.ToString()} " +
                    $"with {trainer.FirstName} {trainer.LastName} for " +
                    $"{appointment.StartTime.Hour.ToString("d2")}:{appointment.StartTime.Minute.ToString("d2")} " +
                    $"o'clock on {appointment.StartTime.Date.DayOfWeek}",
                    $"/Trainers/Appointments/Requests",
                    trainer.Id);
            }

            return(appointment);
        }