Skip to content

Commit

Permalink
#34 - add predictable assignation order
Browse files Browse the repository at this point in the history
  • Loading branch information
cbellone committed Feb 15, 2015
1 parent 81d6690 commit 0d24524
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 23 deletions.
23 changes: 19 additions & 4 deletions src/main/java/alfio/controller/api/SpecialPriceApiController.java
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
/**
* This file is part of alf.io.
*
* alf.io is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* alf.io is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with alf.io. If not, see <http://www.gnu.org/licenses/>.
*/
package alfio.controller.api;

import alfio.manager.SpecialPriceManager;
Expand All @@ -16,7 +32,6 @@
import java.security.Principal;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

@RestController
Expand Down Expand Up @@ -50,20 +65,20 @@ public List<SendCodeModification> linkAssigneeToCodes(@PathVariable("eventName")
Validate.isTrue(StringUtils.isNotEmpty(eventName));
try(InputStreamReader isr = new InputStreamReader(file.getInputStream())) {
CSVReader reader = new CSVReader(isr);
Set<SendCodeModification> content = reader.readAll().stream()
List<SendCodeModification> content = reader.readAll().stream()
.map(line -> {
Validate.isTrue(line.length >= 4);
return new SendCodeModification(StringUtils.trimToNull(line[0]), line[1], line[2], line[3]);
})
.collect(Collectors.toSet());
.collect(Collectors.toList());
return specialPriceManager.linkAssigneeToCode(content, eventName, categoryId, principal.getName());
}
}

