Skip to content

Commit

Permalink
update billing documents, update email messages
Browse files Browse the repository at this point in the history
  • Loading branch information
cbellone committed Feb 26, 2021
1 parent 9aab2d2 commit adad1af
Show file tree
Hide file tree
Showing 17 changed files with 136 additions and 88 deletions.
7 changes: 5 additions & 2 deletions src/main/java/alfio/config/WebSecurityConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -286,13 +286,16 @@ protected void configure(HttpSecurity http) throws Exception {
ADMIN_API + "/overridable-template/",
ADMIN_API + "/events/*/promo-code",
ADMIN_API + "/reservation/event/*/reservations/list",
ADMIN_API + "/events/*/email/",
ADMIN_API + "/event/*/email/",
ADMIN_API + "/event/*/waiting-queue/load",
ADMIN_API + "/events/*/pending-payments",
ADMIN_API + "/events/*/export",
ADMIN_API + "/events/*/sponsor-scan/export",
ADMIN_API + "/events/*/invoices/**",
ADMIN_API + "/reservation/event/*/*/audit"
ADMIN_API + "/reservation/*/*/*/audit",
ADMIN_API + "/subscription/*/email/",
ADMIN_API + "/organization/*/subscription/**",
ADMIN_API + "/reservation/subscription/**"
};

configurer.csrfTokenRepository(csrfTokenRepository)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@
package alfio.controller.api.admin;

import alfio.controller.api.support.PageAndContent;
import alfio.manager.EventManager;
import alfio.manager.NotificationManager;
import alfio.manager.PurchaseContextManager;
import alfio.model.EmailMessage;
import alfio.model.Event;
import alfio.model.LightweightMailMessage;
import alfio.model.PurchaseContext;
import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.experimental.Delegate;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.security.Principal;
Expand All @@ -36,36 +36,35 @@
import java.util.Optional;
import java.util.stream.Collectors;

