diff --git a/src/main/java/alfio/controller/api/admin/CheckInApiController.java b/src/main/java/alfio/controller/api/admin/CheckInApiController.java index 7e1b46c720..d5344a758e 100644 --- a/src/main/java/alfio/controller/api/admin/CheckInApiController.java +++ b/src/main/java/alfio/controller/api/admin/CheckInApiController.java @@ -73,6 +73,12 @@ public boolean manualCheckIn(@PathVariable("eventId") int eventId, @PathVariable return checkInManager.manualCheckIn(ticketIdentifier); } + @RequestMapping(value = "/check-in/{eventId}/ticket/{ticketIdentifier}/revert-check-in", method = POST) + public boolean revertCheckIn(@PathVariable("eventId") int eventId, @PathVariable("ticketIdentifier") String ticketIdentifier) { + log.warn("for event id : {} and ticket : {}, a revert of the check in has been done", eventId, ticketIdentifier); + return checkInManager.revertCheckIn(ticketIdentifier); + } + @RequestMapping(value = "/check-in/event/{eventName}/ticket/{ticketIdentifier}/confirm-on-site-payment", method = POST) public TicketAndCheckInResult confirmOnSitePayment(@PathVariable("eventName") String eventName, @PathVariable("ticketIdentifier") String ticketIdentifier, diff --git a/src/main/java/alfio/manager/CheckInManager.java b/src/main/java/alfio/manager/CheckInManager.java index 7564fe1c4e..3bbadec202 100644 --- a/src/main/java/alfio/manager/CheckInManager.java +++ b/src/main/java/alfio/manager/CheckInManager.java @@ -24,8 +24,11 @@ import alfio.model.FullTicketInfo; import alfio.model.Ticket; import alfio.model.Ticket.TicketStatus; +import alfio.model.TicketReservation; +import alfio.model.transaction.PaymentProxy; import alfio.repository.EventRepository; import alfio.repository.TicketRepository; +import alfio.repository.TicketReservationRepository; import alfio.util.MonetaryUtil; import lombok.extern.log4j.Log4j2; import org.apache.commons.lang3.StringUtils; @@ -48,11 +51,13 @@ public class CheckInManager { private final TicketRepository ticketRepository; private final EventRepository eventRepository; + private final TicketReservationRepository ticketReservationRepository; @Autowired - public CheckInManager(TicketRepository ticketRepository, EventRepository eventRepository) { + public CheckInManager(TicketRepository ticketRepository, EventRepository eventRepository, TicketReservationRepository ticketReservationRepository) { this.ticketRepository = ticketRepository; this.eventRepository = eventRepository; + this.ticketReservationRepository = ticketReservationRepository; } @@ -108,6 +113,18 @@ public boolean manualCheckIn(String ticketIdentifier) { }).orElse(false); } + public boolean revertCheckIn(String ticketIdentifier) { + return findAndLockTicket(ticketIdentifier).map((t) -> { + if(t.getStatus() == TicketStatus.CHECKED_IN) { + TicketReservation reservation = ticketReservationRepository.findReservationById(t.getTicketsReservationId()); + TicketStatus revertedStatus = reservation.getPaymentMethod() == PaymentProxy.ON_SITE ? TicketStatus.TO_BE_PAID : TicketStatus.ACQUIRED; + ticketRepository.updateTicketStatusWithUUID(ticketIdentifier, revertedStatus.toString()); + return true; + } + return false; + }).orElse(false); + } + private Optional findAndLockTicket(String uuid) { return ticketRepository.findByUUIDForUpdate(uuid); } @@ -169,5 +186,4 @@ private TicketAndCheckInResult extractStatus(Optional maybeEvent, Optiona return new TicketAndCheckInResult(ticket, new DefaultCheckInResult(OK_READY_TO_BE_CHECKED_IN, "Ready to be checked in")); } - } diff --git a/src/main/webapp/resources/angular-templates/admin/partials/event/check-in.html b/src/main/webapp/resources/angular-templates/admin/partials/event/check-in.html index c7015768a1..7280043bd4 100644 --- a/src/main/webapp/resources/angular-templates/admin/partials/event/check-in.html +++ b/src/main/webapp/resources/angular-templates/admin/partials/event/check-in.html @@ -132,6 +132,7 @@

Check-In: {{event.displayName}}

Payment Type Transaction id Transaction timestamp + Actions @@ -148,6 +149,7 @@

Check-In: {{event.displayName}}

{{::ticket.ticketReservation.paymentMethod}} {{::ticket.transaction.id}} {{::ticket.transactionTimestamp | formatDate:'DD.MM.YYYY HH:mm:ss'}} + diff --git a/src/main/webapp/resources/js/admin/ng-app/admin-application.js b/src/main/webapp/resources/js/admin/ng-app/admin-application.js index 2e798ac374..92a39b4846 100644 --- a/src/main/webapp/resources/js/admin/ng-app/admin-application.js +++ b/src/main/webapp/resources/js/admin/ng-app/admin-application.js @@ -1125,6 +1125,10 @@ $scope.selection = {}; }); }; + + $scope.revertCheckIn = function(ticket) { + CheckInService.revertCheckIn(ticket).then($scope.reloadTickets); + }; }); admin.controller('EventCheckInScanController', function($scope, $stateParams, $timeout, $log, $state, EventService, CheckInService) { diff --git a/src/main/webapp/resources/js/admin/service/service.js b/src/main/webapp/resources/js/admin/service/service.js index ba06485eba..a3a7b06eb9 100644 --- a/src/main/webapp/resources/js/admin/service/service.js +++ b/src/main/webapp/resources/js/admin/service/service.js @@ -346,6 +346,10 @@ manualCheckIn: function(ticket) { return $http['post']('/admin/api/check-in/' + ticket.eventId + '/ticket/' + ticket.uuid + '/manual-check-in', ticket); }, + + revertCheckIn: function(ticket) { + return $http['post']('/admin/api/check-in/' + ticket.eventId + '/ticket/' + ticket.uuid + '/revert-check-in', ticket); + }, confirmPayment: function(eventId, ticket) { var ticketIdentifier = ticket.code.split('/')[0];