Skip to content
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
1 change: 1 addition & 0 deletions api-cinema-challenge/api-cinema-challenge.sln
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{3C371BAA-344D-4C8A-AF08-7829816D726F}"
ProjectSection(SolutionItems) = preProject
..\.gitignore = ..\.gitignore
..\..\..\..\Downloads\CinemaChallengeERD.drawio.png = ..\..\..\..\Downloads\CinemaChallengeERD.drawio.png
..\README.md = ..\README.md
EndProjectSection
EndProject
Expand Down
10 changes: 9 additions & 1 deletion api-cinema-challenge/api-cinema-challenge/Data/CinemaContext.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.EntityFrameworkCore;
using api_cinema_challenge.Models;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json.Linq;

namespace api_cinema_challenge.Data
Expand All @@ -18,8 +19,15 @@ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
optionsBuilder.UseNpgsql(_connectionString);
}

// DbSet properties for each entity
public DbSet<Customer> Customers { get; set; }
public DbSet<Movie> Movies { get; set; }
public DbSet<Screening> Screenings { get; set; }
public DbSet<Ticket> Tickets { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);

}
}
Expand Down
58 changes: 58 additions & 0 deletions api-cinema-challenge/api-cinema-challenge/Data/Seeder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using api_cinema_challenge.Data;
using api_cinema_challenge.Models;
using Microsoft.EntityFrameworkCore;