@RequestMapping("/events/{eventName}/categories/{categoryId}/send-codes")
public boolean sendCodes(@PathVariable("eventName") String eventName,
@PathVariable("categoryId") int categoryId,
@RequestBody Set<SendCodeModification> codes,
@RequestBody List<SendCodeModification> codes,
Principal principal) throws IOException {

Validate.isTrue(StringUtils.isNotEmpty(eventName));
Expand Down
34 changes: 26 additions & 8 deletions src/main/java/alfio/manager/SpecialPriceManager.java
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
/**
* This file is part of alf.io.
*
* alf.io is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* alf.io is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with alf.io. If not, see <http://www.gnu.org/licenses/>.
*/
package alfio.manager;

import alfio.model.Event;
Expand Down Expand Up @@ -55,21 +71,23 @@ private List<String> checkCodeAssignment(Set<SendCodeModification> input, int ca
return availableCodes;
}

public List<SendCodeModification> linkAssigneeToCode(Set<SendCodeModification> input, String eventName, int categoryId, String username) {
public List<SendCodeModification> linkAssigneeToCode(List<SendCodeModification> input, String eventName, int categoryId, String username) {
final Event event = eventManager.getSingleEvent(eventName, username);
List<String> availableCodes = checkCodeAssignment(input, categoryId, event, username);
Set<SendCodeModification> set = new LinkedHashSet<>(input);
List<String> availableCodes = checkCodeAssignment(set, categoryId, event, username);
final Iterator<String> codes = availableCodes.iterator();
return Stream.concat(input.stream().filter(IS_CODE_PRESENT),
return Stream.concat(set.stream().filter(IS_CODE_PRESENT),
input.stream().filter(IS_CODE_PRESENT.negate())
.map(p -> new SendCodeModification(codes.next(), p.getAssignee(), p.getEmail(), p.getLanguage()))).collect(toList());
}

public boolean sendCodeToAssignee(Set<SendCodeModification> input, String eventName, int categoryId, String username) {
public boolean sendCodeToAssignee(List<SendCodeModification> input, String eventName, int categoryId, String username) {
final Event event = eventManager.getSingleEvent(eventName, username);
final Organization organization = eventManager.loadOrganizer(event, username);
checkCodeAssignment(input, categoryId, event, username);
Validate.isTrue(input.stream().allMatch(IS_CODE_PRESENT), "There are missing codes. Please check input file.");
input.forEach(m -> {
Set<SendCodeModification> set = new LinkedHashSet<>(input);
checkCodeAssignment(set, categoryId, event, username);
Validate.isTrue(set.stream().allMatch(IS_CODE_PRESENT), "There are missing codes. Please check input file.");
set.forEach(m -> {
Locale locale = Locale.forLanguageTag(StringUtils.defaultString(m.getLanguage(), "en"));
Map<String, Object> model = new HashMap<>();
model.put("code", m.getCode());
Expand All @@ -78,7 +96,7 @@ public boolean sendCodeToAssignee(Set<SendCodeModification> input, String eventN
model.put("eventPage", eventManager.getEventUrl(event));
model.put("assignee", m.getAssignee());

notificationManager.sendSimpleEmail(event, m.getEmail(), messageSource.getMessage("email-code.subject", new Object[] {event.getShortName()}, locale), () -> templateManager.renderClassPathResource("/alfio/templates/send-reserved-code-txt.ms", model, locale));
notificationManager.sendSimpleEmail(event, m.getEmail(), messageSource.getMessage("email-code.subject", new Object[] {event.getShortName()}, locale), () -> templateManager.renderClassPathResource("/alfio/templates/send-reserved-code-txt.ms", model, locale, TemplateManager.TemplateOutput.TEXT));
});
return true;
}
Expand Down
16 changes: 16 additions & 0 deletions src/main/java/alfio/model/modification/SendCodeModification.java
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
/**
* This file is part of alf.io.
*
* alf.io is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* alf.io is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with alf.io. If not, see <http://www.gnu.org/licenses/>.
*/
package alfio.model.modification;

import com.fasterxml.jackson.annotation.JsonCreator;
Expand Down
38 changes: 27 additions & 11 deletions src/test/java/alfio/manager/SpecialPriceManagerTest.java
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
/**
* This file is part of alf.io.
*
* alf.io is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* alf.io is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with alf.io. If not, see <http://www.gnu.org/licenses/>.
*/
package alfio.manager;

import alfio.manager.support.TextTemplateGenerator;
Expand All @@ -20,7 +36,7 @@

import static com.insightfullogic.lambdabehave.Suite.describe;
import static java.util.Arrays.asList;
import static java.util.Collections.singleton;
import static java.util.Collections.singletonList;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
Expand Down Expand Up @@ -63,14 +79,14 @@ public class SpecialPriceManagerTest {{
describe("validation error (category not restricted)", it -> {
it.initializesWith(setRestricted(ticketCategory, false));
it.should("throw an exception (category not restricted)", expect -> {
expect.exception(IllegalArgumentException.class, () -> specialPriceManager.linkAssigneeToCode(Collections.<SendCodeModification>emptySet(), "test", 0, "username"));
expect.exception(IllegalArgumentException.class, () -> specialPriceManager.linkAssigneeToCode(Collections.<SendCodeModification>emptyList(), "test", 0, "username"));
});
});

describe("validation error (too much codes requested)", it -> {
it.initializesWith(setRestricted(ticketCategory, true));
it.should("throw an exception (too much codes requested)", expect -> {
Set<SendCodeModification> oneMore = new HashSet<>();
List<SendCodeModification> oneMore = new ArrayList<>();
oneMore.addAll(CODES_REQUESTED);
oneMore.add(new SendCodeModification("123", "", "", ""));
expect.exception(IllegalArgumentException.class, () -> specialPriceManager.linkAssigneeToCode(oneMore, "test", 0, "username"));
Expand All @@ -80,15 +96,15 @@ public class SpecialPriceManagerTest {{
describe("validation error (not available code requested)", it -> {
it.initializesWith(setRestricted(ticketCategory, true));
it.should("throw an exception (not available code requested)", expect -> {
Set<SendCodeModification> notExistingCode = new HashSet<>(asList(new SendCodeModification("AAA", "A 123", "123@123", "it"), new SendCodeModification("456", "A 456", "456@456", "en")));
List<SendCodeModification> notExistingCode = asList(new SendCodeModification("AAA", "A 123", "123@123", "it"), new SendCodeModification("456", "A 456", "456@456", "en"));
expect.exception(IllegalArgumentException.class, () -> specialPriceManager.linkAssigneeToCode(notExistingCode, "test", 0, "username"));
});
});

describe("validation error (code requested twice)", it -> {
it.initializesWith(setRestricted(ticketCategory, true));
it.should("throw an exception (code requested twice)", expect -> {
Set<SendCodeModification> duplicatedCodes = new HashSet<>(asList(new SendCodeModification("123", "A 123", "123@123", "it"), new SendCodeModification("123", "A 456", "456@456", "en")));
List<SendCodeModification> duplicatedCodes = asList(new SendCodeModification("123", "A 123", "123@123", "it"), new SendCodeModification("123", "A 456", "456@456", "en"));
expect.exception(IllegalArgumentException.class, () -> specialPriceManager.linkAssigneeToCode(duplicatedCodes, "test", 0, "username"));
});
});
Expand All @@ -107,12 +123,12 @@ public class SpecialPriceManagerTest {{
describe("send successful - detailed test", it -> {
it.initializesWith(setRestricted(ticketCategory, true));
it.should("send the given code", expect -> {
expect.that(specialPriceManager.sendCodeToAssignee(singleton(new SendCodeModification("123", "me", "[email protected]", "it")), "", 0, "")).is(true);
expect.that(specialPriceManager.sendCodeToAssignee(singletonList(new SendCodeModification("123", "me", "[email protected]", "it")), "", 0, "")).is(true);
ArgumentCaptor<TextTemplateGenerator> templateCaptor = ArgumentCaptor.forClass(TextTemplateGenerator.class);
verify(notificationManager).sendSimpleEmail(eq(event), eq("[email protected]"), anyString(), templateCaptor.capture());
templateCaptor.getValue().generate();
ArgumentCaptor<Map> captor = ArgumentCaptor.forClass(Map.class);
verify(templateManager).renderClassPathResource(endsWith("send-reserved-code-txt.ms"), captor.capture(), eq(Locale.ITALIAN));
verify(templateManager).renderClassPathResource(endsWith("send-reserved-code-txt.ms"), captor.capture(), eq(Locale.ITALIAN), eq(TemplateManager.TemplateOutput.TEXT));
Map<String, Object> model = captor.getValue();
expect.that(model.get("code")).isEqualTo("123");
expect.that(model.get("event")).isEqualTo(event);
Expand All @@ -132,7 +148,7 @@ private static Block setRestricted(TicketCategory ticketCategory, boolean restri
return () -> when(ticketCategory.isAccessRestricted()).thenReturn(restricted);
}

private static Specification testAssigneeLink(SpecialPriceManager specialPriceManager, Set<SendCodeModification> modifications) {
private static Specification testAssigneeLink(SpecialPriceManager specialPriceManager, List<SendCodeModification> modifications) {
return expect -> {
List<SendCodeModification> sendCodeModifications = specialPriceManager.linkAssigneeToCode(modifications, "test", 0, "username");
expect.that(sendCodeModifications.isEmpty()).isEqualTo(false);
Expand All @@ -141,7 +157,7 @@ private static Specification testAssigneeLink(SpecialPriceManager specialPriceMa
};
}

private static final Set<SendCodeModification> CODES_REQUESTED = new HashSet<>(asList(new SendCodeModification("123", "A 123", "123@123", "it"), new SendCodeModification("456", "A 456", "456@456", "en")));
private static final Set<SendCodeModification> CODES_NOT_REQUESTED = new HashSet<>(asList(new SendCodeModification(null, "A 123", "123@123", "it"), new SendCodeModification(null, "A 456", "456@456", "en")));
private static final Set<SendCodeModification> CODES_PARTIALLY_REQUESTED = new HashSet<>(asList(new SendCodeModification(null, "A 123", "123@123", "it"), new SendCodeModification("456", "A 456", "456@456", "en")));
private static final List<SendCodeModification> CODES_REQUESTED = asList(new SendCodeModification("123", "A 123", "123@123", "it"), new SendCodeModification("456", "A 456", "456@456", "en"));
private static final List<SendCodeModification> CODES_NOT_REQUESTED = asList(new SendCodeModification(null, "A 123", "123@123", "it"), new SendCodeModification(null, "A 456", "456@456", "en"));
private static final List<SendCodeModification> CODES_PARTIALLY_REQUESTED = asList(new SendCodeModification(null, "A 123", "123@123", "it"), new SendCodeModification("456", "A 456", "456@456", "en"));
}

0 comments on commit 0d24524

Please sign in to comment.