Skip to content

Commit

Permalink
#107 - download sponsor scan report
Browse files Browse the repository at this point in the history
  • Loading branch information
cbellone committed Apr 6, 2016
1 parent e6422ee commit feb2957
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 9 deletions.
5 changes: 2 additions & 3 deletions src/main/java/alfio/controller/api/AttendeeApiController.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import alfio.manager.AttendeeManager;
import alfio.manager.support.SponsorAttendeeData;
import alfio.manager.support.TicketAndCheckInResult;
import alfio.repository.SponsorScanRepository;
import alfio.util.EventUtil;
import alfio.util.Wrappers;
import com.fasterxml.jackson.annotation.JsonCreator;
Expand All @@ -33,7 +34,6 @@
import org.springframework.web.bind.annotation.*;

import java.security.Principal;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
Expand All @@ -46,7 +46,6 @@
@Log4j2
public class AttendeeApiController {

private static final ZonedDateTime DEFAULT = ZonedDateTime.ofInstant(Instant.EPOCH, ZoneOffset.UTC);
private final AttendeeManager attendeeManager;

@Autowired
Expand Down Expand Up @@ -86,7 +85,7 @@ public ResponseEntity<List<SponsorAttendeeData>> getScannedBadges(@PathVariable(
ZonedDateTime start = Optional.ofNullable(StringUtils.trimToNull(from))
.map(EventUtil.JSON_DATETIME_FORMATTER::parse)
.flatMap(d -> Wrappers.safeSupplier(() -> ZonedDateTime.of(LocalDateTime.from(d), ZoneOffset.UTC)))
.orElse(DEFAULT);
.orElse(SponsorScanRepository.DEFAULT_TIMESTAMP);
return attendeeManager.retrieveScannedAttendees(eventShortName, principal.getName(), start).map(ResponseEntity::ok).orElse(notFound());
}

Expand Down
62 changes: 57 additions & 5 deletions src/main/java/alfio/controller/api/admin/EventApiController.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,16 @@
import alfio.model.modification.*;
import alfio.model.transaction.PaymentProxy;
import alfio.model.user.Organization;
import alfio.repository.DynamicFieldTemplateRepository;
import alfio.repository.TicketCategoryDescriptionRepository;
import alfio.repository.TicketFieldRepository;
import alfio.model.user.Role;
import alfio.repository.*;
import alfio.util.ValidationResult;
import alfio.util.Validator;
import com.opencsv.CSVReader;
import com.opencsv.CSVWriter;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.tuple.Triple;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
Expand Down Expand Up @@ -82,6 +82,8 @@ public class EventApiController {
private final TicketHelper ticketHelper;
private final DynamicFieldTemplateRepository dynamicFieldTemplateRepository;
private final UserManager userManager;
private final SponsorScanRepository sponsorScanRepository;
private final TicketRepository ticketRepository;

@Autowired
public EventApiController(EventManager eventManager,
Expand All @@ -93,7 +95,9 @@ public EventApiController(EventManager eventManager,
DescriptionsLoader descriptionsLoader,
TicketHelper ticketHelper,
DynamicFieldTemplateRepository dynamicFieldTemplateRepository,
UserManager userManager) {
UserManager userManager,
SponsorScanRepository sponsorScanRepository,
TicketRepository ticketRepository) {
this.eventManager = eventManager;
this.eventStatisticsManager = eventStatisticsManager;
this.i18nManager = i18nManager;
Expand All @@ -104,6 +108,8 @@ public EventApiController(EventManager eventManager,
this.ticketHelper = ticketHelper;
this.dynamicFieldTemplateRepository = dynamicFieldTemplateRepository;
this.userManager = userManager;
this.sponsorScanRepository = sponsorScanRepository;
this.ticketRepository = ticketRepository;
}

@ExceptionHandler(DataAccessException.class)
Expand Down Expand Up @@ -231,7 +237,7 @@ public String unbindTickets(@PathVariable("eventName") String eventName, @PathVa
@RequestMapping("/events/{eventName}/export.csv")
public void downloadAllTicketsCSV(@PathVariable("eventName") String eventName, HttpServletRequest request, HttpServletResponse response, Principal principal) throws IOException {
List<String> fields = Arrays.asList(Optional.ofNullable(request.getParameterValues("fields")).orElse(new String[] {}));
Event event = Optional.ofNullable(eventManager.getSingleEvent(eventName, principal.getName())).orElseThrow(IllegalArgumentException::new);
Event event = loadEvent(eventName, principal);
Map<Integer, TicketCategory> categoriesMap = eventManager.loadTicketCategories(event).stream().collect(Collectors.toMap(TicketCategory::getId, Function.identity()));
ZoneId eventZoneId = event.getZoneId();

Expand Down Expand Up @@ -277,6 +283,52 @@ public void downloadAllTicketsCSV(@PathVariable("eventName") String eventName, H
}
}

@RequestMapping("/events/{eventName}/sponsor-scan/export.csv")
public void downloadSponsorScanExport(@PathVariable("eventName") String eventName, HttpServletResponse response, Principal principal) throws IOException {
Event event = loadEvent(eventName, principal);
List<TicketFieldConfiguration> fields = ticketFieldRepository.findAdditionalFieldsForEvent(event.getId());

response.setContentType("text/csv;charset=UTF-8");
response.setHeader("Content-Disposition", "attachment; filename=" + eventName + "-sponsor-scan.csv");

try(ServletOutputStream out = response.getOutputStream()) {
for (int marker : BOM_MARKERS) {
out.write(marker);
}
CSVWriter writer = new CSVWriter(new OutputStreamWriter(out));
List<String> header = new ArrayList<>();
header.add("Username");
header.add("Timestamp");
header.add("Full name");
header.add("Email");
header.addAll(fields.stream().map(TicketFieldConfiguration::getName).collect(Collectors.toList()));
writer.writeNext(header.toArray(new String[header.size()]));
userManager.findAllUsers(principal.getName()).stream()
.map(u -> Pair.of(u, userManager.getUserRole(u)))
.filter(p -> p.getRight() == Role.SPONSOR)
.flatMap(p -> sponsorScanRepository.loadSponsorData(event.getId(), p.getKey().getId(), SponsorScanRepository.DEFAULT_TIMESTAMP)
.stream()
.map(v -> Pair.of(v, ticketFieldRepository.findAllValuesForTicketId(v.getTicket().getId()))))
.map(p -> {
DetailedScanData data = p.getLeft();
Map<String, String> descriptions = p.getRight();
return Pair.of(data, fields.stream().map(x -> descriptions.getOrDefault(x, "")).collect(Collectors.toList()));
}).map(p -> {
List<String> line = new ArrayList<>();
Ticket ticket = p.getLeft().getTicket();
SponsorScan sponsorScan = p.getLeft().getSponsorScan();
line.add(userManager.findUser(sponsorScan.getUserId()).getUsername());
line.add(sponsorScan.getTimestamp().toString());
line.add(ticket.getFullName());
line.add(ticket.getEmail());
line.addAll(p.getRight());
return line.toArray(new String[line.size()]);
}).forEachOrdered(writer::writeNext);
writer.flush();
out.flush();
}
}

@RequestMapping("/events/{eventName}/fields")
public List<String> getAllFields(@PathVariable("eventName") String eventName) {
List<String> fields = new ArrayList<>();
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/alfio/repository/SponsorScanRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,17 @@
import ch.digitalfondue.npjt.Query;
import ch.digitalfondue.npjt.QueryRepository;

import java.time.Instant;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.List;
import java.util.Optional;

@QueryRepository
public interface SponsorScanRepository {

ZonedDateTime DEFAULT_TIMESTAMP = ZonedDateTime.ofInstant(Instant.EPOCH, ZoneOffset.UTC);

@Query("select creation from sponsor_scan where user_id = :userId and event_id = :eventId and ticket_id = :ticketId")
Optional<ZonedDateTime> getRegistrationTimestamp(@Bind("userId") int userId, @Bind("eventId") int eventId, @Bind("ticketId") int ticketId);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ <h1>{{event.displayName}} <a class="btn btn-default" data-ng-if="isInternal(even
<h4 class="text-muted">{{event.shortDescription}}</h4>
<div data-ng-if="isInternal(event)">
<span><button class="btn btn-primary" type="button" data-ng-click="openFieldSelectionModal()" ><i class="fa fa-download"></i> download attendees' data</button></span>
<!--<span><a class="btn btn-success" data-ng-href="{{ ('events/'+event.shortName+'/export/badges.csv') | addTrailingSlash }}" target="_blank"><i class="fa fa-ticket"></i> download badges' data</a></span>-->
<span><a class="btn btn-warning" data-ui-sref="compose-custom-message({eventName: event.shortName})"><i class="fa fa-envelope"></i> send a message to attendees</a></span>
<waiting-queue-display-counter data-event="event"></waiting-queue-display-counter>
<span><a class="btn btn-warning" data-ng-click="downloadSponsorsScan()" ><i class="fa fa-download"></i> download sponsors scan</a></span>
<span><a class="btn btn-default" data-ui-sref="events.email-log({eventName:event.shortName})"><i class="fa fa-paper-plane-o"></i> view sent messages</a></span>
<span><a class="btn btn-default" data-ui-sref="events.plugin-log({eventName:event.shortName})"><i class="fa fa-plug"></i> view Plugins log</a></span>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -762,6 +762,10 @@
});
};

$scope.downloadSponsorsScan = function() {
$window.open($window.location.pathname+"/api/events/"+parentScope.event.shortName+"/sponsor-scan/export.csv");
};

$scope.prepareFieldDescriptionEdit = function(baseObject, field) {
angular.copy(field, baseObject);
};
Expand Down

0 comments on commit feb2957

Please sign in to comment.