alfio.controller.api.user.RestEventApiController.java Source code

Java tutorial

Introduction

Here is the source code for alfio.controller.api.user.RestEventApiController.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.user;

import alfio.controller.api.support.DescriptionsLoader;
import alfio.controller.api.support.EventListItem;
import alfio.controller.api.support.PublicCategory;
import alfio.controller.api.support.PublicEvent;
import alfio.controller.form.ReservationForm;
import alfio.manager.EventManager;
import alfio.manager.TicketReservationManager;
import alfio.manager.system.ConfigurationManager;
import alfio.model.Event;
import alfio.model.SpecialPrice;
import alfio.model.TicketCategory;
import alfio.model.result.Result;
import alfio.model.system.Configuration;
import alfio.model.system.ConfigurationKeys;
import alfio.model.user.Organization;
import alfio.repository.*;
import alfio.repository.user.OrganizationRepository;
import alfio.util.ErrorsCode;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/api/public/")
public class RestEventApiController {

    private final EventManager eventManager;
    private final OrganizationRepository organizationRepository;
    private final EventRepository eventRepository;
    private final DescriptionsLoader descriptionsLoader;
    private final TicketReservationManager ticketReservationManager;
    private final ConfigurationManager configurationManager;
    private final SpecialPriceRepository specialPriceRepository;
    private final TicketCategoryRepository ticketCategoryRepository;
    private final AdditionalServiceRepository additionalServiceRepository;

    @Autowired
    public RestEventApiController(EventManager eventManager, OrganizationRepository organizationRepository,
            EventRepository eventRepository, DescriptionsLoader descriptionsLoader,
            TicketReservationManager ticketReservationManager, ConfigurationManager configurationManager,
            SpecialPriceRepository specialPriceRepository, TicketCategoryRepository ticketCategoryRepository,
            AdditionalServiceRepository additionalServiceRepository) {
        this.eventManager = eventManager;
        this.organizationRepository = organizationRepository;
        this.eventRepository = eventRepository;
        this.descriptionsLoader = descriptionsLoader;
        this.ticketReservationManager = ticketReservationManager;
        this.configurationManager = configurationManager;
        this.specialPriceRepository = specialPriceRepository;
        this.ticketCategoryRepository = ticketCategoryRepository;
        this.additionalServiceRepository = additionalServiceRepository;
    }

    @RequestMapping("events")
    public List<EventListItem> listEvents(HttpServletRequest request) {
        return eventManager.getPublishedEvents().stream()
                .map(e -> new EventListItem(e, request.getContextPath(), descriptionsLoader.eventDescriptions()))
                .collect(Collectors.toList());
    }

    @RequestMapping("events/{shortName}")
    public ResponseEntity<PublicEvent> showEvent(@PathVariable("shortName") String shortName,
            @RequestParam(value = "specialCode", required = false) String specialCodeParam,
            HttpServletRequest request) {

        Optional<SpecialPrice> specialCode = Optional.ofNullable(StringUtils.trimToNull(specialCodeParam))
                .flatMap((trimmedCode) -> specialPriceRepository.getByCode(trimmedCode));

        return eventRepository.findOptionalByShortName(shortName).map((e) -> {
            List<PublicCategory> categories = ticketCategoryRepository.findAllTicketCategories(e.getId()).stream()
                    .filter((c) -> !c.isAccessRestricted()
                            || (specialCode.filter(sc -> sc.getTicketCategoryId() == c.getId()).isPresent()))
                    .map(c -> buildPublicCategory(c, e)).collect(Collectors.toList());
            Organization organization = organizationRepository.getById(e.getOrganizationId());

            return new ResponseEntity<>(new PublicEvent(e, request.getContextPath(),
                    descriptionsLoader.eventDescriptions(), categories, organization), HttpStatus.OK);
        }).orElseGet(() -> new ResponseEntity<>(HttpStatus.NOT_FOUND));
    }

    /*
        
    fetch('/api/public/events/eventname/reserve-tickets', {method: 'POST', body: JSON.stringify({reservation: [{ticketCategoryId: 0, amount:1}]}), credentials: 'same-origin', headers: new Headers({'X-Requested-With':'XMLHttpRequest', 'Content-Type': 'application/json', 'X-CSRF-TOKEN': 'cfda015e-87c8-4780-b41d-3db805f45a78'})})
    .then(r =>r.json())
    .then(json => console.log(json))
        
        
     */
    @RequestMapping(value = "events/{shortName}/reserve-tickets", method = RequestMethod.POST)
    public ResponseEntity<Result<String>> reserveTickets(@PathVariable("shortName") String shortName,
            @RequestBody ReservationForm reservation, BindingResult bindingResult, Locale locale) {
        return eventRepository.findOptionalByShortName(shortName).map(event -> {
            Optional<String> reservationUrl = reservation.validate(bindingResult, ticketReservationManager,
                    additionalServiceRepository, eventManager, event).flatMap(selected -> {
                        Date expiration = DateUtils.addMinutes(new Date(),
                                ticketReservationManager.getReservationTimeout(event));
                        try {
                            String reservationId = ticketReservationManager.createTicketReservation(event,
                                    selected.getLeft(), selected.getRight(), expiration,
                                    Optional.ofNullable(reservation.getPromoCode()), //FIXME check
                                    Optional.ofNullable(reservation.getPromoCode()), //FIXME check
                                    locale, false);
                            return Optional.of("/event/" + shortName + "/reservation/" + reservationId + "/book");
                        } catch (TicketReservationManager.NotEnoughTicketsException nete) {
                            bindingResult.reject(ErrorsCode.STEP_1_NOT_ENOUGH_TICKETS);
                        } catch (TicketReservationManager.MissingSpecialPriceTokenException missing) {
                            bindingResult.reject(ErrorsCode.STEP_1_ACCESS_RESTRICTED);
                        } catch (TicketReservationManager.InvalidSpecialPriceTokenException invalid) {
                            bindingResult.reject(ErrorsCode.STEP_1_CODE_NOT_FOUND);
                        }
                        return Optional.empty();
                    });

            Result<String> result = reservationUrl.map(url -> Result.success(url))
                    .orElseGet(() -> Result.validationError(bindingResult.getAllErrors()));
            return new ResponseEntity<>(result, HttpStatus.OK);
        }).orElseGet(() -> new ResponseEntity<>(HttpStatus.NOT_FOUND));
    }

    private PublicCategory buildPublicCategory(TicketCategory c, Event e) {
        return new PublicCategory(c, e, ticketReservationManager.countAvailableTickets(e, c),
                configurationManager.getIntConfigValue(Configuration.from(e.getOrganizationId(), e.getId(),
                        c.getId(), ConfigurationKeys.MAX_AMOUNT_OF_TICKETS_BY_RESERVATION), 5),
                descriptionsLoader.ticketCategoryDescriptions());
    }
}