namespace api_cinema_challenge.Data
{
public static class Seeder
{
public async static Task SeedCinemaData(this WebApplication app)
{
using (var scope = app.Services.CreateScope())
{
var db = scope.ServiceProvider.GetRequiredService<CinemaContext>();

if (!db.Movies.Any())
{
db.Movies.AddRange(
new Movie { Title = "The Matrix", Rating = "R", Description = "A computer hacker learns from mysterious rebels about the true nature of his reality and his role in the war against its controllers.", RuntimeMins = 136, CreatedAt = DateTime.UtcNow, UpdatedAt = DateTime.UtcNow },
new Movie { Title = "Inception", Rating = "PG-13", Description = "A thief who enters the dreams of others to steal secrets from their subconscious is given the inverse task of planting an idea into the mind of a CEO.", RuntimeMins = 148, CreatedAt = DateTime.UtcNow, UpdatedAt = DateTime.UtcNow }
);
await db.SaveChangesAsync();
}

if (!db.Customers.Any())
{
db.Customers.AddRange(
new Customer { Name = "Chris Wolstenholme", Email = "chris@muse.mu", Phone = "+44729388192", CreatedAt = DateTime.UtcNow, UpdatedAt = DateTime.UtcNow },
new Customer { Name = "Jonny Greenwood", Email = "jonny@radiohead.com", Phone = "+44720488192", CreatedAt = DateTime.UtcNow, UpdatedAt = DateTime.UtcNow }
);
await db.SaveChangesAsync();
}

if (!db.Screenings.Any())
{
db.Screenings.AddRange(
new Screening { MovieId = 1, ScreenNumber = 1, Capacity = 100, StartsAt = DateTime.UtcNow.AddDays(1), CreatedAt = DateTime.UtcNow, UpdatedAt = DateTime.UtcNow },
new Screening { MovieId = 2, ScreenNumber = 2, Capacity = 80, StartsAt = DateTime.UtcNow.AddDays(2), CreatedAt = DateTime.UtcNow, UpdatedAt = DateTime.UtcNow }
);
await db.SaveChangesAsync();
}

if (!db.Tickets.Any())
{
var customerChris = db.Customers.First(c => c.Name == "Chris Wolstenholme");
var customerJonny = db.Customers.First(c => c.Name == "Jonny Greenwood");
var screeningMatrix = db.Screenings.First(s => s.MovieId == 1);
var screeningInception = db.Screenings.First(s => s.MovieId == 2);

db.Tickets.AddRange(
new Ticket { CustomerId = customerChris.Id, ScreeningId = screeningMatrix.Id, NumSeats = 2, CreatedAt = DateTime.UtcNow, UpdatedAt = DateTime.UtcNow },
new Ticket { CustomerId = customerJonny.Id, ScreeningId = screeningInception.Id, NumSeats = 1, CreatedAt = DateTime.UtcNow, UpdatedAt = DateTime.UtcNow }
);
await db.SaveChangesAsync();
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using api_cinema_challenge.Models;
using api_cinema_challenge.Repositories.GenericRepositories;
using Microsoft.AspNetCore.Mvc;

namespace api_cinema_challenge.Endpoints
{
public static class CustomerEndpoints
{
public static void ConfigureCustomerApi(this WebApplication app)
{
var customers = app.MapGroup("/customers");
customers.MapPost("/", CreateCustomer);
customers.MapGet("/", GetAllCustomers);
customers.MapPut("/{id}", UpdateCustomer);
customers.MapDelete("/{id}", DeleteCustomer);

}

// Create a Customer
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status201Created)]
public static async Task<IResult> CreateCustomer(Customer customer, IRepository<Customer> repository)
{
await repository.AddAsync(customer);
return TypedResults.Created($"/customers/{customer.Id}", new { status = "success", data = customer });
}

// Get all Customers
[ProducesResponseType(StatusCodes.Status200OK)]
public static async Task<IResult> GetAllCustomers(IRepository<Customer> repository)
{
var customers = await repository.GetAllAsync();
return TypedResults.Ok(new { status = "success", data = customers });
}

// Update a Customer
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status201Created)]
public static async Task<IResult> UpdateCustomer(int id, Customer customer, IRepository<Customer> repository)
{
var existingCustomer = await repository.GetByIdAsync(id);
if (existingCustomer == null)
return TypedResults.NotFound();

existingCustomer.Name = customer.Name;
existingCustomer.Email = customer.Email;
existingCustomer.Phone = customer.Phone;

await repository.UpdateAsync(existingCustomer);
return TypedResults.Created($"/customers/{id}", new { status = "success", data = existingCustomer });
}

// Delete a Customer
[ProducesResponseType(StatusCodes.Status200OK)]
public static async Task<IResult> DeleteCustomer(int id, IRepository<Customer> repository)
{
var customer = await repository.GetByIdAsync(id);
if (customer == null)
return TypedResults.NotFound();

await repository.DeleteAsync(id);
return TypedResults.Ok(new { status = "success", data = customer });
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
using api_cinema_challenge.Models;
using api_cinema_challenge.Repositories.GenericRepositories;
using Microsoft.AspNetCore.Mvc;

namespace api_cinema_challenge.Endpoints
{
public static class MovieEndpoints
{
public static void ConfigureMovieApi(this WebApplication app)
{
var movies = app.MapGroup("/movies");
movies.MapPost("/", CreateMovie);
movies.MapGet("/", GetAllMovies);
movies.MapPut("/{id}", UpdateMovie);
movies.MapDelete("/{id}", DeleteMovie);
}

// Create a Movie
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status201Created)]
public static async Task<IResult> CreateMovie(Movie movie, IRepository<Movie> repository)
{
await repository.AddAsync(movie);
return TypedResults.Created($"/movies/{movie.Id}", new { status = "success", data = movie });
}


// Get all Movies
[ProducesResponseType(StatusCodes.Status200OK)]
public static async Task<IResult> GetAllMovies(IRepository<Movie> repository)
{
var movies = await repository.GetAllAsync();
return TypedResults.Ok(new { status = "success", data = movies });
}

// Update a Movie
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status201Created)]
public static async Task<IResult> UpdateMovie(int id, Movie movie, IRepository<Movie> repository)
{
var existingMovie = await repository.GetByIdAsync(id);
if (existingMovie == null)
return TypedResults.NotFound();

existingMovie.Title = movie.Title;
existingMovie.Rating = movie.Rating;
existingMovie.Description = movie.Description;
existingMovie.RuntimeMins = movie.RuntimeMins;

await repository.UpdateAsync(existingMovie);
return TypedResults.Created($"/movies/{id}", new { status = "success", data = existingMovie });
}

// Delete a Movie
[ProducesResponseType(StatusCodes.Status200OK)]
public static async Task<IResult> DeleteMovie(int id, IRepository<Movie> repository)
{
var movie = await repository.GetByIdAsync(id);
if (movie == null)
return TypedResults.NotFound();

await repository.DeleteAsync(id);
return TypedResults.Ok(new { status = "success", data = movie });
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using api_cinema_challenge.Models;
using api_cinema_challenge.Repositories.SpecificRepositories;
using Microsoft.AspNetCore.Mvc;

namespace api_cinema_challenge.Endpoints
{
public static class ScreeningEndpoints
{

public static void ConfigureScreeningApi(this WebApplication app)
{

var screenings = app.MapGroup("/movies/{movieId}/screenings");
screenings.MapPost("/", CreateScreening);
screenings.MapGet("/", GetAllScreeningsForMovie);
}

// Create a Screening for a Movie
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status201Created)]
public static async Task<IResult> CreateScreening(int movieId, Screening screening, IScreeningRepository screeningRepository)
{
screening.MovieId = movieId;
await screeningRepository.AddAsync(screening);
return TypedResults.Created($"/movies/{movieId}/screenings/{screening.Id}", new { status = "success", data = screening });
}

// Get all Screenings for a Movie
[ProducesResponseType(StatusCodes.Status200OK)]
public static async Task<IResult> GetAllScreeningsForMovie(int movieId, IScreeningRepository screeningRepository)
{
var screenings = await screeningRepository.GetScreeningsByMovieAsync(movieId);
return TypedResults.Ok(new { status = "success", data = screenings });
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using api_cinema_challenge.Models;
using api_cinema_challenge.Repositories.SpecificRepositories;
using Microsoft.AspNetCore.Mvc;

namespace api_cinema_challenge.Endpoints
{
public static class TicketEndpoints
{
public static void ConfigureTicketApi(this WebApplication app)
{
var tickets = app.MapGroup("/customers/{customerId}/screenings/{screeningId}");

tickets.MapPost("/", BookTicket);
tickets.MapGet("/", GetAllTicketsForCustomer);
}

// Book a Ticket for a Customer and Screening
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status201Created)]
public static async Task<IResult> BookTicket(int customerId, int screeningId, Ticket ticket, ITicketRepository ticketRepository)
{
ticket.CustomerId = customerId;
ticket.ScreeningId = screeningId;
await ticketRepository.AddAsync(ticket);
return TypedResults.Created($"/customers/{customerId}/screenings/{screeningId}", new { status = "success", data = ticket });
}

// Get all Tickets for a Customer and Screening
[ProducesResponseType(StatusCodes.Status200OK)]
public static async Task<IResult> GetAllTicketsForCustomer(int customerId, int screeningId, ITicketRepository ticketRepository)
{
var tickets = await ticketRepository.GetTicketsByCustomerAsync(customerId);
return TypedResults.Ok(new { status = "success", data = tickets });
}
}
}
Loading