Skip to content

Commit

Permalink
restore update ticket view
Browse files Browse the repository at this point in the history
  • Loading branch information
cbellone committed Jan 13, 2020
1 parent b2fb506 commit 228434b
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 69 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ junitVersion=5.1.0
systemProp.jdk.tls.client.protocols="TLSv1,TLSv1.1,TLSv1.2"

# https://jitpack.io/#alfio-event/alf.io-public-frontend -> go to commit tab, set the version
alfioPublicFrontendVersion=03e5d06c5b
alfioPublicFrontendVersion=290339eb1b
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import alfio.controller.api.v2.model.ReservationInfo.TicketsByTicketCategory;
import alfio.controller.api.v2.model.ReservationPaymentResult;
import alfio.controller.api.v2.model.ReservationStatusInfo;
import alfio.controller.api.v2.user.support.BookingInfoTicketLoader;
import alfio.controller.form.ContactAndTicketsForm;
import alfio.controller.form.PaymentForm;
import alfio.controller.support.TemplateProcessor;
Expand Down Expand Up @@ -65,7 +66,6 @@
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;

import static alfio.model.PriceContainer.VatStatus.*;
Expand Down Expand Up @@ -93,7 +93,7 @@ public class ReservationApiV2Controller {
private final TicketHelper ticketHelper;
private final EuVatChecker vatChecker;
private final RecaptchaService recaptchaService;
private final AdditionalServiceItemRepository additionalServiceItemRepository;
private final BookingInfoTicketLoader bookingInfoTicketLoader;

/**
* Note: now it will return for any states of the reservation.
Expand Down Expand Up @@ -126,7 +126,7 @@ public ResponseEntity<ReservationInfo> getReservationInfo(@PathVariable("eventNa
boolean hasPaidSupplement = ticketReservationManager.hasPaidSupplements(reservationId);
//

var ticketFieldsFilterer = getTicketFieldsFilterer(reservationId, event);
var ticketFieldsFilterer = bookingInfoTicketLoader.getTicketFieldsFilterer(reservationId, event);

var ticketsByCategory = tickets.stream().collect(Collectors.groupingBy(Ticket::getCategoryId));
//TODO: cleanup this transformation, we most likely don't need to fully load the ticket category
Expand All @@ -135,16 +135,9 @@ public ResponseEntity<ReservationInfo> getReservationInfo(@PathVariable("eventNa
.stream()
.map(e -> {
var tc = eventManager.getTicketCategoryById(e.getKey(), event.getId());
var ts = e.getValue().stream().map(t -> {//


// TODO: n+1, should be cleaned up! see TicketDecorator.getCancellationEnabled
boolean cancellationEnabled = t.getFinalPriceCts() == 0 &&
(!hasPaidSupplement && configurationManager.getFor(ALLOW_FREE_TICKETS_CANCELLATION, ConfigurationLevel.ticketCategory(event, t.getCategoryId())).getValueAsBooleanOrDefault(false)) && // freeCancellationEnabled
eventManager.checkTicketCancellationPrerequisites().apply(t); // cancellationPrerequisitesMet
//
return toBookingInfoTicket(t, cancellationEnabled, ticketFieldsFilterer.getFieldsForTicket(t.getUuid()), descriptionsByTicketFieldId, valuesByTicketIds.getOrDefault(t.getId(), Collections.emptyList()));
}).collect(Collectors.toList());
var ts = e.getValue().stream()
.map(t -> bookingInfoTicketLoader.toBookingInfoTicket(t, hasPaidSupplement, event, ticketFieldsFilterer, descriptionsByTicketFieldId, valuesByTicketIds))
.collect(Collectors.toList());
return new TicketsByTicketCategory(tc.getName(), ts);
})
.collect(Collectors.toList());
Expand Down Expand Up @@ -211,13 +204,6 @@ private Map<PaymentMethod, PaymentProxyWithParameters> getActivePaymentMethods(E
}
}

private Validator.TicketFieldsFilterer getTicketFieldsFilterer(String reservationId, EventAndOrganizationId event) {
var fields = ticketFieldRepository.findAdditionalFieldsForEvent(event.getId());
return new Validator.TicketFieldsFilterer(fields, ticketHelper.getTicketUUIDToCategoryId(),
new HashSet<>(additionalServiceItemRepository.findAdditionalServiceIdsByReservationUuid(reservationId)),
ticketReservationManager.findFirstInReservation(reservationId));
}

@GetMapping("/event/{eventName}/reservation/{reservationId}/status")
public ResponseEntity<ReservationStatusInfo> getReservationStatus(@PathVariable("eventName") String eventName,
@PathVariable("reservationId") String reservationId) {
Expand Down Expand Up @@ -389,7 +375,7 @@ public ResponseEntity<ValidatedResponse<Boolean>> validateToOverview(@PathVariab

Map<ConfigurationKeys, Boolean> formValidationParameters = Collections.singletonMap(ENABLE_ITALY_E_INVOICING, italyEInvoicing);

var ticketFieldFilterer = getTicketFieldsFilterer(reservationId, event);
var ticketFieldFilterer = bookingInfoTicketLoader.getTicketFieldsFilterer(reservationId, event);
//
contactAndTicketsForm.validate(bindingResult, event,
new SameCountryValidator(configurationManager, extensionManager, event, reservationId, vatChecker),
Expand Down Expand Up @@ -630,45 +616,6 @@ public ResponseEntity<ReservationPaymentResult> getTransactionStatus(@PathVariab
}


private static ReservationInfo.AdditionalField toAdditionalField(TicketFieldConfigurationDescriptionAndValue t, Map<String, ReservationInfo.Description> description) {
var fields = t.getFields().stream().map(f -> new ReservationInfo.Field(f.getFieldIndex(), f.getFieldValue())).collect(Collectors.toList());
return new ReservationInfo.AdditionalField(t.getName(), t.getValue(), t.getType(), t.isRequired(), t.isEditable(),
t.getMinLength(), t.getMaxLength(), t.getRestrictedValues(),
fields, t.isBeforeStandardFields(), description);
}

private static Map<String, ReservationInfo.Description> fromFieldDescriptions(List<TicketFieldDescription> descs) {
return descs.stream().collect(Collectors.toMap(TicketFieldDescription::getLocale,
d -> new ReservationInfo.Description(d.getLabelDescription(), d.getPlaceholderDescription(), d.getRestrictedValuesDescription())));
}

private static ReservationInfo.BookingInfoTicket toBookingInfoTicket(Ticket ticket,
boolean cancellationEnabled,
List<TicketFieldConfiguration> ticketFields,
Map<Integer, List<TicketFieldDescription>> descriptionsByTicketFieldId,
List<TicketFieldValue> ticketFieldValues) {


var valueById = ticketFieldValues.stream().collect(Collectors.toMap(TicketFieldValue::getTicketFieldConfigurationId, Function.identity()));


var tfcdav = ticketFields.stream()
.sorted(Comparator.comparing(TicketFieldConfiguration::getOrder))
.map(tfc -> {
var tfd = descriptionsByTicketFieldId.get(tfc.getId()).get(0);//take first, temporary!
var fieldValue = valueById.get(tfc.getId());
var t = new TicketFieldConfigurationDescriptionAndValue(tfc, tfd, tfc.getCount(), fieldValue == null ? null : fieldValue.getValue());
var descs = fromFieldDescriptions(descriptionsByTicketFieldId.get(t.getTicketFieldConfigurationId()));
return toAdditionalField(t, descs);
}).collect(Collectors.toList());

return new ReservationInfo.BookingInfoTicket(ticket.getUuid(),
ticket.getFirstName(), ticket.getLastName(),
ticket.getEmail(), ticket.getFullName(),
ticket.getUserLanguage(),
ticket.getAssigned(), ticket.getLockedAssignment(), ticket.getStatus() == Ticket.TicketStatus.ACQUIRED, cancellationEnabled, tfcdav);
}

private Map<String, String> formatDateForLocales(Event event, ZonedDateTime date, String formattingCode) {

var messageSource = messageSourceManager.getMessageSourceForEvent(event);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,27 +18,26 @@

import alfio.controller.api.support.TicketHelper;
import alfio.controller.api.v2.model.DatesWithTimeZoneOffset;
import alfio.controller.api.v2.model.ReservationInfo;
import alfio.controller.api.v2.model.TicketInfo;
import alfio.controller.api.v2.user.support.BookingInfoTicketLoader;
import alfio.controller.form.UpdateTicketOwnerForm;
import alfio.controller.support.Formatters;
import alfio.controller.support.TemplateProcessor;
import alfio.manager.ExtensionManager;
import alfio.manager.FileUploadManager;
import alfio.manager.NotificationManager;
import alfio.manager.TicketReservationManager;
import alfio.manager.*;
import alfio.manager.i18n.MessageSourceManager;
import alfio.manager.support.response.ValidatedResponse;
import alfio.model.Event;
import alfio.model.Ticket;
import alfio.model.TicketCategory;
import alfio.model.TicketReservation;
import alfio.manager.system.ConfigurationManager;
import alfio.model.*;
import alfio.model.transaction.PaymentProxy;
import alfio.model.user.Organization;
import alfio.repository.TicketCategoryRepository;
import alfio.repository.TicketFieldRepository;
import alfio.repository.user.OrganizationRepository;
import alfio.util.ImageUtil;
import alfio.util.LocaleUtil;
import alfio.util.TemplateManager;
import alfio.util.Validator;
import lombok.AllArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
Expand All @@ -51,8 +50,10 @@
import java.io.IOException;
import java.io.OutputStream;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.stream.Collectors;

@RestController
@AllArgsConstructor
Expand All @@ -67,6 +68,7 @@ public class TicketApiV2Controller {
private final OrganizationRepository organizationRepository;
private final TemplateManager templateManager;
private final NotificationManager notificationManager;
private final BookingInfoTicketLoader bookingInfoTicketLoader;


@GetMapping(value = {
Expand Down Expand Up @@ -157,6 +159,19 @@ public ResponseEntity<Boolean> releaseTicket(@PathVariable("eventName") String e
}
}

@GetMapping("/api/v2/public/event/{eventName}/ticket/{ticketIdentifier}/full")
public ResponseEntity<ReservationInfo.TicketsByTicketCategory> getTicket(@PathVariable("eventName") String eventName,
@PathVariable("ticketIdentifier") String ticketIdentifier) {

var optionalTicket = ticketReservationManager.fetchCompleteAndAssigned(eventName, ticketIdentifier)
.map(complete -> {
var ticket = complete.getRight();
var event = complete.getLeft();
var categoryName = ticketCategoryRepository.getByIdAndActive(ticket.getCategoryId(), event.getId()).getName();
return new ReservationInfo.TicketsByTicketCategory(categoryName, List.of(bookingInfoTicketLoader.toBookingInfoTicket(ticket, event)));
});
return ResponseEntity.of(optionalTicket);
}

@GetMapping("/api/v2/public/event/{eventName}/ticket/{ticketIdentifier}")
public ResponseEntity<TicketInfo> getTicketInfo(@PathVariable("eventName") String eventName,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
/**
* This file is part of alf.io.
*
* alf.io is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* alf.io is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with alf.io. If not, see <http://www.gnu.org/licenses/>.
*/
package alfio.controller.api.v2.user.support;

import alfio.controller.api.support.TicketHelper;
import alfio.controller.api.v2.model.ReservationInfo;
import alfio.manager.EventManager;
import alfio.manager.TicketReservationManager;
import alfio.manager.system.ConfigurationLevel;
import alfio.manager.system.ConfigurationManager;
import alfio.model.*;
import alfio.repository.AdditionalServiceItemRepository;
import alfio.repository.TicketFieldRepository;
import alfio.util.Validator;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static alfio.model.system.ConfigurationKeys.ALLOW_FREE_TICKETS_CANCELLATION;

@Component
@AllArgsConstructor
public class BookingInfoTicketLoader {

private final EventManager eventManager;
private final ConfigurationManager configurationManager;
private final TicketFieldRepository ticketFieldRepository;
private final TicketHelper ticketHelper;
private final AdditionalServiceItemRepository additionalServiceItemRepository;
private final TicketReservationManager ticketReservationManager;


public ReservationInfo.BookingInfoTicket toBookingInfoTicket(Ticket ticket, Event event) {
var descriptionsByTicketFieldId = ticketFieldRepository.findDescriptions(event.getShortName())
.stream()
.collect(Collectors.groupingBy(TicketFieldDescription::getTicketFieldConfigurationId));

var valuesByTicketIds = ticketFieldRepository.findAllValuesByTicketIds(List.of(ticket.getId()))
.stream()
.collect(Collectors.groupingBy(TicketFieldValue::getTicketId));

boolean hasPaidSupplement = ticketReservationManager.hasPaidSupplements(ticket.getTicketsReservationId());

return toBookingInfoTicket(ticket,
hasPaidSupplement,
event,
getTicketFieldsFilterer(ticket.getTicketsReservationId(), event),
descriptionsByTicketFieldId,
valuesByTicketIds);
}

public ReservationInfo.BookingInfoTicket toBookingInfoTicket(Ticket t,
boolean hasPaidSupplement,
Event event,
Validator.TicketFieldsFilterer ticketFieldsFilterer,
Map<Integer, List<TicketFieldDescription>> descriptionsByTicketFieldId,
Map<Integer, List<TicketFieldValue>> valuesByTicketIds) {
// TODO: n+1, should be cleaned up! see TicketDecorator.getCancellationEnabled
boolean cancellationEnabled = t.getFinalPriceCts() == 0 &&
(!hasPaidSupplement && configurationManager.getFor(ALLOW_FREE_TICKETS_CANCELLATION, ConfigurationLevel.ticketCategory(event, t.getCategoryId())).getValueAsBooleanOrDefault(false)) && // freeCancellationEnabled
eventManager.checkTicketCancellationPrerequisites().apply(t); // cancellationPrerequisitesMet
//
return toBookingInfoTicket(t, cancellationEnabled, ticketFieldsFilterer.getFieldsForTicket(t.getUuid()), descriptionsByTicketFieldId, valuesByTicketIds.getOrDefault(t.getId(), Collections.emptyList()));
}

public Validator.TicketFieldsFilterer getTicketFieldsFilterer(String reservationId, EventAndOrganizationId event) {
var fields = ticketFieldRepository.findAdditionalFieldsForEvent(event.getId());
return new Validator.TicketFieldsFilterer(fields, ticketHelper.getTicketUUIDToCategoryId(),
new HashSet<>(additionalServiceItemRepository.findAdditionalServiceIdsByReservationUuid(reservationId)),
ticketReservationManager.findFirstInReservation(reservationId));
}

private static ReservationInfo.BookingInfoTicket toBookingInfoTicket(Ticket ticket,
boolean cancellationEnabled,
List<TicketFieldConfiguration> ticketFields,
Map<Integer, List<TicketFieldDescription>> descriptionsByTicketFieldId,
List<TicketFieldValue> ticketFieldValues) {


var valueById = ticketFieldValues.stream().collect(Collectors.toMap(TicketFieldValue::getTicketFieldConfigurationId, Function.identity()));


var tfcdav = ticketFields.stream()
.sorted(Comparator.comparing(TicketFieldConfiguration::getOrder))
.map(tfc -> {
var tfd = descriptionsByTicketFieldId.get(tfc.getId()).get(0);//take first, temporary!
var fieldValue = valueById.get(tfc.getId());
var t = new TicketFieldConfigurationDescriptionAndValue(tfc, tfd, tfc.getCount(), fieldValue == null ? null : fieldValue.getValue());
var descs = fromFieldDescriptions(descriptionsByTicketFieldId.get(t.getTicketFieldConfigurationId()));
return toAdditionalField(t, descs);
}).collect(Collectors.toList());

return new ReservationInfo.BookingInfoTicket(ticket.getUuid(),
ticket.getFirstName(), ticket.getLastName(),
ticket.getEmail(), ticket.getFullName(),
ticket.getUserLanguage(),
ticket.getAssigned(), ticket.getLockedAssignment(), ticket.getStatus() == Ticket.TicketStatus.ACQUIRED, cancellationEnabled, tfcdav);
}

private static ReservationInfo.AdditionalField toAdditionalField(TicketFieldConfigurationDescriptionAndValue t, Map<String, ReservationInfo.Description> description) {
var fields = t.getFields().stream().map(f -> new ReservationInfo.Field(f.getFieldIndex(), f.getFieldValue())).collect(Collectors.toList());
return new ReservationInfo.AdditionalField(t.getName(), t.getValue(), t.getType(), t.isRequired(), t.isEditable(),
t.getMinLength(), t.getMaxLength(), t.getRestrictedValues(),
fields, t.isBeforeStandardFields(), description);
}

private static Map<String, ReservationInfo.Description> fromFieldDescriptions(List<TicketFieldDescription> descs) {
return descs.stream().collect(Collectors.toMap(TicketFieldDescription::getLocale,
d -> new ReservationInfo.Description(d.getLabelDescription(), d.getPlaceholderDescription(), d.getRestrictedValuesDescription())));
}
}

0 comments on commit 228434b

Please sign in to comment.