Skip to content

Commit

Permalink
refactor bookingRequest into service and improve error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
SjoenH committed Apr 18, 2024
1 parent 5e33226 commit c657e0f
Show file tree
Hide file tree
Showing 5 changed files with 178 additions and 76 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
using kabinizer_api.Dtos.BookingRequest;
using kabinizer_api.Model;
using kabinizer_api.Services;
using kabinizer_api.Services.BookingRequest;
using kabinizer_api.Services.Export;
using kabinizer_data;
using kabinizer_data.Entities;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
Expand All @@ -12,71 +11,69 @@ namespace kabinizer_api.Controllers;

[Route("api/[controller]")]
[ApiController]
public class BookingRequestController(EntityContext entityContext, ITokenService tokenService) : ControllerBase
public class BookingRequestController(
EntityContext entityContext,
BookingRequestService bookingRequestService
) : ControllerBase
{
[HttpGet]
public IEnumerable<BookingRequest> GetBookingRequests()
[HttpGet("{id:guid}")]
public async Task<IActionResult> GetBookingRequest([Required] Guid id)
{
var currentUserId = tokenService.GetUserId();
return entityContext.BookingRequests
.Include(br => br.User)
.Include(br => br.Period)
.Where(b => b.UserId == currentUserId)
.AsEnumerable().Select(BookingRequest.FromModel);
try
{
var bookingRequest = await bookingRequestService.GetBookingRequest(id);
return Ok(BookingRequestDto.FromModel(bookingRequest));
}
catch (Exception ex)
{
return NotFound(ex.Message);
}
}

[HttpPost]
public void AddBookingRequests([Required] IEnumerable<CreateBookingRequestDto> requests)
[HttpGet]
public async Task<IActionResult> GetBookingRequests()
{
var currentUserId = tokenService.GetUserId();
var periodIds = requests.Select(e => e.PeriodId).ToList();

var periods = entityContext.Periods
.Where(p => periodIds.Contains(p.Id))
.Include(p => p.Draw)
.ToList();

if (periods.Count != periodIds.Count)
try
{
throw new Exception("One or more periods do not exist");
var bookingRequests = await bookingRequestService.GetBookingRequests();
return Ok(bookingRequests.Select(BookingRequestDto.FromModel));
}
catch (Exception ex)
{
return NotFound(ex.Message);
}
}

var periodsWithoutDraw = periods.Where(p => p.Draw == null).ToList();
if (periodsWithoutDraw.Count != 0)
[HttpPost]
public async Task<IActionResult> AddBookingRequests([Required] IEnumerable<CreateBookingRequestDto> requests)
{
try
{
throw new Exception("One or more periods are not part of a draw");
var bookingRequest = await bookingRequestService.AddBookingRequest(requests.First());
return Ok(BookingRequestDto.FromModel(bookingRequest));
}

var periodsWithEndedDraw = periods.Where(p => p.Draw?.DeadlineEnd > DateTime.Now).ToList();
if (periodsWithEndedDraw.Count != 0)
catch (Exception e)
{
throw new Exception("Cannot make a booking request for a draw that has ended");
return BadRequest(e.Message);
}

var bookingRequestEntities = periodIds.Select(id => new BookingRequestEntity(currentUserId, id));
entityContext.BookingRequests.AddRange(bookingRequestEntities);
entityContext.SaveChanges();
}

[HttpDelete]
public bool DeleteBookingRequests([Required] IEnumerable<Guid> requests)
public async Task<IActionResult> DeleteBookingRequests([Required] IEnumerable<Guid> requests)
{
var currentUserId = tokenService.GetUserId();

foreach (Guid requestId in requests)
try
{
BookingRequestEntity entityToRemove = entityContext.BookingRequests.Single(br => br.Id == requestId);

if (entityToRemove.UserId != currentUserId)
foreach (Guid request in requests)
{
throw new Exception("You cannot remove a booking request for another user");
await bookingRequestService.DeleteBookingRequest(request);
}

entityContext.BookingRequests.Remove(entityToRemove);
return Ok("Booking requests deleted");
}
catch (Exception e)
{
return BadRequest(e.Message);
}

entityContext.SaveChanges();
return true;
}

[HttpGet]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using kabinizer_data.Entities;

namespace kabinizer_api.Dtos.BookingRequest;

public class BookingRequestDto(
Guid id,
Guid userId,
Guid periodId,
DateTime createdDate,
Guid createdBy,
DateTime? updatedDate,
Guid? updatedBy,
UserEntity user,
PeriodEntity period)
{
public Guid Id { get; set; } = id;
public Guid UserId { get; set; } = userId;
public UserEntity User { get; set; } = user;
public PeriodEntity Period { get; set; } = period;
public Guid PeriodId { get; set; } = periodId;
public DateTime CreatedDate { get; set; } = createdDate;
public Guid CreatedBy { get; set; } = createdBy;
public DateTime? UpdatedDate { get; set; } = updatedDate;
public Guid? UpdatedBy { get; set; } = updatedBy;

public static BookingRequestDto FromModel(BookingRequestEntity? e)
{
return new BookingRequestDto(e.Id, e.UserId, e.PeriodId, e.CreatedDate, e.CreatedBy, e.UpdatedDate, e.UpdatedBy,

Check warning on line 28 in kabinizer-back-end/kabinizer-api/Dtos/BookingRequest/BookingRequestDto.cs

View workflow job for this annotation

GitHub Actions / build

Dereference of a possibly null reference.

Check warning on line 28 in kabinizer-back-end/kabinizer-api/Dtos/BookingRequest/BookingRequestDto.cs

View workflow job for this annotation

GitHub Actions / build

Dereference of a possibly null reference.
e.User, e.Period);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
using kabinizer_api.Dtos.BookingRequest;
using kabinizer_data;
using kabinizer_data.Entities;
using Microsoft.EntityFrameworkCore;

namespace kabinizer_api.Services.BookingRequest;

public abstract class BookingRequestService(EntityContext entityContext, ITokenService tokenService)
{
private async Task<BookingRequestEntity?> GetBookingRequestById(Guid bookingRequestId)
{
return await entityContext.BookingRequests
.Include(br => br.User)
.Include(br => br.Period)
.FirstOrDefaultAsync(b => b.Id == bookingRequestId && b.UserId == tokenService.GetUserId())
?? throw new InvalidOperationException("No matching booking request found.");
}

public async Task<BookingRequestEntity?> GetBookingRequest(Guid bookingRequestId)
{
BookingRequestEntity? id = await GetBookingRequestById(bookingRequestId);
if (id == null)
{
throw new Exception("Booking request does not exist or does not belong to the current user");
}

return id;
}

public async Task<IEnumerable<BookingRequestEntity>> GetBookingRequests()
{
var bookingRequestEntities = await entityContext.BookingRequests
.Include(br => br.User)
.Include(br => br.Period)
.Where(b => b.UserId == tokenService.GetUserId())
.ToListAsync();
if (bookingRequestEntities == null)
{
throw new Exception("No booking requests found for the current user");
}

return bookingRequestEntities;
}

public async Task<BookingRequestEntity?> AddBookingRequest(CreateBookingRequestDto request)
{
var period = await entityContext.Periods
.Include(p => p.Draw)
.FirstOrDefaultAsync(p => p.Draw != null && p.Id == request.PeriodId && p.Draw.DeadlineEnd >= DateTime.Now);

if (period == null)
{
throw new Exception("Period does not exist, is not part of a draw, or the draw has ended");
}

var user = await entityContext.Users.FirstOrDefaultAsync(u => u.Id == tokenService.GetUserId());
if (user == null)
{
throw new Exception("User does not exist");
}

var bookingRequest = new BookingRequestEntity(tokenService.GetUserId(), request.PeriodId, user, period);
entityContext.BookingRequests.Add(bookingRequest);
await entityContext.SaveChangesAsync();
return bookingRequest;
}

public async Task<bool> DeleteBookingRequest(Guid bookingRequestId)
{
var bookingRequest = await GetBookingRequestById(bookingRequestId);
if (bookingRequest == null)
{
throw new Exception(
$"Booking request with id {bookingRequestId} does not exist or does not belong to the current user");
}

entityContext.BookingRequests.Remove(bookingRequest);
await entityContext.SaveChangesAsync();
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace kabinizer_api.Services.Export;

public static class CsvService
{
public static byte[] ExportToCsv(IEnumerable<BookingRequest> requests)
public static byte[] ExportToCsv(IEnumerable<Model.BookingRequest> requests)
{
using MemoryStream memoryStream = new();
using StreamWriter streamWriter = new(memoryStream);
Expand All @@ -25,7 +25,7 @@ private static int ConvertDateToWeekNumber(DateTime date)
return ISOWeek.GetWeekOfYear(date);
}

private static IEnumerable<CsvRecord> ConvertToCsvRecords(IEnumerable<BookingRequest> bookingRequests)
private static IEnumerable<CsvRecord> ConvertToCsvRecords(IEnumerable<Model.BookingRequest> bookingRequests)
{
return bookingRequests
.GroupBy(
Expand Down
49 changes: 21 additions & 28 deletions kabinizer-back-end/kabinizer-data/Entities/BookingRequestEntity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,29 @@
namespace kabinizer_data.Entities;

[Table("BookingRequest")]
public class BookingRequestEntity
public class BookingRequestEntity(
Guid id,
Guid userId,
Guid periodId,
DateTime createdDate,
Guid createdBy,
DateTime? updatedDate,
Guid? updatedBy,
UserEntity user,
PeriodEntity period)
{
public Guid Id { get; set; }
public Guid UserId { get; set; }
public UserEntity User { get; set; }
public PeriodEntity Period { get; set; }
public Guid PeriodId { get; set; }
public DateTime CreatedDate { get; set; }
public Guid CreatedBy { get; set; }
public DateTime? UpdatedDate { get; set; }
public Guid? UpdatedBy { get; set; }
public Guid Id { get; set; } = id;
public Guid UserId { get; set; } = userId;
public UserEntity User { get; set; } = user;
public PeriodEntity Period { get; set; } = period;
public Guid PeriodId { get; set; } = periodId;
public DateTime CreatedDate { get; set; } = createdDate;
public Guid CreatedBy { get; set; } = createdBy;
public DateTime? UpdatedDate { get; set; } = updatedDate;
public Guid? UpdatedBy { get; set; } = updatedBy;

public BookingRequestEntity(Guid id, Guid userId, Guid periodId, DateTime createdDate,
Guid createdBy, DateTime? updatedDate, Guid? updatedBy)
public BookingRequestEntity(Guid userId, Guid periodId, UserEntity user, PeriodEntity period) : this(Guid.NewGuid(),
userId, periodId, DateTime.Now, userId, null, null, user, period)
{
Id = id;
UserId = userId;
PeriodId = periodId;
CreatedDate = createdDate;
CreatedBy = createdBy;
UpdatedDate = updatedDate;
UpdatedBy = updatedBy;
}

public BookingRequestEntity(Guid userId, Guid periodId)
{
Id = Guid.NewGuid();
UserId = userId;
PeriodId = periodId;
CreatedDate = DateTime.Now;
CreatedBy = userId; // Is this even needed? Won't it always be the same as the user id?
}
}

0 comments on commit c657e0f

Please sign in to comment.