Search in sources :

Example 1 with TicketMetadata

use of alfio.model.metadata.TicketMetadata in project alf.io by alfio-event.

the class TicketReservationManager method acquireEventTickets.

private void acquireEventTickets(PaymentProxy paymentProxy, String reservationId, PurchaseContext purchaseContext, Event event) {
    TicketStatus ticketStatus = paymentProxy.isDeskPaymentRequired() ? TicketStatus.TO_BE_PAID : TicketStatus.ACQUIRED;
    AdditionalServiceItemStatus asStatus = paymentProxy.isDeskPaymentRequired() ? AdditionalServiceItemStatus.TO_BE_PAID : AdditionalServiceItemStatus.ACQUIRED;
    Map<Integer, Ticket> preUpdateTicket = ticketRepository.findTicketsInReservation(reservationId).stream().collect(toMap(Ticket::getId, Function.identity()));
    int updatedTickets = ticketRepository.updateTicketsStatusWithReservationId(reservationId, ticketStatus.toString());
    if (!configurationManager.getFor(ENABLE_TICKET_TRANSFER, purchaseContext.getConfigurationLevel()).getValueAsBooleanOrDefault()) {
        // automatically lock assignment
        int locked = ticketRepository.forbidReassignment(preUpdateTicket.keySet());
        Validate.isTrue(updatedTickets == locked, "Expected to lock " + updatedTickets + " tickets, locked " + locked);
        Map<Integer, Ticket> postUpdateTicket = ticketRepository.findTicketsInReservation(reservationId).stream().collect(toMap(Ticket::getId, Function.identity()));
        postUpdateTicket.forEach((id, ticket) -> auditUpdateTicket(preUpdateTicket.get(id), Collections.emptyMap(), ticket, Collections.emptyMap(), event.getId()));
    }
    var ticketsWithMetadataById = ticketRepository.findTicketsInReservationWithMetadata(reservationId).stream().collect(toMap(twm -> twm.getTicket().getId(), Function.identity()));
    ticketsWithMetadataById.forEach((id, ticketWithMetadata) -> {
        var newMetadataOptional = extensionManager.handleTicketAssignmentMetadata(ticketWithMetadata, event);
        newMetadataOptional.ifPresent(metadata -> {
            var existingContainer = TicketMetadataContainer.copyOf(ticketWithMetadata.getMetadata());
            var general = new HashMap<>(existingContainer.getMetadataForKey(TicketMetadataContainer.GENERAL).orElseGet(TicketMetadata::empty).getAttributes());
            general.putAll(metadata.getAttributes());
            existingContainer.putMetadata(TicketMetadataContainer.GENERAL, new TicketMetadata(null, null, general));
            ticketRepository.updateTicketMetadata(id, existingContainer);
            auditUpdateMetadata(reservationId, id, event.getId(), existingContainer, ticketWithMetadata.getMetadata());
        });
        auditUpdateTicket(preUpdateTicket.get(id), Collections.emptyMap(), ticketWithMetadata.getTicket(), Collections.emptyMap(), event.getId());
    });
    int updatedAS = additionalServiceItemRepository.updateItemsStatusWithReservationUUID(reservationId, asStatus);
    Validate.isTrue(updatedTickets + updatedAS > 0, "no items have been updated");
}
Also used : AtomicInteger(java.util.concurrent.atomic.AtomicInteger) alfio.repository(alfio.repository) TicketMetadataContainer(alfio.model.metadata.TicketMetadataContainer) ZonedDateTime(java.time.ZonedDateTime) TicketCheckInUtil.ticketOnlineCheckInUrl(alfio.util.checkin.TicketCheckInUtil.ticketOnlineCheckInUrl) UncategorizedSQLException(org.springframework.jdbc.UncategorizedSQLException) StringUtils(org.apache.commons.lang3.StringUtils) TransactionSynchronizationManager(org.springframework.transaction.support.TransactionSynchronizationManager) Collections.singletonList(java.util.Collections.singletonList) BigDecimal(java.math.BigDecimal) DateUtils.truncate(org.apache.commons.lang3.time.DateUtils.truncate) ErrorCode(alfio.model.result.ErrorCode) Pair(org.apache.commons.lang3.tuple.Pair) Arrays.asList(java.util.Arrays.asList) ASReservationWithOptionalCodeModification(alfio.model.modification.ASReservationWithOptionalCodeModification) Triple(org.apache.commons.lang3.tuple.Triple) TICKET(alfio.model.Audit.EntityType.TICKET) Organization(alfio.model.user.Organization) UserIdAndOrganizationId(alfio.model.support.UserIdAndOrganizationId) ZoneId(java.time.ZoneId) SubscriptionTimeUnit(alfio.model.subscription.SubscriptionDescriptor.SubscriptionTimeUnit) EventType(alfio.model.Audit.EventType) Stream(java.util.stream.Stream) Type(alfio.model.BillingDocument.Type) PlatformTransactionManager(org.springframework.transaction.PlatformTransactionManager) alfio.model(alfio.model) UserRepository(alfio.repository.user.UserRepository) AdditionalServiceItemPriceContainer(alfio.model.decorator.AdditionalServiceItemPriceContainer) AdditionalServiceItemStatus(alfio.model.AdditionalServiceItem.AdditionalServiceItemStatus) AdditionalServiceReservationModification(alfio.model.modification.AdditionalServiceReservationModification) PromoCodeDiscount.categoriesOrNull(alfio.model.PromoCodeDiscount.categoriesOrNull) java.util(java.util) TicketHelper(alfio.controller.api.support.TicketHelper) ConfigurationLevel(alfio.manager.system.ConfigurationLevel) MessageSourceManager(alfio.manager.i18n.MessageSourceManager) SummaryType(alfio.model.SummaryRow.SummaryType) MapSqlParameterSource(org.springframework.jdbc.core.namedparam.MapSqlParameterSource) BindingResult(org.springframework.validation.BindingResult) ConfigurationManager(alfio.manager.system.ConfigurationManager) CollectionUtils(org.apache.commons.collections4.CollectionUtils) Objects.requireNonNullElse(java.util.Objects.requireNonNullElse) TicketReservationStatus(alfio.model.TicketReservation.TicketReservationStatus) RESERVATION(alfio.model.Audit.EntityType.RESERVATION) TicketReservationWithOptionalCodeModification(alfio.model.modification.TicketReservationWithOptionalCodeModification) WebhookHandler(alfio.model.transaction.capabilities.WebhookHandler) Status(alfio.model.SpecialPrice.Status) DateUtils(org.apache.commons.lang3.time.DateUtils) Result(alfio.model.result.Result) LinkedGroup(alfio.model.group.LinkedGroup) Validate(org.apache.commons.lang3.Validate) ChronoUnit(java.time.temporal.ChronoUnit) MonetaryUtil(alfio.util.MonetaryUtil) UserManager(alfio.manager.user.UserManager) WarningMessage(alfio.model.result.WarningMessage) Wrappers.optionally(alfio.util.Wrappers.optionally) UriComponentsBuilder(org.springframework.web.util.UriComponentsBuilder) ServerInitiatedTransaction(alfio.model.transaction.capabilities.ServerInitiatedTransaction) TemplateProcessor(alfio.controller.support.TemplateProcessor) DiscountType(alfio.model.PromoCodeDiscount.DiscountType) NamedParameterJdbcTemplate(org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate) AdditionalServicePriceContainer(alfio.model.decorator.AdditionalServicePriceContainer) Mailer(alfio.manager.system.Mailer) TicketStatus(alfio.model.Ticket.TicketStatus) TicketCheckInUtil(alfio.util.checkin.TicketCheckInUtil) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) DefaultTransactionDefinition(org.springframework.transaction.support.DefaultTransactionDefinition) OfflineProcessor(alfio.model.transaction.capabilities.OfflineProcessor) OrganizationRepository(alfio.repository.user.OrganizationRepository) Predicate(java.util.function.Predicate) Collectors(java.util.stream.Collectors) Role(alfio.model.user.Role) Principal(java.security.Principal) Entry(java.util.Map.Entry) CodeType(alfio.model.PromoCodeDiscount.CodeType) OnlineCheckInFullInfo(alfio.model.checkin.OnlineCheckInFullInfo) IntStream(java.util.stream.IntStream) CustomEmailText(alfio.model.extension.CustomEmailText) ChronoField(java.time.temporal.ChronoField) TransactionDefinition(org.springframework.transaction.TransactionDefinition) PurchaseContextType(alfio.model.PurchaseContext.PurchaseContextType) Function(java.util.function.Function) alfio.util(alfio.util) ReservationPriceCalculator(alfio.manager.system.ReservationPriceCalculator) TicketPriceContainer(alfio.model.decorator.TicketPriceContainer) ObjectUtils(org.apache.commons.lang3.ObjectUtils) alfio.model.transaction(alfio.model.transaction) UserDetails(org.springframework.security.core.userdetails.UserDetails) alfio.model.subscription(alfio.model.subscription) Collections.singletonMap(java.util.Collections.singletonMap) VatStatus(alfio.model.PriceContainer.VatStatus) ONCE_PER_EVENT(alfio.model.subscription.SubscriptionDescriptor.SubscriptionUsageType.ONCE_PER_EVENT) alfio.manager.support(alfio.manager.support) BankTransferManager(alfio.manager.payment.BankTransferManager) UpdateTicketOwnerForm(alfio.controller.form.UpdateTicketOwnerForm) TicketMetadata(alfio.model.metadata.TicketMetadata) DateUtils.addHours(org.apache.commons.lang3.time.DateUtils.addHours) Component(org.springframework.stereotype.Component) PaymentSpecification(alfio.manager.payment.PaymentSpecification) TransactionTemplate(org.springframework.transaction.support.TransactionTemplate) Log4j2(lombok.extern.log4j.Log4j2) PaymentMethodStatus(alfio.manager.PaymentManager.PaymentMethodDTO.PaymentMethodStatus) Clock(java.time.Clock) ConfigurationKeys(alfio.model.system.ConfigurationKeys) Transactional(org.springframework.transaction.annotation.Transactional) Assert(org.springframework.util.Assert) AdditionalServiceItemStatus(alfio.model.AdditionalServiceItem.AdditionalServiceItemStatus) TicketMetadata(alfio.model.metadata.TicketMetadata) TicketStatus(alfio.model.Ticket.TicketStatus)

