alfio.controller.api.ReservationApiController.java Source code

Java tutorial

Introduction

Here is the source code for alfio.controller.api.ReservationApiController.java

Source

/**
 * 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;

import alfio.controller.api.support.TicketHelper;
import alfio.controller.form.PaymentForm;
import alfio.controller.form.UpdateTicketOwnerForm;
import alfio.manager.EuVatChecker;
import alfio.manager.TicketReservationManager;
import alfio.manager.i18n.I18nManager;
import alfio.model.*;
import alfio.model.result.ValidationResult;
import alfio.model.transaction.PaymentProxy;
import alfio.repository.EventRepository;
import alfio.repository.TicketReservationRepository;
import alfio.util.Json;
import alfio.util.TemplateManager;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.tuple.Triple;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.support.RequestContextUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

import static alfio.model.PriceContainer.VatStatus.*;
import static org.apache.commons.lang3.StringUtils.isNotEmpty;

@RestController
@AllArgsConstructor
public class ReservationApiController {

    private final EventRepository eventRepository;
    private final TicketHelper ticketHelper;
    private final TemplateManager templateManager;
    private final I18nManager i18nManager;
    private final EuVatChecker vatChecker;
    private final TicketReservationRepository ticketReservationRepository;
    private final TicketReservationManager ticketReservationManager;

    @RequestMapping(value = "/event/{eventName}/ticket/{ticketIdentifier}/assign", method = RequestMethod.POST, headers = "X-Requested-With=XMLHttpRequest")
    public Map<String, Object> assignTicketToPerson(@PathVariable("eventName") String eventName,
            @PathVariable("ticketIdentifier") String ticketIdentifier,
            @RequestParam(value = "single-ticket", required = false, defaultValue = "false") boolean singleTicket,
            UpdateTicketOwnerForm updateTicketOwner, BindingResult bindingResult, HttpServletRequest request,
            Model model, Authentication authentication) throws Exception {

        Optional<UserDetails> userDetails = Optional.ofNullable(authentication).map(Authentication::getPrincipal)
                .filter(UserDetails.class::isInstance).map(UserDetails.class::cast);

        Optional<Triple<ValidationResult, Event, Ticket>> assignmentResult = ticketHelper.assignTicket(eventName,
                ticketIdentifier, updateTicketOwner, Optional.of(bindingResult), request, t -> {
                    Locale requestLocale = RequestContextUtils.getLocale(request);
                    model.addAttribute("ticketFieldConfiguration",
                            ticketHelper.findTicketFieldConfigurationAndValue(t.getMiddle().getId(), t.getRight(),
                                    requestLocale));
                    model.addAttribute("value", t.getRight());
                    model.addAttribute("validationResult", t.getLeft());
                    model.addAttribute("countries", TicketHelper.getLocalizedCountries(requestLocale));
                    model.addAttribute("event", t.getMiddle());
                    model.addAttribute("useFirstAndLastName", t.getMiddle().mustUseFirstAndLastName());
                    model.addAttribute("availableLanguages", i18nManager.getEventLanguages(eventName).stream()
                            .map(ContentLanguage.toLanguage(requestLocale)).collect(Collectors.toList()));
                    String uuid = t.getRight().getUuid();
                    model.addAttribute("urlSuffix", singleTicket ? "ticket/" + uuid + "/view" : uuid);
                    model.addAttribute("elementNamePrefix", "");
                }, userDetails);
        Map<String, Object> result = new HashMap<>();

        Optional<ValidationResult> validationResult = assignmentResult.map(Triple::getLeft);
        if (validationResult.isPresent() && validationResult.get().isSuccess()) {
            result.put("partial",
                    templateManager.renderServletContextResource("/WEB-INF/templates/event/assign-ticket-result.ms",
                            model.asMap(), request, TemplateManager.TemplateOutput.HTML));
        }
        result.put("validationResult", validationResult.orElse(
                ValidationResult.failed(new ValidationResult.ErrorDescriptor("fullName", "error.fullname"))));
        return result;
    }

    @RequestMapping(value = "/event/{eventName}/reservation/{reservationId}/vat-validation", method = RequestMethod.POST)
    @Transactional
    public ResponseEntity<VatDetail> validateEUVat(@PathVariable("eventName") String eventName,
            @PathVariable("reservationId") String reservationId, PaymentForm paymentForm, Locale locale,
            HttpServletRequest request) {

        String country = paymentForm.getVatCountryCode();
        Optional<Triple<Event, TicketReservation, VatDetail>> 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)));

        vatDetail.filter(t -> t.getRight().isValid()).ifPresent(t -> {
            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);
            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.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());
                }
            });
        });

        return vatDetail.map(Triple::getRight).map(vd -> {
            if (vd.isValid()) {
                return ResponseEntity.ok(vd);
            } else {
                return new ResponseEntity<VatDetail>(HttpStatus.BAD_REQUEST);
            }
        }).orElseGet(() -> new ResponseEntity<>(HttpStatus.NOT_FOUND));
    }

    private static PriceContainer.VatStatus determineVatStatus(PriceContainer.VatStatus current,
            boolean isVatExempt) {
        if (!isVatExempt) {
            return current;
        }
        return current == NOT_INCLUDED ? NOT_INCLUDED_EXEMPT : INCLUDED_EXEMPT;
    }
}