From a915311dbad21841ef869c4a57260e83271721e2 Mon Sep 17 00:00:00 2001 From: Celestino Bellone Date: Wed, 22 Nov 2017 08:27:07 +0100 Subject: [PATCH] #365 - Reset UUID when ticket is released by the attendee or removed by the admin --- .../java/alfio/manager/AdminReservationManager.java | 13 +++++++++---- .../alfio/manager/TicketReservationManager.java | 3 ++- .../java/alfio/repository/TicketRepository.java | 8 ++++++-- .../alfio/manager/TicketReservationManagerTest.java | 12 ++++++------ .../WaitingQueueProcessorIntegrationTest.java | 2 +- 5 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/main/java/alfio/manager/AdminReservationManager.java b/src/main/java/alfio/manager/AdminReservationManager.java index bd4ac547c1..b470c8dc80 100644 --- a/src/main/java/alfio/manager/AdminReservationManager.java +++ b/src/main/java/alfio/manager/AdminReservationManager.java @@ -61,6 +61,8 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import static alfio.model.Audit.EntityType.TICKET; +import static alfio.model.Audit.EventType.CANCEL_TICKET; import static alfio.model.modification.DateTimeModification.fromZonedDateTime; import static alfio.util.EventUtil.generateEmptyTickets; import static alfio.util.OptionalWrapper.optionally; @@ -559,13 +561,16 @@ private void removeTicketsFromReservation(String reservationId, Event event, Lis Integer userId = userRepository.findIdByUserName(username).orElse(null); Date date = new Date(); - ticketIds.forEach(id -> { - auditingRepository.insert(reservationId, userId, event.getId(), Audit.EventType.CANCEL_TICKET, date, Audit.EntityType.TICKET, id.toString()); - }); + ticketIds.forEach(id -> auditingRepository.insert(reservationId, userId, event.getId(), CANCEL_TICKET, date, TICKET, id.toString())); ticketRepository.resetCategoryIdForUnboundedCategoriesWithTicketIds(ticketIds); ticketFieldRepository.deleteAllValuesForTicketIds(ticketIds); - ticketRepository.resetTickets(ticketIds); + MapSqlParameterSource[] args = ticketIds.stream().map(id -> new MapSqlParameterSource("ticketId", id) + .addValue("reservationId", reservationId) + .addValue("eventId", event.getId()) + .addValue("newUuid", UUID.randomUUID().toString()) + ).toArray(MapSqlParameterSource[]::new); + jdbc.batchUpdate(ticketRepository.batchReleaseTickets(), args); } private void sendTicketHasBeenRemoved(Event event, Organization organization, Ticket ticket) { diff --git a/src/main/java/alfio/manager/TicketReservationManager.java b/src/main/java/alfio/manager/TicketReservationManager.java index 26f786405d..a43f1404bf 100644 --- a/src/main/java/alfio/manager/TicketReservationManager.java +++ b/src/main/java/alfio/manager/TicketReservationManager.java @@ -1246,7 +1246,8 @@ public void releaseTicket(Event event, TicketReservation ticketReservation, Tick throw new IllegalStateException("Cannot release reserved tickets"); } String reservationId = ticketReservation.getId(); - int result = ticketRepository.releaseTicket(reservationId, event.getId(), ticket.getId()); + //#365 - reset UUID when releasing a ticket + int result = ticketRepository.releaseTicket(reservationId, UUID.randomUUID().toString(), event.getId(), ticket.getId()); Validate.isTrue(result == 1, String.format("Expected 1 row to be updated, got %d", result)); if(category.isAccessRestricted() || !category.isBounded()) { ticketRepository.unbindTicketsFromCategory(event.getId(), category.getId(), singletonList(ticket.getId())); diff --git a/src/main/java/alfio/repository/TicketRepository.java b/src/main/java/alfio/repository/TicketRepository.java index 4137cf4033..1dec89a5d0 100644 --- a/src/main/java/alfio/repository/TicketRepository.java +++ b/src/main/java/alfio/repository/TicketRepository.java @@ -245,9 +245,13 @@ Integer countAllModifiedTicketsWithReservationAndTransaction(@Bind("eventId") in int flagTicketAsReminderSent(@Bind("id") int ticketId); String RESET_TICKET = " TICKETS_RESERVATION_ID = null, FULL_NAME = null, EMAIL_ADDRESS = null, SPECIAL_PRICE_ID_FK = null, LOCKED_ASSIGNMENT = false, USER_LANGUAGE = null, REMINDER_SENT = false, SRC_PRICE_CTS = 0, FINAL_PRICE_CTS = 0, VAT_CTS = 0, DISCOUNT_CTS = 0, FIRST_NAME = null, LAST_NAME = null, EXT_REFERENCE = null "; + String RELEASE_TICKET_QUERY = "update ticket set status = 'RELEASED', uuid = :newUuid, " + RESET_TICKET + " where id = :ticketId and status = 'ACQUIRED' and tickets_reservation_id = :reservationId and event_id = :eventId"; - @Query("update ticket set status = 'RELEASED', " + RESET_TICKET + " where id = :ticketId and status = 'ACQUIRED' and tickets_reservation_id = :reservationId and event_id = :eventId") - int releaseTicket(@Bind("reservationId") String reservationId, @Bind("eventId") int eventId, @Bind("ticketId") int ticketId); + @Query(RELEASE_TICKET_QUERY) + int releaseTicket(@Bind("reservationId") String reservationId, @Bind("newUuid") String newUuid, @Bind("eventId") int eventId, @Bind("ticketId") int ticketId); + + @Query(value = RELEASE_TICKET_QUERY, type = QueryType.TEMPLATE) + String batchReleaseTickets(); @Query("update ticket set status = 'RELEASED', " + RESET_TICKET + " where id = :ticketId and status = 'PENDING' and tickets_reservation_id = :reservationId and event_id = :eventId") int releaseExpiredTicket(@Bind("reservationId") String reservationId, @Bind("eventId") int eventId, @Bind("ticketId") int ticketId); diff --git a/src/test/java/alfio/manager/TicketReservationManagerTest.java b/src/test/java/alfio/manager/TicketReservationManagerTest.java index e2dd159ab6..8dc5aa7c3b 100644 --- a/src/test/java/alfio/manager/TicketReservationManagerTest.java +++ b/src/test/java/alfio/manager/TicketReservationManagerTest.java @@ -616,13 +616,13 @@ public void sendEmailToAssigneeOnSuccess() throws Exception { String organizationEmail = "ciccio@test"; when(organization.getEmail()).thenReturn(organizationEmail); when(ticketCategory.isAccessRestricted()).thenReturn(false); - when(ticketRepository.releaseTicket(eq(RESERVATION_ID), eq(EVENT_ID), eq(TICKET_ID))).thenReturn(1); + when(ticketRepository.releaseTicket(eq(RESERVATION_ID), anyString(), eq(EVENT_ID), eq(TICKET_ID))).thenReturn(1); when(ticketCategory.isAccessRestricted()).thenReturn(false); List expectedReservations = singletonList(RESERVATION_ID); when(ticketReservationRepository.remove(eq(expectedReservations))).thenReturn(1); when(transactionRepository.loadOptionalByReservationId(anyString())).thenReturn(Optional.empty()); trm.releaseTicket(event, ticketReservation, ticket); - verify(ticketRepository).releaseTicket(eq(RESERVATION_ID), eq(EVENT_ID), eq(TICKET_ID)); + verify(ticketRepository).releaseTicket(eq(RESERVATION_ID), anyString(), eq(EVENT_ID), eq(TICKET_ID)); verify(notificationManager).sendSimpleEmail(eq(event), eq(RESERVATION_EMAIL), any(), any(TextTemplateGenerator.class)); verify(notificationManager).sendSimpleEmail(eq(event), eq(organizationEmail), any(), any(TextTemplateGenerator.class)); verify(organizationRepository).getById(eq(ORGANIZATION_ID)); @@ -643,7 +643,7 @@ public void cannotReleaseRestrictedTicketIfNoUnboundedCategory() throws Exceptio public void releaseRestrictedTicketIfUnboundedCategoryPresent() throws Exception { initReleaseTicket(); when(ticketCategory.getId()).thenReturn(TICKET_CATEGORY_ID); - when(ticketRepository.releaseTicket(eq(RESERVATION_ID), eq(EVENT_ID), eq(TICKET_ID))).thenReturn(1); + when(ticketRepository.releaseTicket(eq(RESERVATION_ID), anyString(), eq(EVENT_ID), eq(TICKET_ID))).thenReturn(1); when(ticketCategoryRepository.getByIdAndActive(eq(TICKET_CATEGORY_ID), eq(EVENT_ID))).thenReturn(ticketCategory); when(ticketCategory.isAccessRestricted()).thenReturn(true); when(ticketCategoryRepository.countUnboundedCategoriesByEventId(eq(EVENT_ID))).thenReturn(1); @@ -651,7 +651,7 @@ public void releaseRestrictedTicketIfUnboundedCategoryPresent() throws Exception when(ticketReservationRepository.remove(eq(expectedReservations))).thenReturn(1); when(transactionRepository.loadOptionalByReservationId(anyString())).thenReturn(Optional.empty()); trm.releaseTicket(event, ticketReservation, ticket); - verify(ticketRepository).releaseTicket(eq(RESERVATION_ID), eq(EVENT_ID), eq(TICKET_ID)); + verify(ticketRepository).releaseTicket(eq(RESERVATION_ID), anyString(), eq(EVENT_ID), eq(TICKET_ID)); verify(ticketRepository).unbindTicketsFromCategory(eq(EVENT_ID), eq(TICKET_CATEGORY_ID), eq(singletonList(TICKET_ID))); verify(notificationManager).sendSimpleEmail(eq(event), eq(RESERVATION_EMAIL), any(), any(TextTemplateGenerator.class)); verify(organizationRepository).getById(eq(ORGANIZATION_ID)); @@ -661,12 +661,12 @@ public void releaseRestrictedTicketIfUnboundedCategoryPresent() throws Exception @Test public void throwExceptionIfMultipleTickets() throws Exception { initReleaseTicket(); - when(ticketRepository.releaseTicket(eq(RESERVATION_ID), eq(EVENT_ID), eq(TICKET_ID))).thenReturn(2); + when(ticketRepository.releaseTicket(eq(RESERVATION_ID), anyString(), eq(EVENT_ID), eq(TICKET_ID))).thenReturn(2); try { trm.releaseTicket(event, ticketReservation, ticket); fail(); } catch (IllegalArgumentException e) { - verify(ticketRepository).releaseTicket(eq(RESERVATION_ID), eq(EVENT_ID), eq(TICKET_ID)); + verify(ticketRepository).releaseTicket(eq(RESERVATION_ID), anyString(), eq(EVENT_ID), eq(TICKET_ID)); verify(notificationManager, never()).sendSimpleEmail(any(), any(), any(), any(TextTemplateGenerator.class)); } } diff --git a/src/test/java/alfio/manager/WaitingQueueProcessorIntegrationTest.java b/src/test/java/alfio/manager/WaitingQueueProcessorIntegrationTest.java index d3028819be..a7431f5341 100644 --- a/src/test/java/alfio/manager/WaitingQueueProcessorIntegrationTest.java +++ b/src/test/java/alfio/manager/WaitingQueueProcessorIntegrationTest.java @@ -145,7 +145,7 @@ public void testSoldOut() throws InterruptedException { Event event = pair.getRight(); String reservationId = pair.getLeft(); Ticket firstTicket = ticketRepository.findTicketsInReservation(reservationId).get(0); - ticketRepository.releaseTicket(reservationId, event.getId(), firstTicket.getId()); + ticketRepository.releaseTicket(reservationId, UUID.randomUUID().toString(), event.getId(), firstTicket.getId()); waitingQueueSubscriptionProcessor.distributeAvailableSeats(event); List subscriptions = waitingQueueRepository.loadAll(event.getId()); assertEquals(1, subscriptions.stream().filter(w -> StringUtils.isNotBlank(w.getReservationId())).count());