Example 2 with TicketMetadata

use of alfio.model.metadata.TicketMetadata in project alf.io by alfio-event.

the class TicketReservationManager method reserveTicketsForCategory.

void reserveTicketsForCategory(Event event, String reservationId, TicketReservationWithOptionalCodeModification ticketReservation, Locale locale, boolean forWaitingQueue, PromoCodeDiscount accessCodeOrDiscount, PromoCodeDiscount dynamicDiscount) {
    List<SpecialPrice> specialPrices;
    if (accessCodeOrDiscount != null && accessCodeOrDiscount.getCodeType() == CodeType.ACCESS && ticketReservation.getTicketCategoryId().equals(accessCodeOrDiscount.getHiddenCategoryId()) && Boolean.TRUE.equals(ticketCategoryRepository.isAccessRestricted(accessCodeOrDiscount.getHiddenCategoryId()))) {
        specialPrices = reserveTokensForAccessCode(ticketReservation, accessCodeOrDiscount);
    } else {
        // 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(), ticketReservation);
        specialPrices = specialPrice.stream().collect(toList());
    }
    List<Integer> reservedForUpdate = reserveTickets(event.getId(), ticketReservation, forWaitingQueue ? asList(TicketStatus.RELEASED, TicketStatus.PRE_RESERVED) : singletonList(TicketStatus.FREE));
    int requested = ticketReservation.getQuantity();
    if (reservedForUpdate.size() != requested) {
        throw new NotEnoughTicketsException();
    }
    TicketCategory category = ticketCategoryRepository.getByIdAndActive(ticketReservation.getTicketCategoryId(), event.getId());
    List<Map<String, String>> ticketMetadata = requireNonNullElse(ticketReservation.getMetadata(), List.of());
    if (!specialPrices.isEmpty()) {
        if (specialPrices.size() != reservedForUpdate.size()) {
            throw new NotEnoughTicketsException();
        }
        AtomicInteger counter = new AtomicInteger(0);
        var ticketsAndSpecialPrices = specialPrices.stream().map(sp -> {
            int index = counter.getAndIncrement();
            return Triple.of(reservedForUpdate.get(index), sp, getAtIndexOrNull(ticketMetadata, index));
        }).collect(Collectors.toList());
        if (specialPrices.size() == 1) {
            var ticketId = reservedForUpdate.get(0);
            var sp = specialPrices.get(0);
            var accessCodeId = accessCodeOrDiscount != null && accessCodeOrDiscount.getHiddenCategoryId() != null ? accessCodeOrDiscount.getId() : null;
            TicketMetadata metadata = null;
            var attributes = getAtIndexOrNull(ticketMetadata, 0);
            if (attributes != null) {
                metadata = new TicketMetadata(null, null, attributes);
            }
            ticketRepository.reserveTicket(reservationId, ticketId, sp.getId(), locale.getLanguage(), category.getSrcPriceCts(), category.getCurrencyCode(), event.getVatStatus(), TicketMetadataContainer.fromMetadata(metadata));
            specialPriceRepository.updateStatus(sp.getId(), Status.PENDING.toString(), null, accessCodeId);
        } else {
            jdbcTemplate.batchUpdate(ticketRepository.batchReserveTicketsForSpecialPrice(), ticketsAndSpecialPrices.stream().map(triple -> {
                TicketMetadataContainer metadata = null;
                if (triple.getRight() != null) {
                    metadata = TicketMetadataContainer.fromMetadata(new TicketMetadata(null, null, triple.getRight()));
                }
                return new MapSqlParameterSource(RESERVATION_ID, reservationId).addValue("ticketId", triple.getLeft()).addValue("specialCodeId", triple.getMiddle().getId()).addValue("userLanguage", locale.getLanguage()).addValue("srcPriceCts", category.getSrcPriceCts()).addValue("currencyCode", category.getCurrencyCode()).addValue("ticketMetadata", json.asJsonString(metadata)).addValue("vatStatus", event.getVatStatus().toString());
            }).toArray(MapSqlParameterSource[]::new));
            specialPriceRepository.batchUpdateStatus(specialPrices.stream().map(SpecialPrice::getId).collect(toList()), Status.PENDING, Objects.requireNonNull(accessCodeOrDiscount).getId());
        }
    } else {
        int reserved = ticketRepository.reserveTickets(reservationId, reservedForUpdate, category, locale.getLanguage(), event.getVatStatus(), idx -> {
            var metadata = getAtIndexOrNull(ticketMetadata, idx);
            if (metadata != null) {
                return json.asJsonString(TicketMetadataContainer.fromMetadata(new TicketMetadata(null, null, metadata)));
            }
            return null;
        });
        Validate.isTrue(reserved == reservedForUpdate.size(), "Cannot reserve all tickets");
    }
    Ticket ticket = ticketRepository.findById(reservedForUpdate.get(0), category.getId());
    var discountToApply = ObjectUtils.firstNonNull(dynamicDiscount, accessCodeOrDiscount);
    TicketPriceContainer priceContainer = TicketPriceContainer.from(ticket, null, event.getVat(), event.getVatStatus(), discountToApply);
    var currencyCode = priceContainer.getCurrencyCode();
    ticketRepository.updateTicketPrice(reservedForUpdate, category.getId(), event.getId(), category.getSrcPriceCts(), MonetaryUtil.unitToCents(priceContainer.getFinalPrice(), currencyCode), MonetaryUtil.unitToCents(priceContainer.getVAT(), currencyCode), MonetaryUtil.unitToCents(priceContainer.getAppliedDiscount(), currencyCode), category.getCurrencyCode(), priceContainer.getVatStatus());
}
Also used : alfio.repository(alfio.repository) TicketMetadataContainer(alfio.model.metadata.TicketMetadataContainer) ZonedDateTime(java.time.ZonedDateTime) TicketCheckInUtil.ticketOnlineCheckInUrl(alfio.util.checkin.TicketCheckInUtil.ticketOnlineCheckInUrl) UncategorizedSQLException(org.springframework.jdbc.UncategorizedSQLException) StringUtils(org.apache.commons.lang3.StringUtils) TransactionSynchronizationManager(org.springframework.transaction.support.TransactionSynchronizationManager) Collections.singletonList(java.util.Collections.singletonList) BigDecimal(java.math.BigDecimal) DateUtils.truncate(org.apache.commons.lang3.time.DateUtils.truncate) ErrorCode(alfio.model.result.ErrorCode) Pair(org.apache.commons.lang3.tuple.Pair) Arrays.asList(java.util.Arrays.asList) ASReservationWithOptionalCodeModification(alfio.model.modification.ASReservationWithOptionalCodeModification) Triple(org.apache.commons.lang3.tuple.Triple) TICKET(alfio.model.Audit.EntityType.TICKET) Organization(alfio.model.user.Organization) UserIdAndOrganizationId(alfio.model.support.UserIdAndOrganizationId) ZoneId(java.time.ZoneId) SubscriptionTimeUnit(alfio.model.subscription.SubscriptionDescriptor.SubscriptionTimeUnit) EventType(alfio.model.Audit.EventType) Stream(java.util.stream.Stream) Type(alfio.model.BillingDocument.Type) PlatformTransactionManager(org.springframework.transaction.PlatformTransactionManager) alfio.model(alfio.model) UserRepository(alfio.repository.user.UserRepository) AdditionalServiceItemPriceContainer(alfio.model.decorator.AdditionalServiceItemPriceContainer) AdditionalServiceItemStatus(alfio.model.AdditionalServiceItem.AdditionalServiceItemStatus) AdditionalServiceReservationModification(alfio.model.modification.AdditionalServiceReservationModification) PromoCodeDiscount.categoriesOrNull(alfio.model.PromoCodeDiscount.categoriesOrNull) java.util(java.util) TicketHelper(alfio.controller.api.support.TicketHelper) ConfigurationLevel(alfio.manager.system.ConfigurationLevel) MessageSourceManager(alfio.manager.i18n.MessageSourceManager) SummaryType(alfio.model.SummaryRow.SummaryType) MapSqlParameterSource(org.springframework.jdbc.core.namedparam.MapSqlParameterSource) BindingResult(org.springframework.validation.BindingResult) ConfigurationManager(alfio.manager.system.ConfigurationManager) CollectionUtils(org.apache.commons.collections4.CollectionUtils) Objects.requireNonNullElse(java.util.Objects.requireNonNullElse) TicketReservationStatus(alfio.model.TicketReservation.TicketReservationStatus) RESERVATION(alfio.model.Audit.EntityType.RESERVATION) TicketReservationWithOptionalCodeModification(alfio.model.modification.TicketReservationWithOptionalCodeModification) WebhookHandler(alfio.model.transaction.capabilities.WebhookHandler) Status(alfio.model.SpecialPrice.Status) DateUtils(org.apache.commons.lang3.time.DateUtils) Result(alfio.model.result.Result) LinkedGroup(alfio.model.group.LinkedGroup) Validate(org.apache.commons.lang3.Validate) ChronoUnit(java.time.temporal.ChronoUnit) MonetaryUtil(alfio.util.MonetaryUtil) UserManager(alfio.manager.user.UserManager) WarningMessage(alfio.model.result.WarningMessage) Wrappers.optionally(alfio.util.Wrappers.optionally) UriComponentsBuilder(org.springframework.web.util.UriComponentsBuilder) ServerInitiatedTransaction(alfio.model.transaction.capabilities.ServerInitiatedTransaction) TemplateProcessor(alfio.controller.support.TemplateProcessor) DiscountType(alfio.model.PromoCodeDiscount.DiscountType) NamedParameterJdbcTemplate(org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate) AdditionalServicePriceContainer(alfio.model.decorator.AdditionalServicePriceContainer) Mailer(alfio.manager.system.Mailer) TicketStatus(alfio.model.Ticket.TicketStatus) TicketCheckInUtil(alfio.util.checkin.TicketCheckInUtil) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) DefaultTransactionDefinition(org.springframework.transaction.support.DefaultTransactionDefinition) OfflineProcessor(alfio.model.transaction.capabilities.OfflineProcessor) OrganizationRepository(alfio.repository.user.OrganizationRepository) Predicate(java.util.function.Predicate) Collectors(java.util.stream.Collectors) Role(alfio.model.user.Role) Principal(java.security.Principal) Entry(java.util.Map.Entry) CodeType(alfio.model.PromoCodeDiscount.CodeType) OnlineCheckInFullInfo(alfio.model.checkin.OnlineCheckInFullInfo) IntStream(java.util.stream.IntStream) CustomEmailText(alfio.model.extension.CustomEmailText) ChronoField(java.time.temporal.ChronoField) TransactionDefinition(org.springframework.transaction.TransactionDefinition) PurchaseContextType(alfio.model.PurchaseContext.PurchaseContextType) Function(java.util.function.Function) alfio.util(alfio.util) ReservationPriceCalculator(alfio.manager.system.ReservationPriceCalculator) TicketPriceContainer(alfio.model.decorator.TicketPriceContainer) ObjectUtils(org.apache.commons.lang3.ObjectUtils) alfio.model.transaction(alfio.model.transaction) UserDetails(org.springframework.security.core.userdetails.UserDetails) alfio.model.subscription(alfio.model.subscription) Collections.singletonMap(java.util.Collections.singletonMap) VatStatus(alfio.model.PriceContainer.VatStatus) ONCE_PER_EVENT(alfio.model.subscription.SubscriptionDescriptor.SubscriptionUsageType.ONCE_PER_EVENT) alfio.manager.support(alfio.manager.support) BankTransferManager(alfio.manager.payment.BankTransferManager) UpdateTicketOwnerForm(alfio.controller.form.UpdateTicketOwnerForm) TicketMetadata(alfio.model.metadata.TicketMetadata) DateUtils.addHours(org.apache.commons.lang3.time.DateUtils.addHours) Component(org.springframework.stereotype.Component) PaymentSpecification(alfio.manager.payment.PaymentSpecification) TransactionTemplate(org.springframework.transaction.support.TransactionTemplate) Log4j2(lombok.extern.log4j.Log4j2) PaymentMethodStatus(alfio.manager.PaymentManager.PaymentMethodDTO.PaymentMethodStatus) Clock(java.time.Clock) ConfigurationKeys(alfio.model.system.ConfigurationKeys) Transactional(org.springframework.transaction.annotation.Transactional) Assert(org.springframework.util.Assert) TicketPriceContainer(alfio.model.decorator.TicketPriceContainer) TicketMetadata(alfio.model.metadata.TicketMetadata) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) MapSqlParameterSource(org.springframework.jdbc.core.namedparam.MapSqlParameterSource) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) TicketMetadataContainer(alfio.model.metadata.TicketMetadataContainer) Collections.singletonMap(java.util.Collections.singletonMap)

