Skip to content
Merged
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
177 changes: 81 additions & 96 deletions TickAPI/TickAPI.Tests/Events/Services/EventServiceTests.cs

Large diffs are not rendered by default.

5 changes: 2 additions & 3 deletions TickAPI/TickAPI/Common/Mail/Abstractions/IMailService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ namespace TickAPI.Common.Mail.Abstractions;

public interface IMailService
{
public Task<Result> SendTicketAsync(string toEmail, string toLogin, string eventName, byte[] pdfData);
public Task<Result> SendTicketAsync(MailRecipient recipient, string eventName, byte[] pdfData);

public Task<Result> SendMailAsync(string toEmail, string toLogin, string subject, string content,
List<MailAttachment>? attachments);
public Task<Result> SendMailAsync(IEnumerable<MailRecipient> recipients, string subject, string content, List<MailAttachment>? attachments);
}
11 changes: 5 additions & 6 deletions TickAPI/TickAPI/Common/Mail/Models/MailAttachment.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
namespace TickAPI.Common.Mail.Models;

public class MailAttachment
{
public string fileName { get; set; }
public string base64Content { get; set; }
public string fileType { get; set; }
}
public record MailAttachment(
string FileName,
string Base64Content,
string FileType
);
6 changes: 6 additions & 0 deletions TickAPI/TickAPI/Common/Mail/Models/MailRecipient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace TickAPI.Common.Mail.Models;

public record MailRecipient(
string Email,
string Login
);
24 changes: 9 additions & 15 deletions TickAPI/TickAPI/Common/Mail/Services/MailService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,35 +20,29 @@ public MailService(IConfiguration configuration)
_fromEmailAddress = new EmailAddress(fromEmail, fromName);
}

