alfio.manager.SpecialPriceManager.java Source code

Java tutorial

Introduction

Here is the source code for alfio.manager.SpecialPriceManager.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.manager;

import alfio.manager.i18n.I18nManager;
import alfio.model.ContentLanguage;
import alfio.model.Event;
import alfio.model.SpecialPrice;
import alfio.model.TicketCategory;
import alfio.model.modification.SendCodeModification;
import alfio.model.user.Organization;
import alfio.repository.SpecialPriceRepository;
import alfio.util.TemplateManager;
import alfio.util.TemplateResource;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Component;

import java.time.ZonedDateTime;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Stream;

import static java.util.stream.Collectors.toList;

@Component
public class SpecialPriceManager {

    private static final Predicate<SendCodeModification> IS_CODE_PRESENT = v -> Optional.ofNullable(v.getCode())
            .isPresent();
    private final EventManager eventManager;
    private final NotificationManager notificationManager;
    private final SpecialPriceRepository specialPriceRepository;
    private final TemplateManager templateManager;
    private final MessageSource messageSource;
    private final I18nManager i18nManager;

    @Autowired
    public SpecialPriceManager(EventManager eventManager, NotificationManager notificationManager,
            SpecialPriceRepository specialPriceRepository, TemplateManager templateManager,
            MessageSource messageSource, I18nManager i18nManager) {
        this.eventManager = eventManager;
        this.notificationManager = notificationManager;
        this.specialPriceRepository = specialPriceRepository;
        this.templateManager = templateManager;
        this.messageSource = messageSource;
        this.i18nManager = i18nManager;
    }

    private List<String> checkCodeAssignment(Set<SendCodeModification> input, int categoryId, Event event,
            String username) {
        final TicketCategory category = checkOwnership(categoryId, event, username);
        List<String> availableCodes = new ArrayList<>(
                specialPriceRepository.findActiveByCategoryId(category.getId()).stream()
                        .filter(SpecialPrice::notSent).map(SpecialPrice::getCode).collect(toList()));
        Validate.isTrue(input.size() <= availableCodes.size(),
                "Requested codes: " + input.size() + ", available: " + availableCodes.size() + ".");
        List<String> requestedCodes = input.stream().filter(IS_CODE_PRESENT).map(SendCodeModification::getCode)
                .collect(toList());
        Validate.isTrue(requestedCodes.stream().distinct().count() == requestedCodes.size(),
                "Cannot assign the same code twice. Please fix the input file.");
        Validate.isTrue(requestedCodes.stream().allMatch(availableCodes::contains),
                "some requested codes don't exist.");
        return availableCodes;
    }

    private TicketCategory checkOwnership(int categoryId, Event event, String username) {
        eventManager.checkOwnership(event, username, event.getOrganizationId());
        final List<TicketCategory> categories = eventManager.loadTicketCategories(event);
        final TicketCategory category = categories.stream().filter(tc -> tc.getId() == categoryId).findFirst()
                .orElseThrow(IllegalArgumentException::new);
        Validate.isTrue(category.isAccessRestricted(), "Access to the selected category is not restricted.");
        return category;
    }

    public List<SendCodeModification> linkAssigneeToCode(List<SendCodeModification> input, String eventName,
            int categoryId, String username) {
        final Event event = eventManager.getSingleEvent(eventName, username);
        Set<SendCodeModification> set = new LinkedHashSet<>(input);
        List<String> availableCodes = checkCodeAssignment(set, categoryId, event, username);
        final Iterator<String> codes = availableCodes.iterator();
        return Stream.concat(set.stream().filter(IS_CODE_PRESENT), input.stream().filter(IS_CODE_PRESENT.negate())
                .map(p -> new SendCodeModification(codes.next(), p.getAssignee(), p.getEmail(), p.getLanguage())))
                .collect(toList());
    }

    public List<SpecialPrice> loadSentCodes(String eventName, int categoryId, String username) {
        final Event event = eventManager.getSingleEvent(eventName, username);
        checkOwnership(categoryId, event, username);
        Predicate<SpecialPrice> p = SpecialPrice::notSent;
        return specialPriceRepository.findAllByCategoryId(categoryId).stream().filter(p.negate()).collect(toList());
    }

    public boolean clearRecipientData(String eventName, int categoryId, int codeId, String username) {
        final Event event = eventManager.getSingleEvent(eventName, username);
        checkOwnership(categoryId, event, username);
        int result = specialPriceRepository.clearRecipientData(codeId, categoryId);
        Validate.isTrue(result <= 1, "too many records affected");
        return result == 1;
    }

    public boolean sendCodeToAssignee(List<SendCodeModification> input, String eventName, int categoryId,
            String username) {
        final Event event = eventManager.getSingleEvent(eventName, username);
        final Organization organization = eventManager.loadOrganizer(event, username);
        Set<SendCodeModification> set = new LinkedHashSet<>(input);
        checkCodeAssignment(set, categoryId, event, username);
        Validate.isTrue(set.stream().allMatch(IS_CODE_PRESENT),
                "There are missing codes. Please check input file.");
        List<ContentLanguage> eventLanguages = i18nManager.getEventLanguages(event.getLocales());
        Validate.isTrue(!eventLanguages.isEmpty(),
                "No locales have been defined for the event. Please check the configuration");
        ContentLanguage defaultLocale = eventLanguages.contains(ContentLanguage.ENGLISH) ? ContentLanguage.ENGLISH
                : eventLanguages.get(0);
        set.forEach(m -> {
            Locale locale = Locale.forLanguageTag(StringUtils.defaultString(StringUtils.trimToNull(m.getLanguage()),
                    defaultLocale.getLanguage()));
            Map<String, Object> model = TemplateResource.prepareModelForSendReservedCode(organization, event, m,
                    eventManager.getEventUrl(event));
            notificationManager.sendSimpleEmail(event, m.getEmail(),
                    messageSource.getMessage("email-code.subject", new Object[] { event.getDisplayName() }, locale),
                    () -> templateManager.renderTemplate(event, TemplateResource.SEND_RESERVED_CODE, model,
                            locale));
            int marked = specialPriceRepository.markAsSent(ZonedDateTime.now(event.getZoneId()),
                    m.getAssignee().trim(), m.getEmail().trim(), m.getCode().trim());
            Validate.isTrue(marked == 1, "Expected exactly one row updated, got " + marked);
        });
        return true;
    }
}