public async Task <Unit> Handle(DeleteRideshareCommand request, CancellationToken cancellationToken) { var entity = await _context.Rideshares .Include(r => r.Car) .FirstOrDefaultAsync(r => r.Id == request.Id); if (entity == null) { throw new NotFoundException(nameof(Rideshare), request.Id); } // Don't rely on cascade, manually remove all EmployeeRideshare entities var employeeRideshares = await _context.EmployeeRideshares .Where(er => er.RideshareId == request.Id) .ToListAsync(); _context.EmployeeRideshares.RemoveRange(employeeRideshares); _context.Rideshares.Remove(entity); await _context.SaveChangesAsync(cancellationToken); return(Unit.Value); }
public async Task <int> Handle(CreateRideshareCommand request, CancellationToken cancellationToken) { // TODO: Split into multiple smaller methods // Date validation logic if (request.StartDate.Value >= request.EndDate) { throw new InvalidDateException(InvalidDateMessageEnum.StartAfterEnd); } // Check if selected car exists var car = await _context.Cars .FindAsync(request.Car.Id); if (car == null) { throw new NotFoundException(nameof(Car), request.Car.Id); } // Check if specified employees exist foreach (var e in request.Employees) { var employee = await _context.Employees .FindAsync(e.Id); if (employee == null) { throw new NotFoundException(nameof(Employee), e.Id); } } // Check if car is available during selected time period var rideshares = await _context.Rideshares .Include(r => r.Car) .Where(r => r.Car.Id == request.Car.Id) .Where(r => r.EndDate > request.StartDate) .ToListAsync(); foreach (var r in rideshares) { if (request.StartDate < r.StartDate) { if (request.EndDate > r.StartDate) { throw new InvalidDateException(InvalidDateMessageEnum.TravelPeriodTaken); } } else { if (request.StartDate < r.EndDate) { throw new InvalidDateException(InvalidDateMessageEnum.TravelPeriodTaken); } } } // Check if employees can fit into select car var employees = await _context.Employees .Select(ce => new { ce.Id, ce.IsDriver }) .Where(ce => request.Employees.Select(re => re.Id).Contains(ce.Id)) .ToListAsync(); if (employees.Count > car.NumberOfSeats) { throw new TooManyEmployeesException(request.Car.Id); } // Check if at least one employee is a driver if (!employees.Any(e => e.IsDriver)) { throw new NoDriverException(); } // Create new Rideshare entity var entity = new Rideshare { StartLocation = request.StartLocation, EndLocation = request.EndLocation, StartDate = request.StartDate, EndDate = request.EndDate, Car = car }; foreach (var e in request.Employees) { var er = new EmployeeRideshare { Employee = await _context.Employees.FindAsync(e.Id), EmployeeId = e.Id, Rideshare = entity, RideshareId = entity.Id }; entity.EmployeeRideshares.Add(er); } _context.Rideshares.Add(entity); await _context.SaveChangesAsync(cancellationToken); return(entity.Id); }
public async Task <Unit> Handle(UpdateRideshareCommand request, CancellationToken cancellationToken) { var entity = await _context.Rideshares .Include(r => r.Car) .FirstOrDefaultAsync(r => r.Id == request.Id); if (entity == null) { throw new NotFoundException(nameof(Rideshare), request.Id); } // TODO: Split into multiple smaller methods // TODO: optimize this to skip checking unchanged fields // Date validation logic if (request.StartDate.Value >= request.EndDate) { throw new InvalidDateException(InvalidDateMessageEnum.StartAfterEnd); } // Check if selected car exists var car = await _context.Cars .FindAsync(request.Car.Id); if (car == null) { throw new NotFoundException(nameof(Car), request.Car.Id); } // Check if specified employees exist foreach (var e in request.Employees) { var employee = await _context.Employees .FindAsync(e.Id); if (employee == null) { throw new NotFoundException(nameof(Employee), e.Id); } } // Check if car is available during selected time period var rideshares = await _context.Rideshares .Include(r => r.Car) .Where(r => r.Car.Id == request.Car.Id) .Where(r => r.EndDate > request.StartDate) .Where(r => r.Id != request.Id) // since we want to update this rideshare we skip checking on it .ToListAsync(); foreach (var r in rideshares) { if (request.StartDate < r.StartDate) { if (request.EndDate > r.StartDate) { throw new InvalidDateException(InvalidDateMessageEnum.TravelPeriodTaken); } } else { if (request.StartDate < r.EndDate) { throw new InvalidDateException(InvalidDateMessageEnum.TravelPeriodTaken); } } } // Check if employees can fit into select car var employees = await _context.Employees .Select(ce => new { ce.Id, ce.IsDriver }) .Where(ce => request.Employees.Select(re => re.Id).Contains(ce.Id)) .ToListAsync(); if (employees.Count > car.NumberOfSeats) { throw new TooManyEmployeesException(request.Car.Id); } // Check if at least one employee is a driver if (!employees.Any(e => e.IsDriver)) { throw new NoDriverException(); } entity.StartLocation = request.StartLocation; entity.EndLocation = request.EndLocation; entity.StartDate = request.StartDate; entity.EndDate = request.EndDate; entity.Car = car; // Remove old employee-rideshare entities and remake them with new IDs var erForRemoval = await _context.EmployeeRideshares .Where(er => er.RideshareId == request.Id) .ToListAsync(); _context.EmployeeRideshares.RemoveRange(erForRemoval); entity.EmployeeRideshares.Clear(); foreach (var e in request.Employees) { var er = new EmployeeRideshare { Employee = await _context.Employees.FindAsync(e.Id), EmployeeId = e.Id, Rideshare = entity, RideshareId = entity.Id }; entity.EmployeeRideshares.Add(er); } await _context.SaveChangesAsync(cancellationToken); return(Unit.Value); }