diff --git a/Backend/backend_assessment/CineFlex/CineFlex.API/CineFlex.API.csproj b/Backend/backend_assessment/CineFlex/CineFlex.API/CineFlex.API.csproj
index 8471c9b1d..2b06cb521 100644
--- a/Backend/backend_assessment/CineFlex/CineFlex.API/CineFlex.API.csproj
+++ b/Backend/backend_assessment/CineFlex/CineFlex.API/CineFlex.API.csproj
@@ -12,12 +12,14 @@
all
runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.API/Controllers/AccountController.cs b/Backend/backend_assessment/CineFlex/CineFlex.API/Controllers/AccountController.cs
new file mode 100644
index 000000000..27b2a6508
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.API/Controllers/AccountController.cs
@@ -0,0 +1,30 @@
+using CineFlex.Application.Contracts.Identity;
+using CineFlex.Application.Models.Identity;
+using Microsoft.AspNetCore.Mvc;
+using System.Threading.Tasks;
+
+namespace CineFlex.Api.Controllers
+{
+ [Route("api/[controller]")]
+ [ApiController]
+ public class AccountController : ControllerBase
+ {
+ private readonly IAuthService _authenticationService;
+ public AccountController(IAuthService authenticationService)
+ {
+ _authenticationService = authenticationService;
+ }
+
+ [HttpPost("login")]
+ public async Task> Login(AuthRequest request)
+ {
+ return Ok(await _authenticationService.Login(request));
+ }
+
+ [HttpPost("register")]
+ public async Task> Register(RegistrationRequest request)
+ {
+ return Ok(await _authenticationService.Register(request));
+ }
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.API/Controllers/SeatController.cs b/Backend/backend_assessment/CineFlex/CineFlex.API/Controllers/SeatController.cs
new file mode 100644
index 000000000..712925aa3
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.API/Controllers/SeatController.cs
@@ -0,0 +1,53 @@
+using CineFlex.Application.Features.Seats.CQRS.Commands;
+using CineFlex.Application.Features.Seats.CQRS.Queries;
+using CineFlex.Application.Features.Seats.DTO;
+using MediatR;
+using Microsoft.AspNetCore.Mvc;
+using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database;
+
+namespace CineFlex.API.Controllers
+{
+ [Route("api/[Controller]")]
+ [ApiController]
+ public class SeatController : BaseApiController
+ {
+ private readonly IMediator _mediator;
+
+ public SeatController(IMediator mediator)
+ {
+ _mediator = mediator;
+ }
+
+
+
+ [HttpGet("{id}")]
+ public async Task Get(int id)
+ {
+ return HandleResult(await _mediator.Send(new GetSeatRequest { Id = id }));
+
+ }
+
+ [HttpPost]
+ public async Task Post([FromBody] CreateSeatDto createSeatDto)
+ {
+ var command = new CreateSeatCommand { CreateSeatDto = createSeatDto };
+ return HandleResult(await _mediator.Send(command));
+ }
+
+ [HttpPut]
+ public async Task Put([FromBody] UpdateSeatDto updateSeatDto)
+ {
+
+
+ var command = new UpdateSeatCommand { UpdateSeatDto = updateSeatDto };
+ return HandleResult(await _mediator.Send(command));
+ }
+
+ [HttpDelete("{id}")]
+ public async Task Delete(int id)
+ {
+ var command = new DeleteSeatCommand { Id = id };
+ return HandleResult(await _mediator.Send(command));
+ }
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.API/Middleware/ExceptionMiddleware.cs b/Backend/backend_assessment/CineFlex/CineFlex.API/Middleware/ExceptionMiddleware.cs
new file mode 100644
index 000000000..ab22cabb0
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.API/Middleware/ExceptionMiddleware.cs
@@ -0,0 +1,65 @@
+using CineFlex.Application.Exceptions;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Threading.Tasks;
+
+namespace CineFlex.Api.Middleware
+{
+ public class ExceptionMiddleware
+ {
+ private readonly RequestDelegate _next;
+ public ExceptionMiddleware(RequestDelegate next)
+ {
+ _next = next;
+ }
+ public async Task InvokeAsync(HttpContext httpContext)
+ {
+ try
+ {
+ await _next(httpContext);
+ }
+ catch (Exception ex)
+ {
+ await HandleExceptionAsync(httpContext, ex);
+ }
+ }
+ private Task HandleExceptionAsync(HttpContext context, Exception exception)
+ {
+ context.Response.ContentType = "application/json";
+ HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+ string result = JsonConvert.SerializeObject(new ErrorDeatils
+ {
+ ErrorMessage = exception.Message,
+ ErrorType = "Failure"
+ });
+
+ switch (exception)
+ {
+ case BadRequestException badRequestException:
+ statusCode = HttpStatusCode.BadRequest;
+ break;
+ case ValidationException validationException:
+ statusCode = HttpStatusCode.BadRequest;
+ result = JsonConvert.SerializeObject(validationException.Errors);
+ break;
+ case NotFoundException notFoundException:
+ statusCode = HttpStatusCode.NotFound;
+ break;
+ default:
+ break;
+ }
+
+ context.Response.StatusCode = (int)statusCode;
+ return context.Response.WriteAsync(result);
+ }
+ }
+
+ public class ErrorDeatils
+ {
+ public string ErrorType { get; set; }
+ public string ErrorMessage { get; set; }
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.API/Program.cs b/Backend/backend_assessment/CineFlex/CineFlex.API/Program.cs
index 4e1afd370..08d82bad3 100644
--- a/Backend/backend_assessment/CineFlex/CineFlex.API/Program.cs
+++ b/Backend/backend_assessment/CineFlex/CineFlex.API/Program.cs
@@ -1,13 +1,18 @@
using CineFlex.Application;
using CineFlex.Persistence;
+using CineFlex.Identity;
using Microsoft.OpenApi.Models;
using Microsoft.AspNetCore.Identity;
+using CineFlex.Api.Middleware;
+using Microsoft.AspNetCore.Cors.Infrastructure;
var builder = WebApplication.CreateBuilder(args);
// Add services
builder.Services.ConfigureApplicationServices();
builder.Services.ConfigurePersistenceServices(builder.Configuration);
+builder.Services.ConfigureIdentityServices(builder.Configuration);
+
builder.Services.AddHttpContextAccessor();
AddSwaggerDoc(builder.Services);
builder.Services.AddControllers();
@@ -40,6 +45,7 @@
app.UseHttpsRedirection();
app.UseAuthorization();
+app.UseMiddleware();
app.MapControllers();
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.API/appsettings.json b/Backend/backend_assessment/CineFlex/CineFlex.API/appsettings.json
index 2b720c223..92bd8fc7d 100644
--- a/Backend/backend_assessment/CineFlex/CineFlex.API/appsettings.json
+++ b/Backend/backend_assessment/CineFlex/CineFlex.API/appsettings.json
@@ -1,6 +1,7 @@
{
"ConnectionStrings": {
- "CineFlexConnectionString": "User ID=postgres;Password=1234;Server=localhost;Port=5432;Database=CineFlex;Integrated Security=true;Pooling=true;"
+ "CineFlexConnectionString": "User ID=postgres;Password=postgres;Server=localhost;Port=5432;Database=CineFlex;Integrated Security=true;Pooling=true;",
+ "CineFlexIdentityConnectionString": "User ID=postgres;Password=postgres;Server=localhost;Port=5432;Database=CineFlexIdentity;Integrated Security=true;Pooling=true;"
},
"Logging": {
"LogLevel": {
@@ -12,5 +13,12 @@
"compilationOptions": {
"emitEntryPoint": true,
"preserveCompilationContext": true
+ },
+ "JwtSettings": {
+ "Key": "2J9JFA9THQTH9AHRHTQ9YAQTJ",
+ "Issuer": "CineFlexApi",
+ "Audience": "CineFlexApiUser",
+ "DurationInMinutes": 60
}
+
}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Application/CineFlex.Application.csproj b/Backend/backend_assessment/CineFlex/CineFlex.Application/CineFlex.Application.csproj
index 117b85cd5..6666f2979 100644
--- a/Backend/backend_assessment/CineFlex/CineFlex.Application/CineFlex.Application.csproj
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Application/CineFlex.Application.csproj
@@ -26,6 +26,13 @@
+
+
+
+
+
+
+
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Application/Contracts/Identity/IAuthService.cs b/Backend/backend_assessment/CineFlex/CineFlex.Application/Contracts/Identity/IAuthService.cs
new file mode 100644
index 000000000..11453b182
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Application/Contracts/Identity/IAuthService.cs
@@ -0,0 +1,15 @@
+using CineFlex.Application.Models.Identity;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CineFlex.Application.Contracts.Identity
+{
+ public interface IAuthService
+ {
+ Task Login(AuthRequest request);
+ Task Register(RegistrationRequest request);
+
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Application/Contracts/Persistence/IBookingRepository.cs b/Backend/backend_assessment/CineFlex/CineFlex.Application/Contracts/Persistence/IBookingRepository.cs
new file mode 100644
index 000000000..412d53a0b
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Application/Contracts/Persistence/IBookingRepository.cs
@@ -0,0 +1,13 @@
+using CineFlex.Domain;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CineFlex.Application.Contracts.Persistence
+{
+ public interface IBookingRepository : IGenericRepository
+ {
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Application/Contracts/Persistence/IGenreRepository.cs b/Backend/backend_assessment/CineFlex/CineFlex.Application/Contracts/Persistence/IGenreRepository.cs
new file mode 100644
index 000000000..4639f4ae1
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Application/Contracts/Persistence/IGenreRepository.cs
@@ -0,0 +1,13 @@
+using CineFlex.Domain;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CineFlex.Application.Contracts.Persistence
+{
+ public interface IGenreRepository : IGenericRepository
+ {
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Application/Contracts/Persistence/ISeatRepository.cs b/Backend/backend_assessment/CineFlex/CineFlex.Application/Contracts/Persistence/ISeatRepository.cs
new file mode 100644
index 000000000..28cf3abfc
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Application/Contracts/Persistence/ISeatRepository.cs
@@ -0,0 +1,13 @@
+using CineFlex.Domain;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CineFlex.Application.Contracts.Persistence
+{
+ public interface ISeatRepository : IGenericRepository
+ {
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Application/Contracts/Persistence/IUnitOfWork.cs b/Backend/backend_assessment/CineFlex/CineFlex.Application/Contracts/Persistence/IUnitOfWork.cs
index 60a0724e4..fc3787d03 100644
--- a/Backend/backend_assessment/CineFlex/CineFlex.Application/Contracts/Persistence/IUnitOfWork.cs
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Application/Contracts/Persistence/IUnitOfWork.cs
@@ -11,6 +11,10 @@ public interface IUnitOfWork : IDisposable
{
IMovieRepository MovieRepository { get; }
ICinemaRepository CinemaRepository { get; }
+ ISeatRepository SeatRepository { get; }
+ IBookingRepository BookingRepository { get; }
+ IGenreRepository GenreRepository { get; }
+
Task Save();
}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Bookings/DTO/BookingDto.cs b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Bookings/DTO/BookingDto.cs
new file mode 100644
index 000000000..d0d189a40
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Bookings/DTO/BookingDto.cs
@@ -0,0 +1,23 @@
+using CineFlex.Application.Features.Common;
+using CineFlex.Domain;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CineFlex.Application.Features.Bookings.DTO
+{
+ public class BookingDto : BaseDto, IBookingDto
+ {
+ public DateTime BookingTime { get; set; }
+ public decimal TotalPrice { get; set; }
+ public int MovieId { get; set; }
+ public List SeatIds { get; set; }
+ public string CustomerName { get; set; }
+ public string CustomerEmail { get; set; }
+
+
+ }
+}
+
\ No newline at end of file
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Bookings/DTO/CreateBookingDto.cs b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Bookings/DTO/CreateBookingDto.cs
new file mode 100644
index 000000000..9556b0e62
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Bookings/DTO/CreateBookingDto.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CineFlex.Application.Features.Bookings.DTO
+{
+ public class CreateBookingDto
+ {
+ public int MovieId { get; set; }
+ public List SeatIds { get; set; }
+ public string CustomerName { get; set; }
+ public string CustomerEmail { get; set; }
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Bookings/DTO/IBookingDto.cs b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Bookings/DTO/IBookingDto.cs
new file mode 100644
index 000000000..37781f013
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Bookings/DTO/IBookingDto.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CineFlex.Application.Features.Bookings.DTO
+{
+ public interface IBookingDto
+ {
+ int Id { get; set; }
+ DateTime BookingTime { get; set; }
+ decimal TotalPrice { get; set; }
+ int MovieId { get; set; }
+ List SeatIds { get; set; }
+ string CustomerName { get; set; }
+ string CustomerEmail { get; set; }
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Bookings/DTO/UpdateBookingDto.cs b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Bookings/DTO/UpdateBookingDto.cs
new file mode 100644
index 000000000..a64c09c5d
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Bookings/DTO/UpdateBookingDto.cs
@@ -0,0 +1,22 @@
+using CineFlex.Application.Features.Common;
+using CineFlex.Domain;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CineFlex.Application.Features.Bookings.DTO
+{
+ public class UpdateBookingDto : BaseDto, IBookingDto
+ {
+ public DateTime BookingTime { get; set; }
+ public decimal TotalPrice { get; set; }
+ public int MovieId { get; set; }
+ public List SeatIds { get; set; }
+ public string CustomerName { get; set; }
+ public string CustomerEmail { get; set; }
+
+
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Genres/DTO/CreateGenreDto.cs b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Genres/DTO/CreateGenreDto.cs
new file mode 100644
index 000000000..0f2d818cc
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Genres/DTO/CreateGenreDto.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CineFlex.Application.Features.Genres.DTO
+{
+ public class CreateGenreDto
+ {
+ public string Name { get; set; }
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Genres/DTO/GenreDto.cs b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Genres/DTO/GenreDto.cs
new file mode 100644
index 000000000..d4b7e350f
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Genres/DTO/GenreDto.cs
@@ -0,0 +1,15 @@
+using CineFlex.Application.Features.Common;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CineFlex.Application.Features.Genres.DTO
+{
+ public class GenreDto : BaseDto
+ {
+ public string Name { get; set; }
+
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Genres/DTO/UpdateGenreDto.cs b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Genres/DTO/UpdateGenreDto.cs
new file mode 100644
index 000000000..0b5102121
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Genres/DTO/UpdateGenreDto.cs
@@ -0,0 +1,15 @@
+using CineFlex.Application.Features.Common;
+using CineFlex.Domain;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CineFlex.Application.Features.Genres.DTO
+{
+ public class UpdateGenreDto : BaseDto
+ {
+ public string Name { get; set; }
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Genres/DTO/Validators/CreateGenreDtoValidator.cs b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Genres/DTO/Validators/CreateGenreDtoValidator.cs
new file mode 100644
index 000000000..53b2c1960
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Genres/DTO/Validators/CreateGenreDtoValidator.cs
@@ -0,0 +1,17 @@
+using FluentValidation;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CineFlex.Application.Features.Genres.DTO.Validators
+{
+ public class CreateGenreDtoValidator : AbstractValidator
+ {
+ public CreateGenreDtoValidator()
+ {
+ RuleFor(x => x.Name).NotEmpty().WithMessage("Name is required.");
+ }
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Genres/DTO/Validators/UpdateGenreDtoValidator.cs b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Genres/DTO/Validators/UpdateGenreDtoValidator.cs
new file mode 100644
index 000000000..3121a122a
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Genres/DTO/Validators/UpdateGenreDtoValidator.cs
@@ -0,0 +1,18 @@
+using FluentValidation;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CineFlex.Application.Features.Genres.DTO.Validators
+{
+ public class UpdateGenreDtoValidator : AbstractValidator
+ {
+ public UpdateGenreDtoValidator()
+ {
+ RuleFor(x => x.Id).GreaterThan(0).WithMessage("Id must be greater than 0.");
+ RuleFor(x => x.Name).NotEmpty().WithMessage("Name is required.");
+ }
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/CQRS/Commands/CreateSeatCommand.cs b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/CQRS/Commands/CreateSeatCommand.cs
new file mode 100644
index 000000000..f7dd7491d
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/CQRS/Commands/CreateSeatCommand.cs
@@ -0,0 +1,16 @@
+using CineFlex.Application.Features.Seats.DTO;
+using CineFlex.Application.Responses;
+using MediatR;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CineFlex.Application.Features.Seats.CQRS.Commands
+{
+ public class CreateSeatCommand : IRequest>
+ {
+ public CreateSeatDto CreateSeatDto { get; set; }
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/CQRS/Commands/DeleteSeatCommand.cs b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/CQRS/Commands/DeleteSeatCommand.cs
new file mode 100644
index 000000000..7b04d8921
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/CQRS/Commands/DeleteSeatCommand.cs
@@ -0,0 +1,16 @@
+using CineFlex.Application.Responses;
+using MediatR;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CineFlex.Application.Features.Seats.CQRS.Commands
+{
+ public class DeleteSeatCommand : IRequest>
+ {
+ public int Id { get; set; }
+
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/CQRS/Commands/UpdateSeatCommand.cs b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/CQRS/Commands/UpdateSeatCommand.cs
new file mode 100644
index 000000000..f7691aad8
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/CQRS/Commands/UpdateSeatCommand.cs
@@ -0,0 +1,16 @@
+using CineFlex.Application.Features.Seats.DTO;
+using CineFlex.Application.Responses;
+using MediatR;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CineFlex.Application.Features.Seats.CQRS.Commands
+{
+ public class UpdateSeatCommand : IRequest>
+ {
+ public UpdateSeatDto UpdateSeatDto { get; set; }
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/CQRS/Handlers/CreateSeatCommandHandler.cs b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/CQRS/Handlers/CreateSeatCommandHandler.cs
new file mode 100644
index 000000000..cf1dfcc59
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/CQRS/Handlers/CreateSeatCommandHandler.cs
@@ -0,0 +1,59 @@
+using AutoMapper;
+using CineFlex.Application.Contracts.Persistence;
+using CineFlex.Application.Exceptions;
+using CineFlex.Application.Features.Seats.CQRS.Commands;
+using CineFlex.Application.Features.Seats.DTO.Validators;
+using CineFlex.Application.Responses;
+using CineFlex.Domain;
+using MediatR;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CineFlex.Application.Features.Seats.CQRS.Handlers
+{
+ public class CreateSeatCommandHandler : IRequestHandler>
+ {
+ private readonly IMapper _mapper;
+ private readonly IUnitOfWork _unitOfWork;
+
+ public CreateSeatCommandHandler(IMapper mapper, IUnitOfWork unitOfWork)
+ {
+ _mapper = mapper;
+ _unitOfWork = unitOfWork;
+
+ }
+ public async Task> Handle(CreateSeatCommand request, CancellationToken cancellationToken)
+ {
+ var validator = new CreateSeatDtoValidator();
+ var validationResult = await validator.ValidateAsync(request.CreateSeatDto);
+ var response = new BaseCommandResponse();
+
+ if (!validationResult.IsValid)
+ throw new ValidationException(validationResult);
+
+ var seat= _mapper.Map(request.CreateSeatDto);
+
+ seat = await _unitOfWork.SeatRepository.Add(seat);
+
+ if (await _unitOfWork.Save() > 0)
+ {
+ response.Success = true;
+ response.Message = "Creation Successful";
+ response.Value = seat.Id;
+ }
+ else
+ {
+ response.Success = false;
+ response.Message = "Creation Failed";
+
+ }
+
+ return response;
+
+
+ }
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/CQRS/Handlers/DeleteSeatCommandHandler.cs b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/CQRS/Handlers/DeleteSeatCommandHandler.cs
new file mode 100644
index 000000000..b63c83293
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/CQRS/Handlers/DeleteSeatCommandHandler.cs
@@ -0,0 +1,57 @@
+using AutoMapper;
+using CineFlex.Application.Contracts.Persistence;
+using CineFlex.Application.Exceptions;
+using CineFlex.Application.Features.Seats.CQRS.Commands;
+using CineFlex.Application.Features.Seats.DTO.Validators;
+using CineFlex.Application.Responses;
+using MediatR;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CineFlex.Application.Features.Seats.CQRS.Handlers
+{
+ public class DeleteSeatCommandHandler : IRequestHandler>
+ {
+ private readonly IMapper _mapper;
+ private readonly IUnitOfWork _unitOfWork;
+
+ public DeleteSeatCommandHandler(IMapper mapper, IUnitOfWork unitOfWork)
+ {
+ _mapper = mapper;
+ _unitOfWork = unitOfWork;
+
+ }
+ public async Task> Handle(DeleteSeatCommand request, CancellationToken cancellationToken)
+ {
+
+ var response = new BaseCommandResponse();
+
+
+ var seat = await _unitOfWork.SeatRepository.Get(request.Id);
+
+ if (seat == null)
+ throw new NotFoundException(nameof(seat), request.Id);
+
+ await _unitOfWork.SeatRepository.Delete(seat);
+
+
+ if (await _unitOfWork.Save() > 0)
+ {
+ response.Success = true;
+ response.Message = "Update Successful";
+ response.Value = Unit.Value;
+
+ }
+ else
+ {
+ response.Success = false;
+ response.Message = "Update Failed";
+ }
+
+ return response;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/CQRS/Handlers/GetSeatRequestHandler.cs b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/CQRS/Handlers/GetSeatRequestHandler.cs
new file mode 100644
index 000000000..59be82976
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/CQRS/Handlers/GetSeatRequestHandler.cs
@@ -0,0 +1,50 @@
+using AutoMapper;
+using CineFlex.Application.Contracts.Persistence;
+using CineFlex.Application.Exceptions;
+using CineFlex.Application.Features.Seats.CQRS.Queries;
+using CineFlex.Application.Features.Seats.DTO;
+using CineFlex.Application.Features.Seats.DTO.Validators;
+using CineFlex.Application.Responses;
+using CineFlex.Domain;
+using MediatR;
+using Microsoft.AspNetCore.Http;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CineFlex.Application.Features.Seats.CQRS.Handlers
+{
+ public class GetSeatRequestHandler : IRequestHandler>
+ {
+ private readonly IMapper _mapper;
+ private readonly IUnitOfWork _unitOfWork;
+
+ public GetSeatRequestHandler(IMapper mapper, IUnitOfWork unitOfWork)
+ {
+ _mapper = mapper;
+ _unitOfWork = unitOfWork;
+
+ }
+ public async Task> Handle(GetSeatRequest request, CancellationToken cancellationToken)
+ {
+
+ var response = new BaseCommandResponse();
+ var seat = await _unitOfWork.SeatRepository.Get(request.Id);
+
+ if (seat == null) {
+ throw new NotFoundException(nameof(seat), request.Id);
+ }
+
+ response.Success = true;
+ response.Message = "Fetch Succesful";
+ response.Value = _mapper.Map(seat);
+
+ return response;
+
+
+
+ }
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/CQRS/Handlers/UpdateSeatCommandHandler.cs b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/CQRS/Handlers/UpdateSeatCommandHandler.cs
new file mode 100644
index 000000000..889aacb1e
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/CQRS/Handlers/UpdateSeatCommandHandler.cs
@@ -0,0 +1,61 @@
+using AutoMapper;
+using CineFlex.Application.Contracts.Persistence;
+using CineFlex.Application.Exceptions;
+using CineFlex.Application.Features.Seats.CQRS.Commands;
+using CineFlex.Application.Features.Seats.DTO.Validators;
+using CineFlex.Application.Responses;
+using MediatR;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CineFlex.Application.Features.Seats.CQRS.Handlers
+{
+ public class UpdateSeatCommandHandler : IRequestHandler>
+ {
+ private readonly IMapper _mapper;
+ private readonly IUnitOfWork _unitOfWork;
+
+ public UpdateSeatCommandHandler(IMapper mapper, IUnitOfWork unitOfWork)
+ {
+ _mapper = mapper;
+ _unitOfWork = unitOfWork;
+
+ }
+ public async Task> Handle(UpdateSeatCommand request, CancellationToken cancellationToken)
+ {
+ var validator = new UpdateSeatDtoValidator();
+ var validationResult = await validator.ValidateAsync(request.UpdateSeatDto);
+ var response = new BaseCommandResponse();
+
+ if (!validationResult.IsValid)
+ throw new ValidationException(validationResult);
+
+ var seat = await _unitOfWork.SeatRepository.Get(request.UpdateSeatDto.Id);
+
+ if (seat == null)
+ throw new NotFoundException(nameof(seat), request.UpdateSeatDto.Id);
+
+ _mapper.Map(request.UpdateSeatDto, seat);
+
+ await _unitOfWork.SeatRepository.Update(seat);
+
+ if (await _unitOfWork.Save() > 0)
+ {
+ response.Success = true;
+ response.Message = "Update Successful";
+ response.Value = Unit.Value;
+
+ }
+ else
+ {
+ response.Success = false;
+ response.Message = "Update Failed";
+ }
+
+ return response;
+ }
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/CQRS/Queries/GetSeatRequest.cs b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/CQRS/Queries/GetSeatRequest.cs
new file mode 100644
index 000000000..c4a86e176
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/CQRS/Queries/GetSeatRequest.cs
@@ -0,0 +1,16 @@
+using CineFlex.Application.Features.Seats.DTO;
+using CineFlex.Application.Responses;
+using MediatR;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CineFlex.Application.Features.Seats.CQRS.Queries
+{
+ public class GetSeatRequest : IRequest>
+ {
+ public int Id { get; set; }
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/DTO/CreateSeatDto.cs b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/DTO/CreateSeatDto.cs
new file mode 100644
index 000000000..49bd8bcc1
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/DTO/CreateSeatDto.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CineFlex.Application.Features.Seats.DTO
+{
+ public class CreateSeatDto
+ {
+ public int RowNumber { get; set; }
+ public int SeatNumber { get; set; }
+ public string SeatType { get; set; }
+ public bool Availability { get; set; }
+ public decimal Price { get; set; }
+ public int CinemaHallId { get; set; }
+ public int? BookingId { get; set; }
+
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/DTO/ISeatDto.cs b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/DTO/ISeatDto.cs
new file mode 100644
index 000000000..df249dea9
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/DTO/ISeatDto.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CineFlex.Application.Features.Seats.DTO
+{
+ public interface ISeatDto
+ {
+ int RowNumber { get; set; }
+ int SeatNumber { get; set; }
+ string SeatType { get; set; }
+ bool Availability { get; set; }
+ decimal Price { get; set; }
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/DTO/SeatDto.cs b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/DTO/SeatDto.cs
new file mode 100644
index 000000000..1dfbf9a69
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/DTO/SeatDto.cs
@@ -0,0 +1,23 @@
+using CineFlex.Application.Features.Common;
+using CineFlex.Domain;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CineFlex.Application.Features.Seats.DTO
+{
+ public class SeatDto : BaseDto, ISeatDto
+ {
+ public int RowNumber { get; set; }
+ public int SeatNumber { get; set; }
+ public string SeatType { get; set; }
+ public bool Availability { get; set; }
+ public decimal Price { get; set; }
+ public int CinemaHallId { get; set; }
+ public int? BookingId { get; set; }
+
+
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/DTO/UpdateSeatDto.cs b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/DTO/UpdateSeatDto.cs
new file mode 100644
index 000000000..8c7893ed5
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/DTO/UpdateSeatDto.cs
@@ -0,0 +1,23 @@
+using CineFlex.Application.Features.Common;
+using CineFlex.Domain;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CineFlex.Application.Features.Seats.DTO
+{
+ public class UpdateSeatDto : BaseDto, ISeatDto
+ {
+ public int RowNumber { get; set; }
+ public int SeatNumber { get; set; }
+ public string SeatType { get; set; }
+ public bool Availability { get; set; }
+ public decimal Price { get; set; }
+ public int CinemaHallId { get; set; }
+ public int? BookingId { get; set; }
+
+
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/DTO/Validators/CreateSeatDtoValidator.cs b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/DTO/Validators/CreateSeatDtoValidator.cs
new file mode 100644
index 000000000..69cb69f52
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/DTO/Validators/CreateSeatDtoValidator.cs
@@ -0,0 +1,21 @@
+using FluentValidation;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CineFlex.Application.Features.Seats.DTO.Validators
+{
+ public class CreateSeatDtoValidator : AbstractValidator
+ {
+ public CreateSeatDtoValidator()
+ {
+ RuleFor(x => x.RowNumber).GreaterThan(0).WithMessage("{PropertyName} must be greater than 0.");
+ RuleFor(x => x.SeatNumber).GreaterThan(0).WithMessage("{PropertyName} must be greater than 0.");
+ RuleFor(x => x.SeatType).NotEmpty().WithMessage("{PropertyName} is required.");
+ RuleFor(x => x.Price).GreaterThan(0).WithMessage("{PropertyName} must be greater than 0.");
+ RuleFor(x => x.CinemaHallId).GreaterThan(0).WithMessage("{PropertyName} must be greater than 0.");
+ }
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/DTO/Validators/SeatDtoValidator.cs b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/DTO/Validators/SeatDtoValidator.cs
new file mode 100644
index 000000000..b0d0fa604
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/DTO/Validators/SeatDtoValidator.cs
@@ -0,0 +1,21 @@
+using FluentValidation;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CineFlex.Application.Features.Seats.DTO.Validators
+{
+ public class SeatDtoValidator : AbstractValidator
+ {
+ public SeatDtoValidator()
+ {
+ RuleFor(x => x.RowNumber).GreaterThan(0).WithMessage("{PropertyName} must be greater than 0.");
+ RuleFor(x => x.SeatNumber).GreaterThan(0).WithMessage("{PropertyName} must be greater than 0.");
+ RuleFor(x => x.SeatType).NotEmpty().WithMessage("{PropertyName} is required.");
+ RuleFor(x => x.Price).GreaterThan(0).WithMessage("{PropertyName} must be greater than 0.");
+ RuleFor(x => x.CinemaHallId).GreaterThan(0).WithMessage("{PropertyName} must be greater than 0.");
+ }
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/DTO/Validators/UpdateSeatDtoValidator.cs b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/DTO/Validators/UpdateSeatDtoValidator.cs
new file mode 100644
index 000000000..288bfb430
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Application/Features/Seats/DTO/Validators/UpdateSeatDtoValidator.cs
@@ -0,0 +1,22 @@
+using FluentValidation;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CineFlex.Application.Features.Seats.DTO.Validators
+{
+ public class UpdateSeatDtoValidator : AbstractValidator
+ {
+ public UpdateSeatDtoValidator()
+ {
+ RuleFor(x => x.Id).GreaterThan(0).WithMessage("{PropertyName} must be greater than 0.");
+ RuleFor(x => x.RowNumber).GreaterThan(0).WithMessage("{PropertyName} must be greater than 0.");
+ RuleFor(x => x.SeatNumber).GreaterThan(0).WithMessage("{PropertyName} must be greater than 0.");
+ RuleFor(x => x.SeatType).NotEmpty().WithMessage("{PropertyName} is required.");
+ RuleFor(x => x.Price).GreaterThan(0).WithMessage("{PropertyName} must be greater than 0.");
+ RuleFor(x => x.CinemaHallId).GreaterThan(0).WithMessage("{PropertyName} must be greater than 0.");
+ }
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Application/Models/Identity/AuthRequest.cs b/Backend/backend_assessment/CineFlex/CineFlex.Application/Models/Identity/AuthRequest.cs
new file mode 100644
index 000000000..a2c4442d8
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Application/Models/Identity/AuthRequest.cs
@@ -0,0 +1,8 @@
+namespace CineFlex.Application.Models.Identity
+{
+ public class AuthRequest
+ {
+ public string Email { get; set; }
+ public string Password { get; set; }
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Application/Models/Identity/AuthResponse.cs b/Backend/backend_assessment/CineFlex/CineFlex.Application/Models/Identity/AuthResponse.cs
new file mode 100644
index 000000000..9d5a9a3de
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Application/Models/Identity/AuthResponse.cs
@@ -0,0 +1,10 @@
+namespace CineFlex.Application.Models.Identity
+{
+ public class AuthResponse
+ {
+ public string Id { get; set; }
+ public string UserName { get; set; }
+ public string Email { get; set; }
+ public string Token { get; set; }
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Application/Models/Identity/JwtSettings.cs b/Backend/backend_assessment/CineFlex/CineFlex.Application/Models/Identity/JwtSettings.cs
new file mode 100644
index 000000000..d26819b92
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Application/Models/Identity/JwtSettings.cs
@@ -0,0 +1,10 @@
+namespace CineFlex.Application.Models.Identity
+{
+ public class JwtSettings
+ {
+ public string Key { get; set; }
+ public string Issuer { get; set; }
+ public string Audience { get; set; }
+ public double DurationInMinutes { get; set; }
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Application/Models/Identity/RegistrationRequest.cs b/Backend/backend_assessment/CineFlex/CineFlex.Application/Models/Identity/RegistrationRequest.cs
new file mode 100644
index 000000000..d2394525e
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Application/Models/Identity/RegistrationRequest.cs
@@ -0,0 +1,25 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace CineFlex.Application.Models.Identity
+{
+ public class RegistrationRequest
+ {
+ [Required]
+ public string FirstName { get; set; }
+
+ [Required]
+ public string LastName { get; set; }
+
+ [Required]
+ [EmailAddress]
+ public string Email { get; set; }
+
+ [Required]
+ [MinLength(6)]
+ public string UserName { get; set; }
+
+ [Required]
+ [MinLength(6)]
+ public string Password { get; set; }
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Application/Models/Identity/RegistrationResponse.cs b/Backend/backend_assessment/CineFlex/CineFlex.Application/Models/Identity/RegistrationResponse.cs
new file mode 100644
index 000000000..60b4f9f3f
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Application/Models/Identity/RegistrationResponse.cs
@@ -0,0 +1,7 @@
+namespace CineFlex.Application.Models.Identity
+{
+ public class RegistrationResponse
+ {
+ public string UserId { get; set; }
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Application/Profiles/MappingProfile.cs b/Backend/backend_assessment/CineFlex/CineFlex.Application/Profiles/MappingProfile.cs
index 7c00bdd4c..2b58e3db6 100644
--- a/Backend/backend_assessment/CineFlex/CineFlex.Application/Profiles/MappingProfile.cs
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Application/Profiles/MappingProfile.cs
@@ -8,6 +8,9 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using CineFlex.Application.Features.Seats.DTO;
+using CineFlex.Application.Features.Genres.DTO;
+using CineFlex.Application.Features.Bookings.DTO;
namespace CineFlex.Application.Profiles
{
@@ -26,6 +29,22 @@ public MappingProfile()
CreateMap().ReverseMap();
CreateMap().ReverseMap();
CreateMap().ReverseMap();
+
+
+ CreateMap().ReverseMap();
+ CreateMap().ReverseMap();
+ CreateMap().ReverseMap();
+
+ CreateMap().ReverseMap();
+ CreateMap().ReverseMap();
+ CreateMap().ReverseMap();
+
+
+ CreateMap().ReverseMap();
+ CreateMap().ReverseMap();
+ CreateMap().ReverseMap();
+
+
}
}
}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Domain/Booking.cs b/Backend/backend_assessment/CineFlex/CineFlex.Domain/Booking.cs
new file mode 100644
index 000000000..f169f915b
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Domain/Booking.cs
@@ -0,0 +1,18 @@
+using CineFlex.Domain.Common;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CineFlex.Domain
+{
+ public class Booking : BaseDomainEntity
+ {
+ public DateTime BookingTime { get; set; }
+ public decimal TotalPrice { get; set; }
+ public int MovieId { get; set; }
+ public Movie Movie { get; set; }
+ public List Seats { get; set; }
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Domain/CinemaEntity.cs b/Backend/backend_assessment/CineFlex/CineFlex.Domain/CinemaEntity.cs
index b70624cef..c4baec47e 100644
--- a/Backend/backend_assessment/CineFlex/CineFlex.Domain/CinemaEntity.cs
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Domain/CinemaEntity.cs
@@ -12,5 +12,6 @@ public class CinemaEntity:BaseDomainEntity
public string Name { get; set; }
public string Location { get; set; }
public string ContactInformation { get; set; }
+ public List Seats {get; set;}
}
}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Domain/Genre.cs b/Backend/backend_assessment/CineFlex/CineFlex.Domain/Genre.cs
new file mode 100644
index 000000000..2bf62f63f
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Domain/Genre.cs
@@ -0,0 +1,16 @@
+using CineFlex.Domain.Common;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CineFlex.Domain
+{
+ public class Genre : BaseDomainEntity
+ {
+ public int Id { get; set; }
+ public string Name { get; set; }
+ public List Movies { get; set; }
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Domain/Movie.cs b/Backend/backend_assessment/CineFlex/CineFlex.Domain/Movie.cs
index b6f39be96..c56898aef 100644
--- a/Backend/backend_assessment/CineFlex/CineFlex.Domain/Movie.cs
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Domain/Movie.cs
@@ -10,8 +10,9 @@ namespace CineFlex.Domain
public class Movie: BaseDomainEntity
{
public string Title { get; set; }
- public string Genre { get; set; }
+ public List Genres { get; set; }
public string ReleaseYear { get; set; }
+ public List Bookings { get; set; }
}
}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Domain/Seat.cs b/Backend/backend_assessment/CineFlex/CineFlex.Domain/Seat.cs
new file mode 100644
index 000000000..ef5aff9a1
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Domain/Seat.cs
@@ -0,0 +1,22 @@
+using CineFlex.Domain.Common;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CineFlex.Domain
+{
+ public class Seat : BaseDomainEntity
+ {
+ public int RowNumber { get; set; }
+ public int SeatNumber { get; set; }
+ public string SeatType { get; set; }
+ public bool Availability { get; set; }
+ public decimal Price { get; set; }
+ public int CinemaHallId { get; set; }
+ public CinemaEntity Cinema { get; set; }
+ public int BookingId { get; set; }
+ public Booking Booking { get; set; }
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Identity/CineFlex.Identity.csproj b/Backend/backend_assessment/CineFlex/CineFlex.Identity/CineFlex.Identity.csproj
new file mode 100644
index 000000000..8c0b120a6
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Identity/CineFlex.Identity.csproj
@@ -0,0 +1,33 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Identity/CineFlexDbContextFactory.cs b/Backend/backend_assessment/CineFlex/CineFlex.Identity/CineFlexDbContextFactory.cs
new file mode 100644
index 000000000..bde3338d1
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Identity/CineFlexDbContextFactory.cs
@@ -0,0 +1,26 @@
+using CineFlex.Identity;
+using CineFlex;
+using Microsoft.EntityFrameworkCore.Design;
+using Microsoft.Extensions.Configuration;
+using Microsoft.EntityFrameworkCore;
+
+namespace CineFlex.Persistence
+{
+ public class CineFlexIdentityDbContextFactory : IDesignTimeDbContextFactory
+ {
+ public CineFlexIdentityDbContext CreateDbContext(string[] args)
+ {
+ IConfigurationRoot configuration = new ConfigurationBuilder()
+ .SetBasePath(Directory.GetCurrentDirectory())
+ .AddJsonFile("appsettings.json")
+ .Build();
+
+ var builder = new DbContextOptionsBuilder();
+ var connectionString = configuration.GetConnectionString("CineFlexIdentityConnectionString");
+
+ builder.UseNpgsql(connectionString);
+
+ return new CineFlexIdentityDbContext(builder.Options);
+ }
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Identity/CineFlexIdentityDbContext.cs b/Backend/backend_assessment/CineFlex/CineFlex.Identity/CineFlexIdentityDbContext.cs
new file mode 100644
index 000000000..4efd6a427
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Identity/CineFlexIdentityDbContext.cs
@@ -0,0 +1,26 @@
+using CineFlex.Identity.Models;
+using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore;
+using CineFlex.Identity.Configurations;
+using System.Collections.Generic;
+using System.Text;
+
+namespace CineFlex.Identity
+{
+ public class CineFlexIdentityDbContext : IdentityDbContext
+ {
+ public CineFlexIdentityDbContext(DbContextOptions options)
+ : base(options)
+ {
+ }
+
+ protected override void OnModelCreating(ModelBuilder modelBuilder)
+ {
+ base.OnModelCreating(modelBuilder);
+
+ modelBuilder.ApplyConfiguration(new RoleConfiguration());
+ modelBuilder.ApplyConfiguration(new UserConfiguration());
+ modelBuilder.ApplyConfiguration(new UserRoleConfiguration());
+ }
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Identity/Configurations/RoleConfiguration.cs b/Backend/backend_assessment/CineFlex/CineFlex.Identity/Configurations/RoleConfiguration.cs
new file mode 100644
index 000000000..01fbf98a5
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Identity/Configurations/RoleConfiguration.cs
@@ -0,0 +1,31 @@
+using Microsoft.AspNetCore.Identity;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace CineFlex.Identity.Configurations
+{
+ public class RoleConfiguration : IEntityTypeConfiguration
+ {
+ public void Configure(EntityTypeBuilder builder)
+ {
+ builder.HasData(
+ new IdentityRole
+ {
+ Id = "cac43a6e-f7bb-4448-baaf-1add431ccbbf",
+ Name = "Employee",
+ NormalizedName = "EMPLOYEE"
+ },
+ new IdentityRole
+ {
+ Id = "cbc43a8e-f7bb-4445-baaf-1add431ffbbf",
+ Name = "Administrator",
+ NormalizedName = "ADMINISTRATOR"
+ }
+ );
+ }
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Identity/Configurations/UserConfiguration.cs b/Backend/backend_assessment/CineFlex/CineFlex.Identity/Configurations/UserConfiguration.cs
new file mode 100644
index 000000000..2101d742a
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Identity/Configurations/UserConfiguration.cs
@@ -0,0 +1,45 @@
+using CineFlex.Identity.Models;
+using Microsoft.AspNetCore.Identity;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace CineFlex.Identity.Configurations
+{
+ public class UserConfiguration : IEntityTypeConfiguration
+ {
+ public void Configure(EntityTypeBuilder builder)
+ {
+ var hasher = new PasswordHasher();
+ builder.HasData(
+ new ApplicationUser
+ {
+ Id = "8e445865-a24d-4543-a6c6-9443d048cdb9",
+ Email = "admin@localhost.com",
+ NormalizedEmail = "ADMIN@LOCALHOST.COM",
+ FirstName = "System",
+ LastName = "Admin",
+ UserName = "admin@localhost.com",
+ NormalizedUserName = "ADMIN@LOCALHOST.COM",
+ PasswordHash = hasher.HashPassword(null, "P@ssword1"),
+ EmailConfirmed = true
+ },
+ new ApplicationUser
+ {
+ Id = "9e224968-33e4-4652-b7b7-8574d048cdb9",
+ Email = "user@localhost.com",
+ NormalizedEmail = "USER@LOCALHOST.COM",
+ FirstName = "System",
+ LastName = "User",
+ UserName = "user@localhost.com",
+ NormalizedUserName = "USER@LOCALHOST.COM",
+ PasswordHash = hasher.HashPassword(null, "P@ssword1"),
+ EmailConfirmed = true
+ }
+ );
+ }
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Identity/Configurations/UserRoleConfiguration.cs b/Backend/backend_assessment/CineFlex/CineFlex.Identity/Configurations/UserRoleConfiguration.cs
new file mode 100644
index 000000000..872c01820
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Identity/Configurations/UserRoleConfiguration.cs
@@ -0,0 +1,26 @@
+using Microsoft.AspNetCore.Identity;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+
+
+namespace CineFlex.Identity.Configurations
+{
+ public class UserRoleConfiguration : IEntityTypeConfiguration>
+ {
+ public void Configure(EntityTypeBuilder> builder)
+ {
+ builder.HasData(
+ new IdentityUserRole
+ {
+ RoleId = "cbc43a8e-f7bb-4445-baaf-1add431ffbbf",
+ UserId = "8e445865-a24d-4543-a6c6-9443d048cdb9"
+ },
+ new IdentityUserRole
+ {
+ RoleId = "cac43a6e-f7bb-4448-baaf-1add431ccbbf",
+ UserId = "9e224968-33e4-4652-b7b7-8574d048cdb9"
+ }
+ );
+ }
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Identity/IdentityServicesRegistration.cs b/Backend/backend_assessment/CineFlex/CineFlex.Identity/IdentityServicesRegistration.cs
new file mode 100644
index 000000000..2be95e346
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Identity/IdentityServicesRegistration.cs
@@ -0,0 +1,58 @@
+using CineFlex.Application.Contracts.Identity;
+using CineFlex.Application.Models.Identity;
+using CineFlex.Identity.Models;
+using CineFlex.Identity.Services;
+using Microsoft.AspNetCore.Authentication.JwtBearer;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Identity;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.IdentityModel.Tokens;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Text;
+
+namespace CineFlex.Identity
+{
+ public static class IdentityServicesRegistration
+ {
+ public static IServiceCollection ConfigureIdentityServices(this IServiceCollection services, IConfiguration configuration)
+ {
+ services.Configure(configuration.GetSection("JwtSettings"));
+
+ services.AddDbContext(options =>
+ options.UseNpgsql(configuration.GetConnectionString("CineFlexIdentityConnectionString"),
+ b => b.MigrationsAssembly(typeof(CineFlexIdentityDbContext).Assembly.FullName)));
+
+ services.AddIdentity()
+ .AddEntityFrameworkStores().AddDefaultTokenProviders();
+
+ services.AddTransient();
+
+ services.AddAuthentication(options =>
+ {
+ options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
+ options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
+ })
+ .AddJwtBearer(o =>
+ {
+ o.TokenValidationParameters = new TokenValidationParameters
+ {
+ ValidateIssuerSigningKey = true,
+ ValidateIssuer = true,
+ ValidateAudience = true,
+ ValidateLifetime = true,
+ ClockSkew = TimeSpan.Zero,
+ ValidIssuer = configuration["JwtSettings:Issuer"],
+ ValidAudience = configuration["JwtSettings:Audience"],
+ IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["JwtSettings:Key"]))
+ };
+ });
+
+ return services;
+ }
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Identity/Models/ApplicationUser.cs b/Backend/backend_assessment/CineFlex/CineFlex.Identity/Models/ApplicationUser.cs
new file mode 100644
index 000000000..4962e082a
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Identity/Models/ApplicationUser.cs
@@ -0,0 +1,13 @@
+using Microsoft.AspNetCore.Identity;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace CineFlex.Identity.Models
+{
+ public class ApplicationUser : IdentityUser
+ {
+ public string FirstName { get; set; }
+ public string LastName { get; set; }
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Identity/Services/AuthService.cs b/Backend/backend_assessment/CineFlex/CineFlex.Identity/Services/AuthService.cs
new file mode 100644
index 000000000..ef507c7ed
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Identity/Services/AuthService.cs
@@ -0,0 +1,133 @@
+using CineFlex.Application.Constants;
+using CineFlex.Application.Contracts.Identity;
+using CineFlex.Application.Models.Identity;
+using CineFlex.Identity.Models;
+using Microsoft.AspNetCore.Identity;
+using Microsoft.Extensions.Options;
+using Microsoft.IdentityModel.Tokens;
+using System.Collections.Generic;
+using System.IdentityModel.Tokens.Jwt;
+using System.Security.Claims;
+using System.Text;
+
+namespace CineFlex.Identity.Services
+{
+ public class AuthService : IAuthService
+ {
+ private readonly UserManager _userManager;
+ private readonly SignInManager _signInManager;
+ private readonly JwtSettings _jwtSettings;
+
+ public AuthService(UserManager userManager,
+ IOptions jwtSettings,
+ SignInManager signInManager)
+ {
+ _userManager = userManager;
+ _jwtSettings = jwtSettings.Value;
+ _signInManager = signInManager;
+ }
+
+ public async Task Login(AuthRequest request)
+ {
+ var user = await _userManager.FindByEmailAsync(request.Email);
+
+ if (user == null)
+ {
+ throw new Exception($"User with {request.Email} not found.");
+ }
+
+ var result = await _signInManager.PasswordSignInAsync(user.UserName, request.Password, false, lockoutOnFailure: false);
+
+ if (!result.Succeeded)
+ {
+ throw new Exception($"Credentials for '{request.Email} aren't valid'.");
+ }
+
+ JwtSecurityToken jwtSecurityToken = await GenerateToken(user);
+
+ AuthResponse response = new AuthResponse
+ {
+ Id = user.Id,
+ Token = new JwtSecurityTokenHandler().WriteToken(jwtSecurityToken),
+ Email = user.Email,
+ UserName = user.UserName
+ };
+
+ return response;
+ }
+
+ public async Task Register(RegistrationRequest request)
+ {
+ var existingUser = await _userManager.FindByNameAsync(request.UserName);
+
+ if (existingUser != null)
+ {
+ throw new Exception($"Username '{request.UserName}' already exists.");
+ }
+
+ var user = new ApplicationUser
+ {
+ Email = request.Email,
+ FirstName = request.FirstName,
+ LastName = request.LastName,
+ UserName = request.UserName,
+ EmailConfirmed = true
+ };
+
+ var existingEmail = await _userManager.FindByEmailAsync(request.Email);
+
+ if (existingEmail == null)
+ {
+ var result = await _userManager.CreateAsync(user, request.Password);
+
+ if (result.Succeeded)
+ {
+ await _userManager.AddToRoleAsync(user, "Employee");
+ return new RegistrationResponse() { UserId = user.Id };
+ }
+ else
+ {
+ throw new Exception($"{result.Errors}");
+ }
+ }
+ else
+ {
+ throw new Exception($"Email {request.Email } already exists.");
+ }
+ }
+
+ private async Task GenerateToken(ApplicationUser user)
+ {
+ var userClaims = await _userManager.GetClaimsAsync(user);
+ var roles = await _userManager.GetRolesAsync(user);
+
+ var roleClaims = new List();
+
+ for (int i = 0; i < roles.Count; i++)
+ {
+ roleClaims.Add(new Claim(ClaimTypes.Role, roles[i]));
+ }
+
+ var claims = new[]
+ {
+ new Claim(JwtRegisteredClaimNames.Sub, user.UserName),
+ new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
+ new Claim(JwtRegisteredClaimNames.Email, user.Email),
+ new Claim(CustomClaimTypes.Uid, user.Id)
+ }
+ .Union(userClaims)
+ .Union(roleClaims);
+
+ var symmetricSecurityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtSettings.Key));
+ var signingCredentials = new SigningCredentials(symmetricSecurityKey, SecurityAlgorithms.HmacSha256);
+
+ var jwtSecurityToken = new JwtSecurityToken(
+ issuer: _jwtSettings.Issuer,
+ audience: _jwtSettings.Audience,
+ claims: claims,
+ expires: DateTime.UtcNow.AddMinutes(_jwtSettings.DurationInMinutes),
+ signingCredentials: signingCredentials);
+ return jwtSecurityToken;
+ }
+ }
+}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Persistence/CineFlex.Persistence.csproj b/Backend/backend_assessment/CineFlex/CineFlex.Persistence/CineFlex.Persistence.csproj
index d4438f88f..cab284b46 100644
--- a/Backend/backend_assessment/CineFlex/CineFlex.Persistence/CineFlex.Persistence.csproj
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Persistence/CineFlex.Persistence.csproj
@@ -13,6 +13,10 @@
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Persistence/CineFlexDbContex.cs b/Backend/backend_assessment/CineFlex/CineFlex.Persistence/CineFlexDbContex.cs
index 20ccf56db..6e28680cf 100644
--- a/Backend/backend_assessment/CineFlex/CineFlex.Persistence/CineFlexDbContex.cs
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Persistence/CineFlexDbContex.cs
@@ -23,6 +23,31 @@ public CineFlexDbContex(DbContextOptions options)
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfigurationsFromAssembly(typeof(CineFlexDbContex).Assembly);
+ // Relationship between CinemaEntity and Seat
+ modelBuilder.Entity()
+ .HasMany(c => c.Seats)
+ .WithOne(s => s.Cinema)
+ .HasForeignKey(s => s.CinemaHallId);
+
+ // Relationship between Movie and Genre
+ modelBuilder.Entity()
+ .HasMany(m => m.Genres)
+ .WithMany(g => g.Movies)
+ .UsingEntity(j => j.ToTable("MovieGenres"));
+
+ // Relationship between Movie and Booking
+ modelBuilder.Entity()
+ .HasMany(m => m.Bookings)
+ .WithOne(b => b.Movie)
+ .HasForeignKey(b => b.MovieId);
+
+ // Relationship between Booking and Seat
+ modelBuilder.Entity()
+ .HasMany(b => b.Seats)
+ .WithOne(s => s.Booking)
+ .HasForeignKey(s => s.BookingId);
+
+
}
public override Task SaveChangesAsync(CancellationToken cancellationToken = default)
@@ -43,6 +68,9 @@ public override Task SaveChangesAsync(CancellationToken cancellationToken =
public DbSet Cinemas { get; set; }
public DbSet Movies { get; set; }
+ public DbSet Seats { get; set; }
+ public DbSet Genres { get; set; }
+ public DbSet Bookings { get; set; }
}
}
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Persistence/Configurations/Entities/BookingConfiguration.cs b/Backend/backend_assessment/CineFlex/CineFlex.Persistence/Configurations/Entities/BookingConfiguration.cs
new file mode 100644
index 000000000..5987feac9
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Persistence/Configurations/Entities/BookingConfiguration.cs
@@ -0,0 +1,34 @@
+using CineFlex.Domain;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CineFlex.Persistence.Configurations.Seeds
+{
+ public class BookingConfiguration : IEntityTypeConfiguration
+ {
+ public void Configure(EntityTypeBuilder builder)
+ {
+ builder.HasData(
+ new Booking
+ {
+ Id = 1,
+ BookingTime = DateTime.Now,
+ TotalPrice = 20.0m,
+ MovieId = 1
+ },
+ new Booking
+ {
+ Id = 2,
+ BookingTime = DateTime.Now,
+ TotalPrice = 30.0m,
+ MovieId = 2
+ }
+ );
+ }
+ }
+}
\ No newline at end of file
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Persistence/Configurations/Entities/GenreConfiguration.cs b/Backend/backend_assessment/CineFlex/CineFlex.Persistence/Configurations/Entities/GenreConfiguration.cs
new file mode 100644
index 000000000..31b8eb970
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Persistence/Configurations/Entities/GenreConfiguration.cs
@@ -0,0 +1,30 @@
+using CineFlex.Domain;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CineFlex.Persistence.Configurations.Entities
+{
+ public class GenreConfiguration : IEntityTypeConfiguration
+ {
+ public void Configure(EntityTypeBuilder builder)
+ {
+ builder.HasData(
+ new Genre
+ {
+ Id = 1,
+ Name = "Action"
+ },
+ new Genre
+ {
+ Id = 2,
+ Name = "Comedy"
+ }
+ );
+ }
+ }
+}
\ No newline at end of file
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Persistence/Configurations/Entities/MovieConfiguration.cs b/Backend/backend_assessment/CineFlex/CineFlex.Persistence/Configurations/Entities/MovieConfiguration.cs
index aed239b9d..2ebdf0d82 100644
--- a/Backend/backend_assessment/CineFlex/CineFlex.Persistence/Configurations/Entities/MovieConfiguration.cs
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Persistence/Configurations/Entities/MovieConfiguration.cs
@@ -1,11 +1,11 @@
-using Microsoft.EntityFrameworkCore.Metadata.Builders;
+using CineFlex.Domain;
using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
-using CineFlex.Domain;
namespace CineFlex.Persistence.Configurations.Entities
{
@@ -17,21 +17,18 @@ public void Configure(EntityTypeBuilder builder)
new Movie
{
Id = 1,
- Title = "Sample Movie",
- Genre = "Trailer",
+ Title = "Sample Movie 1",
ReleaseYear = "1999",
+
},
-
- new Movie
- {
- Id = 2,
- Title = "Sample Movie",
- Genre = "Sci Fi",
- ReleaseYear = "2022",
- }
- ); ;
+ new Movie
+ {
+ Id = 2,
+ Title = "Sample Movie 2",
+ ReleaseYear = "2022",
+
+ }
+ );
}
-
-
}
-}
+}
\ No newline at end of file
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Persistence/Configurations/Entities/SeatConfiguration.cs b/Backend/backend_assessment/CineFlex/CineFlex.Persistence/Configurations/Entities/SeatConfiguration.cs
new file mode 100644
index 000000000..df29f9c7f
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Persistence/Configurations/Entities/SeatConfiguration.cs
@@ -0,0 +1,42 @@
+using CineFlex.Domain;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CineFlex.Persistence.Configurations.Entities
+{
+ public class SeatConfiguration : IEntityTypeConfiguration
+ {
+ public void Configure(EntityTypeBuilder builder)
+ {
+ builder.HasData(
+ new Seat
+ {
+ Id = 1,
+ RowNumber = 1,
+ SeatNumber = 1,
+ SeatType = "Standard",
+ Availability = true,
+ Price = 10.0m,
+ CinemaHallId = 1,
+ BookingId = 1
+ },
+ new Seat
+ {
+ Id = 2,
+ RowNumber = 1,
+ SeatNumber = 2,
+ SeatType = "Standard",
+ Availability = true,
+ Price = 10.0m,
+ CinemaHallId = 1,
+ BookingId = 2
+ }
+ );
+ }
+ }
+}
\ No newline at end of file
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Persistence/Repositories/BookingRepository.cs b/Backend/backend_assessment/CineFlex/CineFlex.Persistence/Repositories/BookingRepository.cs
new file mode 100644
index 000000000..76ee2aa37
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Persistence/Repositories/BookingRepository.cs
@@ -0,0 +1,17 @@
+using System;
+using CineFlex.Application.Contracts.Persistence;
+using CineFlex.Domain;
+
+namespace CineFlex.Persistence.Repositories
+{
+ public class BookingRepository : GenericRepository, IBookingRepository
+ {
+ private readonly CineFlexDbContex _dbContext;
+
+ public BookingRepository(CineFlexDbContex context) : base(context)
+ {
+ _dbContext = context;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Persistence/Repositories/GenreRepository.cs b/Backend/backend_assessment/CineFlex/CineFlex.Persistence/Repositories/GenreRepository.cs
new file mode 100644
index 000000000..47ad1d0bd
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Persistence/Repositories/GenreRepository.cs
@@ -0,0 +1,19 @@
+using System;
+using CineFlex.Application.Contracts.Persistence;
+using CineFlex.Domain;
+
+namespace CineFlex.Persistence.Repositories
+{
+ public class GenreRepository : GenericRepository, IGenreRepository
+ {
+ private readonly CineFlexDbContex _dbContext;
+
+ public GenreRepository(CineFlexDbContex context) : base(context)
+ {
+
+ _dbContext = context;
+ }
+
+
+ }
+}
\ No newline at end of file
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Persistence/Repositories/SeatRepository.cs b/Backend/backend_assessment/CineFlex/CineFlex.Persistence/Repositories/SeatRepository.cs
new file mode 100644
index 000000000..77d191e34
--- /dev/null
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Persistence/Repositories/SeatRepository.cs
@@ -0,0 +1,18 @@
+using System;
+using CineFlex.Application.Contracts.Persistence;
+using CineFlex.Domain;
+
+namespace CineFlex.Persistence.Repositories
+{
+ public class SeatRepository : GenericRepository, ISeatRepository
+ {
+ private readonly CineFlexDbContex _dbContext;
+
+
+ public SeatRepository(CineFlexDbContex context) : base(context)
+ {
+ _dbContext = context;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.Persistence/Repositories/UnitOfWork.cs b/Backend/backend_assessment/CineFlex/CineFlex.Persistence/Repositories/UnitOfWork.cs
index 7fdd26456..df445cca7 100644
--- a/Backend/backend_assessment/CineFlex/CineFlex.Persistence/Repositories/UnitOfWork.cs
+++ b/Backend/backend_assessment/CineFlex/CineFlex.Persistence/Repositories/UnitOfWork.cs
@@ -15,6 +15,9 @@ public class UnitOfWork : IUnitOfWork
private IMovieRepository _MovieRepository;
private ICinemaRepository _cinemaRepository;
+ private ISeatRepository _seatRepository;
+ private IGenreRepository _genreRepository;
+ private IBookingRepository _bookingRepository;
public UnitOfWork(CineFlexDbContex context)
{
_context = context;
@@ -39,6 +42,30 @@ public ICinemaRepository CinemaRepository
}
}
+ public ISeatRepository SeatRepository{
+ get {
+ if (_seatRepository == null)
+ _seatRepository = new SeatRepository(_context);
+ return _seatRepository;
+ }
+ }
+
+ public IGenreRepository GenreRepository{
+ get{
+ if (_genreRepository == null)
+ _genreRepository = new GenreRepository(_context);
+ return _genreRepository;
+ }
+ }
+
+ public IBookingRepository BookingRepository{
+ get{
+ if (_bookingRepository == null)
+ _bookingRepository = new BookingRepository(_context);
+ return _bookingRepository;
+ }
+ }
+
public void Dispose()
{
diff --git a/Backend/backend_assessment/CineFlex/CineFlex.sln b/Backend/backend_assessment/CineFlex/CineFlex.sln
index 22cdfded1..e959e512a 100644
--- a/Backend/backend_assessment/CineFlex/CineFlex.sln
+++ b/Backend/backend_assessment/CineFlex/CineFlex.sln
@@ -7,15 +7,17 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{7B1B95A0-9DB
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{F5977BC8-191D-48B9-8833-80091338052F}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CineFlex.Domain", "CineFlex.Domain\CineFlex.Domain.csproj", "{50EEE1CA-423A-4F8C-8AEB-8F21104E48F5}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CineFlex.Domain", "CineFlex.Domain\CineFlex.Domain.csproj", "{50EEE1CA-423A-4F8C-8AEB-8F21104E48F5}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CineFlex.Application.UnitTest", "CineFlex.Application.UnitTest\CineFlex.Application.UnitTest.csproj", "{6C23CA30-5F1B-4733-9298-0221D22BC142}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CineFlex.Application.UnitTest", "CineFlex.Application.UnitTest\CineFlex.Application.UnitTest.csproj", "{6C23CA30-5F1B-4733-9298-0221D22BC142}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CineFlex.Application", "CineFlex.Application\CineFlex.Application.csproj", "{104F9AAF-4CC1-4578-9061-146FF1315A64}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CineFlex.Application", "CineFlex.Application\CineFlex.Application.csproj", "{104F9AAF-4CC1-4578-9061-146FF1315A64}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CineFlex.Persistence", "CineFlex.Persistence\CineFlex.Persistence.csproj", "{37F60AFF-7E17-4EC3-A20A-042C6F59F1D9}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CineFlex.Persistence", "CineFlex.Persistence\CineFlex.Persistence.csproj", "{37F60AFF-7E17-4EC3-A20A-042C6F59F1D9}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CineFlex.API", "CineFlex.API\CineFlex.API.csproj", "{8D82F498-631C-450B-982F-E7333EB92D7C}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CineFlex.API", "CineFlex.API\CineFlex.API.csproj", "{8D82F498-631C-450B-982F-E7333EB92D7C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CineFlex.Identity", "CineFlex.Identity\CineFlex.Identity.csproj", "{4978DB40-C294-4B4E-B747-205C1782F6FA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -43,6 +45,10 @@ Global
{8D82F498-631C-450B-982F-E7333EB92D7C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8D82F498-631C-450B-982F-E7333EB92D7C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8D82F498-631C-450B-982F-E7333EB92D7C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4978DB40-C294-4B4E-B747-205C1782F6FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4978DB40-C294-4B4E-B747-205C1782F6FA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4978DB40-C294-4B4E-B747-205C1782F6FA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4978DB40-C294-4B4E-B747-205C1782F6FA}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -53,6 +59,7 @@ Global
{104F9AAF-4CC1-4578-9061-146FF1315A64} = {7B1B95A0-9DBB-4C5D-82E6-3895BCF66EE8}
{37F60AFF-7E17-4EC3-A20A-042C6F59F1D9} = {7B1B95A0-9DBB-4C5D-82E6-3895BCF66EE8}
{8D82F498-631C-450B-982F-E7333EB92D7C} = {7B1B95A0-9DBB-4C5D-82E6-3895BCF66EE8}
+ {4978DB40-C294-4B4E-B747-205C1782F6FA} = {7B1B95A0-9DBB-4C5D-82E6-3895BCF66EE8}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {30B8E19C-B56E-4DDD-8243-978C779E3BD4}