@RequiredArgsConstructor
@RestController
@RequestMapping("/admin/api/events/{eventName}/email")
@RequestMapping("/admin/api/{purchaseContextType}/{publicIdentifier}/email")
public class EmailMessageApiController {

private final NotificationManager notificationManager;
private final EventManager eventManager;

@Autowired
public EmailMessageApiController(NotificationManager notificationManager, EventManager eventManager) {
this.notificationManager = notificationManager;
this.eventManager = eventManager;
}
private final PurchaseContextManager purchaseContextManager;

@GetMapping("/")
public PageAndContent<List<LightweightEmailMessage>> loadEmailMessages(@PathVariable("eventName") String eventName,
@RequestParam(value = "page", required = false) Integer page,
@RequestParam(value = "search", required = false) String search,
Principal principal) {
Event event = eventManager.getSingleEvent(eventName, principal.getName());
ZoneId zoneId = event.getZoneId();
Pair<Integer, List<LightweightMailMessage>> found = notificationManager.loadAllMessagesForEvent(event.getId(), page, search);
public PageAndContent<List<LightweightEmailMessage>> loadEmailMessages(@PathVariable("purchaseContextType") PurchaseContext.PurchaseContextType purchaseContextType,
@PathVariable("publicIdentifier") String publicIdentifier,
@RequestParam(value = "page", required = false) Integer page,
@RequestParam(value = "search", required = false) String search,
Principal principal) {
var purchaseContext = purchaseContextManager.findBy(purchaseContextType, publicIdentifier).orElseThrow();
ZoneId zoneId = purchaseContext.getZoneId();
Pair<Integer, List<LightweightMailMessage>> found = notificationManager.loadAllMessagesForPurchaseContext(purchaseContext, page, search);
return new PageAndContent<>(found.getRight().stream()
.map(m -> new LightweightEmailMessage(m, zoneId, true))
.collect(Collectors.toList()), found.getLeft());
}

@GetMapping("/{messageId}")
public LightweightEmailMessage loadEmailMessage(@PathVariable("eventName") String eventName, @PathVariable("messageId") int messageId, Principal principal) {
Event event = eventManager.getSingleEvent(eventName, principal.getName());
return notificationManager.loadSingleMessageForEvent(event.getId(), messageId).map(m -> new LightweightEmailMessage(m, event.getZoneId(), false)).orElseThrow(IllegalArgumentException::new);
public LightweightEmailMessage loadEmailMessage(@PathVariable("purchaseContextType") PurchaseContext.PurchaseContextType purchaseContextType,
@PathVariable("publicIdentifier") String publicIdentifier,
@PathVariable("messageId") int messageId,
Principal principal) {
var purchaseContext = purchaseContextManager.findBy(purchaseContextType, publicIdentifier).orElseThrow();
return notificationManager.loadSingleMessageForPurchaseContext(purchaseContext, messageId).map(m -> new LightweightEmailMessage(m, purchaseContext.getZoneId(), false)).orElseThrow(IllegalArgumentException::new);
}

@AllArgsConstructor
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/alfio/manager/BillingDocumentManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import alfio.manager.system.ConfigurationManager;
import alfio.manager.system.Mailer;
import alfio.model.*;
import alfio.model.PurchaseContext.PurchaseContextType;
import alfio.model.system.ConfigurationKeys;
import alfio.model.user.Organization;
import alfio.repository.*;
Expand Down Expand Up @@ -157,6 +158,7 @@ private Map<String, Object> prepareModelForBillingDocument(PurchaseContext purch
boolean euBusiness = StringUtils.isNotBlank(reservation.getVatCountryCode()) && StringUtils.isNotBlank(reservation.getVatNr())
&& configurationManager.getForSystem(ConfigurationKeys.EU_COUNTRIES_LIST).getRequiredValue().contains(reservation.getVatCountryCode())
&& PriceContainer.VatStatus.isVatExempt(reservation.getVatStatus());
model.put("isEvent", purchaseContext.getType() == PurchaseContextType.event);
model.put("euBusiness", euBusiness);
model.put("publicId", configurationManager.getPublicReservationID(purchaseContext, reservation));
model.put("invoicingAdditionalInfo", ticketReservationRepository.getAdditionalInfo(reservation.getId()).getInvoicingAdditionalInfo());
Expand Down
18 changes: 14 additions & 4 deletions src/main/java/alfio/manager/NotificationManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -313,20 +313,30 @@ private static Pair<Integer, UUID> getEventIdSubscriptionId(PurchaseContext purc
}
}

public Pair<Integer, List<LightweightMailMessage>> loadAllMessagesForEvent(int eventId, Integer page, String search) {
public Pair<Integer, List<LightweightMailMessage>> loadAllMessagesForPurchaseContext(PurchaseContext purchaseContext, Integer page, String search) {
final int pageSize = 50;
int offset = page == null ? 0 : page * pageSize;
String toSearch = StringUtils.trimToNull(search);
toSearch = toSearch == null ? null : ("%" + toSearch + "%");
return Pair.of(emailMessageRepository.countFindByEventId(eventId, toSearch), emailMessageRepository.findByEventId(eventId, offset, pageSize, toSearch));
if(purchaseContext.getType() == PurchaseContextType.event) {
int eventId = ((Event) purchaseContext).getId();
return Pair.of(emailMessageRepository.countFindByEventId(eventId, toSearch), emailMessageRepository.findByEventId(eventId, offset, pageSize, toSearch));
} else {
var subscriptionDescriptorId = ((SubscriptionDescriptor)purchaseContext).getId();
return Pair.of(emailMessageRepository.countFindBySubscriptionDescriptorId(subscriptionDescriptorId, toSearch), emailMessageRepository.findBySubscriptionDescriptorId(subscriptionDescriptorId, offset, pageSize, toSearch));
}
}

public List<LightweightMailMessage> loadAllMessagesForReservationId(PurchaseContext purchaseContext, String reservationId) {
return emailMessageRepository.findByPurchaseContextAndReservationId(purchaseContext, reservationId);
}

public Optional<EmailMessage> loadSingleMessageForEvent(int eventId, int messageId) {
return emailMessageRepository.findByEventIdAndMessageId(eventId, messageId);
public Optional<LightweightMailMessage> loadSingleMessageForPurchaseContext(PurchaseContext purchaseContext, int messageId) {
if(purchaseContext.getType() == PurchaseContextType.event) {
return emailMessageRepository.findByEventIdAndMessageId(((Event)purchaseContext).getId(), messageId);
} else {
return emailMessageRepository.findBySubscriptionDescriptorIdAndMessageId(((SubscriptionDescriptor)purchaseContext).getId(), messageId);
}
}

@Transactional
Expand Down
7 changes: 5 additions & 2 deletions src/main/java/alfio/manager/TicketReservationManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -810,8 +810,11 @@ public void sendConfirmationEmail(PurchaseContext purchaseContext, TicketReserva
attachments = generateAttachmentForConfirmationEmail(purchaseContext, ticketReservation, language, summary, username);
}

notificationManager.sendSimpleEmail(purchaseContext, ticketReservation.getId(), ticketReservation.getEmail(), messageSourceManager.getMessageSourceFor(purchaseContext).getMessage("reservation-email-subject",
new Object[]{getShortReservationID(purchaseContext, ticketReservation), purchaseContext.getDisplayName()}, language),

var messageSource = messageSourceManager.getMessageSourceFor(purchaseContext);
var localizedType = messageSource.getMessage("purchase-context."+purchaseContext.getType(), null, language);
notificationManager.sendSimpleEmail(purchaseContext, ticketReservation.getId(), ticketReservation.getEmail(), messageSource.getMessage("reservation-email-subject",
new Object[]{getShortReservationID(purchaseContext, ticketReservation), purchaseContext.getTitle().get(language.getLanguage()), localizedType}, language),
() -> templateManager.renderTemplate(purchaseContext, templateResource, reservationEmailModel, language),
attachments);
}
Expand Down
15 changes: 9 additions & 6 deletions src/main/java/alfio/manager/payment/BaseStripeManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@
import alfio.manager.support.PaymentResult;
import alfio.manager.system.ConfigurationManager;
import alfio.manager.user.UserManager;
import alfio.model.*;
import alfio.model.Configurable;
import alfio.model.PaymentInformation;
import alfio.model.PurchaseContext;
import alfio.model.PurchaseContext.PurchaseContextType;
import alfio.model.system.ConfigurationKeys;
import alfio.model.system.ConfigurationPathLevel;
import alfio.model.transaction.PaymentContext;
Expand Down Expand Up @@ -150,14 +153,14 @@ protected Map<String, Object> createParams(PaymentSpecification spec, Map<String
int tickets = ticketRepository.countTicketsInReservation(spec.getReservationId());
Map<String, Object> chargeParams = new HashMap<>();
chargeParams.put("amount", spec.getPriceWithVAT());
FeeCalculator.getCalculator(spec.getPurchaseContext(), configurationManager, spec.getCurrencyCode())
var purchaseContext = spec.getPurchaseContext();
FeeCalculator.getCalculator(purchaseContext, configurationManager, spec.getCurrencyCode())
.apply(tickets, (long) spec.getPriceWithVAT())
.filter(l -> l > 0)
.ifPresent(fee -> chargeParams.put("application_fee_amount", fee));
chargeParams.put("currency", spec.getPurchaseContext().getCurrency());

chargeParams.put("description", String.format("%d ticket(s) for event %s", tickets, spec.getPurchaseContext().getDisplayName()));

chargeParams.put("currency", purchaseContext.getCurrency());
var description = purchaseContext.getType() == PurchaseContextType.event ? "ticket(s) for event" : "x subscription";
chargeParams.put("description", String.format("%d %s %s", tickets, description, purchaseContext.getDisplayName()));
chargeParams.put("metadata", MetadataBuilder.buildMetadata(spec, baseMetadata));
return chargeParams;
}
Expand Down
26 changes: 19 additions & 7 deletions src/main/java/alfio/repository/EmailMessageRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -88,16 +88,23 @@ int insert(@Bind("eventId") Integer eventId,
@Query("update email_message set status = 'SENT', sent_ts = :sentTimestamp, html_message = null where id = :id and checksum = :checksum and status in (:expectedStatuses)")
int updateStatusToSent(@Bind("id") int id, @Bind("checksum") String checksum, @Bind("sentTimestamp") ZonedDateTime sentTimestamp, @Bind("expectedStatuses") List<String> expectedStatuses);

String FIND_MAILS = "select id, event_id, subscription_descriptor_id_fk, status, recipient, subject, message, checksum, request_ts, sent_ts, attempts, email_cc, organization_id_fk from email_message where event_id = :eventId and " +
String LIGHTWEIGHT_FIELDS = "id, event_id, subscription_descriptor_id_fk, status, recipient, subject, message, checksum, request_ts, sent_ts, attempts, email_cc, organization_id_fk ";
String FIND_MAILS_BY_EVENT = "select " + LIGHTWEIGHT_FIELDS + " from email_message where event_id = :eventId and " +
" (:search is null or (recipient like :search or subject like :search or message like :search)) order by sent_ts desc, id ";

@Query("select * from (" + FIND_MAILS +"limit :pageSize offset :page) as d_tbl")
String FIND_MAILS_BY_SUBSCRIPTION = "select " + LIGHTWEIGHT_FIELDS + " from email_message where subscription_descriptor_id_fk = :subscriptionId and " +
" (:search is null or (recipient like :search or subject like :search or message like :search)) order by sent_ts desc, id ";

@Query("select * from (" + FIND_MAILS_BY_EVENT +" limit :pageSize offset :page) as d_tbl")
List<LightweightMailMessage> findByEventId(@Bind("eventId") int eventId, @Bind("page") int page, @Bind("pageSize") int pageSize, @Bind("search") String search);

@Query("select id, event_id, status, recipient, subject, message, checksum, request_ts, sent_ts, attempts, email_cc from email_message where event_id = :eventId and reservation_id = :reservationId order by sent_ts desc, id")
@Query("select id, event_id, status, recipient, subject, message, checksum, request_ts, sent_ts, attempts, email_cc, subscription_descriptor_id_fk, organization_id_fk from email_message where event_id = :eventId and reservation_id = :reservationId order by sent_ts desc, id")
List<LightweightMailMessage> findByEventIdAndReservationId(@Bind("eventId") int eventId, @Bind("reservationId") String reservationId);

@Query("select id, event_id, status, recipient, subject, message, checksum, request_ts, sent_ts, attempts, email_cc from email_message where subscription_descriptor_id_fk = :subscriptionDescriptorId and reservation_id = :reservationId order by sent_ts desc, id")
@Query("select * from (" + FIND_MAILS_BY_SUBSCRIPTION + " limit :pageSize offset :page) as d_tbl")
List<LightweightMailMessage> findBySubscriptionDescriptorId(@Bind("subscriptionId") UUID subscriptionDescriptorId, @Bind("page") int page, @Bind("pageSize") int pageSize, @Bind("search") String search);

@Query("select id, event_id, status, recipient, subject, message, checksum, request_ts, sent_ts, attempts, email_cc, subscription_descriptor_id_fk, organization_id_fk from email_message where subscription_descriptor_id_fk = :subscriptionDescriptorId and reservation_id = :reservationId order by sent_ts desc, id")
List<LightweightMailMessage> findBySubscriptionDescriptorAndReservationId(@Bind("subscriptionDescriptorId") UUID subscriptionDescriptorId, @Bind("reservationId") String reservationId);

default List<LightweightMailMessage> findByPurchaseContextAndReservationId(PurchaseContext purchaseContext, String reservationId) {
Expand All @@ -108,15 +115,20 @@ default List<LightweightMailMessage> findByPurchaseContextAndReservationId(Purch
}
}

@Query("select count(*) from (" + FIND_MAILS + ") as d_tbl")
@Query("select count(*) from (" + FIND_MAILS_BY_EVENT + ") as d_tbl")
Integer countFindByEventId(@Bind("eventId") int eventId, @Bind("search") String search);

@Query("select count(*) from ("+FIND_MAILS_BY_SUBSCRIPTION+") as d_tbl")
Integer countFindBySubscriptionDescriptorId(@Bind("subscriptionId") UUID subscriptionId, @Bind("search") String search);

@Query("select * from email_message where id = :id")
EmailMessage findById(@Bind("id") int id);

@Query("select * from email_message where id = :messageId and event_id = :eventId")
Optional<EmailMessage> findByEventIdAndMessageId(@Bind("eventId") int eventId, @Bind("messageId") int messageId);
@Query("select "+LIGHTWEIGHT_FIELDS+" from email_message where id = :messageId and event_id = :eventId")
Optional<LightweightMailMessage> findByEventIdAndMessageId(@Bind("eventId") int eventId, @Bind("messageId") int messageId);

@Query("select "+LIGHTWEIGHT_FIELDS+" from email_message where id = :messageId and subscription_descriptor_id_fk = :subscriptionId")
Optional<LightweightMailMessage> findBySubscriptionDescriptorIdAndMessageId(@Bind("subscriptionId") UUID subscriptionId, @Bind("messageId") int messageId);

@Query("update email_message set status = 'RETRY', attempts = coalesce(attempts, 0) +1 where status = 'IN_PROCESS' and request_ts < :date")
int setToRetryOldInProcess(@Bind("date") ZonedDateTime date);
Expand Down
4 changes: 3 additions & 1 deletion src/main/resources/alfio/i18n/public.properties
Original file line number Diff line number Diff line change
Expand Up @@ -273,8 +273,10 @@ email.ticket-email-sent=The ticket has been sent by email.


#email
purchase-context.event=Event
purchase-context.subscription=Subscription
ticket-email-subject=Your ticket for event {0}
reservation-email-subject=Your reservation n. {0} for event {1}
reservation-email-subject=Your reservation n. {0} for {2} {1}
reservation-email-expired-subject=Your reservation n. {0} for event {1} has been cancelled
ticket-has-changed-owner-subject=Notice: your ticket for event {0} has changed email owner

Expand Down
Loading

0 comments on commit adad1af

Please sign in to comment.