Skip to content

Commit

Permalink
fix #866 Cannot delete deferred payments
Browse files Browse the repository at this point in the history
(cherry picked from commit 8c43c5b)
  • Loading branch information
cbellone committed Feb 9, 2020
1 parent 0b04923 commit 24da7b3
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 4 deletions.
3 changes: 2 additions & 1 deletion src/main/java/alfio/manager/TicketReservationManager.java
Expand Up @@ -795,7 +795,8 @@ private Locale findReservationLanguage(String reservationId) {

public void deleteOfflinePayment(Event event, String reservationId, boolean expired, boolean credit, String username) {
TicketReservation reservation = findById(reservationId).orElseThrow(IllegalArgumentException::new);
Validate.isTrue(reservation.getStatus() == OFFLINE_PAYMENT, "Invalid reservation status");
Validate.isTrue(reservation.getStatus() == OFFLINE_PAYMENT || reservation.getStatus() == DEFERRED_OFFLINE_PAYMENT, "Invalid reservation status");
Validate.isTrue(!(credit && reservation.getStatus() == DEFERRED_OFFLINE_PAYMENT), "Cannot credit deferred payment");
if(credit) {
creditReservation(reservation, username);
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/alfio/model/system/ConfigurationKeys.java
Expand Up @@ -111,7 +111,7 @@ public enum ConfigurationKeys {
SMTP_PROPERTIES("SMTP Properties", false, SettingCategory.MAIL, ComponentType.TEXTAREA, false, EnumSet.of(SYSTEM)),

BANK_TRANSFER_ENABLED("Bank transfer enabled", false, SettingCategory.PAYMENT_OFFLINE, ComponentType.BOOLEAN, false, EnumSet.of(SYSTEM, ORGANIZATION)),
DEFERRED_BANK_TRANSFER_ENABLED("Handle Bank Transfer payment externally (default false)", false, SettingCategory.PAYMENT_OFFLINE, ComponentType.BOOLEAN, false, EnumSet.of(SYSTEM, ORGANIZATION, EVENT)),
DEFERRED_BANK_TRANSFER_ENABLED("Send payment instructions manually (default false)", false, SettingCategory.PAYMENT_OFFLINE, ComponentType.BOOLEAN, false, EnumSet.of(SYSTEM, ORGANIZATION, EVENT)),
OFFLINE_PAYMENT_DAYS("Maximum number of days allowed to pay an offline ticket", false, SettingCategory.PAYMENT_OFFLINE, ComponentType.TEXT, false, EnumSet.of(SYSTEM, ORGANIZATION, EVENT)),
OFFLINE_REMINDER_HOURS("How many hours before expiration should be sent a reminder e-mail for offline payments?", false, SettingCategory.PAYMENT_OFFLINE, ComponentType.TEXT, false, EnumSet.of(SYSTEM, ORGANIZATION, EVENT)),

Expand Down
Expand Up @@ -50,7 +50,7 @@ <h2>Manual confirmation</h2>
</td>
<td>
<button class="btn btn-success btn-xs" data-ng-disabled="loading" data-ng-click="registerPayment(eventName, pending.ticketReservation.id)"><i class="fa fa-check"></i> confirm</button>
<button data-ng-disabled="loading" ng-if="pending.ticketReservation.invoiceNumber" data-ng-click="deletePayment(eventName, pending.ticketReservation.id, true)" class="btn btn-warning btn-xs" uib-tooltip="Issue a Credit Note for this Reservation"><i class="fa fa-undo"></i> credit</button>
<button data-ng-disabled="loading" ng-if="pending.ticketReservation.status === 'OFFLINE_PAYMENT' && pending.ticketReservation.invoiceNumber" data-ng-click="deletePayment(eventName, pending.ticketReservation.id, true)" class="btn btn-warning btn-xs" uib-tooltip="Issue a Credit Note for this Reservation"><i class="fa fa-undo"></i> credit</button>
<button data-ng-disabled="loading" data-ng-click="deletePayment(eventName, pending.ticketReservation.id, false)" class="btn btn-danger btn-xs" uib-tooltip="Cancel the payment and delete the Reservation"><i class="fa fa-trash-o"></i> delete</button>
</td>
</tr>
Expand Down
Expand Up @@ -56,6 +56,7 @@
import ch.digitalfondue.jfiveparse.Selector;
import com.fasterxml.jackson.core.type.TypeReference;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.QRCodeReader;
Expand Down Expand Up @@ -935,7 +936,7 @@ public void reservationFlowTest() throws Exception {

var fullTicketInfo = ticketRepository.findByUUID(ticket.getUuid());
var qrCodeReader = new QRCodeReader();
var qrCodeRead = qrCodeReader.decode(new BinaryBitmap(new HybridBinarizer(new BufferedImageLuminanceSource(ImageIO.read(new ByteArrayInputStream(ticketQRCodeResp.getContentAsByteArray()))))));
var qrCodeRead = qrCodeReader.decode(new BinaryBitmap(new HybridBinarizer(new BufferedImageLuminanceSource(ImageIO.read(new ByteArrayInputStream(ticketQRCodeResp.getContentAsByteArray()))))), Map.of(DecodeHintType.PURE_BARCODE, Boolean.TRUE));
assertEquals(fullTicketInfo.ticketCode(event.getPrivateKey()), qrCodeRead.getText());

//can only be done for free tickets
Expand Down
Expand Up @@ -54,6 +54,7 @@
import java.util.stream.Collectors;

import static alfio.model.system.ConfigurationKeys.AUTOMATIC_REMOVAL_EXPIRED_OFFLINE_PAYMENT;
import static alfio.model.system.ConfigurationKeys.DEFERRED_BANK_TRANSFER_ENABLED;
import static alfio.test.util.IntegrationTestUtil.AVAILABLE_SEATS;
import static alfio.test.util.IntegrationTestUtil.initEvent;
import static org.junit.Assert.*;
Expand Down Expand Up @@ -227,6 +228,63 @@ public void testTicketSelection() {
Assert.assertFalse(ticketReservationManager.findById(reservationId2).isPresent());
}

@Test
public void deferredOfflinePayment() {
// enable deferred payment
configurationRepository.insert(DEFERRED_BANK_TRANSFER_ENABLED.name(), "true", "");

List<TicketCategoryModification> categories = List.of(
new TicketCategoryModification(null, "default", AVAILABLE_SEATS,
new DateTimeModification(LocalDate.now(), LocalTime.now()),
new DateTimeModification(LocalDate.now(), LocalTime.now()),
DESCRIPTION, BigDecimal.TEN, false, "", false, null, null, null, null, null, 0, null, null));
Pair<Event, String> eventAndUsername = initEvent(categories, organizationRepository, userManager, eventManager, eventRepository);
Event event = eventAndUsername.getKey();

TicketCategory unbounded = ticketCategoryRepository.findAllTicketCategories(event.getId()).get(0);


TicketReservationModification trForDeferred = new TicketReservationModification();
trForDeferred.setAmount(1);
trForDeferred.setTicketCategoryId(unbounded.getId());
TicketReservationWithOptionalCodeModification modForDeferred = new TicketReservationWithOptionalCodeModification(trForDeferred, Optional.empty());
String reservationId = ticketReservationManager.createTicketReservation(event, Collections.singletonList(modForDeferred), Collections.emptyList(), DateUtils.addDays(new Date(), 1), Optional.empty(), Locale.ENGLISH, false);

TotalPrice totalPrice = ticketReservationManager.totalReservationCostWithVAT(reservationId);

PaymentSpecification specificationDeferred = new PaymentSpecification(reservationId, null, totalPrice.getPriceWithVAT(),
event, "email@example.com", new CustomerName("full name", "full", "name", event.mustUseFirstAndLastName()),
"billing address", null, Locale.ENGLISH, true, false, null, "IT", "123456", PriceContainer.VatStatus.INCLUDED, true, false);

PaymentResult confirm = ticketReservationManager.performPayment(specificationDeferred, totalPrice, PaymentProxy.OFFLINE, PaymentMethod.BANK_TRANSFER);
assertTrue(confirm.isSuccessful());

var status = ticketReservationRepository.findOptionalStatusAndValidationById(reservationId).orElseThrow().getStatus();
assertEquals(TicketReservation.TicketReservationStatus.DEFERRED_OFFLINE_PAYMENT, status);

// confirm deferred payment
ticketReservationManager.confirmOfflinePayment(event, reservationId, null);

reservationId = ticketReservationManager.createTicketReservation(event, Collections.singletonList(modForDeferred), Collections.emptyList(), DateUtils.addDays(new Date(), 1), Optional.empty(), Locale.ENGLISH, false);

specificationDeferred = new PaymentSpecification(reservationId, null, totalPrice.getPriceWithVAT(),
event, "email@example.com", new CustomerName("full name", "full", "name", event.mustUseFirstAndLastName()),
"billing address", null, Locale.ENGLISH, true, false, null, "IT", "123456", PriceContainer.VatStatus.INCLUDED, true, false);

confirm = ticketReservationManager.performPayment(specificationDeferred, totalPrice, PaymentProxy.OFFLINE, PaymentMethod.BANK_TRANSFER);
assertTrue(confirm.isSuccessful());

try {
ticketReservationManager.deleteOfflinePayment(event, reservationId, false, true, null);
fail("Credit should not be enabled for deferred payments");
} catch (IllegalArgumentException ex) {
// do nothing, because this is the expected behavior
}

ticketReservationManager.deleteOfflinePayment(event, reservationId, false, false, null);
Assert.assertFalse(ticketReservationManager.findById(reservationId).isPresent());
}

@Test
public void testTicketWithDiscount() {
List<TicketCategoryModification> categories = Collections.singletonList(
Expand Down

0 comments on commit 24da7b3

Please sign in to comment.