Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New reservation flow #484

Merged
merged 23 commits into from
Jul 2, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
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
301 changes: 196 additions & 105 deletions src/main/java/alfio/controller/ReservationController.java

Large diffs are not rendered by default.

21 changes: 11 additions & 10 deletions src/main/java/alfio/controller/api/ReservationApiController.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
package alfio.controller.api;

import alfio.controller.api.support.TicketHelper;
import alfio.controller.form.PaymentForm;
import alfio.controller.form.ContactAndTicketsForm;
import alfio.controller.form.UpdateTicketOwnerForm;
import alfio.manager.EuVatChecker;
import alfio.manager.TicketReservationManager;
Expand Down Expand Up @@ -128,18 +128,18 @@ public ResponseEntity<Boolean> resetVat(@PathVariable("eventName") String eventN
@Transactional
public ResponseEntity<VatDetail> validateEUVat(@PathVariable("eventName") String eventName,
@PathVariable("reservationId") String reservationId,
PaymentForm paymentForm,
ContactAndTicketsForm contactAndTicketsForm,
Locale locale,
HttpServletRequest request) {

String country = paymentForm.getVatCountryCode();
/*String country = contactAndTicketsForm.getVatCountryCode();
Optional<Triple<Event, TicketReservation, VatDetail>> vatDetail;
try {
vatDetail = eventRepository.findOptionalByShortName(eventName)
.flatMap(e -> ticketReservationRepository.findOptionalReservationById(reservationId).map(r -> Pair.of(e, r)))
.filter(e -> EnumSet.of(INCLUDED, NOT_INCLUDED).contains(e.getKey().getVatStatus()))
.filter(e -> vatChecker.isVatCheckingEnabledFor(e.getKey().getOrganizationId()))
.flatMap(e -> vatChecker.checkVat(paymentForm.getVatNr(), country, e.getKey().getOrganizationId()).map(vd -> Triple.of(e.getLeft(), e.getRight(), vd)));
.flatMap(e -> vatChecker.checkVat(contactAndTicketsForm.getVatNr(), country, e.getKey().getOrganizationId()).map(vd -> Triple.of(e.getLeft(), e.getRight(), vd)));
} catch (IllegalStateException e) {
return new ResponseEntity<>(HttpStatus.SERVICE_UNAVAILABLE);
}
Expand All @@ -151,13 +151,13 @@ public ResponseEntity<VatDetail> validateEUVat(@PathVariable("eventName") String
VatDetail vd = t.getRight();
String billingAddress = vd.getName() + "\n" + vd.getAddress();
PriceContainer.VatStatus vatStatus = determineVatStatus(t.getLeft().getVatStatus(), t.getRight().isVatExempt());
ticketReservationRepository.updateBillingData(vatStatus, vd.getVatNr(), country, paymentForm.isInvoiceRequested(), reservationId);
ticketReservationRepository.updateBillingData(vatStatus, vd.getVatNr(), country, contactAndTicketsForm.isInvoiceRequested(), reservationId);
OrderSummary orderSummary = ticketReservationManager.orderSummaryForReservationId(reservationId, t.getLeft(), Locale.forLanguageTag(t.getMiddle().getUserLanguage()));
ticketReservationRepository.addReservationInvoiceOrReceiptModel(reservationId, Json.toJson(orderSummary));
ticketReservationRepository.updateTicketReservation(reservationId, t.getMiddle().getStatus().name(), paymentForm.getEmail(),
paymentForm.getFullName(), paymentForm.getFirstName(), paymentForm.getLastName(), locale.getLanguage(), billingAddress, null,
Optional.ofNullable(paymentForm.getPaymentMethod()).map(PaymentProxy::name).orElse(null), paymentForm.getCustomerReference());
paymentForm.getTickets().forEach((ticketId, owner) -> {
ticketReservationRepository.updateTicketReservation(reservationId, t.getMiddle().getStatus().name(), contactAndTicketsForm.getEmail(),
contactAndTicketsForm.getFullName(), contactAndTicketsForm.getFirstName(), contactAndTicketsForm.getLastName(), locale.getLanguage(), billingAddress, null,
Optional.ofNullable(contactAndTicketsForm.getPaymentMethod()).map(PaymentProxy::name).orElse(null), contactAndTicketsForm.getCustomerReference());
contactAndTicketsForm.getTickets().forEach((ticketId, owner) -> {
if(isNotEmpty(owner.getEmail()) && ((isNotEmpty(owner.getFirstName()) && isNotEmpty(owner.getLastName())) || isNotEmpty(owner.getFullName()))) {
ticketHelper.preAssignTicket(eventName, reservationId, ticketId, owner, Optional.empty(), request, (tr) -> {}, Optional.empty());
}
Expand All @@ -173,7 +173,8 @@ public ResponseEntity<VatDetail> validateEUVat(@PathVariable("eventName") String
return new ResponseEntity<VatDetail>(HttpStatus.BAD_REQUEST);
}
})
.orElseGet(() -> new ResponseEntity<>(HttpStatus.NOT_FOUND));
.orElseGet(() -> new ResponseEntity<>(HttpStatus.NOT_FOUND));*/
return null;
}

private static PriceContainer.VatStatus determineVatStatus(PriceContainer.VatStatus current, boolean isVatExempt) {
Expand Down
3 changes: 1 addition & 2 deletions src/main/java/alfio/controller/api/support/TicketHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,6 @@ public Optional<Triple<ValidationResult, Event, Ticket>> preAssignTicket(String
}

public Optional<Triple<ValidationResult, Event, Ticket>> assignTicket(String eventName,
String reservationId,
String ticketIdentifier,
UpdateTicketOwnerForm updateTicketOwner,
Optional<Errors> bindingResult,
Expand Down Expand Up @@ -171,7 +170,7 @@ public Optional<Triple<ValidationResult, Event, Ticket>> directTicketAssignment(
form.setFirstName(firstName);
form.setLastName(lastName);
form.setUserLanguage(userLanguage);
return assignTicket(eventName, reservationId, ticketUuid, form, bindingResult, request, model);
return assignTicket(eventName, ticketUuid, form, bindingResult, request, model);
}

public static List<Pair<String, String>> getLocalizedCountries(Locale locale) {
Expand Down
176 changes: 176 additions & 0 deletions src/main/java/alfio/controller/form/ContactAndTicketsForm.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
/**
* 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.form;

import alfio.manager.EuVatChecker;
import alfio.model.*;
import alfio.model.result.ValidationResult;
import alfio.util.ErrorsCode;
import alfio.util.Validator;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ValidationUtils;

import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

import static alfio.util.ErrorsCode.STEP_2_INVALID_VAT;
import static alfio.util.ErrorsCode.STEP_2_MISSING_ATTENDEE_DATA;

// step 2 : contact/claim tickets
//
@Data
public class ContactAndTicketsForm implements Serializable {

private String email;
private String fullName;
private String firstName;
private String lastName;
private String billingAddress;
private String customerReference;
private Boolean cancelReservation;

private Boolean expressCheckoutRequested;
private boolean postponeAssignment = false;
private String vatCountryCode;
private String vatNr;
private boolean invoiceRequested = false;
private Map<String, UpdateTicketOwnerForm> tickets = new HashMap<>();
//
private String billingAddressCompany;
private String billingAddressLine1;
private String billingAddressLine2;
private String billingAddressZip;
private String billingAddressCity;

private boolean addCompanyBillingDetails = false;
private Boolean backFromOverview;

private static void rejectIfOverLength(BindingResult bindingResult, String field, String errorCode,
String value, int maxLength) {
if (value != null && value.length() > maxLength) {
bindingResult.rejectValue(field, errorCode);
}
}



public void validate(BindingResult bindingResult, Event event, List<TicketFieldConfiguration> fieldConf, EuVatChecker.SameCountryValidator vatValidator) {



email = StringUtils.trim(email);

fullName = StringUtils.trim(fullName);
firstName = StringUtils.trim(firstName);
lastName = StringUtils.trim(lastName);

billingAddress = StringUtils.trim(billingAddress);

ValidationUtils.rejectIfEmptyOrWhitespace(bindingResult, "email", ErrorsCode.STEP_2_EMPTY_EMAIL);
rejectIfOverLength(bindingResult, "email", ErrorsCode.STEP_2_MAX_LENGTH_EMAIL, email, 255);

if(event.mustUseFirstAndLastName()) {
ValidationUtils.rejectIfEmptyOrWhitespace(bindingResult, "firstName", ErrorsCode.STEP_2_EMPTY_FIRSTNAME);
rejectIfOverLength(bindingResult, "firstName", ErrorsCode.STEP_2_MAX_LENGTH_FIRSTNAME, fullName, 255);
ValidationUtils.rejectIfEmptyOrWhitespace(bindingResult, "lastName", ErrorsCode.STEP_2_EMPTY_LASTNAME);
rejectIfOverLength(bindingResult, "lastName", ErrorsCode.STEP_2_MAX_LENGTH_LASTNAME, fullName, 255);
} else {
ValidationUtils.rejectIfEmptyOrWhitespace(bindingResult, "fullName", ErrorsCode.STEP_2_EMPTY_FULLNAME);
rejectIfOverLength(bindingResult, "fullName", ErrorsCode.STEP_2_MAX_LENGTH_FULLNAME, fullName, 255);
}



if(invoiceRequested) {
/*if(companyVatChecked) {
ValidationUtils.rejectIfEmptyOrWhitespace(bindingResult, "billingAddressCompany", "error.emptyField");
rejectIfOverLength(bindingResult, "billingAddressCompany", "error.tooLong", billingAddressCompany, 256);
}*/

ValidationUtils.rejectIfEmptyOrWhitespace(bindingResult, "billingAddressLine1", "error.emptyField");
rejectIfOverLength(bindingResult, "billingAddressLine1", "error.tooLong", billingAddressLine1, 256);

rejectIfOverLength(bindingResult, "billingAddressLine2", "error.tooLong", billingAddressLine2, 256);

ValidationUtils.rejectIfEmptyOrWhitespace(bindingResult, "billingAddressZip", "error.emptyField");
rejectIfOverLength(bindingResult, "billingAddressZip", "error.tooLong", billingAddressZip, 51);

ValidationUtils.rejectIfEmptyOrWhitespace(bindingResult, "billingAddressCity", "error.emptyField");
rejectIfOverLength(bindingResult, "billingAddressCity", "error.tooLong", billingAddressCity, 256);
}

if (email != null && !email.contains("@") && !bindingResult.hasFieldErrors("email")) {
bindingResult.rejectValue("email", ErrorsCode.STEP_2_INVALID_EMAIL);
}

if(!postponeAssignment) {
Optional<List<ValidationResult>> validationResults = Optional.ofNullable(tickets)
.filter(m -> !m.isEmpty())
.map(m -> m.entrySet().stream().map(e -> Validator.validateTicketAssignment(e.getValue(),
fieldConf, Optional.of(bindingResult), event, "tickets[" + e.getKey() + "]", vatValidator)))
.map(s -> s.collect(Collectors.toList()));

boolean success = validationResults
.filter(l -> l.stream().allMatch(ValidationResult::isSuccess))
.isPresent();
if(!success) {
String errorCode = validationResults.filter(this::containsVatValidationError).isPresent() ? STEP_2_INVALID_VAT : STEP_2_MISSING_ATTENDEE_DATA;
bindingResult.reject(errorCode);
}
}
}

private boolean containsVatValidationError(List<ValidationResult> l) {
return l.stream().anyMatch(v -> !v.isSuccess() && v.getErrorDescriptors().stream().anyMatch(ed -> ed.getCode().equals(STEP_2_INVALID_VAT)));
}

public Boolean shouldCancelReservation() {
return Optional.ofNullable(cancelReservation).orElse(false);
}

public static ContactAndTicketsForm fromExistingReservation(TicketReservation reservation, TicketReservationAdditionalInfo additionalInfo) {
ContactAndTicketsForm form = new ContactAndTicketsForm();
form.setFirstName(reservation.getFirstName());
form.setLastName(reservation.getLastName());
form.setBillingAddress(reservation.getBillingAddress());
form.setEmail(reservation.getEmail());
form.setFullName(reservation.getFullName());
form.setVatCountryCode(reservation.getVatCountryCode());
form.setVatNr(reservation.getVatNr());
form.setInvoiceRequested(reservation.isInvoiceRequested());
form.setCustomerReference(reservation.getCustomerReference());


form.setBillingAddressCompany(additionalInfo.getBillingAddressCompany());
form.setBillingAddressLine1(additionalInfo.getBillingAddressLine1());
form.setBillingAddressLine2(additionalInfo.getBillingAddressLine2());
form.setBillingAddressZip(additionalInfo.getBillingAddressZip());
form.setBillingAddressCity(additionalInfo.getBillingAddressCity());
return form;
}

public boolean getHasVatCountryCode() {
return !StringUtils.isEmpty(vatCountryCode);
}

public boolean isBackFromOverview() {
return Optional.ofNullable(backFromOverview).orElse(false);
}
}
Loading