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

Supporting External Reference in List of Attendees Download #1429

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
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,8 @@ public ResponseEntity<String> rearrangeCategories(@PathVariable String eventName
}

private static final String PAYMENT_METHOD = "Payment Method";
private static final List<String> FIXED_FIELDS = Arrays.asList("ID", "Category", "Event", "Status", "OriginalPrice", "PaidPrice", "Discount", "VAT", "ReservationID", "Full Name", "First Name", "Last Name", "E-Mail", "Locked", "Language", "Confirmation", "Billing Address", "Country Code", "Payment ID", PAYMENT_METHOD);
private static final String EXTERNAL_REFERENCE = "External Reference";
static final List<String> FIXED_FIELDS = Arrays.asList("ID", "Category", "Event", "Status", "OriginalPrice", "PaidPrice", "Discount", "VAT", "ReservationID", "Full Name", "First Name", "Last Name", "E-Mail", "Locked", "Language", "Confirmation", "Billing Address", "Country Code", "Payment ID", PAYMENT_METHOD, EXTERNAL_REFERENCE);
private static final List<SerializablePair<String, String>> FIXED_PAIRS = FIXED_FIELDS.stream().map(f -> SerializablePair.of(f, f)).collect(toList());
private static final String FISCAL_CODE = "Fiscal Code";
private static final String REFERENCE_TYPE = "Reference Type";
Expand Down Expand Up @@ -435,6 +436,7 @@ private Stream<String[]> exportLines(String eventName, Principal principal, List
if(paymentIdRequested) { line.add(Objects.toString(transaction.map(Transaction::getPaymentId).orElse(null), transaction.map(Transaction::getTransactionId).orElse(""))); }
if(paymentGatewayRequested) { line.add(transaction.map(tr -> tr.getPaymentProxy().name()).orElse("")); }
}
if(fields.contains(EXTERNAL_REFERENCE)) {line.add(t.getExtReference());}

