diff options
-rw-r--r-- | Controllers/TicketsController.cs | 74 | ||||
-rw-r--r-- | Logics/CreateTicketLogic.cs | 69 | ||||
-rw-r--r-- | Program.cs | 1 | ||||
-rw-r--r-- | Services/ITicketService.cs | 10 | ||||
-rw-r--r-- | Services/RaffleService.cs | 7 | ||||
-rw-r--r-- | Services/TicketService.cs | 39 |
6 files changed, 194 insertions, 6 deletions
diff --git a/Controllers/TicketsController.cs b/Controllers/TicketsController.cs new file mode 100644 index 0000000..97a4a26 --- /dev/null +++ b/Controllers/TicketsController.cs @@ -0,0 +1,74 @@ +using AutoMapper; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Mvc; +using BackendPIA.Errors; +using BackendPIA.Forms; +using BackendPIA.Logics; +using BackendPIA.Models; +using BackendPIA.Services; + +namespace BackendPIA.Controllers { + [Route("api/raffles/{raffleId:int}/tickets")] + [ApiController] + public class TicketsController : ControllerBase { + private readonly IMapper _mapper; + private readonly ITicketService _ticket_service; + private readonly ApplicationDbContext _context; + private readonly UserManager<UserAccount> _manager; + + public TicketsController(IMapper mapper, ITicketService service, ApplicationDbContext context, UserManager<UserAccount> manager) { + _mapper = mapper; + _ticket_service = service; + _context = context; + _manager = manager; + } + + [Authorize] + [HttpGet] + public async Task<ActionResult<IEnumerable<TicketDTO>>> Index(long raffleId) { + var result = await _ticket_service.GetTickets(raffleId); + + if(result == null) + return StatusCode(404, new NotFoundError(404, "The resource doesn't exist")); + + return Ok(_mapper.Map<List<TicketDTO>>(result)); + } + + [Authorize] + [HttpGet("{id:int}")] + public async Task<ActionResult<TicketDTO>> Show(long raffleId, long id) { + var result = await _ticket_service.GetTicket(raffleId, id); + + if(result == null) + return StatusCode(404, new NotFoundError(404, "The resource doesn't exist")); + + return Ok(_mapper.Map<TicketDTO>(result)); + } + + [Authorize] + [HttpPost] + public async Task <ActionResult<TicketDTO>> Create(long raffleId, TicketForm form) { + string email = HttpContext.User.Claims.Where(c => c.Type.Contains("email")).First().Value; + var user = await _manager.FindByEmailAsync(email); + CreateTicketLogic logic = new CreateTicketLogic(_ticket_service, _context, _mapper, form, user, raffleId); + var result = await logic.Call(); + + if(!result) + return StatusCode(422, new InvalidInputError(422, logic.ErrorMessage)); + + return Ok(_mapper.Map<TicketDTO>(logic.Created)); + } + + [Authorize(Roles = "Administrator")] + [HttpDelete("{id:int}")] + public async Task <ActionResult> Delete(long raffleId, long id) { + bool result = await _ticket_service.DeleteTicket(raffleId, id); + + if(!result) + return StatusCode(404, new NotFoundError(404, "The ticket couldn't be found.")); + + return Ok(new { Message = "The ticket has been deleted."}); + } + } +}
\ No newline at end of file diff --git a/Logics/CreateTicketLogic.cs b/Logics/CreateTicketLogic.cs new file mode 100644 index 0000000..df64a1a --- /dev/null +++ b/Logics/CreateTicketLogic.cs @@ -0,0 +1,69 @@ +using AutoMapper; +using BackendPIA.Services; +using BackendPIA.Models; +using BackendPIA.Forms; + +namespace BackendPIA.Logics { + public class CreateTicketLogic { + private readonly ITicketService _ticket_service; + private readonly ApplicationDbContext _context; + private readonly UserAccount _user; + private readonly long _raffle_id; + private readonly IMapper _mapper; + private readonly TicketForm _form; + public string? ErrorMessage { get; set; } + public Ticket? Created { get; set; } + + public CreateTicketLogic(ITicketService service, ApplicationDbContext context, IMapper mapper, TicketForm form, UserAccount user, long raffle_id) { + _ticket_service = service; + _mapper = mapper; + _form = form; + _user = user; + _raffle_id = raffle_id; + _context = context; + } + + public async Task<bool> Call() { + // Check if the user exists. + if(_user == null) + return false; + + // Check if the given raffle exists- + if(!_context.Raffles.Any(r => r.Id == _raffle_id)) { + ErrorMessage = "The raffle doesn't exist."; + + return false; + } + + // Check if the user already has a ticket for the given raffle. + if(_context.Tickets.Where(t => t.RaffleId == _raffle_id).Where(t => t.UserAccountId == _user.Id).Count() > 0) { + ErrorMessage = $"There's already a ticket for {_user.UserName}."; + + return false; + } + + // Check if the number has been taken. + if(_context.Tickets.Where(t => t.RaffleId == _raffle_id).Where(t => t.Number == _form.Number).Count() > 0) { + ErrorMessage = $"There's already a registered ticket with the number {_form.Number}."; + + return false; + } + + var ticket = _mapper.Map<Ticket>(_form); + ticket.RaffleId = _raffle_id; + + // Check if the given raffle has reached the ticket limit. + if(_context.Tickets.Where(t => t.RaffleId == _raffle_id).Count() >= 54) { + ErrorMessage = $"The raffle with id {_raffle_id} has reached the ticket limit"; + + return false; + } + + ticket.UserAccountId = _user.Id; + ticket.IsWinner = false; + Created = await _ticket_service.CreateTicket(ticket); + + return true; + } + } +}
\ No newline at end of file @@ -28,6 +28,7 @@ builder.Services.AddAutoMapper(typeof(Program)); builder.Services.AddSingleton<ITokenGenerator>(s => new TokenGenerator(builder.Configuration["Jwt:Key"])); builder.Services.AddScoped<IUserAccountService, UserAccountService>(); builder.Services.AddScoped<IRaffleService, RaffleService>(); +builder.Services.AddScoped<ITicketService, TicketService>(); // End of custom services configuration. // Swagger configuration. diff --git a/Services/ITicketService.cs b/Services/ITicketService.cs new file mode 100644 index 0000000..b25ec83 --- /dev/null +++ b/Services/ITicketService.cs @@ -0,0 +1,10 @@ +using BackendPIA.Models; + +namespace BackendPIA.Services { + public interface ITicketService { + public Task<Ticket> CreateTicket(Ticket to_create); + public Task<IEnumerable<Ticket>> GetTickets(long raffle_id); + public Task<Ticket> GetTicket(long raffle_id, long id); + public Task<bool> DeleteTicket(long raffle_id, long id); + } +}
\ No newline at end of file diff --git a/Services/RaffleService.cs b/Services/RaffleService.cs index 6cdae3b..58401b8 100644 --- a/Services/RaffleService.cs +++ b/Services/RaffleService.cs @@ -38,12 +38,7 @@ namespace BackendPIA.Services { } public async Task<Raffle> GetRaffle(long id) { - var raffle = await _context.Raffles.FindAsync(id); - - if(raffle == null) - return null; - - return raffle; + return await _context.Raffles.FindAsync(id); } public async Task<bool> DeleteRaffle(long id) { diff --git a/Services/TicketService.cs b/Services/TicketService.cs new file mode 100644 index 0000000..3ac9660 --- /dev/null +++ b/Services/TicketService.cs @@ -0,0 +1,39 @@ +using Microsoft.EntityFrameworkCore; +using BackendPIA.Models; + +namespace BackendPIA.Services { + public class TicketService : ITicketService { + private readonly ApplicationDbContext _context; + + public TicketService(ApplicationDbContext context) { + _context = context; + } + + public async Task<Ticket> CreateTicket(Ticket to_create) { + await _context.AddAsync(to_create); + await _context.SaveChangesAsync(); + + return to_create; + } + + public async Task<IEnumerable<Ticket>> GetTickets(long raffle_id) { + return await _context.Tickets.Where(t => t.RaffleId == raffle_id).ToListAsync(); + } + + public async Task<Ticket> GetTicket(long raffle_id, long id) { + return await _context.Tickets.Where(t => t.RaffleId == raffle_id).FirstOrDefaultAsync(t => t.Id == id); + } + + public async Task<bool> DeleteTicket(long raffle_id, long id) { + var to_delete = await _context.Tickets.Where(t => t.RaffleId == raffle_id).FirstOrDefaultAsync(t => t.Id == id); + + if(to_delete == null) + return false; + + _context.Tickets.Remove(to_delete); + await _context.SaveChangesAsync(); + + return true; + } + } +}
\ No newline at end of file |