Search in sources :

Example 1 with TicketPriceContainer

use of alfio.model.decorator.TicketPriceContainer in project alf.io by alfio-event.

the class TicketReservationManager method totalReservationCostWithVAT.

private static TotalPrice totalReservationCostWithVAT(PromoCodeDiscount promoCodeDiscount, Event event, PriceContainer.VatStatus reservationVatStatus, List<Ticket> tickets, Stream<Pair<AdditionalService, List<AdditionalServiceItem>>> additionalServiceItems) {
    List<TicketPriceContainer> ticketPrices = tickets.stream().map(t -> TicketPriceContainer.from(t, reservationVatStatus, event, promoCodeDiscount)).collect(toList());
    BigDecimal totalVAT = ticketPrices.stream().map(TicketPriceContainer::getVAT).reduce(BigDecimal.ZERO, BigDecimal::add);
    BigDecimal totalDiscount = ticketPrices.stream().map(TicketPriceContainer::getAppliedDiscount).reduce(BigDecimal.ZERO, BigDecimal::add);
    BigDecimal totalNET = ticketPrices.stream().map(TicketPriceContainer::getFinalPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
    int discountedTickets = (int) ticketPrices.stream().filter(t -> t.getAppliedDiscount().compareTo(BigDecimal.ZERO) > 0).count();
    int discountAppliedCount = discountedTickets <= 1 || promoCodeDiscount.getDiscountType() == DiscountType.FIXED_AMOUNT ? discountedTickets : 1;
    List<AdditionalServiceItemPriceContainer> asPrices = additionalServiceItems.flatMap(generateASIPriceContainers(event, null)).collect(toList());
    BigDecimal asTotalVAT = asPrices.stream().map(AdditionalServiceItemPriceContainer::getVAT).reduce(BigDecimal.ZERO, BigDecimal::add);
    // FIXME discount is not applied to donations, as it wouldn't make sense. Must be implemented for #111
    BigDecimal asTotalNET = asPrices.stream().map(AdditionalServiceItemPriceContainer::getFinalPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
    return new TotalPrice(unitToCents(totalNET.add(asTotalNET)), unitToCents(totalVAT.add(asTotalVAT)), -(MonetaryUtil.unitToCents(totalDiscount)), discountAppliedCount);
}
Also used : alfio.repository(alfio.repository) PaymentProxy(alfio.model.transaction.PaymentProxy) DiscountType(alfio.model.PromoCodeDiscount.DiscountType) ZonedDateTime(java.time.ZonedDateTime) PaymentResult(alfio.manager.support.PaymentResult) AdditionalServicePriceContainer(alfio.model.decorator.AdditionalServicePriceContainer) PartialTicketTextGenerator(alfio.manager.support.PartialTicketTextGenerator) Mailer(alfio.manager.system.Mailer) TicketStatus(alfio.model.Ticket.TicketStatus) StringUtils(org.apache.commons.lang3.StringUtils) Collections.singletonList(java.util.Collections.singletonList) BigDecimal(java.math.BigDecimal) MonetaryUtil.formatCents(alfio.util.MonetaryUtil.formatCents) DateUtils.truncate(org.apache.commons.lang3.time.DateUtils.truncate) Pair(org.apache.commons.lang3.tuple.Pair) OFFLINE_PAYMENT(alfio.model.TicketReservation.TicketReservationStatus.OFFLINE_PAYMENT) Arrays.asList(java.util.Arrays.asList) ASReservationWithOptionalCodeModification(alfio.model.modification.ASReservationWithOptionalCodeModification) DefaultTransactionDefinition(org.springframework.transaction.support.DefaultTransactionDefinition) Triple(org.apache.commons.lang3.tuple.Triple) OrganizationRepository(alfio.repository.user.OrganizationRepository) Organization(alfio.model.user.Organization) Predicate(java.util.function.Predicate) FeeCalculator(alfio.manager.support.FeeCalculator) Visit(de.danielbechler.diff.node.Visit) Collectors(java.util.stream.Collectors) ZoneId(java.time.ZoneId) DiffNode(de.danielbechler.diff.node.DiffNode) Role(alfio.model.user.Role) Stream(java.util.stream.Stream) PlatformTransactionManager(org.springframework.transaction.PlatformTransactionManager) alfio.model(alfio.model) UserRepository(alfio.repository.user.UserRepository) AdditionalServiceItemPriceContainer(alfio.model.decorator.AdditionalServiceItemPriceContainer) Configuration(alfio.model.system.Configuration) AdditionalServiceItemStatus(alfio.model.AdditionalServiceItem.AdditionalServiceItemStatus) AdditionalServiceReservationModification(alfio.model.modification.AdditionalServiceReservationModification) OptionalWrapper.optionally(alfio.util.OptionalWrapper.optionally) IntStream(java.util.stream.IntStream) java.util(java.util) MonetaryUtil.unitToCents(alfio.util.MonetaryUtil.unitToCents) TransactionDefinition(org.springframework.transaction.TransactionDefinition) ConfigurationManager(alfio.manager.system.ConfigurationManager) Function(java.util.function.Function) alfio.util(alfio.util) TicketPriceContainer(alfio.model.decorator.TicketPriceContainer) IN_PAYMENT(alfio.model.TicketReservation.TicketReservationStatus.IN_PAYMENT) UserDetails(org.springframework.security.core.userdetails.UserDetails) TicketReservationStatus(alfio.model.TicketReservation.TicketReservationStatus) MessageSource(org.springframework.context.MessageSource) ObjectDifferBuilder(de.danielbechler.diff.ObjectDifferBuilder) TicketReservationWithOptionalCodeModification(alfio.model.modification.TicketReservationWithOptionalCodeModification) UpdateTicketOwnerForm(alfio.controller.form.UpdateTicketOwnerForm) IOException(java.io.IOException) Status(alfio.model.SpecialPrice.Status) DateUtils.addHours(org.apache.commons.lang3.time.DateUtils.addHours) Component(org.springframework.stereotype.Component) Validate(org.apache.commons.lang3.Validate) ChronoUnit(java.time.temporal.ChronoUnit) CategoryEvaluator(alfio.manager.support.CategoryEvaluator) TransactionTemplate(org.springframework.transaction.support.TransactionTemplate) Log4j2(lombok.extern.log4j.Log4j2) Clock(java.time.Clock) ConfigurationKeys(alfio.model.system.ConfigurationKeys) Transactional(org.springframework.transaction.annotation.Transactional) TicketPriceContainer(alfio.model.decorator.TicketPriceContainer) AdditionalServiceItemPriceContainer(alfio.model.decorator.AdditionalServiceItemPriceContainer) BigDecimal(java.math.BigDecimal)

Example 2 with TicketPriceContainer

use of alfio.model.decorator.TicketPriceContainer in project alf.io by alfio-event.

the class TicketReservationManager method extractSummary.

List<SummaryRow> extractSummary(String reservationId, PriceContainer.VatStatus reservationVatStatus, Event event, Locale locale, PromoCodeDiscount promoCodeDiscount, TotalPrice reservationCost) {
    List<SummaryRow> summary = new ArrayList<>();
    List<TicketPriceContainer> tickets = ticketRepository.findTicketsInReservation(reservationId).stream().map(t -> TicketPriceContainer.from(t, reservationVatStatus, event, promoCodeDiscount)).collect(toList());
    tickets.stream().collect(Collectors.groupingBy(TicketPriceContainer::getCategoryId)).forEach((categoryId, ticketsByCategory) -> {
        final int subTotal = ticketsByCategory.stream().mapToInt(TicketPriceContainer::getSummarySrcPriceCts).sum();
        final int subTotalBeforeVat = ticketsByCategory.stream().mapToInt(TicketPriceContainer::getSummaryPriceBeforeVatCts).sum();
        TicketPriceContainer firstTicket = ticketsByCategory.get(0);
        final int ticketPriceCts = firstTicket.getSummarySrcPriceCts();
        final int priceBeforeVat = firstTicket.getSummaryPriceBeforeVatCts();
        String categoryName = ticketCategoryRepository.getByIdAndActive(categoryId, event.getId()).getName();
        summary.add(new SummaryRow(categoryName, formatCents(ticketPriceCts), formatCents(priceBeforeVat), ticketsByCategory.size(), formatCents(subTotal), formatCents(subTotalBeforeVat), subTotal, SummaryRow.SummaryType.TICKET));
    });
    summary.addAll(collectAdditionalServiceItems(reservationId, event).map(entry -> {
        String language = locale.getLanguage();
        AdditionalServiceText title = additionalServiceTextRepository.findBestMatchByLocaleAndType(entry.getKey().getId(), language, AdditionalServiceText.TextType.TITLE);
        if (!title.getLocale().equals(language) || title.getId() == -1) {
            log.debug("additional service {}: title not found for locale {}", title.getAdditionalServiceId(), language);
        }
        List<AdditionalServiceItemPriceContainer> prices = generateASIPriceContainers(event, null).apply(entry).collect(toList());
        AdditionalServiceItemPriceContainer first = prices.get(0);
        final int subtotal = prices.stream().mapToInt(AdditionalServiceItemPriceContainer::getSrcPriceCts).sum();
        final int subtotalBeforeVat = prices.stream().mapToInt(AdditionalServiceItemPriceContainer::getSummaryPriceBeforeVatCts).sum();
        return new SummaryRow(title.getValue(), formatCents(first.getSrcPriceCts()), formatCents(first.getSummaryPriceBeforeVatCts()), prices.size(), formatCents(subtotal), formatCents(subtotalBeforeVat), subtotal, SummaryRow.SummaryType.ADDITIONAL_SERVICE);
    }).collect(Collectors.toList()));
    Optional.ofNullable(promoCodeDiscount).ifPresent(promo -> {
        String formattedSingleAmount = "-" + (promo.getDiscountType() == DiscountType.FIXED_AMOUNT ? formatCents(promo.getDiscountAmount()) : (promo.getDiscountAmount() + "%"));
        summary.add(new SummaryRow(formatPromoCode(promo, ticketRepository.findTicketsInReservation(reservationId)), formattedSingleAmount, formattedSingleAmount, reservationCost.getDiscountAppliedCount(), formatCents(reservationCost.getDiscount()), formatCents(reservationCost.getDiscount()), reservationCost.getDiscount(), SummaryRow.SummaryType.PROMOTION_CODE));
    });
    return summary;
}
Also used : alfio.repository(alfio.repository) PaymentProxy(alfio.model.transaction.PaymentProxy) DiscountType(alfio.model.PromoCodeDiscount.DiscountType) ZonedDateTime(java.time.ZonedDateTime) PaymentResult(alfio.manager.support.PaymentResult) AdditionalServicePriceContainer(alfio.model.decorator.AdditionalServicePriceContainer) PartialTicketTextGenerator(alfio.manager.support.PartialTicketTextGenerator) Mailer(alfio.manager.system.Mailer) TicketStatus(alfio.model.Ticket.TicketStatus) StringUtils(org.apache.commons.lang3.StringUtils) Collections.singletonList(java.util.Collections.singletonList) BigDecimal(java.math.BigDecimal) MonetaryUtil.formatCents(alfio.util.MonetaryUtil.formatCents) DateUtils.truncate(org.apache.commons.lang3.time.DateUtils.truncate) Pair(org.apache.commons.lang3.tuple.Pair) OFFLINE_PAYMENT(alfio.model.TicketReservation.TicketReservationStatus.OFFLINE_PAYMENT) Arrays.asList(java.util.Arrays.asList) ASReservationWithOptionalCodeModification(alfio.model.modification.ASReservationWithOptionalCodeModification) DefaultTransactionDefinition(org.springframework.transaction.support.DefaultTransactionDefinition) Triple(org.apache.commons.lang3.tuple.Triple) OrganizationRepository(alfio.repository.user.OrganizationRepository) Organization(alfio.model.user.Organization) Predicate(java.util.function.Predicate) FeeCalculator(alfio.manager.support.FeeCalculator) Visit(de.danielbechler.diff.node.Visit) Collectors(java.util.stream.Collectors) ZoneId(java.time.ZoneId) DiffNode(de.danielbechler.diff.node.DiffNode) Role(alfio.model.user.Role) Stream(java.util.stream.Stream) PlatformTransactionManager(org.springframework.transaction.PlatformTransactionManager) alfio.model(alfio.model) UserRepository(alfio.repository.user.UserRepository) AdditionalServiceItemPriceContainer(alfio.model.decorator.AdditionalServiceItemPriceContainer) Configuration(alfio.model.system.Configuration) AdditionalServiceItemStatus(alfio.model.AdditionalServiceItem.AdditionalServiceItemStatus) AdditionalServiceReservationModification(alfio.model.modification.AdditionalServiceReservationModification) OptionalWrapper.optionally(alfio.util.OptionalWrapper.optionally) IntStream(java.util.stream.IntStream) java.util(java.util) MonetaryUtil.unitToCents(alfio.util.MonetaryUtil.unitToCents) TransactionDefinition(org.springframework.transaction.TransactionDefinition) ConfigurationManager(alfio.manager.system.ConfigurationManager) Function(java.util.function.Function) alfio.util(alfio.util) TicketPriceContainer(alfio.model.decorator.TicketPriceContainer) IN_PAYMENT(alfio.model.TicketReservation.TicketReservationStatus.IN_PAYMENT) UserDetails(org.springframework.security.core.userdetails.UserDetails) TicketReservationStatus(alfio.model.TicketReservation.TicketReservationStatus) MessageSource(org.springframework.context.MessageSource) ObjectDifferBuilder(de.danielbechler.diff.ObjectDifferBuilder) TicketReservationWithOptionalCodeModification(alfio.model.modification.TicketReservationWithOptionalCodeModification) UpdateTicketOwnerForm(alfio.controller.form.UpdateTicketOwnerForm) IOException(java.io.IOException) Status(alfio.model.SpecialPrice.Status) DateUtils.addHours(org.apache.commons.lang3.time.DateUtils.addHours) Component(org.springframework.stereotype.Component) Validate(org.apache.commons.lang3.Validate) ChronoUnit(java.time.temporal.ChronoUnit) CategoryEvaluator(alfio.manager.support.CategoryEvaluator) TransactionTemplate(org.springframework.transaction.support.TransactionTemplate) Log4j2(lombok.extern.log4j.Log4j2) Clock(java.time.Clock) ConfigurationKeys(alfio.model.system.ConfigurationKeys) Transactional(org.springframework.transaction.annotation.Transactional) TicketPriceContainer(alfio.model.decorator.TicketPriceContainer) AdditionalServiceItemPriceContainer(alfio.model.decorator.AdditionalServiceItemPriceContainer)

Example 3 with TicketPriceContainer

use of alfio.model.decorator.TicketPriceContainer in project alf.io by alfio-event.

the class TicketReservationManager method reserveTicketsForCategory.

void reserveTicketsForCategory(Event event, Optional<String> specialPriceSessionId, String transactionId, TicketReservationWithOptionalCodeModification ticketReservation, Locale locale, boolean forWaitingQueue, PromoCodeDiscount discount) {
    // first check if there is another pending special price token bound to the current sessionId
    Optional<SpecialPrice> specialPrice = fixToken(ticketReservation.getSpecialPrice(), ticketReservation.getTicketCategoryId(), event.getId(), specialPriceSessionId, ticketReservation);
    List<Integer> reservedForUpdate = reserveTickets(event.getId(), ticketReservation, forWaitingQueue ? asList(TicketStatus.RELEASED, TicketStatus.PRE_RESERVED) : singletonList(TicketStatus.FREE));
    int requested = ticketReservation.getAmount();
    if (reservedForUpdate.size() != requested) {
        throw new NotEnoughTicketsException();
    }
    TicketCategory category = ticketCategoryRepository.getByIdAndActive(ticketReservation.getTicketCategoryId(), event.getId());
    if (specialPrice.isPresent()) {
        if (reservedForUpdate.size() != 1) {
            throw new NotEnoughTicketsException();
        }
        SpecialPrice sp = specialPrice.get();
        ticketRepository.reserveTicket(transactionId, reservedForUpdate.stream().findFirst().orElseThrow(IllegalStateException::new), sp.getId(), locale.getLanguage(), category.getSrcPriceCts());
        specialPriceRepository.updateStatus(sp.getId(), Status.PENDING.toString(), sp.getSessionIdentifier());
    } else {
        ticketRepository.reserveTickets(transactionId, reservedForUpdate, ticketReservation.getTicketCategoryId(), locale.getLanguage(), category.getSrcPriceCts());
    }
    Ticket ticket = ticketRepository.findById(reservedForUpdate.get(0), category.getId());
    TicketPriceContainer priceContainer = TicketPriceContainer.from(ticket, null, event, discount);
    ticketRepository.updateTicketPrice(reservedForUpdate, category.getId(), event.getId(), category.getSrcPriceCts(), MonetaryUtil.unitToCents(priceContainer.getFinalPrice()), MonetaryUtil.unitToCents(priceContainer.getVAT()), MonetaryUtil.unitToCents(priceContainer.getAppliedDiscount()));
}
Also used : TicketPriceContainer(alfio.model.decorator.TicketPriceContainer)

Example 4 with TicketPriceContainer

use of alfio.model.decorator.TicketPriceContainer in project alf.io by alfio-event.

the class AdminReservationManager method reserveForTicketsInfo.

private Result<List<Ticket>> reserveForTicketsInfo(Event event, AdminReservationModification arm, String reservationId, String specialPriceSessionId, Pair<TicketCategory, TicketsInfo> pair) {
    TicketCategory category = pair.getLeft();
    TicketsInfo ticketsInfo = pair.getRight();
    int categoryId = category.getId();
    List<Attendee> attendees = ticketsInfo.getAttendees();
    List<Integer> reservedForUpdate = ticketReservationManager.reserveTickets(event.getId(), categoryId, attendees.size(), singletonList(Ticket.TicketStatus.FREE));
    if (reservedForUpdate.size() != attendees.size()) {
        return Result.error(ErrorCode.CategoryError.NOT_ENOUGH_SEATS);
    }
    ticketRepository.reserveTickets(reservationId, reservedForUpdate, categoryId, arm.getLanguage(), category.getSrcPriceCts());
    Ticket ticket = ticketRepository.findById(reservedForUpdate.get(0), categoryId);
    TicketPriceContainer priceContainer = TicketPriceContainer.from(ticket, null, event, null);
    ticketRepository.updateTicketPrice(reservedForUpdate, categoryId, event.getId(), category.getSrcPriceCts(), MonetaryUtil.unitToCents(priceContainer.getFinalPrice()), MonetaryUtil.unitToCents(priceContainer.getVAT()), MonetaryUtil.unitToCents(priceContainer.getAppliedDiscount()));
    List<SpecialPrice> codes = category.isAccessRestricted() ? bindSpecialPriceTokens(specialPriceSessionId, categoryId, attendees) : Collections.emptyList();
    assignTickets(event, attendees, categoryId, reservedForUpdate, codes, reservationId, arm.getLanguage(), category.getSrcPriceCts());
    List<Ticket> tickets = reservedForUpdate.stream().map(id -> ticketRepository.findById(id, categoryId)).collect(toList());
    return Result.success(tickets);
}
Also used : alfio.repository(alfio.repository) PaymentProxy(alfio.model.transaction.PaymentProxy) ZonedDateTime(java.time.ZonedDateTime) BiFunction(java.util.function.BiFunction) RequiredArgsConstructor(lombok.RequiredArgsConstructor) NamedParameterJdbcTemplate(org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate) StringUtils(org.apache.commons.lang3.StringUtils) Collections.singletonList(java.util.Collections.singletonList) ResultStatus(alfio.model.result.Result.ResultStatus) BigDecimal(java.math.BigDecimal) Json(alfio.util.Json) ErrorCode(alfio.model.result.ErrorCode) Pair(org.apache.commons.lang3.tuple.Pair) DataIntegrityViolationException(org.springframework.dao.DataIntegrityViolationException) DefaultTransactionDefinition(org.springframework.transaction.support.DefaultTransactionDefinition) Triple(org.apache.commons.lang3.tuple.Triple) TemplateResource(alfio.util.TemplateResource) TICKET(alfio.model.Audit.EntityType.TICKET) StringUtils.trimToNull(org.apache.commons.lang3.StringUtils.trimToNull) Organization(alfio.model.user.Organization) TemplateManager(alfio.util.TemplateManager) Collectors(java.util.stream.Collectors) CANCEL_TICKET(alfio.model.Audit.EventType.CANCEL_TICKET) Stream(java.util.stream.Stream) PlatformTransactionManager(org.springframework.transaction.PlatformTransactionManager) alfio.model(alfio.model) UserRepository(alfio.repository.user.UserRepository) OptionalWrapper.optionally(alfio.util.OptionalWrapper.optionally) java.util(java.util) DuplicateReferenceException(alfio.manager.support.DuplicateReferenceException) MapSqlParameterSource(org.springframework.jdbc.core.namedparam.MapSqlParameterSource) Function(java.util.function.Function) Attendee(alfio.model.modification.AdminReservationModification.Attendee) DateTimeModification(alfio.model.modification.DateTimeModification) TicketPriceContainer(alfio.model.decorator.TicketPriceContainer) TicketReservationStatus(alfio.model.TicketReservation.TicketReservationStatus) MessageSource(org.springframework.context.MessageSource) DateTimeModification.fromZonedDateTime(alfio.model.modification.DateTimeModification.fromZonedDateTime) TicketCategoryModification(alfio.model.modification.TicketCategoryModification) TicketsInfo(alfio.model.modification.AdminReservationModification.TicketsInfo) Result(alfio.model.result.Result) Component(org.springframework.stereotype.Component) MonetaryUtil(alfio.util.MonetaryUtil) TransactionTemplate(org.springframework.transaction.support.TransactionTemplate) Log4j2(lombok.extern.log4j.Log4j2) Category(alfio.model.modification.AdminReservationModification.Category) EventUtil.generateEmptyTickets(alfio.util.EventUtil.generateEmptyTickets) AdminReservationModification(alfio.model.modification.AdminReservationModification) Transactional(org.springframework.transaction.annotation.Transactional) Assert(org.springframework.util.Assert) TicketPriceContainer(alfio.model.decorator.TicketPriceContainer) TicketsInfo(alfio.model.modification.AdminReservationModification.TicketsInfo) Attendee(alfio.model.modification.AdminReservationModification.Attendee)

Aggregations

TicketPriceContainer (alfio.model.decorator.TicketPriceContainer)4 alfio.model (alfio.model)3 TicketReservationStatus (alfio.model.TicketReservation.TicketReservationStatus)3 PaymentProxy (alfio.model.transaction.PaymentProxy)3 Organization (alfio.model.user.Organization)3 alfio.repository (alfio.repository)3 UserRepository (alfio.repository.user.UserRepository)3 OptionalWrapper.optionally (alfio.util.OptionalWrapper.optionally)3 BigDecimal (java.math.BigDecimal)3 ZonedDateTime (java.time.ZonedDateTime)3 java.util (java.util)3 Collections.singletonList (java.util.Collections.singletonList)3 Function (java.util.function.Function)3 Collectors (java.util.stream.Collectors)3 Stream (java.util.stream.Stream)3 Log4j2 (lombok.extern.log4j.Log4j2)3 StringUtils (org.apache.commons.lang3.StringUtils)3 Pair (org.apache.commons.lang3.tuple.Pair)3 Triple (org.apache.commons.lang3.tuple.Triple)3 MessageSource (org.springframework.context.MessageSource)3