public async Task<Result> SendTicketAsync(string toEmail, string toLogin, string eventName, byte[] pdfData)
public async Task<Result> SendTicketAsync(MailRecipient recipient, string eventName, byte[] pdfData)
{
var subject = $"Ticket for {eventName}";
var htmlContent = "<strong>Download your ticket from attachments</strong>";
var base64Content = Convert.ToBase64String(pdfData);
List<MailAttachment> attachments =
[
new MailAttachment
{
base64Content = base64Content,
fileName = "ticket.pdf",
fileType = "application/pdf"
}
List<MailAttachment> attachments = [
new MailAttachment("ticket.pdf", base64Content, "application/pdf")
];
var res = await SendMailAsync(toEmail, toLogin, subject, htmlContent, attachments);
var res = await SendMailAsync([recipient], subject, htmlContent, attachments);
return res;
}

public async Task<Result> SendMailAsync(string toEmail, string toLogin, string subject, string content,
public async Task<Result> SendMailAsync(IEnumerable<MailRecipient> recipients, string subject, string content,
List<MailAttachment>? attachments = null)
{
var toEmailAddress = new EmailAddress(toEmail, toLogin);
var msg = MailHelper.CreateSingleEmail(_fromEmailAddress, toEmailAddress, subject,
null, content);
var toEmailAddresses = recipients.Select(r => new EmailAddress(r.Email, r.Login)).ToList();
var msg = MailHelper.CreateSingleEmailToMultipleRecipients(_fromEmailAddress, toEmailAddresses, subject, null, content);

if (attachments != null)
{
foreach (var a in attachments)
{
msg.AddAttachment(a.fileName, a.base64Content, a.fileType);
msg.AddAttachment(a.FileName, a.Base64Content, a.FileType);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ public interface ICustomerRepository
{
Task<Result<Customer>> GetCustomerByEmailAsync(string customerEmail);
Task AddNewCustomerAsync(Customer customer);
IQueryable<Customer> GetCustomersWithTicketForEvent(Guid eventId);
}
6 changes: 6 additions & 0 deletions TickAPI/TickAPI/Customers/Repositories/CustomerRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,10 @@ public async Task AddNewCustomerAsync(Customer customer)
_tickApiDbContext.Customers.Add(customer);
await _tickApiDbContext.SaveChangesAsync();
}

public IQueryable<Customer> GetCustomersWithTicketForEvent(Guid eventId)
{
return _tickApiDbContext.Customers
.Where(c => c.Tickets.Any(t => t.Type.Event.Id == eventId));
}
}
2 changes: 2 additions & 0 deletions TickAPI/TickAPI/Events/Abstractions/IEventService.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using TickAPI.Addresses.DTOs.Request;
using TickAPI.Common.Pagination.Responses;
using TickAPI.Categories.DTOs.Request;
using TickAPI.Common.Results;
using TickAPI.Events.Models;
using TickAPI.Common.Results.Generic;
using TickAPI.Events.DTOs.Request;
Expand All @@ -21,4 +22,5 @@ public Task<Result<Event>> CreateNewEventAsync(string name, string description,
public Task<Result<PaginationDetails>> GetEventsPaginationDetailsAsync(int pageSize);
public Task<Result<GetEventDetailsResponseDto>> GetEventDetailsAsync(Guid eventId);
public Task<Result<Event>> EditEventAsync(Organizer organizer, Guid eventId, string name, string description, DateTime startDate, DateTime endDate, uint? minimumAge, CreateAddressDto editAddress, List<EditEventCategoryDto> categories, EventStatus eventStatus);
public Task<Result> SendMessageToParticipants(Organizer organizer, Guid eventId, string subject, string message);
}
22 changes: 22 additions & 0 deletions TickAPI/TickAPI/Events/Controllers/EventsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,4 +141,26 @@ public async Task<ActionResult<EditEventResponseDto>> EditEvent([FromRoute] Guid

return Ok("Event edited succesfully");
}

[AuthorizeWithPolicy(AuthPolicies.VerifiedOrganizerPolicy)]
[HttpPost("{id:guid}/message-to-participants")]
public async Task<ActionResult> SendMessageToEventParticipants([FromRoute] Guid id, [FromBody] SendMessageToParticipantsDto request)
{
var emailResult = _claimsService.GetEmailFromClaims(User.Claims);
if (emailResult.IsError)
{
return emailResult.ToObjectResult();
}
var email = emailResult.Value!;

var organizerResult = await _organizerService.GetOrganizerByEmailAsync(email);
if (organizerResult.IsError)
{
return organizerResult.ToObjectResult();
}
var organizer = organizerResult.Value!;

var result = await _eventService.SendMessageToParticipants(organizer, id, request.Subject, request.Message);
return result.ToObjectResult();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace TickAPI.Events.DTOs.Request;

public record SendMessageToParticipantsDto(
string Subject,
string Message
);
27 changes: 25 additions & 2 deletions TickAPI/TickAPI/Events/Services/EventService.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
using TickAPI.Addresses.Abstractions;
using Microsoft.EntityFrameworkCore;
using TickAPI.Addresses.Abstractions;
using TickAPI.Addresses.DTOs.Request;
using TickAPI.Common.Pagination.Abstractions;
using TickAPI.Common.Pagination.Responses;
using TickAPI.Categories.Abstractions;
using TickAPI.Categories.DTOs.Request;
using TickAPI.Common.Mail.Abstractions;
using TickAPI.Common.Mail.Models;
using TickAPI.Common.Results;
using TickAPI.Common.Time.Abstractions;
using TickAPI.Events.Abstractions;
using TickAPI.Events.Models;
using TickAPI.Common.Results.Generic;
using TickAPI.Customers.Abstractions;
using TickAPI.Events.DTOs.Request;
using TickAPI.Events.DTOs.Response;
using TickAPI.Events.Filters;
Expand All @@ -29,8 +33,10 @@ public class EventService : IEventService
private readonly IPaginationService _paginationService;
private readonly ICategoryService _categoryService;
private readonly ITicketService _ticketService;
private readonly ICustomerRepository _customerRepository;
private readonly IMailService _mailService;

public EventService(IEventRepository eventRepository, IOrganizerService organizerService, IAddressService addressService, IDateTimeService dateTimeService, IPaginationService paginationService, ICategoryService categoryService, ITicketService ticketService)
public EventService(IEventRepository eventRepository, IOrganizerService organizerService, IAddressService addressService, IDateTimeService dateTimeService, IPaginationService paginationService, ICategoryService categoryService, ITicketService ticketService, ICustomerRepository customerRepository, IMailService mailService)
{
_eventRepository = eventRepository;
_organizerService = organizerService;
Expand All @@ -39,6 +45,8 @@ public EventService(IEventRepository eventRepository, IOrganizerService organize
_paginationService = paginationService;
_categoryService = categoryService;
_ticketService = ticketService;
_customerRepository = customerRepository;
_mailService = mailService;
}

public async Task<Result<Event>> CreateNewEventAsync(string name, string description, DateTime startDate, DateTime endDate,
Expand Down Expand Up @@ -221,6 +229,21 @@ public async Task<Result<Event>> EditEventAsync(Organizer organizer, Guid eventI
return Result<Event>.Success(existingEvent);
}

public async Task<Result> SendMessageToParticipants(Organizer organizer, Guid eventId, string subject, string message)
{
var eventResult = await _eventRepository.GetEventByIdAndOrganizerAsync(eventId, organizer);
if (eventResult.IsError)
{
return Result.PropagateError(eventResult);
}
var ev = eventResult.Value!;

var eventParticipants = await _customerRepository.GetCustomersWithTicketForEvent(ev.Id).ToListAsync();
var recipients = eventParticipants.Select(p => new MailRecipient(p.Email, $"{p.FirstName} {p.LastName}"));

return await _mailService.SendMailAsync(recipients, subject, message, null);
}

private async Task<Result<PaginatedData<GetEventResponseDto>>> GetPaginatedEventsAsync(IQueryable<Event> events, int page, int pageSize)
{
var paginatedEventsResult = await _paginationService.PaginateAsync(events, pageSize, page);
Expand Down
Loading