Skip to content

Commit

Permalink
#464 re enable validation for step2, highlight errors
Browse files Browse the repository at this point in the history
  • Loading branch information
syjer committed Jul 2, 2018
1 parent 3955356 commit 02ac16b
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 70 deletions.
9 changes: 5 additions & 4 deletions src/main/java/alfio/controller/ReservationController.java
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ public String showBookingPage(@PathVariable("eventName") String eventName,
!hasPaidSupplement && configurationManager.getBooleanConfigValue(Configuration.from(event.getOrganizationId(), event.getId(), category.getId(), ALLOW_FREE_TICKETS_CANCELLATION), false),
eventManager.checkTicketCancellationPrerequisites(),
ticketHelper::findTicketFieldConfigurationAndValue,
true, (t) -> "tickets['"+t.getUuid()+"'].");
true, (t) -> "tickets["+t.getUuid()+"].");
return Pair.of(category, decorators);
})
.collect(toList()));
Expand Down Expand Up @@ -276,7 +276,7 @@ public String validateToOverview(@PathVariable("eventName") String eventName, @P
paymentForm.setInvoiceRequested(true);
}

CustomerName customerName = new CustomerName(paymentForm.getFullName(), paymentForm.getFirstName(), paymentForm.getLastName(), event);
CustomerName customerName = new CustomerName(paymentForm.getFullName(), paymentForm.getFirstName(), paymentForm.getLastName(), event, false);

