Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix #148: Improve VAT/Price management #149

Merged
merged 1 commit into from
Aug 5, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/main/java/alfio/controller/EventController.java
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ public String reserveTicket(@PathVariable("eventName") String eventName,
Date expiration = DateUtils.addMinutes(new Date(), ticketReservationManager.getReservationTimeout(event));

try {
String reservationId = ticketReservationManager.createTicketReservation(event.getId(),
String reservationId = ticketReservationManager.createTicketReservation(event,
selected.getLeft(), selected.getRight(), expiration,
SessionUtil.retrieveSpecialPriceSessionId(request.getRequest()),
SessionUtil.retrievePromotionCodeDiscount(request.getRequest()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,9 @@ public ResponseEntity<EventModification.AdditionalService> update(@PathVariable(
Validate.isTrue(additionalServiceId == additionalService.getId(), "wrong input");
return optionally(() -> eventRepository.findById(eventId))
.map(event -> {
int result = additionalServiceRepository.update(additionalServiceId, Optional.ofNullable(additionalService.getPrice()).map(MonetaryUtil::unitToCents).orElse(0), additionalService.isFixPrice(),
int result = additionalServiceRepository.update(additionalServiceId, additionalService.isFixPrice(),
additionalService.getOrdinal(), additionalService.getAvailableQuantity(), additionalService.getMaxQtyPerOrder(), additionalService.getInception().toZonedDateTime(event.getZoneId()),
additionalService.getExpiration().toZonedDateTime(event.getZoneId()), additionalService.getVat(), additionalService.getVatType());
additionalService.getExpiration().toZonedDateTime(event.getZoneId()), additionalService.getVat(), additionalService.getVatType(), Optional.ofNullable(additionalService.getPrice()).map(MonetaryUtil::unitToCents).orElse(0));
Validate.isTrue(result <= 1, "too many records updated");
Stream.concat(additionalService.getTitle().stream(), additionalService.getDescription().stream()).
forEach(t -> additionalServiceTextRepository.update(t.getId(), t.getLocale(), t.getType(), t.getValue()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import alfio.repository.SponsorScanRepository;
import alfio.repository.TicketCategoryDescriptionRepository;
import alfio.repository.TicketFieldRepository;
import alfio.util.MonetaryUtil;
import alfio.util.ValidationResult;
import alfio.util.Validator;
import com.opencsv.CSVReader;
Expand Down Expand Up @@ -267,8 +268,10 @@ public void downloadAllTicketsCSV(@PathVariable("eventName") String eventName, H
if(fields.contains("category")) {line.add(categoriesMap.get(t.getCategoryId()).getName());}
if(fields.contains("event")) {line.add(eventName);}
if(fields.contains("status")) {line.add(t.getStatus().toString());}
if(fields.contains("originalPrice")) {line.add(t.getOriginalPrice().toString());}
if(fields.contains("paidPrice")) {line.add(t.getPaidPrice().toString());}
if(fields.contains("originalPrice")) {line.add(MonetaryUtil.centsToUnit(t.getSrcPriceCts()).toString());}
if(fields.contains("paidPrice")) {line.add(MonetaryUtil.centsToUnit(t.getFinalPriceCts()).toString());}
if(fields.contains("discount")) {line.add(MonetaryUtil.centsToUnit(t.getDiscountCts()).toString());}
if(fields.contains("vat")) {line.add(MonetaryUtil.centsToUnit(t.getVatCts()).toString());}
if(fields.contains("reservationID")) {line.add(t.getTicketsReservationId());}
if(fields.contains("Name")) {line.add(t.getFullName());}
if(fields.contains("E-Mail")) {line.add(t.getEmail());}
Expand Down
32 changes: 26 additions & 6 deletions src/main/java/alfio/controller/api/support/PublicCategory.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,9 @@
package alfio.controller.api.support;

import alfio.model.Event;
import alfio.model.PriceContainer;
import alfio.model.TicketCategory;
import alfio.model.TicketCategoryDescription;
import alfio.util.EventUtil;
import alfio.util.MonetaryUtil;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.apache.commons.lang3.builder.CompareToBuilder;

Expand All @@ -29,12 +28,13 @@
import java.time.ZonedDateTime;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;

import static java.lang.Math.max;
import static java.lang.Math.min;

public class PublicCategory {
public static Comparator<PublicCategory> SORT_BY_DATE = (c1, c2) -> new CompareToBuilder()
public class PublicCategory implements PriceContainer {
static Comparator<PublicCategory> SORT_BY_DATE = (c1, c2) -> new CompareToBuilder()
.append(c1.getUtcInception(), c2.getUtcInception())
.append(c1.getUtcExpiration(), c2.getUtcExpiration())
.toComparison();
Expand Down Expand Up @@ -90,8 +90,28 @@ public ZonedDateTime getExpiration() {
return getUtcExpiration().withZoneSameInstant(Clock.systemUTC().getZone());
}

public BigDecimal getFinalPrice() {
return MonetaryUtil.centsToUnit(EventUtil.getFinalPriceInCents(event, category));
@Override
@JsonIgnore
public int getSrcPriceCts() {
return category.getSrcPriceCts();
}

@Override
@JsonIgnore
public String getCurrencyCode() {
return event.getCurrency();
}

@Override
@JsonIgnore
public Optional<BigDecimal> getOptionalVatPercentage() {
return Optional.ofNullable(event.getVat());
}

@Override
@JsonIgnore
public VatStatus getVatStatus() {
return event.getVatStatus();
}

public int getMaxTickets() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,18 @@

import alfio.model.AdditionalService;
import alfio.model.Event;
import alfio.model.PriceContainer;
import alfio.model.PromoCodeDiscount;
import alfio.util.EventUtil;
import lombok.experimental.Delegate;

import java.math.BigDecimal;
import java.time.Clock;
import java.time.ZonedDateTime;
import java.util.Optional;

import static alfio.util.MonetaryUtil.formatCents;

public class SaleableAdditionalService {
public class SaleableAdditionalService implements PriceContainer {
private final Event event;
@Delegate(excludes = Exclusions.class)
@Delegate(excludes = {Exclusions.class, PriceContainer.class})
private final AdditionalService additionalService;
private final String title;
private final String description;
Expand Down Expand Up @@ -66,7 +64,7 @@ private static ZonedDateTime now() {
}

public boolean getFree() {
return isFixPrice() && getPriceInCents() == 0;
return isFixPrice() && getFinalPrice().compareTo(BigDecimal.ZERO) == 0;
}

public boolean getSaleable() {
Expand All @@ -81,12 +79,47 @@ public ZonedDateTime getZonedExpiration() {
return getExpiration(event.getZoneId());
}

public String getFinalPrice() {
return formatCents(getFinalPriceInCents());
@Override
public int getSrcPriceCts() {
return Optional.ofNullable(additionalService.getSrcPriceCts()).orElse(0);
}

@Override
public Optional<PromoCodeDiscount> getDiscount() {
return Optional.ofNullable(promoCodeDiscount);
}

@Override
public String getCurrencyCode() {
return event.getCurrency();
}

private int getFinalPriceInCents() {
return EventUtil.getFinalPriceInCents(event, additionalService);
@Override
public Optional<BigDecimal> getOptionalVatPercentage() {
if(getVatStatus() != VatStatus.NONE) {
return Optional.ofNullable(event.getVat()); //FIXME implement VAT override
}
return Optional.of(BigDecimal.ZERO);
}

@Override
public VatStatus getVatStatus() {
switch (getVatType()) {
case INHERITED:
return event.getVatStatus();
case NONE:
return VatStatus.NONE;
case CUSTOM_EXCLUDED:
return VatStatus.NOT_INCLUDED;
case CUSTOM_INCLUDED:
return VatStatus.INCLUDED;
default:
return VatStatus.NOT_INCLUDED;
}
}

public String getFormattedFinalPrice() {
return getFinalPrice().add(getAppliedDiscount()).toPlainString();
}

public boolean getSupportsDiscount() {
Expand All @@ -98,7 +131,7 @@ public boolean getUserDefinedPrice() {
}

public String getDiscountedPrice() {
return Optional.ofNullable(promoCodeDiscount).map(d -> formatCents(DecoratorUtil.calcDiscount(d, getFinalPriceInCents()))).orElseGet(this::getFinalPrice);
return getFinalPrice().toPlainString();
}

public boolean getVatIncluded() {
Expand All @@ -109,7 +142,7 @@ public boolean getVatIncluded() {
case CUSTOM_EXCLUDED:
return false;
case CUSTOM_INCLUDED:
return false;
return true;
default:
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,18 @@
package alfio.controller.decorator;

import alfio.model.Event;
import alfio.model.PriceContainer;
import alfio.model.PromoCodeDiscount;
import alfio.model.TicketCategory;
import alfio.util.EventUtil;
import lombok.experimental.Delegate;

import java.math.BigDecimal;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Optional;

import static alfio.util.MonetaryUtil.formatCents;

public class SaleableTicketCategory {
public class SaleableTicketCategory implements PriceContainer {

@Delegate
private final TicketCategory ticketCategory;
Expand Down Expand Up @@ -99,12 +98,28 @@ public ZonedDateTime getZonedInception() {
return getInception(zoneId);
}

public String getFinalPrice() {
return formatCents(getFinalPriceInCents());
@Override
public Optional<PromoCodeDiscount> getDiscount() {
return Optional.ofNullable(promoCodeDiscount);
}

@Override
public String getCurrencyCode() {
return event.getCurrency();
}

@Override
public Optional<BigDecimal> getOptionalVatPercentage() {
return Optional.ofNullable(event.getVat());
}

private int getFinalPriceInCents() {
return EventUtil.getFinalPriceInCents(event, ticketCategory);
@Override
public VatStatus getVatStatus() {
return event.getVatStatus();
}

public String getFormattedFinalPrice() {
return getFinalPriceToDisplay(getFinalPrice().add(getAppliedDiscount()), getVAT(), getVatStatus()).toString();
}

public int[] getAmountOfTickets() {
Expand All @@ -116,7 +131,7 @@ public int getAvailableTickets() {
}

public String getDiscountedPrice() {
return Optional.ofNullable(promoCodeDiscount).map(d -> formatCents(DecoratorUtil.calcDiscount(d, getFinalPriceInCents()))).orElseGet(this::getFinalPrice);
return getFinalPriceToDisplay(getFinalPrice(), getVAT(), getVatStatus()).toString();
}

public boolean getSupportsDiscount() {
Expand All @@ -127,5 +142,12 @@ public PromoCodeDiscount getPromoCodeDiscount() {
return promoCodeDiscount;
}

private static BigDecimal getFinalPriceToDisplay(BigDecimal price, BigDecimal vat, VatStatus vatStatus) {
if(vatStatus == VatStatus.NOT_INCLUDED) {
return price.subtract(vat);
}
return price;
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public boolean hasBeenPaid() {
}

public boolean isFree() {
return getPaidPriceInCents() == 0;
return getFinalPriceCts() == 0;
}

public boolean getCancellationEnabled() {
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/alfio/manager/CheckInManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ private TicketAndCheckInResult extractStatus(Optional<Event> maybeEvent, Optiona
final TicketStatus ticketStatus = ticket.getStatus();

if (ticketStatus == TicketStatus.TO_BE_PAID) {
return new TicketAndCheckInResult(ticket, new OnSitePaymentResult(MUST_PAY, "Must pay for ticket", MonetaryUtil.addVAT(ticket.getOriginalPrice(), event.getVat()), event.getCurrency()));
return new TicketAndCheckInResult(ticket, new OnSitePaymentResult(MUST_PAY, "Must pay for ticket", MonetaryUtil.addVAT(MonetaryUtil.centsToUnit(ticket.getFinalPriceCts()), event.getVat()), event.getCurrency()));
}

if (ticketStatus == TicketStatus.CHECKED_IN) {
Expand Down
Loading