Skip to content

Commit

Permalink
improve event API
Browse files Browse the repository at this point in the history
  • Loading branch information
cbellone committed Feb 4, 2023
1 parent 976f88a commit e1e6b4d
Show file tree
Hide file tree
Showing 3 changed files with 218 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@

import static alfio.controller.api.admin.EventApiController.validateEvent;
import static alfio.manager.system.AdminJobExecutor.JobName.ASSIGN_TICKETS_TO_SUBSCRIBERS;
import static alfio.model.api.v1.admin.EventCreationRequest.findExistingCategory;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;

Expand Down Expand Up @@ -95,6 +96,7 @@ public ResponseEntity<String> create(@RequestBody EventCreationRequest request,
.checkPrecondition(() -> isNotBlank(request.getImageUrl()), ErrorCode.custom("invalid.imageUrl", "Invalid Image URL"))
.checkPrecondition(() -> isNotBlank(request.getTimezone()), ErrorCode.custom("invalid.timezone", "Invalid Timezone"))
.checkPrecondition(() -> isNotBlank(imageRef), ErrorCode.custom("invalid.image", "Image is either missing or too big (max 200kb)"))
.checkPrecondition(() -> validateCategoriesSalesPeriod(request), ErrorCode.custom("invalid.categories", "Ticket categories: sales period not compatible with event dates"))
.checkPrecondition(() -> {
EventModification eventModification = request.toEventModification(organization, eventNameManager::generateShortName, imageRef);
errorsContainer.set(new BeanPropertyBindingResult(eventModification, "event"));
Expand All @@ -107,7 +109,7 @@ public ResponseEntity<String> create(@RequestBody EventCreationRequest request,
}, ErrorCode.lazy(() -> toErrorCode(errorsContainer.get())))
//TODO all location validation
//TODO language validation, for all the description the same languages
.build(() -> insertEvent(request, user, imageRef).map(Event::getShortName).orElseThrow(IllegalStateException::new));
.build(() -> insertEvent(request, user, imageRef).orElseThrow(IllegalStateException::new));

if(result.isSuccess()) {
return ResponseEntity.ok(result.getData());
Expand All @@ -117,6 +119,12 @@ public ResponseEntity<String> create(@RequestBody EventCreationRequest request,

}

private boolean validateCategoriesSalesPeriod(EventCreationRequest request) {
var eventEnd = request.getEndDate();
return request.getTickets().getCategories().stream()
.allMatch(tc -> tc.getStartSellingDate().isBefore(tc.getEndSellingDate()) && tc.getEndSellingDate().isBefore(eventEnd));
}

private ErrorCode toErrorCode(Errors errors) {
return errors.getFieldErrors().stream()
.map(e -> ErrorCode.custom(e.getField(), e.getCode()))
Expand Down Expand Up @@ -157,7 +165,7 @@ public ResponseEntity<String> update(@PathVariable("slug") String slug, @Request
String imageRef = fetchImage(request.getImageUrl());

Result<String> result = new Result.Builder<String>()
.build(() -> updateEvent(slug, request, user, imageRef).map(Event::getShortName).get());
.build(() -> updateEvent(slug, request, user, imageRef).map(Event::getShortName).orElseThrow());

if(result.isSuccess()) {
return ResponseEntity.ok(result.getData());
Expand Down Expand Up @@ -224,18 +232,22 @@ private Optional<Event> updateEvent(String slug, EventCreationRequest request, P
Event event = original.getEvent();


EventModification em = request.toEventModificationUpdate(original,organization,imageRef);
EventModification em = request.toEventModificationUpdate(original, organization, imageRef);

eventManager.updateEventHeader(event, em, user.getName());
eventManager.updateEventPrices(event, em, user.getName());


if (em.getTicketCategories() != null && !em.getTicketCategories().isEmpty()) {
em.getTicketCategories().forEach(c ->
findCategoryByName(event, c.getName()).ifPresent(originalCategory ->
eventManager.updateCategory(originalCategory.getId(), event.getId(), c, user.getName())
)
);
var existingCategories = original.getTicketCategories();
em.getTicketCategories().forEach(c -> {
var existingCategory = findExistingCategory(existingCategories, c.getName(), c.getId());
if (existingCategory.isPresent()) {
eventManager.updateCategory(existingCategory.get().getId(), event.getId(), c, user.getName());
} else {
eventManager.insertCategory(event.getId(), c, user.getName());
}
});
}


Expand All @@ -244,26 +256,21 @@ private Optional<Event> updateEvent(String slug, EventCreationRequest request, P
return eventManager.getOptionalByName(slug,user.getName());
}

private Optional<TicketCategory> findCategoryByName(Event event, String name) {
List<TicketCategory> categories = eventManager.loadTicketCategories(event);
return categories.stream().filter( oc -> oc.getName().equals(name)).findFirst();
}

private Optional<Event> insertEvent(EventCreationRequest request, Principal user, String imageRef) {
Organization organization = userManager.findUserOrganizations(user.getName()).get(0);
EventModification em = request.toEventModification(organization,eventNameManager::generateShortName,imageRef);
eventManager.createEvent(em, user.getName());
Optional<Event> event = eventManager.getOptionalByName(em.getShortName(),user.getName());

event.ifPresent(e -> {
private Optional<String> insertEvent(EventCreationRequest request, Principal user, String imageRef) {
try {
Organization organization = userManager.findUserOrganizations(user.getName()).get(0);
EventModification em = request.toEventModification(organization,eventNameManager::generateShortName,imageRef);
eventManager.createEvent(em, user.getName());
var eventWithStatistics = eventStatisticsManager.getEventWithAdditionalInfo(em.getShortName(),user.getName());
var event = eventWithStatistics.getEvent();
Optional.ofNullable(request.getTickets().getPromoCodes()).ifPresent(promoCodes ->
promoCodes.forEach(pc -> //TODO add ref to categories
eventManager.addPromoCode(
pc.getName(),
e.getId(),
event.getId(),
organization.getId(),
ZonedDateTime.of(pc.getValidFrom(),e.getZoneId()),
ZonedDateTime.of(pc.getValidTo(),e.getZoneId()),
ZonedDateTime.of(pc.getValidFrom(),event.getZoneId()),
ZonedDateTime.of(pc.getValidTo(),event.getZoneId()),
pc.getDiscount(),
pc.getDiscountType(),
Collections.emptyList(),
Expand All @@ -272,7 +279,7 @@ private Optional<Event> insertEvent(EventCreationRequest request, Principal user
null,
PromoCodeDiscount.CodeType.DISCOUNT,
null,
pc.getDiscountType() != PromoCodeDiscount.DiscountType.PERCENTAGE ? e.getCurrency() : null
pc.getDiscountType() != PromoCodeDiscount.DiscountType.PERCENTAGE ? event.getCurrency() : null
)
)
);
Expand All @@ -284,24 +291,24 @@ private Optional<Event> insertEvent(EventCreationRequest request, Principal user
if(link.getRight().isPresent()) {
Group group = link.getRight().get();
EventCreationRequest.CategoryRequest categoryRequest = link.getLeft();
findCategoryByName(e, categoryRequest.getName()).ifPresent(category -> {
findExistingCategory(eventWithStatistics.getTicketCategories(), categoryRequest.getName(), categoryRequest.getId()).ifPresent(category -> {
EventCreationRequest.GroupLinkRequest groupLinkRequest = categoryRequest.getGroupLink();
LinkedGroupModification modification = new LinkedGroupModification(null,
group.getId(),
e.getId(),
event.getId(),
category.getId(),
groupLinkRequest.getType(),
groupLinkRequest.getMatchType(),
groupLinkRequest.getMaxAllocation());
groupManager.createLink(group.getId(), e.getId(), modification);
groupManager.createLink(group.getId(), event.getId(), modification);
});
}
});
if(!CollectionUtils.isEmpty(request.getExtensionSettings())) {
request.getExtensionSettings().stream()
.collect(Collectors.groupingBy(EventCreationRequest.ExtensionSetting::getExtensionId))
.forEach((id,settings) -> {
List<ExtensionSupport.ExtensionMetadataIdAndName> metadata = extensionService.getSingle(organization, e, id)
List<ExtensionSupport.ExtensionMetadataIdAndName> metadata = extensionService.getSingle(organization, event, id)
.map(es -> extensionRepository.findAllParametersForExtension(es.getId()))
.orElseGet(Collections::emptyList);

Expand All @@ -315,13 +322,15 @@ private Optional<Event> insertEvent(EventCreationRequest request, Principal user
})
.map(pair -> new ExtensionMetadataValue(pair.getRight().get().getId(), pair.getLeft().getValue()))
.collect(Collectors.toList());
extensionService.bulkUpdateEventSettings(organization, e, values);
extensionService.bulkUpdateEventSettings(organization, event, values);
});

}

});
return event;
return Optional.of(event.getShortName());
} catch (Exception ex) {
log.error("Error while inserting event", ex);
return Optional.empty();
}
}

private String fetchImage(String url) {
Expand Down
51 changes: 38 additions & 13 deletions src/main/java/alfio/model/api/v1/admin/EventCreationRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,13 @@ public EventModification toEventModification(Organization organization, UnaryOpe
description.stream().collect(Collectors.toMap(DescriptionRequest::getLang,DescriptionRequest::getBody)),
new DateTimeModification(startDate.toLocalDate(),startDate.toLocalTime()),
new DateTimeModification(endDate.toLocalDate(),endDate.toLocalTime()),
tickets.freeOfCharge ? BigDecimal.ZERO : tickets.categories.stream().map(x -> x.price).max(BigDecimal::compareTo).orElse(BigDecimal.ONE).max(BigDecimal.ONE),
Boolean.TRUE.equals(tickets.freeOfCharge) ? BigDecimal.ZERO : tickets.categories.stream().map(x -> x.price).max(BigDecimal::compareTo).orElse(BigDecimal.ONE).max(BigDecimal.ONE),
tickets.currency,
tickets.max,
tickets.taxPercentage,
tickets.taxIncludedInPrice,
tickets.paymentMethods,
tickets.categories.stream().map(CategoryRequest::toTicketCategoryModification).collect(Collectors.toList()),
getTicketCategoryModificationList(),
tickets.freeOfCharge,
new LocationDescriptor(timezone, location.getCoordinate().getLatitude(), location.getCoordinate().getLongitude(), null),
locales,
Expand All @@ -108,6 +108,14 @@ public EventModification toEventModification(Organization organization, UnaryOpe
);
}

private List<TicketCategoryModification> getTicketCategoryModificationList() {
var result = new ArrayList<TicketCategoryModification>();
for (int c = 0; c < tickets.categories.size(); c++) {
result.add(tickets.categories.get(c).toNewTicketCategoryModification(c + 1 ));
}
return List.copyOf(result);
}

private static <T> T first(T value,T other) {
return Optional.ofNullable(value).orElse(other);
}
Expand Down Expand Up @@ -150,7 +158,7 @@ public EventModification toEventModificationUpdate(EventWithAdditionalInfo origi
tickets != null ? first(tickets.taxPercentage,original.getVat()) : original.getVat(),
tickets != null ? first(tickets.taxIncludedInPrice,original.isVatIncluded()) : original.isVatIncluded(),
tickets != null ? first(tickets.paymentMethods, original.getAllowedPaymentProxies()) : original.getAllowedPaymentProxies(),
tickets != null && tickets.categories != null ? tickets.categories.stream().map(tc -> tc.toTicketCategoryModification(findCategoryId(original, tc))).collect(Collectors.toList()) : null,
tickets != null && tickets.categories != null ? createFromExistingCategories(original) : null,
tickets != null ? first(tickets.freeOfCharge,original.isFreeOfCharge()) : original.isFreeOfCharge(),
null,
locales,
Expand All @@ -161,12 +169,28 @@ public EventModification toEventModificationUpdate(EventWithAdditionalInfo origi
);
}

private static Integer findCategoryId(EventWithAdditionalInfo event, CategoryRequest categoryRequest) {
return event.getTicketCategories().stream()
.filter(tc -> tc.getName().equals(categoryRequest.getName()))
.map(TicketCategoryWithAdditionalInfo::getId)
.findFirst()
.orElse(null);
private List<TicketCategoryModification> createFromExistingCategories(EventWithAdditionalInfo event) {
var result = new ArrayList<TicketCategoryModification>(tickets.categories.size());
for(int c = 0; c < tickets.categories.size(); c++) {
var categoryRequest = tickets.categories.get(c);
var existing = findExistingCategory(event.getTicketCategories(), categoryRequest.getName(), categoryRequest.getId());
if (existing.isPresent()) {
var category = existing.get();
result.add(categoryRequest.toExistingTicketCategoryModification(category.getId(), category.getOrdinal()));
} else {
result.add(categoryRequest.toNewTicketCategoryModification(c + 1));
}
}
return List.copyOf(result);
}

public static Optional<TicketCategoryWithAdditionalInfo> findExistingCategory(List<TicketCategoryWithAdditionalInfo> categories,
String name,
Integer id) {
return categories.stream()
// if specified, ID takes precedence over name
.filter(oc -> id != null ? id == oc.getId() : oc.getName().equals(name))
.findFirst();
}


Expand Down Expand Up @@ -207,6 +231,7 @@ public static class CoordinateRequest {
@Getter
@AllArgsConstructor
public static class CategoryRequest {
private Integer id;
private String name;
private List<DescriptionRequest> description;
private Integer maxTickets;
Expand All @@ -219,11 +244,11 @@ public static class CategoryRequest {
private GroupLinkRequest groupLink;
private TicketCategory.TicketAccessType ticketAccessType;

TicketCategoryModification toTicketCategoryModification() {
return toTicketCategoryModification(null);
TicketCategoryModification toNewTicketCategoryModification(int ordinal) {
return toExistingTicketCategoryModification(null, ordinal);
}

TicketCategoryModification toTicketCategoryModification(Integer categoryId) {
TicketCategoryModification toExistingTicketCategoryModification(Integer categoryId, int ordinal) {
int capacity = Optional.ofNullable(maxTickets).orElse(0);

Optional<CustomTicketValidityRequest> customValidityOpt = Optional.ofNullable(customValidity);
Expand All @@ -245,7 +270,7 @@ TicketCategoryModification toTicketCategoryModification(Integer categoryId) {
customValidityOpt.flatMap(x -> Optional.ofNullable(x.checkInTo)).map(x -> new DateTimeModification(x.toLocalDate(),x.toLocalTime())).orElse(null),
customValidityOpt.flatMap(x -> Optional.ofNullable(x.validityStart)).map(x -> new DateTimeModification(x.toLocalDate(),x.toLocalTime())).orElse(null),
customValidityOpt.flatMap(x -> Optional.ofNullable(x.validityEnd)).map(x -> new DateTimeModification(x.toLocalDate(),x.toLocalTime())).orElse(null),
0,
ordinal,
null,
null,
AlfioMetadata.empty());
Expand Down
Loading

0 comments on commit e1e6b4d

Please sign in to comment.