Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Anbar Hussain #4

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 89 additions & 16 deletions api/Controllers/ReservationController.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System.Text.RegularExpressions;
using Microsoft.AspNetCore.Mvc;
using Models;
using Models.Errors;
using Models.Validators;
using Repositories;

namespace Controllers
Expand All @@ -9,18 +11,32 @@ namespace Controllers
public class ReservationController : Controller
{
private ReservationRepository _repo { get; set; }
private readonly ReservationValidator _validator;
private readonly RoomValidator _roomValidator;
private readonly ILogger<ReservationController> _logger;

public ReservationController(ReservationRepository reservationRepository)
public ReservationController(ReservationRepository reservationRepository, ReservationValidator reservationValidator, RoomValidator roomValidator, ILogger<ReservationController> logger)
{
_repo = reservationRepository;
_validator = reservationValidator;
_roomValidator = roomValidator;
_logger = logger;
}

[HttpGet, Produces("application/json"), Route("")]
public async Task<ActionResult<Reservation>> GetReservations()
{
var reservations = await _repo.GetReservations();

return Json(reservations);
try
{
var reservations = await _repo.GetReservations();
_logger.LogInformation("Successfully fetched {ReservationCount} reservations.", reservations.Count());
return Json(reservations);
}
catch (Exception ex)
{
_logger.LogError(ex, "An error occurred while fetching reservations.");
return StatusCode(500, "An error occurred while fetching the reservations.");
}
}

[HttpGet, Produces("application/json"), Route("{reservationId}")]
Expand All @@ -29,12 +45,19 @@ public async Task<ActionResult<Reservation>> GetRoom(Guid reservationId)
try
{
var reservation = await _repo.GetReservation(reservationId);
_logger.LogInformation("Successfully fetched reservation with ID {ReservationId}.", reservationId);
return Json(reservation);
}
catch (NotFoundException)
{
_logger.LogWarning("Reservation with ID {ReservationId} not found.", reservationId);
return NotFound();
}
catch (Exception ex)
{
_logger.LogError(ex, "An error occurred while fetching the reservation with ID {ReservationId}.", reservationId);
return StatusCode(500, "An error occurred while fetching the reservation.");
}
}

/// <summary>
Expand All @@ -43,36 +66,86 @@ public async Task<ActionResult<Reservation>> GetRoom(Guid reservationId)
/// <param name="newBooking"></param>
/// <returns></returns>
[HttpPost, Produces("application/json"), Route("")]
public async Task<ActionResult<Reservation>> BookReservation(
[FromBody] Reservation newBooking
)
public async Task<ActionResult<Reservation>> BookReservation([FromBody] Reservation newBooking)


{
// Provide a real ID if one is not provided
if (newBooking.Id == Guid.Empty)
var validationResult = _validator.ValidateReservation(newBooking);
if (!validationResult.IsValid)
{
_logger.LogWarning("Invalid reservation: {ErrorMessage}", validationResult.ErrorMessage);
return BadRequest(validationResult.ErrorMessage);
}

if (!_roomValidator.IsValidRoomNumber(newBooking.RoomNumber))
{
newBooking.Id = Guid.NewGuid();
_logger.LogWarning("Invalid room number provided: {RoomNumber}", newBooking.RoomNumber);
return BadRequest("Invalid room number. Ensure it follows the proper format and rules.");
}

try
{
if (newBooking.Id == Guid.Empty)
{
newBooking.Id = Guid.NewGuid();
}

var createdReservation = await _repo.CreateReservation(newBooking);
return Created($"/reservation/${createdReservation.Id}", createdReservation);
_logger.LogInformation("Successfully created a reservation with ID {ReservationId}.", createdReservation.Id);
return Created($"/reservation/{createdReservation.Id}", createdReservation);
}
catch (Exception ex)
{
Console.WriteLine("An error occured when trying to book a reservation:");
Console.WriteLine(ex.ToString());
_logger.LogError(ex, "An error occurred while trying to book a reservation.");
return BadRequest("An error occurred while processing the reservation.");


return BadRequest("Invalid reservation");
}
}

[HttpDelete, Produces("application/json"), Route("{reservationId}")]
public async Task<IActionResult> DeleteReservation(Guid reservationId)
{
var result = await _repo.DeleteReservation(reservationId);
try
{
var result = await _repo.DeleteReservation(reservationId);
if (result)
{
_logger.LogInformation("Reservation with ID {ReservationId} successfully deleted.", reservationId);
return NoContent();
}
else
{
_logger.LogWarning("Reservation with ID {ReservationId} not found for deletion.", reservationId);
return NotFound();
}
}
catch (Exception ex)
{
_logger.LogError(ex, "An error occurred while trying to delete reservation with ID {ReservationId}.", reservationId);
return StatusCode(500, "An error occurred while deleting the reservation.");
}
}

