use of alfio.model.decorator.AdditionalServiceItemPriceContainer 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);
}
use of alfio.model.decorator.AdditionalServiceItemPriceContainer 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;
}
use of alfio.model.decorator.AdditionalServiceItemPriceContainer in project alf.io by alfio-event.
the class TicketReservationManager method extractSummary.
List<SummaryRow> extractSummary(VatStatus reservationVatStatus, PurchaseContext purchaseContext, Locale locale, PromoCodeDiscount promoCodeDiscount, TotalPrice reservationCost, List<Ticket> ticketsToInclude, Stream<Pair<AdditionalService, List<AdditionalServiceItem>>> additionalServicesToInclude, List<Subscription> subscriptionsToInclude) {
log.trace("extract summary subscriptionsToInclude {}", subscriptionsToInclude);
List<SummaryRow> summary = new ArrayList<>();
var currencyCode = reservationCost.getCurrencyCode();
List<TicketPriceContainer> tickets = ticketsToInclude.stream().map(t -> TicketPriceContainer.from(t, reservationVatStatus, purchaseContext.getVat(), purchaseContext.getVatStatus(), promoCodeDiscount)).collect(toList());
purchaseContext.event().ifPresent(event -> {
boolean multipleTaxRates = tickets.stream().map(TicketPriceContainer::getVatStatus).collect(Collectors.toSet()).size() > 1;
var ticketsByCategory = tickets.stream().collect(Collectors.groupingBy(TicketPriceContainer::getCategoryId));
List<Entry<Integer, List<TicketPriceContainer>>> sorted;
if (multipleTaxRates) {
sorted = ticketsByCategory.entrySet().stream().sorted(Comparator.comparing((Entry<Integer, List<TicketPriceContainer>> e) -> e.getValue().get(0).getVatStatus()).reversed()).collect(Collectors.toList());
} else {
sorted = new ArrayList<>(ticketsByCategory.entrySet());
}
Map<Integer, TicketCategory> categoriesById;
if (ticketsByCategory.isEmpty()) {
categoriesById = Map.of();
} else {
categoriesById = ticketCategoryRepository.getByIdsAndActive(ticketsByCategory.keySet(), event.getId()).stream().collect(Collectors.toMap(TicketCategory::getId, Function.identity()));
}
for (var categoryWithTickets : sorted) {
var categoryTickets = categoryWithTickets.getValue();
final int subTotal = categoryTickets.stream().mapToInt(TicketPriceContainer::getSummarySrcPriceCts).sum();
final int subTotalBeforeVat = SummaryPriceContainer.getSummaryPriceBeforeVatCts(categoryTickets);
var firstTicket = categoryTickets.get(0);
final int ticketPriceCts = firstTicket.getSummarySrcPriceCts();
final int priceBeforeVat = SummaryPriceContainer.getSummaryPriceBeforeVatCts(singletonList(firstTicket));
String categoryName = categoriesById.get(categoryWithTickets.getKey()).getName();
summary.add(new SummaryRow(categoryName, formatCents(ticketPriceCts, currencyCode), formatCents(priceBeforeVat, currencyCode), categoryTickets.size(), formatCents(subTotal, currencyCode), formatCents(subTotalBeforeVat, currencyCode), subTotal, SummaryType.TICKET, null));
var ticketVatStatus = firstTicket.getVatStatus();
if (VatStatus.isVatExempt(ticketVatStatus) && ticketVatStatus != reservationVatStatus) {
summary.add(new SummaryRow(null, "", "", 0, formatCents(0, currencyCode, true), formatCents(0, currencyCode, true), 0, SummaryType.TAX_DETAIL, "0"));
}
}
});
summary.addAll(additionalServicesToInclude.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(purchaseContext, null).apply(entry).collect(toList());
AdditionalServiceItemPriceContainer first = prices.get(0);
final int subtotal = prices.stream().mapToInt(AdditionalServiceItemPriceContainer::getSrcPriceCts).sum();
final int subtotalBeforeVat = SummaryPriceContainer.getSummaryPriceBeforeVatCts(prices);
return new SummaryRow(title.getValue(), formatCents(first.getSrcPriceCts(), currencyCode), formatCents(SummaryPriceContainer.getSummaryPriceBeforeVatCts(singletonList(first)), currencyCode), prices.size(), formatCents(subtotal, currencyCode), formatCents(subtotalBeforeVat, currencyCode), subtotal, SummaryType.ADDITIONAL_SERVICE, null);
}).collect(toList()));
Optional.ofNullable(promoCodeDiscount).ifPresent(promo -> {
String formattedSingleAmount = "-" + (DiscountType.isFixedAmount(promo.getDiscountType()) ? formatCents(promo.getDiscountAmount(), currencyCode) : (promo.getDiscountAmount() + "%"));
summary.add(new SummaryRow(formatPromoCode(promo, ticketsToInclude, locale, purchaseContext), formattedSingleAmount, formattedSingleAmount, reservationCost.getDiscountAppliedCount(), formatCents(reservationCost.getDiscount(), currencyCode), formatCents(reservationCost.getDiscount(), currencyCode), reservationCost.getDiscount(), promo.isDynamic() ? SummaryType.DYNAMIC_DISCOUNT : SummaryType.PROMOTION_CODE, null));
});
//
if (purchaseContext instanceof SubscriptionDescriptor) {
if (!subscriptionsToInclude.isEmpty()) {
var subscription = subscriptionsToInclude.get(0);
var priceContainer = new SubscriptionPriceContainer(subscription, promoCodeDiscount, (SubscriptionDescriptor) purchaseContext);
var priceBeforeVat = formatUnit(priceContainer.getNetPrice(), currencyCode);
summary.add(new SummaryRow(purchaseContext.getTitle().get(locale.getLanguage()), formatCents(priceContainer.getSummarySrcPriceCts(), currencyCode), priceBeforeVat, subscriptionsToInclude.size(), formatCents(priceContainer.getSummarySrcPriceCts() * subscriptionsToInclude.size(), currencyCode), formatUnit(priceContainer.getNetPrice().multiply(new BigDecimal(subscriptionsToInclude.size())), currencyCode), priceContainer.getSummarySrcPriceCts(), SummaryType.SUBSCRIPTION, null));
}
} else if (CollectionUtils.isNotEmpty(subscriptionsToInclude)) {
log.trace("subscriptions to include is not empty");
var subscription = subscriptionsToInclude.get(0);
subscriptionRepository.findOne(subscription.getSubscriptionDescriptorId(), subscription.getOrganizationId()).ifPresent(subscriptionDescriptor -> {
log.trace("found subscriptionDescriptor with ID {}", subscriptionDescriptor.getId());
// find tickets with subscription applied
var ticketsSubscription = tickets.stream().filter(t -> Objects.equals(subscription.getId(), t.getSubscriptionId())).collect(toList());
final int ticketPriceCts = ticketsSubscription.stream().mapToInt(TicketPriceContainer::getSummarySrcPriceCts).sum();
final int priceBeforeVat = SummaryPriceContainer.getSummaryPriceBeforeVatCts(ticketsSubscription);
summary.add(new SummaryRow(subscriptionDescriptor.getLocalizedTitle(locale), "-" + formatCents(ticketPriceCts, currencyCode), "-" + formatCents(priceBeforeVat, currencyCode), ticketsSubscription.size(), "-" + formatCents(ticketPriceCts, currencyCode), "-" + formatCents(priceBeforeVat, currencyCode), ticketPriceCts, SummaryType.APPLIED_SUBSCRIPTION, null));
});
}
//
return summary;
}
Aggregations