if(eInvoicingEnabled) {
var billingDetails = trs.getBillingDetails();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,38 +20,49 @@
import alfio.config.DataSourceConfiguration;
import alfio.config.Initializer;
import alfio.controller.api.ControllerConfiguration;
import alfio.manager.AdminReservationRequestManager;
import alfio.manager.EventManager;
import alfio.manager.user.UserManager;
import alfio.model.Event;
import alfio.model.TicketCategory;
import alfio.model.metadata.AlfioMetadata;
import alfio.model.modification.AdminReservationModification;
import alfio.model.modification.DateTimeModification;
import alfio.model.modification.TicketCategoryModification;
import alfio.repository.EventDeleterRepository;
import alfio.repository.EventRepository;
import alfio.repository.TicketCategoryRepository;
import alfio.repository.TicketRepository;
import alfio.repository.system.ConfigurationRepository;
import alfio.repository.user.OrganizationRepository;
import alfio.test.util.AlfioIntegrationTest;
import alfio.test.util.IntegrationTestUtil;
import alfio.util.ClockProvider;
import org.apache.commons.lang3.tuple.Pair;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;

import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZonedDateTime;
import java.util.Collections;
import java.util.List;

import static alfio.controller.api.admin.EventApiController.FIXED_FIELDS;
import static alfio.test.util.IntegrationTestUtil.*;
import static alfio.test.util.TestUtil.clockProvider;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.when;

@AlfioIntegrationTest
Expand All @@ -73,8 +84,21 @@ class EventApiControllerIntegrationTest {
private EventDeleterRepository eventDeleterRepository;
@Autowired
private EventApiController eventApiController;
@Autowired
private AttendeeBulkImportApiController attendeeBulkImportApiController;
@Autowired
private AdminReservationRequestManager adminReservationRequestManager;
@Autowired
private TicketCategoryRepository ticketCategoryRepository;
@Autowired
private TicketRepository ticketRepository;

private Event event;
private static final String TEST_ATTENDEE_EXTERNAL_REFERENCE = "123";
private static final String TEST_ATTENDEE_USER_LANGUAGE = "en";
private static final String TEST_ATTENDEE_FIRST_NAME = "Attendee";
private static final String TEST_ATTENDEE_LAST_NAME = "Test";
private static final String TEST_ATTENDEE_EMAIL = "[email protected]";

@Test
void getAllEventsForExternalInPerson() {
Expand Down Expand Up @@ -119,6 +143,53 @@ void getAllEventsForExternalOnline() {
assertEquals(event.getShortName(), events.get(0).getKey());
}

@Test
void testGivenListOfAttendeesWithFieldsUploadThenSameFieldsAvailableOnCsvDownload() throws IOException {
// GIVEN - creation of event and registration of attendees
var eventAndUser = createEvent(Event.EventFormat.HYBRID);
event = eventAndUser.getKey();
var principal = Mockito.mock(Authentication.class);
when(principal.getName()).thenReturn(owner(eventAndUser.getValue()));
var modification = getTestAdminReservationModification();
var result = this.attendeeBulkImportApiController.createReservations(eventAndUser.getKey().getShortName(), modification, false, principal);

// GIVEN - invocation of async processing job
var requestStatus = this.attendeeBulkImportApiController.getRequestsStatus(eventAndUser.getKey().getShortName(), result.getData(), principal);
assertEquals(1, requestStatus.getData().getCountPending());

// WHEN - processing of pending reservations completes
this.adminReservationRequestManager.processPendingReservations();

// THEN - assert correctness of data persisted
var tickets = this.ticketRepository.findAllConfirmedForCSV(event.getId());
assertEquals(1, tickets.size());
var foundTicket = tickets.get(0).getTicket();
assertEquals(TEST_ATTENDEE_EXTERNAL_REFERENCE, foundTicket.getExtReference());
assertEquals(TEST_ATTENDEE_FIRST_NAME, foundTicket.getFirstName());
assertEquals(TEST_ATTENDEE_LAST_NAME, foundTicket.getLastName());
assertEquals(TEST_ATTENDEE_EMAIL, foundTicket.getEmail());
assertEquals(TEST_ATTENDEE_USER_LANGUAGE, foundTicket.getUserLanguage());

// THEN - assert correct order of CSV fields upon download
MockHttpServletRequest mockRequest = new MockHttpServletRequest();
mockRequest.addParameter("fields", FIXED_FIELDS.toArray(new String[0]));
MockHttpServletResponse mockResponse = new MockHttpServletResponse();
this.eventApiController.downloadAllTicketsCSV(event.getShortName(), "csv", mockRequest, mockResponse, principal);
String expectedTestAttendeeCsvLine = "\""+foundTicket.getUuid()+"\""+",default,"+"\""+event.getShortName()+"\""+",ACQUIRED,0,0,0,0,"+"\""+foundTicket.getTicketsReservationId()+"\""+",\""+TEST_ATTENDEE_FIRST_NAME+" "+TEST_ATTENDEE_LAST_NAME+"\","+TEST_ATTENDEE_FIRST_NAME+","+TEST_ATTENDEE_LAST_NAME+","+TEST_ATTENDEE_EMAIL+",false,"+TEST_ATTENDEE_USER_LANGUAGE;
String returnedCsvContent = mockResponse.getContentAsString().trim().replace("\uFEFF", ""); // remove BOM
assertTrue(returnedCsvContent.startsWith(getExpectedHeaderCsvLine() + "\n" + expectedTestAttendeeCsvLine));
assertTrue(returnedCsvContent.endsWith("\"Billing Address\",,,," + TEST_ATTENDEE_EXTERNAL_REFERENCE));
}

private AdminReservationModification getTestAdminReservationModification() {
DateTimeModification expiration = DateTimeModification.fromZonedDateTime(ZonedDateTime.now(ClockProvider.clock()).plusDays(1));
AdminReservationModification.CustomerData customerData = new AdminReservationModification.CustomerData("Integration", "Test", "[email protected]", "Billing Address", "reference", "en", "1234", "CH", null);
var ticketCategoryList = this.ticketCategoryRepository.findAllTicketCategories(event.getId());
AdminReservationModification.Category category = new AdminReservationModification.Category(ticketCategoryList.get(0).getId(), "name", new BigDecimal("100.00"), null);
List<AdminReservationModification.TicketsInfo> ticketsInfoList = Collections.singletonList(new AdminReservationModification.TicketsInfo(category, Collections.singletonList(generateTestAttendee()), true, false));
return new AdminReservationModification(expiration, customerData, ticketsInfoList, "en", false, false, null, null, null, null);
}

private Pair<Event,String> createEvent(Event.EventFormat format) {
IntegrationTestUtil.ensureMinimalConfiguration(configurationRepository);
List<TicketCategoryModification> categories = List.of(
Expand All @@ -131,6 +202,23 @@ private Pair<Event,String> createEvent(Event.EventFormat format) {

}

private String getExpectedHeaderCsvLine() {
String expectedHeaderCsvLine = String.join(",", FIXED_FIELDS);
expectedHeaderCsvLine = expectedHeaderCsvLine.replaceAll("Full Name", "\"Full Name\"");
expectedHeaderCsvLine = expectedHeaderCsvLine.replaceAll("First Name", "\"First Name\"");
expectedHeaderCsvLine = expectedHeaderCsvLine.replaceAll("Last Name", "\"Last Name\"");
expectedHeaderCsvLine = expectedHeaderCsvLine.replaceAll("Billing Address", "\"Billing Address\"");
expectedHeaderCsvLine = expectedHeaderCsvLine.replaceAll("Country Code", "\"Country Code\"");
expectedHeaderCsvLine = expectedHeaderCsvLine.replaceAll("Payment ID", "\"Payment ID\"");
expectedHeaderCsvLine = expectedHeaderCsvLine.replaceAll("Payment Method", "\"Payment Method\"");
expectedHeaderCsvLine = expectedHeaderCsvLine.replaceAll("External Reference", "\"External Reference\"");
return expectedHeaderCsvLine;
}

private AdminReservationModification.Attendee generateTestAttendee() {
return new AdminReservationModification.Attendee(null, TEST_ATTENDEE_FIRST_NAME, TEST_ATTENDEE_LAST_NAME, TEST_ATTENDEE_EMAIL, TEST_ATTENDEE_USER_LANGUAGE,false, TEST_ATTENDEE_EXTERNAL_REFERENCE, null, Collections.emptyMap(), null);
}

@AfterEach
void tearDown() {
eventDeleterRepository.deleteAllForEvent(event.getId());
Expand Down
Loading