//persist data
ticketReservationManager.updateReservation(reservationId, customerName, paymentForm.getEmail(),
Expand All @@ -287,8 +287,9 @@ public String validateToOverview(@PathVariable("eventName") String eventName, @P
assignTickets(event.getShortName(), reservationId, paymentForm, bindingResult, request, true, true);
//

// FIXME validate!
//paymentForm.validate(bindingResult, event, ticketFieldRepository.findAdditionalFieldsForEvent(event.getId()), companyVatChecked);
//
paymentForm.validate(bindingResult, event, ticketFieldRepository.findAdditionalFieldsForEvent(event.getId()), new SameCountryValidator(vatChecker, event.getOrganizationId(), event.getId(), reservationId));
//

if(bindingResult.hasErrors()) {
SessionUtil.addToFlash(bindingResult, redirectAttributes);
Expand Down
37 changes: 18 additions & 19 deletions src/main/java/alfio/controller/form/PaymentForm.java
Original file line number Diff line number Diff line change
Expand Up @@ -90,25 +90,24 @@ public boolean hasPaypalTokens() {
return StringUtils.isNotBlank(paypalPayerID) && StringUtils.isNotBlank(paypalPaymentId);
}

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

List<PaymentProxy> allowedPaymentMethods = event.getAllowedPaymentProxies();

Optional<PaymentProxy> paymentProxyOptional = Optional.ofNullable(paymentMethod);
PaymentProxy paymentProxy = paymentProxyOptional.filter(allowedPaymentMethods::contains).orElse(PaymentProxy.STRIPE);
boolean priceGreaterThanZero = reservationCost.getPriceWithVAT() > 0;
boolean multiplePaymentMethods = allowedPaymentMethods.size() > 1;
if (multiplePaymentMethods && priceGreaterThanZero && !paymentProxyOptional.isPresent()) {
bindingResult.reject(ErrorsCode.STEP_2_MISSING_PAYMENT_METHOD);
} else if (priceGreaterThanZero && (paymentProxy == PaymentProxy.STRIPE && StringUtils.isBlank(stripeToken))) {
bindingResult.reject(ErrorsCode.STEP_2_MISSING_STRIPE_TOKEN);
}

if(Objects.isNull(termAndConditionsAccepted) || !termAndConditionsAccepted
|| (StringUtils.isNotEmpty(event.getPrivacyPolicyUrl()) && (Objects.isNull(privacyPolicyAccepted) || !privacyPolicyAccepted)) ) {
bindingResult.reject(ErrorsCode.STEP_2_TERMS_NOT_ACCEPTED);
}
public void validate(BindingResult bindingResult, Event event, List<TicketFieldConfiguration> fieldConf, EuVatChecker.SameCountryValidator vatValidator) {

//List<PaymentProxy> allowedPaymentMethods = event.getAllowedPaymentProxies();

//Optional<PaymentProxy> paymentProxyOptional = Optional.ofNullable(paymentMethod);
//PaymentProxy paymentProxy = paymentProxyOptional.filter(allowedPaymentMethods::contains).orElse(PaymentProxy.STRIPE);
//boolean priceGreaterThanZero = reservationCost.getPriceWithVAT() > 0;
//boolean multiplePaymentMethods = allowedPaymentMethods.size() > 1;
//if (multiplePaymentMethods && priceGreaterThanZero && !paymentProxyOptional.isPresent()) {
//bindingResult.reject(ErrorsCode.STEP_2_MISSING_PAYMENT_METHOD);
//} else if (priceGreaterThanZero && (paymentProxy == PaymentProxy.STRIPE && StringUtils.isBlank(stripeToken))) {
//bindingResult.reject(ErrorsCode.STEP_2_MISSING_STRIPE_TOKEN);
//}

//if(Objects.isNull(termAndConditionsAccepted) || !termAndConditionsAccepted
//|| (StringUtils.isNotEmpty(event.getPrivacyPolicyUrl()) && (Objects.isNull(privacyPolicyAccepted) || !privacyPolicyAccepted)) ) {
//bindingResult.reject(ErrorsCode.STEP_2_TERMS_NOT_ACCEPTED);
//}

email = StringUtils.trim(email);

Expand Down
2 changes: 1 addition & 1 deletion src/main/java/alfio/manager/TicketReservationManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -1058,7 +1058,7 @@ public void updateTicketOwner(Ticket ticket,
Map<String, String> preUpdateTicketFields = ticketFieldRepository.findAllByTicketId(ticket.getId()).stream().collect(Collectors.toMap(TicketFieldValue::getName, TicketFieldValue::getValue));

String newEmail = updateTicketOwner.getEmail().trim();
CustomerName customerName = new CustomerName(updateTicketOwner.getFullName(), updateTicketOwner.getFirstName(), updateTicketOwner.getLastName(), event);
CustomerName customerName = new CustomerName(updateTicketOwner.getFullName(), updateTicketOwner.getFirstName(), updateTicketOwner.getLastName(), event, false);
ticketRepository.updateTicketOwner(ticket.getUuid(), newEmail, customerName.getFullName(), customerName.getFirstName(), customerName.getLastName());

//
Expand Down
47 changes: 22 additions & 25 deletions src/main/java/alfio/util/MustacheCustomTagInterceptor.java
Original file line number Diff line number Diff line change
Expand Up @@ -139,18 +139,17 @@ private static Pair<String, Optional<Locale>> parseParams(String r) {
private static final Pattern ARG_PATTERN = Pattern.compile("\\[(.*)\\]");


private static final Function<ModelAndView, Mustache.Lambda> HAS_ERROR = (mv) -> {
return (frag, out) -> {
Errors err = (Errors) mv.getModelMap().get("error");
String execution = frag.execute().trim();
Matcher matcher = ARG_PATTERN.matcher(execution);
if (matcher.find()) {
String field = matcher.group(1);
if (err != null && err.hasFieldErrors(field)) {
out.write(execution.substring(matcher.end(1) + 1));
}

private static final Function<ModelAndView, Mustache.Lambda> HAS_ERROR = (mv) -> (frag, out) -> {
Errors err = (Errors) mv.getModelMap().get("error");
String execution = frag.execute().trim();
Matcher matcher = ARG_PATTERN.matcher(execution);
if (matcher.find()) {
String field = matcher.group(1);
if (err != null && err.hasFieldErrors(field)) {
out.write(execution.substring(matcher.end(1) + 1));
}
};
}
};

private static final Mustache.Lambda IS_PAYMENT_METHOD = (frag, out) -> {
Expand All @@ -166,20 +165,18 @@ private static Pair<String, Optional<Locale>> parseParams(String r) {
}
};

private static final Function<ModelAndView, Mustache.Lambda> FIELD_ERROR = (mv) -> {
return (frag, out) -> {
Errors err = (Errors) mv.getModelMap().get("error");
String field = frag.execute().trim();
if (err != null && err.hasFieldErrors(field)) {
FieldError fe = err.getFieldError(field);
out.write(fe.getCode()
+ " "
+ Arrays.stream(Optional.ofNullable(fe.getArguments()).orElse(new Object[] {}))
.map(x -> "[" + x.toString() + "]").collect(Collectors.joining(" ")));
} else {
out.write("empty");
}
};
private static final Function<ModelAndView, Mustache.Lambda> FIELD_ERROR = (mv) -> (frag, out) -> {
Errors err = (Errors) mv.getModelMap().get("error");
String field = frag.execute().trim();
if (err != null && err.hasFieldErrors(field)) {
FieldError fe = err.getFieldError(field);
out.write(fe.getCode()
+ " "
+ Arrays.stream(Optional.ofNullable(fe.getArguments()).orElse(new Object[] {}))
.map(x -> "[" + x.toString() + "]").collect(Collectors.joining(" ")));
} else {
out.write("empty");
}
};


Expand Down
24 changes: 13 additions & 11 deletions src/main/java/alfio/util/Validator.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@

import java.math.BigDecimal;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;
Expand Down Expand Up @@ -218,37 +219,38 @@ public static ValidationResult validateTicketAssignment(UpdateTicketOwnerForm fo
if(!isField) {
continue;
}

form.getAdditional().get(fieldConf.getName()).forEach(formValue -> {

List<String> values = Optional.ofNullable(form.getAdditional().get(fieldConf.getName())).orElse(Collections.emptyList());
for(int i = 0; i < values.size(); i++) {
String formValue = values.get(i);
if(fieldConf.isMaxLengthDefined()) {
validateMaxLength(formValue, prefixForLambda + "additional['"+fieldConf.getName()+"']", "error."+fieldConf.getName(), fieldConf.getMaxLength(), errors);
validateMaxLength(formValue, prefixForLambda + "additional["+fieldConf.getName()+"]["+i+"]", "error."+fieldConf.getName(), fieldConf.getMaxLength(), errors);
}

if(StringUtils.isNotBlank(formValue) && fieldConf.isMinLengthDefined() && StringUtils.length(formValue) < fieldConf.getMinLength()) {
errors.rejectValue(prefixForLambda + "additional['"+fieldConf.getName()+"']", "error."+fieldConf.getName());
errors.rejectValue(prefixForLambda + "additional["+fieldConf.getName()+"]["+i+"]", "error."+fieldConf.getName());
}

if(!fieldConf.getRestrictedValues().isEmpty()) {
validateRestrictedValue(formValue, prefixForLambda + "additional['"+fieldConf.getName()+"']", "error."+fieldConf.getName(), fieldConf.getRestrictedValues(), errors);
validateRestrictedValue(formValue, prefixForLambda + "additional["+fieldConf.getName()+"]["+i+"]", "error."+fieldConf.getName(), fieldConf.getRestrictedValues(), errors);
}

if(fieldConf.isRequired() && StringUtils.isBlank(formValue)){
errors.rejectValue(prefixForLambda + "additional['"+fieldConf.getName()+"']", "error."+fieldConf.getName());
errors.rejectValue(prefixForLambda + "additional["+fieldConf.getName()+"]["+i+"]", "error."+fieldConf.getName());
}

if(fieldConf.hasDisabledValues() && fieldConf.getDisabledValues().contains(formValue)) {
errors.rejectValue(prefixForLambda + "additional['"+fieldConf.getName()+"']", "error."+fieldConf.getName());
errors.rejectValue(prefixForLambda + "additional["+fieldConf.getName()+"]["+i+"]", "error."+fieldConf.getName());
}

try {
if (fieldConf.isEuVat() && !vatValidator.test(formValue)) {
errors.rejectValue(prefixForLambda + "additional['" + fieldConf.getName() + "']", ErrorsCode.STEP_2_INVALID_VAT);
errors.rejectValue(prefixForLambda + "additional[" + fieldConf.getName() + "]["+i+"]", ErrorsCode.STEP_2_INVALID_VAT);
}
} catch (IllegalStateException e) {
errors.rejectValue(prefixForLambda + "additional['" + fieldConf.getName() + "']", ErrorsCode.VIES_IS_DOWN);
errors.rejectValue(prefixForLambda + "additional[" + fieldConf.getName() + "]["+i+"]", ErrorsCode.VIES_IS_DOWN);
}

});
}


}
Expand Down
20 changes: 10 additions & 10 deletions src/main/webapp/WEB-INF/templates/event/attendee-fields.ms
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{{#useFirstAndLastName}}
<div class="form-group">
<div class="form-group {{#field-has-error}}[{{elementNamePrefix}}firstName] has-error{{/field-has-error}}">
<label class="col-sm-3 control-label" for="first-name-{{uuid}}">{{#i18n}}common.first-name{{/i18n}} *</label>
<div class="col-sm-9">
{{^lockedAssignment}}
Expand All @@ -10,7 +10,7 @@
{{/lockedAssignment}}
</div>
</div>
<div class="form-group">
<div class="form-group {{#field-has-error}}[{{elementNamePrefix}}lastName] has-error{{/field-has-error}}">
<label class="col-sm-3 control-label" for="last-name-{{uuid}}">{{#i18n}}common.last-name{{/i18n}} *</label>
<div class="col-sm-9">
{{^lockedAssignment}}
Expand All @@ -23,7 +23,7 @@
</div>
{{/useFirstAndLastName}}
{{^useFirstAndLastName}}
<div class="form-group">
<div class="form-group {{#field-has-error}}[{{elementNamePrefix}}fullName] has-error{{/field-has-error}}">
<label class="col-sm-3 control-label" for="full-name-{{uuid}}">{{#i18n}}common.full-name{{/i18n}} *</label>
<div class="col-sm-9">
{{^lockedAssignment}}
Expand All @@ -35,7 +35,7 @@
</div>
</div>
{{/useFirstAndLastName}}
<div class="form-group">
<div class="form-group {{#field-has-error}}[{{elementNamePrefix}}email] has-error{{/field-has-error}}">
<label class="col-sm-3 control-label" for="email-{{uuid}}">{{#i18n}}common.email{{/i18n}} *</label>
<div class="col-sm-9">
{{^lockedAssignment}}
Expand All @@ -49,43 +49,43 @@
<div>
{{#ticketFieldConfiguration}}
{{#fields}}
<div class="form-group">
<div class="form-group {{#field-has-error}}[{{elementNamePrefix}}additional[{{name}}][{{fieldIndex}}]] has-error{{/field-has-error}}">
<label class="col-sm-3 control-label" for="{{name}}-title-{{uuid}}">{{labelDescription}}{{#isRequired}}*{{/isRequired}}</label>
<div class="col-sm-9">
{{#inputField}}
<input type="{{inputType}}" name="{{elementNamePrefix}}additional['{{name}}'][{{fieldIndex}}]" value="{{fieldValue}}" id="{{name}}-title-{{uuid}}{{^-first}}-{{fieldCounter}}{{/-first}}" class="form-control {{#isRequired}}field-required{{/isRequired}}"
<input type="{{inputType}}" name="{{elementNamePrefix}}additional[{{name}}][{{fieldIndex}}]" value="{{fieldValue}}" id="{{name}}-title-{{uuid}}{{^-first}}-{{fieldCounter}}{{/-first}}" class="form-control {{#isRequired}}field-required{{/isRequired}}"
{{#placeholderDescriptionDefined}}placeholder="{{placeholderDescription}}"{{/placeholderDescriptionDefined}}
{{#maxLengthDefined}}maxlength="{{maxLength}}"{{/maxLengthDefined}}
{{#minLengthDefined}}minlength="{{minLength}}"{{/minLengthDefined}}
{{#isRequired}}required{{/isRequired}}
>
{{/inputField}}
{{#euVat}}
<input type="text" name="{{elementNamePrefix}}additional['{{name}}'][{{fieldIndex}}]" value="{{fieldValue}}" id="{{name}}-title-{{uuid}}{{^-first}}-{{fieldCounter}}{{/-first}}" class="form-control {{#isRequired}}field-required{{/isRequired}}"
<input type="text" name="{{elementNamePrefix}}additional[{{name}}][{{fieldIndex}}]" value="{{fieldValue}}" id="{{name}}-title-{{uuid}}{{^-first}}-{{fieldCounter}}{{/-first}}" class="form-control {{#isRequired}}field-required{{/isRequired}}"
{{#placeholderDescriptionDefined}}placeholder="{{placeholderDescription}}"{{/placeholderDescriptionDefined}}
{{#maxLengthDefined}}maxlength="{{maxLength}}"{{/maxLengthDefined}}
{{#minLengthDefined}}minlength="{{minLength}}"{{/minLengthDefined}}
{{#isRequired}}required{{/isRequired}}
>
{{/euVat}}
{{#textareaField}}
<textarea name="{{elementNamePrefix}}additional['{{name}}'][{{fieldIndex}}]" id="{{name}}-title-{{uuid}}{{^-first}}-{{fieldCounter}}{{/-first}}" class="form-control"
<textarea name="{{elementNamePrefix}}additional[{{name}}][{{fieldIndex}}]" id="{{name}}-title-{{uuid}}{{^-first}}-{{fieldCounter}}{{/-first}}" class="form-control"
{{#placeholderDescriptionDefined}}placeholder="{{placeholderDescription}}"{{/placeholderDescriptionDefined}}
{{#maxLengthDefined}}maxlength="{{maxLength}}"{{/maxLengthDefined}}
{{#minLengthDefined}}minlength="{{minLength}}"{{/minLengthDefined}}
{{#isRequired}}required{{/isRequired}}
>{{fieldValue}}</textarea>
{{/textareaField}}
{{#countryField}}
<select name="{{elementNamePrefix}}additional['{{name}}'][{{fieldIndex}}]" value="{{fieldValue}}" id="{{name}}-title-{{uuid}}{{^-first}}-{{fieldCounter}}{{/-first}}" class="form-control" {{#isRequired}}required{{/isRequired}}>
<select name="{{elementNamePrefix}}additional[{{name}}][{{fieldIndex}}]" value="{{fieldValue}}" id="{{name}}-title-{{uuid}}{{^-first}}-{{fieldCounter}}{{/-first}}" class="form-control" {{#isRequired}}required{{/isRequired}}>
<option value=""></option>
{{#countries}}
<option value="{{left}}">{{right}}</option>
{{/countries}}
</select>
{{/countryField}}
{{#selectField}}
<select name="{{elementNamePrefix}}additional['{{name}}'][{{fieldIndex}}]" value="{{fieldValue}}" id="{{name}}-title-{{uuid}}{{^-first}}-{{fieldCounter}}{{/-first}}" class="form-control" {{#isRequired}}required{{/isRequired}}>
<select name="{{elementNamePrefix}}additional[{{name}}][{{fieldIndex}}]" value="{{fieldValue}}" id="{{name}}-title-{{uuid}}{{^-first}}-{{fieldCounter}}{{/-first}}" class="form-control" {{#isRequired}}required{{/isRequired}}>
<option value=""></option>
{{#translatedRestrictedValue}}<option value="{{left}}" {{^right}}disabled{{/right}}>{{middle}}</option>{{/translatedRestrictedValue}}
</select>
Expand Down

0 comments on commit 02ac16b

Please sign in to comment.