Aggregations

TicketHelper (alfio.controller.api.support.TicketHelper)2 UpdateTicketOwnerForm (alfio.controller.form.UpdateTicketOwnerForm)2 TemplateProcessor (alfio.controller.support.TemplateProcessor)2 PaymentMethodStatus (alfio.manager.PaymentManager.PaymentMethodDTO.PaymentMethodStatus)2 MessageSourceManager (alfio.manager.i18n.MessageSourceManager)2 BankTransferManager (alfio.manager.payment.BankTransferManager)2 PaymentSpecification (alfio.manager.payment.PaymentSpecification)2 alfio.manager.support (alfio.manager.support)2 ConfigurationLevel (alfio.manager.system.ConfigurationLevel)2 ConfigurationManager (alfio.manager.system.ConfigurationManager)2 Mailer (alfio.manager.system.Mailer)2 ReservationPriceCalculator (alfio.manager.system.ReservationPriceCalculator)2 UserManager (alfio.manager.user.UserManager)2 alfio.model (alfio.model)2 AdditionalServiceItemStatus (alfio.model.AdditionalServiceItem.AdditionalServiceItemStatus)2 RESERVATION (alfio.model.Audit.EntityType.RESERVATION)2 TICKET (alfio.model.Audit.EntityType.TICKET)2 EventType (alfio.model.Audit.EventType)2 Type (alfio.model.BillingDocument.Type)2 VatStatus (alfio.model.PriceContainer.VatStatus)2