return result ? NoContent() : NotFound();
[HttpGet("upcoming")]
public async Task<IActionResult> GetUpcomingReservations()
{
try
{
var upcomingReservations = await _repo.GetUpcomingReservations();

if (upcomingReservations == null || !upcomingReservations.Any())
{
return NoContent();
}

return Ok(upcomingReservations);
}
catch (Exception ex)
{
return StatusCode(500, $"An error occurred: {ex.Message}");
}
}
}
}

96 changes: 83 additions & 13 deletions api/Controllers/RoomController.cs
Original file line number Diff line number Diff line change
@@ -1,64 +1,111 @@
using Microsoft.AspNetCore.Mvc;
using Models;
using Models.Errors;
using Models.Validators;
using Repositories;
using Microsoft.Extensions.Caching.Memory;

namespace Controllers
{
[Tags("Rooms"), Route("room")]
public class RoomController : Controller
{
private RoomRepository _repo { get; set; }
private readonly RoomValidator _roomValidator;
private readonly ILogger<RoomController> _logger;
private readonly IMemoryCache _cache;

public RoomController(RoomRepository roomRepository)
public RoomController(RoomRepository roomRepository, RoomValidator roomValidator, ILogger<RoomController> logger, IMemoryCache memoryCache)
{
_repo = roomRepository;
_roomValidator = roomValidator;
_logger = logger;
_cache = memoryCache;
}

[HttpGet, Produces("application/json"), Route("")]
public async Task<ActionResult<Room>> GetRooms()
{
var rooms = await _repo.GetRooms();
try
{
var rooms = await _repo.GetRooms();

if (rooms == null)
if (rooms == null)
{
_logger.LogWarning("No rooms found in the database.");
return Json(Enumerable.Empty<Room>());
}

_logger.LogInformation("Retrieved all rooms from the database.");
return Json(rooms);
}
catch (Exception ex)
{
return Json(Enumerable.Empty<Room>());
_logger.LogError(ex, "An error occurred while fetching rooms.");
return StatusCode(500, "An error occurred while fetching rooms.");
}

return Json(rooms);

}

[HttpGet, Produces("application/json"), Route("{roomNumber}")]
public async Task<ActionResult<Room>> GetRoom(string roomNumber)
{
if (roomNumber.Length != 3)
if (!_roomValidator.IsValidRoomNumber(roomNumber))
{
return BadRequest("Invalid room ID - format is ###, ex 001 / 002 / 101");
_logger.LogWarning("Invalid room number format: {RoomNumber}", roomNumber);
return BadRequest("Invalid room number. Ensure it follows the proper format and rules.");
}

try
{
var room = await _repo.GetRoom(roomNumber);

if (room == null)
{
_logger.LogWarning("Room not found: {RoomNumber}", roomNumber);
return NotFound();
}

_logger.LogInformation("Room retrieved successfully: {RoomNumber}", roomNumber);
return Json(room);
}
catch (NotFoundException)
catch (Exception ex)
{
return NotFound();
_logger.LogError(ex, "An error occurred while fetching the room with number {RoomNumber}.", roomNumber);
return StatusCode(500, "An error occurred while fetching the room.");
}
}

[HttpPost, Produces("application/json"), Route("")]
public async Task<ActionResult<Room>> CreateRoom([FromBody] Room newRoom)
{
var createdRoom = await _repo.CreateRoom(newRoom);
if (!_roomValidator.IsValidRoomNumber(newRoom.Number))


if (createdRoom == null)
{
return NotFound();
_logger.LogWarning("Invalid room number format: {RoomNumber}", newRoom.Number);
return BadRequest("Invalid room number. Ensure it follows the proper format and rules.");
}

return Json(createdRoom);
try
{
var createdRoom = await _repo.CreateRoom(newRoom);

if (createdRoom == null)
{
_logger.LogWarning("Failed to create room with number: {RoomNumber}", newRoom.Number);
return NotFound();
}

_logger.LogInformation("Room created successfully: {RoomNumber}", newRoom.Number);
return Json(createdRoom);
}
catch (Exception ex)
{
_logger.LogError(ex, "An error occurred while creating the room with number {RoomNumber}.", newRoom.Number);
return StatusCode(500, "An error occurred while creating the room.");
}
}

[HttpDelete, Produces("application/json"), Route("{roomNumber}")]
Expand All @@ -73,5 +120,28 @@ public async Task<IActionResult> DeleteRoom(string roomNumber)

return deleted ? NoContent() : NotFound();
}

[HttpGet, Produces("application/json"), Route("checkRoomAvailability")]
public async Task<ActionResult> CheckRoomAvailability(string roomNumber, string startDate, string endDate)
{
try
{
string cacheKey = $"{roomNumber}_{startDate}_{endDate}";

if (!_cache.TryGetValue(cacheKey, out bool isAvailable))
{
isAvailable = await _repo.CheckRoomAvailability(roomNumber, startDate, endDate);

_cache.Set(cacheKey, isAvailable, TimeSpan.FromMinutes(15));
}

return Json(new { available = isAvailable });
}
catch (Exception ex)
{
_logger.LogError(ex, "An error occurred while checking room availability.");
return StatusCode(500, "An error occurred while checking availability.");
}
}
}
}
Loading