Skip to content

Commit

Permalink
#23 - add warning in ticket PDF/e-mail, GUI improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
cbellone committed Dec 21, 2014
1 parent 0dfda34 commit 78c1736
Show file tree
Hide file tree
Showing 21 changed files with 140 additions and 48 deletions.
2 changes: 1 addition & 1 deletion src/main/java/alfio/controller/ReservationController.java
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ public String handleReservation(@PathVariable("eventName") String eventName,
bindingResult.reject(ErrorsCode.STEP_2_ORDER_EXPIRED);
}
final TicketReservationManager.TotalPrice reservationCost = ticketReservationManager.totalReservationCostWithVAT(reservationId);
paymentForm.validate(bindingResult, reservationCost, event.getMultiplePaymentMethods());
paymentForm.validate(bindingResult, reservationCost, event.getAllowedPaymentProxies());
if (bindingResult.hasErrors()) {
SessionUtil.addToFlash(bindingResult, redirectAttributes);
return redirectReservation(ticketReservation, eventName, reservationId);
Expand Down
7 changes: 5 additions & 2 deletions src/main/java/alfio/controller/TicketController.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import alfio.model.Ticket;
import alfio.model.TicketCategory;
import alfio.model.TicketReservation;
import alfio.model.transaction.PaymentProxy;
import alfio.model.user.Organization;
import alfio.repository.TicketCategoryRepository;
import alfio.repository.user.OrganizationRepository;
Expand Down Expand Up @@ -84,13 +85,15 @@ public String showTicket(@PathVariable("eventName") String eventName, @PathVaria

TicketCategory ticketCategory = ticketCategoryRepository.getById(data.getRight().getCategoryId(), data.getLeft().getId());
Organization organization = organizationRepository.getById(data.getLeft().getOrganizationId());


TicketReservation reservation = data.getMiddle();
model.addAttribute("ticket", data.getRight())//
.addAttribute("reservation", data.getMiddle())//
.addAttribute("reservation", reservation)//
.addAttribute("event", data.getLeft())//
.addAttribute("ticketCategory", ticketCategory)//
.addAttribute("organization", organization)//
.addAttribute("ticketEmailSent", ticketEmailSent)
.addAttribute("alreadyPaid", Optional.ofNullable(reservation.getPaymentMethod()).orElse(PaymentProxy.STRIPE) == PaymentProxy.STRIPE)
.addAttribute("pageTitle", "show-ticket.header.title");

return "/event/show-ticket";
Expand Down
6 changes: 4 additions & 2 deletions src/main/java/alfio/controller/form/PaymentForm.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.springframework.validation.BindingResult;
import org.springframework.validation.ValidationUtils;

import java.util.List;
import java.util.Objects;
import java.util.Optional;

Expand All @@ -46,11 +47,12 @@ private static void rejectIfOverLength(BindingResult bindingResult, String field
}
}

public void validate(BindingResult bindingResult, TicketReservationManager.TotalPrice reservationCost, boolean multiplePaymentMethods) {
public void validate(BindingResult bindingResult, TicketReservationManager.TotalPrice reservationCost, List<PaymentProxy> allowedPaymentMethods) {

Optional<PaymentProxy> paymentProxyOptional = Optional.ofNullable(paymentMethod);
PaymentProxy paymentProxy = paymentProxyOptional.orElse(PaymentProxy.STRIPE);
PaymentProxy paymentProxy = paymentProxyOptional.filter(allowedPaymentMethods::contains).orElse(PaymentProxy.STRIPE);
boolean priceGreaterThanZero = reservationCost.getPriceWithVAT() > 0;
boolean multiplePaymentMethods = allowedPaymentMethods.size() > 1;
if (multiplePaymentMethods && priceGreaterThanZero && !paymentProxyOptional.isPresent()) {
bindingResult.reject(ErrorsCode.STEP_2_MISSING_PAYMENT_METHOD);
} else if (priceGreaterThanZero && (paymentProxy == PaymentProxy.STRIPE && StringUtils.isBlank(stripeToken))) {
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/alfio/controller/support/TemplateProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import alfio.model.Ticket;
import alfio.model.TicketCategory;
import alfio.model.TicketReservation;
import alfio.model.transaction.PaymentProxy;
import alfio.model.user.Organization;
import alfio.repository.user.OrganizationRepository;
import com.google.zxing.WriterException;
Expand All @@ -33,6 +34,7 @@
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

import static alfio.util.TicketUtil.createQRCode;

Expand Down Expand Up @@ -93,6 +95,7 @@ public static PDFTemplateBuilder buildPDFTicket(HttpServletRequest request,
model.put("event", event);
model.put("organization", organization);
model.put("qrCodeDataUri", "data:image/png;base64," + Base64.getEncoder().encodeToString(createQRCode(qrCodeText)));
model.put("hasBeenPaid", Optional.ofNullable(ticketReservation.getPaymentMethod()).orElse(PaymentProxy.STRIPE) == PaymentProxy.STRIPE);

String page = templateManager.render("/alfio/templates/ticket.ms", model, request);

Expand Down
14 changes: 10 additions & 4 deletions src/main/java/alfio/manager/TicketReservationManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ public PaymentResult confirm(String gatewayToken, Event event, String reservatio
}

private void transitionToInPayment(String reservationId, String email, String fullName, String billingAddress) {
int updatedReservation = ticketReservationRepository.updateTicketReservation(reservationId, IN_PAYMENT.toString(), email, fullName, billingAddress, null);
int updatedReservation = ticketReservationRepository.updateTicketReservation(reservationId, IN_PAYMENT.toString(), email, fullName, billingAddress, null, PaymentProxy.STRIPE.toString());
Validate.isTrue(updatedReservation == 1, "expected exactly one updated reservation, got "+updatedReservation);
}

Expand Down Expand Up @@ -278,7 +278,7 @@ private void completeReservation(String reservationId, String email, String full
Validate.isTrue(updatedTickets > 0, "no tickets have been updated");
specialPriceRepository.updateStatusForReservation(Collections.singletonList(reservationId), Status.TAKEN.toString());
ZonedDateTime timestamp = ZonedDateTime.now(ZoneId.of("UTC"));
int updatedReservation = ticketReservationRepository.updateTicketReservation(reservationId, TicketReservationStatus.COMPLETE.toString(), email, fullName, billingAddress, timestamp);
int updatedReservation = ticketReservationRepository.updateTicketReservation(reservationId, TicketReservationStatus.COMPLETE.toString(), email, fullName, billingAddress, timestamp, paymentProxy.toString());
Validate.isTrue(updatedReservation == 1, "expected exactly one updated reservation, got " + updatedReservation);
}
//cleanup unused special price codes...
Expand Down Expand Up @@ -352,9 +352,15 @@ private int totalVat(List<Ticket> tickets, BigDecimal vat) {
}

public OrderSummary orderSummaryForReservationId(String reservationId, Event event) {
TotalPrice reservationCost = totalReservationCostWithVAT(reservationId);
TicketReservation reservation = ticketReservationRepository.findReservationById(reservationId);
TotalPrice reservationCost = totalReservationCostWithVAT(reservationId);
List<SummaryRow> summary = extractSummary(reservationId, event);
return new OrderSummary(reservationCost, summary, reservationCost.getPriceWithVAT() == 0, formatCents(reservationCost.getPriceWithVAT()), formatCents(reservationCost.getVAT()));
boolean free = reservationCost.getPriceWithVAT() == 0;
return new OrderSummary(reservationCost,
summary, free,
formatCents(reservationCost.getPriceWithVAT()), formatCents(reservationCost.getVAT()),
reservation.getStatus() == TicketReservationStatus.OFFLINE_PAYMENT,
reservation.getPaymentMethod() == PaymentProxy.ON_SITE);
}

private List<SummaryRow> extractSummary(String reservationId, Event event) {
Expand Down
14 changes: 14 additions & 0 deletions src/main/java/alfio/manager/support/OrderSummary.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,23 @@ public class OrderSummary {
private final boolean free;
private final String totalPrice;
private final String totalVAT;
private final boolean waitingForPayment;
private final boolean cashPayment;

/* lol jmustache */
public boolean getFree() {
return free;
}

public boolean getWaitingForPayment() {
return waitingForPayment;
}

public boolean getCashPayment() {
return cashPayment;
}

public boolean getNotYetPaid() {
return waitingForPayment || cashPayment;
}
}
4 changes: 4 additions & 0 deletions src/main/java/alfio/model/Event.java
Original file line number Diff line number Diff line change
Expand Up @@ -173,4 +173,8 @@ public PaymentProxy getFirstPaymentMethod() {
return allowedPaymentProxies.get(0);//it is guaranteed that this list is not empty.
}

public boolean supportsPaymentMethod(PaymentProxy paymentProxy) {
return allowedPaymentProxies.contains(paymentProxy);
}

}
18 changes: 11 additions & 7 deletions src/main/java/alfio/model/TicketReservation.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package alfio.model;

import alfio.datamapper.ConstructorAnnotationRowMapper.Column;
import alfio.model.transaction.PaymentProxy;
import lombok.Getter;

import java.time.ZonedDateTime;
Expand All @@ -36,22 +37,25 @@ public enum TicketReservationStatus {
private final String email;
private final String billingAddress;
private final ZonedDateTime confirmationTimestamp;
private final PaymentProxy paymentMethod;

public TicketReservation(@Column("id") String id,
@Column("validity") Date validity,
@Column("status") TicketReservationStatus status,
@Column("full_name") String fullName,
@Column("email_address") String email,
@Column("billing_address") String billingAddress,
@Column("confirmation_ts") ZonedDateTime confirmationTimestamp) {
@Column("validity") Date validity,
@Column("status") TicketReservationStatus status,
@Column("full_name") String fullName,
@Column("email_address") String email,
@Column("billing_address") String billingAddress,
@Column("confirmation_ts") ZonedDateTime confirmationTimestamp,
@Column("payment_method") PaymentProxy paymentMethod) {
this.id = id;
this.validity = validity;
this.status = status;
this.fullName = fullName;
this.email = email;
this.billingAddress = billingAddress;
this.confirmationTimestamp = confirmationTimestamp;
}
this.paymentMethod = paymentMethod;
}

public boolean isStuck() {
return status == TicketReservationStatus.STUCK;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ public interface TicketReservationRepository {
@Query("insert into tickets_reservation(id, validity, status) values (:id, :validity, 'PENDING')")
int createNewReservation(@Bind("id") String id, @Bind("validity") Date validity);

@Query("update tickets_reservation set status = :status, full_name = :fullName, email_address = :email, billing_address = :billingAddress, confirmation_ts = :timestamp where id = :reservationId")
@Query("update tickets_reservation set status = :status, full_name = :fullName, email_address = :email, billing_address = :billingAddress, confirmation_ts = :timestamp, payment_method = :paymentMethod where id = :reservationId")
int updateTicketReservation(@Bind("reservationId") String reservationId, @Bind("status") String status,
@Bind("email") String email, @Bind("fullName") String fullName,
@Bind("billingAddress") String billingAddress, @Bind("timestamp") ZonedDateTime timestamp);
@Bind("billingAddress") String billingAddress, @Bind("timestamp") ZonedDateTime timestamp, @Bind("paymentMethod") String paymentMethod);

@Query("update tickets_reservation set validity = :validity, status = 'OFFLINE_PAYMENT', full_name = :fullName, email_address = :email, billing_address = :billingAddress where id = :reservationId")
@Query("update tickets_reservation set validity = :validity, status = 'OFFLINE_PAYMENT', payment_method = 'OFFLINE', full_name = :fullName, email_address = :email, billing_address = :billingAddress where id = :reservationId")
int postponePayment(@Bind("reservationId") String reservationId, @Bind("validity") Date validity, @Bind("email") String email, @Bind("fullName") String fullName,
@Bind("billingAddress") String billingAddress);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
--
-- This file is part of alf.io.
--
-- alf.io is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- alf.io is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with alf.io. If not, see <http://www.gnu.org/licenses/>.
--

alter table tickets_reservation add column payment_method VARCHAR(255);
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
INSERT INTO organization(name, description, email) VALUES ('demo', 'demo organization', '[email protected]');

insert into event(description, short_name, website_url, website_t_c_url, location, latitude, longitude, start_ts, end_ts, regular_price_cts, currency, available_seats, vat_included, vat, allowed_payment_proxies, private_key, org_id, time_zone, image_url)
values('event desc', 'eventname', 'http://localhost:8080', 'http://localhost:8080', 'demo location', '0', '0', '2015-01-10 05:00:00' , '2015-01-11 04:59:00' , 1000, 'CHF', 440, 'true', 8, 'STRIPE', 'alfio-uberall', 0, 'America/New_York', 'http://localhost:8080/resources/images/sample-logo.png');
values('event desc', 'eventname', 'http://localhost:8080', 'http://localhost:8080', 'demo location', '0', '0', '2015-01-10 05:00:00' , '2015-01-11 04:59:00' , 1000, 'CHF', 440, 'true', 8, 'STRIPE', 'alfio-uberall', 0, 'America/New_York', 'http://localhost:8080/resources/images/sample-logo.png');

insert into ticket_category(inception, expiration, name, description, max_tickets, price_cts, access_restricted, tc_status, event_id) values
('2014-01-10 00:00:00', '2015-10-10 00:00:00', 'Normal', 'Very good category', 2, 0, false, 'ACTIVE', 0),
Expand All @@ -29,27 +29,27 @@ insert into ticket_category(inception, expiration, name, description, max_ticket

insert into tickets_reservation (id, validity, status, full_name, email_address, billing_address) values('abcdefghi', '2014-01-10 00:00:00', 'IN_PAYMENT', 'ciccio', '[email protected]', null);
insert into ticket (uuid, creation, category_id, event_id, status, original_price_cts, paid_price_cts, tickets_reservation_id)
values
-- free tickets
values

-- free tickets
('abcdefghilmn', '2014-01-10 00:00:00', 0, 0, 'FREE', 0, 0, null),
('abcdefghilmo', '2014-01-10 00:00:00', 0, 0, 'FREE', 0, 0, null),
-- paid ticket

-- paid ticket
('abcdefghilmn41', '2014-01-10 00:00:00', 1, 0, 'FREE', 463, 463, null),
('abcdefghilmn42', '2014-01-10 00:00:00', 1, 0, 'FREE', 463, 463, null),
('abcdefghilmn43', '2014-01-10 00:00:00', 1, 0, 'FREE', 463, 463, null),
('abcdefghilmo44', '2014-01-10 00:00:00', 1, 0, 'FREE', 463, 463, null),
-- stuck reservation
-- stuck reservation
('abcdefghilmo55', '2014-01-10 00:00:00', 1, 0, 'PENDING', 463, 463, 'abcdefghi'),

-- still not in sale
-- still not in sale
('abcdefghilmo45', '2014-01-10 00:00:00', 2, 0, 'FREE', 463, 463, null),
--expired

--expired
('abcdefghilmo46', '2014-01-10 00:00:00', 3, 0, 'FREE', 463, 463, null),
--restricted

--restricted
('abcdefghilmo47', '2014-01-10 00:00:00', 4, 0, 'FREE', 463, 463, null),
('abcdefghilmo48', '2014-01-10 00:00:00', 4, 0, 'FREE', 463, 463, null),
('abcdefghilmo49', '2014-01-10 00:00:00', 4, 0, 'FREE', 463, 463, null),
Expand All @@ -60,8 +60,8 @@ insert into special_price (code, price_cts, ticket_category_id, status) values
('424243', 463, 4, 'FREE'),
('424244', 463, 4, 'FREE'),
('424245', 463, 4, 'CANCELLED');

insert into configuration (c_key, c_value, description) values
('STRIPE_SECRET_KEY', 'sk_test_cayJOFUUYF9cWOoMXemJd61Z', 'Stripe''s secret key'),
('STRIPE_PUBLIC_KEY', 'pk_test_gY3X0UiTgKCeStUG67i2kEFq', 'Stripe''s public key'),
('BASE_URL', 'http://localhost:8080/', 'Base application url');
('STRIPE_SECRET_KEY', 'sk_test_cayJOFUUYF9cWOoMXemJd61Z', 'Stripe''s secret key'),
('STRIPE_PUBLIC_KEY', 'pk_test_gY3X0UiTgKCeStUG67i2kEFq', 'Stripe''s public key'),
('BASE_URL', 'http://localhost:8080/', 'Base application url');
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
--
-- This file is part of alf.io.
--
-- alf.io is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- alf.io is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with alf.io. If not, see <http://www.gnu.org/licenses/>.
--

alter table tickets_reservation add column payment_method VARCHAR(255);
8 changes: 4 additions & 4 deletions src/main/resources/alfio/i18n/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,8 @@ ticket.holder=Holder
ticket.type=Type
ticket.reference-number=Reference number
ticket.order-information=Order information
ticket.order-information-values={0} by {1}
ticket.order-information-values={0} by {1}
ticket.payment-required=You must pay the ticket amount at the entrance desk


#mail messages
Expand All @@ -184,6 +185,7 @@ email.event-reminder-date=on the following date:
email.kind-regards=Kind regards,
email-ticket.attached=Attached to this email you will find the ticket for the event: {0}.
email-confirmation.completed=Your reservation for the event {0} has been completed. You can modify/review it at {1}
email-confirmation.waiting-for-payment=Your order for the event {0} has been placed. Please follow the payment instructions at {1}
email-confirmation.reservation-summary=Reservation summary
email-confirmation.summary=Category: {0}, Amount: {1}, Subtotal: {2} {3}
email-confirmation.order-information=Order information : {0}
Expand All @@ -207,6 +209,4 @@ reservation-page-waiting.required-steps=In order to confirm your reservation, we
reservation-page-waiting.required-steps.1=Transfer the amount of <strong>{0}</strong> to the following Bank Account\: <strong>{1}</strong>. You are required to specify <strong>{2}</strong> as payment reason
reservation-page-waiting.required-steps.2=Send us an e-mail (<a href="mailto\:{0}?subject={1}">{0}</a>) with the proof of payment
reservation-page-waiting.required-steps.3=That''s it! After that you''ll receive a confirmation e-mail.


reservation-page-waiting.step1=Your reservation will expire on <strong>{0}</strong>
reservation.not-yet-paid=WARNING: You must pay the amount of {0} in order to attend the event
Loading

0 comments on commit 78c1736

Please sign in to comment.