use of alfio.manager.support.response.ValidatedResponse in project alf.io by alfio-event.
the class EventApiV2Controller method getTicketCategories.
@GetMapping("event/{eventName}/ticket-categories")
public ResponseEntity<ItemsByCategory> getTicketCategories(@PathVariable("eventName") String eventName, @RequestParam(value = "code", required = false) String code) {
//
return eventRepository.findOptionalByShortName(eventName).filter(e -> e.getStatus() != Event.Status.DISABLED).map(event -> {
var configurations = configurationManager.getFor(List.of(DISPLAY_TICKETS_LEFT_INDICATOR, MAX_AMOUNT_OF_TICKETS_BY_RESERVATION, DISPLAY_EXPIRED_CATEGORIES), event.getConfigurationLevel());
var ticketCategoryLevelConfiguration = configurationManager.getAllCategoriesAndValueWith(event, MAX_AMOUNT_OF_TICKETS_BY_RESERVATION);
var messageSource = messageSourceManager.getMessageSourceFor(event);
var appliedPromoCode = promoCodeRequestManager.checkCode(event, code);
Optional<SpecialPrice> specialCode = appliedPromoCode.getValue().getLeft();
Optional<PromoCodeDiscount> promoCodeDiscount = appliedPromoCode.getValue().getRight();
final ZonedDateTime now = event.now(clockProvider);
// hide access restricted ticket categories
var ticketCategories = ticketCategoryRepository.findAllTicketCategories(event.getId());
List<SaleableTicketCategory> saleableTicketCategories = ticketCategories.stream().filter((c) -> !c.isAccessRestricted() || shouldDisplayRestrictedCategory(specialCode, c, promoCodeDiscount)).map((category) -> {
int maxTickets = getMaxAmountOfTicketsPerReservation(configurations, ticketCategoryLevelConfiguration, category.getId());
PromoCodeDiscount filteredPromoCode = promoCodeDiscount.filter(promoCode -> shouldApplyDiscount(promoCode, category)).orElse(null);
if (specialCode.isPresent()) {
maxTickets = Math.min(1, maxTickets);
} else if (filteredPromoCode != null && filteredPromoCode.getMaxUsage() != null) {
maxTickets = filteredPromoCode.getMaxUsage() - promoCodeRepository.countConfirmedPromoCode(filteredPromoCode.getId(), categoriesOrNull(filteredPromoCode), null, categoriesOrNull(filteredPromoCode) != null ? "X" : null);
}
return new SaleableTicketCategory(category, now, event, ticketReservationManager.countAvailableTickets(event, category), maxTickets, filteredPromoCode);
}).collect(Collectors.toList());
var valid = saleableTicketCategories.stream().filter(tc -> !tc.getExpired()).collect(Collectors.toList());
//
var ticketCategoryIds = valid.stream().map(SaleableTicketCategory::getId).collect(Collectors.toList());
var ticketCategoryDescriptions = ticketCategoryDescriptionRepository.descriptionsByTicketCategory(ticketCategoryIds);
boolean displayTicketsLeft = configurations.get(DISPLAY_TICKETS_LEFT_INDICATOR).getValueAsBooleanOrDefault();
var categoriesByExpiredFlag = saleableTicketCategories.stream().map(stc -> {
var description = Formatters.applyCommonMark(ticketCategoryDescriptions.getOrDefault(stc.getId(), Collections.emptyMap()));
var expiration = Formatters.getFormattedDate(event, stc.getZonedExpiration(), "common.ticket-category.date-format", messageSource);
var inception = Formatters.getFormattedDate(event, stc.getZonedInception(), "common.ticket-category.date-format", messageSource);
return new TicketCategory(stc, description, inception, expiration, displayTicketsLeft && !stc.isAccessRestricted());
}).sorted(Comparator.comparingInt(TicketCategory::getOrdinal)).collect(partitioningBy(TicketCategory::isExpired));
var promoCode = Optional.of(appliedPromoCode).filter(ValidatedResponse::isSuccess).map(ValidatedResponse::getValue).flatMap(Pair::getRight);
//
var saleableAdditionalServices = additionalServiceRepository.loadAllForEvent(event.getId()).stream().map(as -> new SaleableAdditionalService(event, as, promoCode.orElse(null))).filter(SaleableAdditionalService::isNotExpired).collect(Collectors.toList());
// will be used for fetching descriptions and titles for all the languages
var saleableAdditionalServicesIds = saleableAdditionalServices.stream().map(SaleableAdditionalService::getId).collect(Collectors.toList());
var additionalServiceTexts = additionalServiceTextRepository.getDescriptionsByAdditionalServiceIds(saleableAdditionalServicesIds);
var additionalServicesRes = saleableAdditionalServices.stream().map(as -> {
var expiration = Formatters.getFormattedDate(event, as.getZonedExpiration(), "common.ticket-category.date-format", messageSource);
var inception = Formatters.getFormattedDate(event, as.getZonedInception(), "common.ticket-category.date-format", messageSource);
var title = additionalServiceTexts.getOrDefault(as.getId(), Collections.emptyMap()).getOrDefault(AdditionalServiceText.TextType.TITLE, Collections.emptyMap());
var description = Formatters.applyCommonMark(additionalServiceTexts.getOrDefault(as.getId(), Collections.emptyMap()).getOrDefault(AdditionalServiceText.TextType.DESCRIPTION, Collections.emptyMap()));
return new AdditionalService(as.getId(), as.getType(), as.getSupplementPolicy(), as.isFixPrice(), as.getAvailableQuantity(), as.getMaxQtyPerOrder(), as.getFree(), as.getFormattedFinalPrice(), as.getSupportsDiscount(), as.getDiscountedPrice(), as.getVatApplies(), as.getVatIncluded(), as.getVatPercentage().toString(), as.isExpired(), as.getSaleInFuture(), inception, expiration, title, description);
}).collect(Collectors.toList());
//
// waiting queue parameters
boolean displayWaitingQueueForm = EventUtil.displayWaitingQueueForm(event, saleableTicketCategories, configurationManager, eventStatisticsManager.noSeatsAvailable());
boolean preSales = EventUtil.isPreSales(event, saleableTicketCategories);
Predicate<SaleableTicketCategory> waitingQueueTargetCategory = tc -> !tc.getExpired() && !tc.isBounded();
List<SaleableTicketCategory> unboundedCategories = saleableTicketCategories.stream().filter(waitingQueueTargetCategory).collect(Collectors.toList());
var tcForWaitingList = unboundedCategories.stream().map(stc -> new ItemsByCategory.TicketCategoryForWaitingList(stc.getId(), stc.getName())).collect(toList());
//
var activeCategories = categoriesByExpiredFlag.get(false);
var expiredCategories = configurations.get(DISPLAY_EXPIRED_CATEGORIES).getValueAsBooleanOrDefault() ? categoriesByExpiredFlag.get(true) : List.<TicketCategory>of();
return new ResponseEntity<>(new ItemsByCategory(activeCategories, expiredCategories, additionalServicesRes, displayWaitingQueueForm, preSales, tcForWaitingList), getCorsHeaders(), HttpStatus.OK);
}).orElseGet(() -> ResponseEntity.notFound().headers(getCorsHeaders()).build());
}
use of alfio.manager.support.response.ValidatedResponse in project alf.io by alfio-event.
the class TicketApiV2Controller method updateTicketInfo.
@PutMapping("/api/v2/public/event/{eventName}/ticket/{ticketIdentifier}")
public ResponseEntity<ValidatedResponse<Boolean>> updateTicketInfo(@PathVariable("eventName") String eventName, @PathVariable("ticketIdentifier") String ticketIdentifier, @RequestBody UpdateTicketOwnerForm updateTicketOwner, BindingResult bindingResult, Authentication authentication) {
var a = ticketReservationManager.fetchComplete(eventName, ticketIdentifier);
if (a.isEmpty()) {
return ResponseEntity.notFound().build();
}
Optional<UserDetails> userDetails = Optional.ofNullable(authentication).map(Authentication::getPrincipal).filter(UserDetails.class::isInstance).map(UserDetails.class::cast);
Locale locale = LocaleUtil.forLanguageTag(a.get().getMiddle().getUserLanguage(), a.get().getLeft());
var assignmentResult = ticketHelper.assignTicket(eventName, ticketIdentifier, updateTicketOwner, Optional.of(bindingResult), locale, userDetails, false);
return assignmentResult.map(r -> ResponseEntity.status(r.getLeft().isSuccess() ? HttpStatus.OK : HttpStatus.UNPROCESSABLE_ENTITY).body(new ValidatedResponse<>(r.getLeft(), r.getLeft().isSuccess()))).orElseThrow(IllegalStateException::new);
}
use of alfio.manager.support.response.ValidatedResponse in project alf.io by alfio-event.
the class PromoCodeRequestManager method checkCode.
public ValidatedResponse<Pair<Optional<SpecialPrice>, Optional<PromoCodeDiscount>>> checkCode(Event event, String promoCode) {
ZoneId eventZoneId = event.getZoneId();
ZonedDateTime now = ZonedDateTime.now(clockProvider.withZone(eventZoneId));
Optional<String> maybeSpecialCode = Optional.ofNullable(StringUtils.trimToNull(promoCode));
Optional<SpecialPrice> specialCode = maybeSpecialCode.flatMap(specialPriceRepository::getByCode);
Optional<PromoCodeDiscount> promotionCodeDiscount = maybeSpecialCode.flatMap((trimmedCode) -> promoCodeRepository.findPublicPromoCodeInEventOrOrganization(event.getId(), trimmedCode));
var result = Pair.of(specialCode, promotionCodeDiscount);
var errorResponse = new ValidatedResponse<>(ValidationResult.failed(new ValidationResult.ErrorDescriptor("promoCode", ErrorsCode.STEP_1_CODE_NOT_FOUND, ErrorsCode.STEP_1_CODE_NOT_FOUND)), result);
//
if (specialCode.isPresent()) {
if (eventManager.getOptionalByIdAndActive(specialCode.get().getTicketCategoryId(), event.getId()).isEmpty()) {
return errorResponse;
}
if (specialCode.get().getStatus() != SpecialPrice.Status.FREE) {
return errorResponse;
}
} else if (promotionCodeDiscount.isPresent() && !promotionCodeDiscount.get().isCurrentlyValid(eventZoneId, now)) {
return errorResponse;
} else if (promotionCodeDiscount.isPresent() && isDiscountCodeUsageExceeded(promotionCodeDiscount.get())) {
return errorResponse;
} else if (promotionCodeDiscount.isEmpty()) {
return errorResponse;
}
return new ValidatedResponse<>(ValidationResult.success(), result);
}
Aggregations