initial commit
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>de.bstly.we</groupId>
|
||||
<artifactId>webstly-main</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
|
||||
<name>membership</name>
|
||||
<artifactId>webstly-membership</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>de.bstly.we</groupId>
|
||||
<artifactId>webstly-core</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,816 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package de.bstly.we.membership.businesslogic;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.Instant;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.Period;
|
||||
import java.time.format.DateTimeParseException;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.apache.commons.csv.CSVFormat;
|
||||
import org.apache.commons.csv.CSVPrinter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.beust.jcommander.internal.Lists;
|
||||
import com.beust.jcommander.internal.Maps;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import de.bstly.we.businesslogic.PretixManager;
|
||||
import de.bstly.we.businesslogic.SystemPropertyManager;
|
||||
import de.bstly.we.businesslogic.support.InstantHelper;
|
||||
|
||||
/**
|
||||
* @author _bastler@bstly.de
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
public class MembershipManager {
|
||||
|
||||
@Autowired
|
||||
private PretixManager pretixManager;
|
||||
@Autowired
|
||||
private SystemPropertyManager systemPropertyManager;
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger(MembershipManager.class);
|
||||
private DateFormat pretixDateFormat = new SimpleDateFormat("yyyy-MM-dd");
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public void generateMembershipIds() {
|
||||
String membershipItemId = systemPropertyManager
|
||||
.get(PretixManager.SYSTEM_PROPERTY_PRETIX_MEMBERSHIP_ITEM, "");
|
||||
|
||||
int membershipInternalIdQuestion = systemPropertyManager.getInteger(
|
||||
PretixManager.SYSTEM_PROPERTY_PRETIX_MEMBERSHIP_INTERNAL_ID_QUESTION, 0);
|
||||
|
||||
int membershipIdQuestion = systemPropertyManager
|
||||
.getInteger(PretixManager.SYSTEM_PROPERTY_PRETIX_MEMBERSHIP_ID_QUESTION, 0);
|
||||
|
||||
if (!StringUtils.hasText(membershipItemId) || membershipInternalIdQuestion == 0
|
||||
|| membershipIdQuestion == 0) {
|
||||
logger.warn("Required system properties for 'generateMembershipIds' not set!");
|
||||
return;
|
||||
}
|
||||
|
||||
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<String, String>();
|
||||
queryParams.add("ordering", "order__datetime");
|
||||
queryParams.add("item", membershipItemId);
|
||||
queryParams.add("order__status", "p");
|
||||
|
||||
List<JsonObject> orderPositions = fetchAllOrderPositions(
|
||||
String.format("/api/v1/organizers/%s/events/%s/orderpositions/",
|
||||
pretixManager.getOrganizer(), pretixManager.getEvent()),
|
||||
queryParams, Lists.newArrayList());
|
||||
|
||||
Map<Instant, JsonObject> newMembershipPositions = new TreeMap<Instant, JsonObject>();
|
||||
|
||||
int nextMembershipId = 1;
|
||||
for (JsonObject orderPosition : orderPositions) {
|
||||
JsonArray answers = new JsonArray();
|
||||
if (orderPosition.has("answers")) {
|
||||
answers = orderPosition.getAsJsonArray("answers");
|
||||
}
|
||||
|
||||
boolean hasInternalMembershipId = false;
|
||||
|
||||
int internalMembershipId = getNumberAnswer(orderPosition, membershipInternalIdQuestion);
|
||||
|
||||
if (internalMembershipId > 0) {
|
||||
if (internalMembershipId >= nextMembershipId) {
|
||||
nextMembershipId = internalMembershipId + 1;
|
||||
}
|
||||
hasInternalMembershipId = true;
|
||||
}
|
||||
|
||||
if (!hasInternalMembershipId) {
|
||||
newMembershipPositions.put(pretixManager.getLastPaymentDateForOrder(
|
||||
orderPosition.get("order").getAsString()), orderPosition);
|
||||
} else {
|
||||
boolean writeMembershipId = true;
|
||||
|
||||
JsonObject membershipIdAnswer = getAnswerObject(orderPosition,
|
||||
membershipIdQuestion);
|
||||
|
||||
if (membershipIdAnswer != null) {
|
||||
int membershipId = Integer.valueOf(membershipIdAnswer.get("answer").getAsInt());
|
||||
if (internalMembershipId == membershipId) {
|
||||
writeMembershipId = false;
|
||||
logger.trace("Order '" + orderPosition.get("order").getAsString()
|
||||
+ "' already processed, membership id: '" + membershipId + "'");
|
||||
}
|
||||
}
|
||||
|
||||
if (writeMembershipId) {
|
||||
if (membershipIdAnswer == null) {
|
||||
membershipIdAnswer = new JsonObject();
|
||||
membershipIdAnswer.addProperty("question", membershipIdQuestion);
|
||||
membershipIdAnswer.add("options", new JsonArray());
|
||||
membershipIdAnswer.add("option_identifiers", new JsonArray());
|
||||
answers.add(membershipIdAnswer);
|
||||
}
|
||||
|
||||
membershipIdAnswer.addProperty("answer", internalMembershipId);
|
||||
|
||||
JsonObject payload = new JsonObject();
|
||||
payload.add("answers", answers);
|
||||
|
||||
logger.debug(
|
||||
"Write membershipId for '" + orderPosition.get("order").getAsString()
|
||||
+ "': " + internalMembershipId);
|
||||
|
||||
pretixManager.request(
|
||||
String.format("/api/v1/organizers/%s/events/%s/orderpositions/%s/",
|
||||
pretixManager.getOrganizer(), pretixManager.getEvent(),
|
||||
orderPosition.get("id").getAsString()),
|
||||
HttpMethod.PATCH, payload);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Iterator<Entry<Instant, JsonObject>> iterator = newMembershipPositions.entrySet()
|
||||
.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<Instant, JsonObject> entry = iterator.next();
|
||||
JsonObject orderPosition = entry.getValue();
|
||||
JsonArray answers = new JsonArray();
|
||||
if (orderPosition.has("answers")) {
|
||||
answers = orderPosition.getAsJsonArray("answers");
|
||||
}
|
||||
|
||||
JsonObject membershipInternalIdAnswer = new JsonObject();
|
||||
membershipInternalIdAnswer.addProperty("question", membershipInternalIdQuestion);
|
||||
membershipInternalIdAnswer.add("options", new JsonArray());
|
||||
membershipInternalIdAnswer.add("option_identifiers", new JsonArray());
|
||||
membershipInternalIdAnswer.addProperty("answer", nextMembershipId);
|
||||
answers.add(membershipInternalIdAnswer);
|
||||
|
||||
JsonObject membershipIdAnswer = new JsonObject();
|
||||
membershipIdAnswer.addProperty("question", membershipIdQuestion);
|
||||
membershipIdAnswer.add("options", new JsonArray());
|
||||
membershipIdAnswer.add("option_identifiers", new JsonArray());
|
||||
membershipIdAnswer.addProperty("answer", nextMembershipId);
|
||||
answers.add(membershipIdAnswer);
|
||||
|
||||
JsonObject payload = new JsonObject();
|
||||
|
||||
payload.add("answers", answers);
|
||||
|
||||
logger.debug("Create membershipId for '" + orderPosition.get("order").getAsString()
|
||||
+ "': " + nextMembershipId);
|
||||
|
||||
pretixManager
|
||||
.request(
|
||||
String.format("/api/v1/organizers/%s/events/%s/orderpositions/%s/",
|
||||
pretixManager.getOrganizer(), pretixManager.getEvent(),
|
||||
orderPosition.get("id").getAsString()),
|
||||
HttpMethod.PATCH, payload);
|
||||
|
||||
nextMembershipId++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public void activeMemberships() {
|
||||
|
||||
String membershipItemId = systemPropertyManager
|
||||
.get(PretixManager.SYSTEM_PROPERTY_PRETIX_MEMBERSHIP_ITEM, "");
|
||||
|
||||
String membershipFeeItemId = systemPropertyManager
|
||||
.get(PretixManager.SYSTEM_PROPERTY_PRETIX_MEMBERSHIPFEE_ITEM, "");
|
||||
|
||||
int membershipInternalIdQuestion = systemPropertyManager.getInteger(
|
||||
PretixManager.SYSTEM_PROPERTY_PRETIX_MEMBERSHIP_INTERNAL_ID_QUESTION, 0);
|
||||
|
||||
int membershipFeeReferenceQuestion = systemPropertyManager.getInteger(
|
||||
PretixManager.SYSTEM_PROPERTY_PRETIX_MEMBERSHIPFEE_REFERENCE_QUESTION, 0);
|
||||
|
||||
int membershipActiveQuestion = systemPropertyManager
|
||||
.getInteger(PretixManager.SYSTEM_PROPERTY_PRETIX_MEMBERSHIP_ACTIVE_QUESTION, 0);
|
||||
|
||||
if (!StringUtils.hasText(membershipItemId) || !StringUtils.hasText(membershipFeeItemId)
|
||||
|| membershipInternalIdQuestion == 0 || membershipFeeReferenceQuestion == 0
|
||||
|| membershipActiveQuestion == 0) {
|
||||
logger.warn("Required system properties for 'activeMemberships' not set!");
|
||||
return;
|
||||
}
|
||||
|
||||
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<String, String>();
|
||||
queryParams.add("ordering", "order__datetime");
|
||||
queryParams.add("item", membershipItemId);
|
||||
queryParams.add("order__status", "p");
|
||||
|
||||
List<JsonObject> membershipOrderPositions = fetchAllOrderPositions(
|
||||
String.format("/api/v1/organizers/%s/events/%s/orderpositions/",
|
||||
pretixManager.getOrganizer(), pretixManager.getEvent()),
|
||||
queryParams, Lists.newArrayList());
|
||||
|
||||
queryParams.remove("item");
|
||||
queryParams.add("item", membershipFeeItemId);
|
||||
|
||||
List<JsonObject> membershipfeeOrderPositions = fetchAllOrderPositions(
|
||||
String.format("/api/v1/organizers/%s/events/%s/orderpositions/",
|
||||
pretixManager.getOrganizer(), pretixManager.getEvent()),
|
||||
queryParams, Lists.newArrayList());
|
||||
|
||||
Map<Integer, List<JsonObject>> membershipfeeOrderPositionMap = Maps.newHashMap();
|
||||
|
||||
for (JsonObject membershipFeeOrderPosition : membershipfeeOrderPositions) {
|
||||
int membershipReference = getNumberAnswer(membershipFeeOrderPosition,
|
||||
membershipFeeReferenceQuestion);
|
||||
if (!membershipfeeOrderPositionMap.containsKey(membershipReference)) {
|
||||
membershipfeeOrderPositionMap.put(membershipReference, Lists.newArrayList());
|
||||
}
|
||||
membershipfeeOrderPositionMap.get(membershipReference).add(membershipFeeOrderPosition);
|
||||
}
|
||||
|
||||
for (JsonObject membershipOrderPosition : membershipOrderPositions) {
|
||||
JsonArray answers = new JsonArray();
|
||||
if (membershipOrderPosition.has("answers")) {
|
||||
answers = membershipOrderPosition.getAsJsonArray("answers");
|
||||
}
|
||||
|
||||
JsonObject membershipActiveAnswer = getAnswerObject(membershipOrderPosition,
|
||||
membershipActiveQuestion);
|
||||
int membershipId = getNumberAnswer(membershipOrderPosition,
|
||||
membershipInternalIdQuestion);
|
||||
|
||||
if (membershipId == 0) {
|
||||
logger.warn("No membership number found for '"
|
||||
+ membershipOrderPosition.get("order").getAsString() + "'!");
|
||||
continue;
|
||||
}
|
||||
|
||||
Instant membershipStart = pretixManager
|
||||
.getLastPaymentDateForOrder(membershipOrderPosition.get("order").getAsString());
|
||||
|
||||
if (membershipStart == null) {
|
||||
logger.warn("No last payment found for '"
|
||||
+ membershipOrderPosition.get("order").getAsString() + "'!");
|
||||
continue;
|
||||
}
|
||||
|
||||
int years = 1;
|
||||
|
||||
if (membershipfeeOrderPositionMap.containsKey(membershipId)) {
|
||||
years += membershipfeeOrderPositionMap.get(membershipId).size();
|
||||
}
|
||||
|
||||
Instant active = InstantHelper.truncate(
|
||||
InstantHelper.plus(membershipStart, years, ChronoUnit.YEARS), ChronoUnit.YEARS);
|
||||
|
||||
String activeAnswer = pretixDateFormat.format(Date.from(active));
|
||||
|
||||
if (membershipActiveAnswer == null) {
|
||||
membershipActiveAnswer = new JsonObject();
|
||||
membershipActiveAnswer.addProperty("question", membershipActiveQuestion);
|
||||
membershipActiveAnswer.add("options", new JsonArray());
|
||||
membershipActiveAnswer.add("option_identifiers", new JsonArray());
|
||||
answers.add(membershipActiveAnswer);
|
||||
}
|
||||
|
||||
if (!membershipActiveAnswer.has("answer")
|
||||
|| !activeAnswer.equals(membershipActiveAnswer.get("answer").getAsString())) {
|
||||
membershipActiveAnswer.addProperty("answer", activeAnswer);
|
||||
|
||||
JsonObject payload = new JsonObject();
|
||||
|
||||
payload.add("answers", answers);
|
||||
pretixManager.request(
|
||||
String.format("/api/v1/organizers/%s/events/%s/orderpositions/%s/",
|
||||
pretixManager.getOrganizer(), pretixManager.getEvent(),
|
||||
membershipOrderPosition.get("id").getAsString()),
|
||||
HttpMethod.PATCH, payload);
|
||||
|
||||
logger.debug("Write active state for '"
|
||||
+ membershipOrderPosition.get("order").getAsString() + "': "
|
||||
+ activeAnswer);
|
||||
} else {
|
||||
logger.trace("Order active state for '"
|
||||
+ membershipOrderPosition.get("order").getAsString() + "' already set: "
|
||||
+ activeAnswer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public void createMembershipExtension() {
|
||||
|
||||
String membershipItemId = systemPropertyManager
|
||||
.get(PretixManager.SYSTEM_PROPERTY_PRETIX_MEMBERSHIP_ITEM, "");
|
||||
|
||||
String membershipFeeItemId = systemPropertyManager
|
||||
.get(PretixManager.SYSTEM_PROPERTY_PRETIX_MEMBERSHIPFEE_ITEM, "");
|
||||
|
||||
int membershipInternalIdQuestion = systemPropertyManager.getInteger(
|
||||
PretixManager.SYSTEM_PROPERTY_PRETIX_MEMBERSHIP_INTERNAL_ID_QUESTION, 0);
|
||||
|
||||
int membershipFeeReferenceQuestion = systemPropertyManager.getInteger(
|
||||
PretixManager.SYSTEM_PROPERTY_PRETIX_MEMBERSHIPFEE_REFERENCE_QUESTION, 0);
|
||||
|
||||
int membershipFeeCodeQuestion = systemPropertyManager
|
||||
.getInteger(PretixManager.SYSTEM_PROPERTY_PRETIX_MEMBERSHIPFEE_CODE_QUESTION, 0);
|
||||
|
||||
int membershipActiveQuestion = systemPropertyManager
|
||||
.getInteger(PretixManager.SYSTEM_PROPERTY_PRETIX_MEMBERSHIP_ACTIVE_QUESTION, 0);
|
||||
|
||||
int membershipfeeOrderDays = systemPropertyManager
|
||||
.getInteger(PretixManager.SYSTEM_PROPERTY_PRETIX_MEMBERSHIPFEE_ORDER_DAYS, 0);
|
||||
|
||||
int membershipfeeReminderDays = systemPropertyManager
|
||||
.getInteger(PretixManager.SYSTEM_PROPERTY_PRETIX_MEMBERSHIPFEE_REMINDER_DAYS, 0);
|
||||
|
||||
int membershipfeeReminderQuestion = systemPropertyManager.getInteger(
|
||||
PretixManager.SYSTEM_PROPERTY_PRETIX_MEMBERSHIPFEE_REMINDER_QUESTION, 0);
|
||||
|
||||
boolean orderSendmail = systemPropertyManager
|
||||
.getBoolean(PretixManager.SYSTEM_PROPERTY_PRETIX_ORDER_SENDMAIL, false);
|
||||
boolean orderTestmode = systemPropertyManager
|
||||
.getBoolean(PretixManager.SYSTEM_PROPERTY_PRETIX_ORDER_TESTMODE, true);
|
||||
boolean orderSimulate = systemPropertyManager
|
||||
.getBoolean(PretixManager.SYSTEM_PROPERTY_PRETIX_ORDER_SIMULATE, false);
|
||||
|
||||
if (!StringUtils.hasText(membershipItemId) || !StringUtils.hasText(membershipFeeItemId)
|
||||
|| membershipInternalIdQuestion == 0 || membershipFeeReferenceQuestion == 0
|
||||
|| membershipFeeCodeQuestion == 0 || membershipActiveQuestion == 0
|
||||
|| membershipfeeOrderDays == 0) {
|
||||
logger.warn("Required system properties for 'createMembershipExtension' not set!");
|
||||
return;
|
||||
}
|
||||
|
||||
MultiValueMap<String, String> queryMembershipParams = new LinkedMultiValueMap<String, String>();
|
||||
queryMembershipParams.add("ordering", "order__datetime");
|
||||
queryMembershipParams.add("item", membershipItemId);
|
||||
queryMembershipParams.add("order__status", "p");
|
||||
|
||||
List<JsonObject> membershipOrderPositions = fetchAllOrderPositions(
|
||||
String.format("/api/v1/organizers/%s/events/%s/orderpositions/",
|
||||
pretixManager.getOrganizer(), pretixManager.getEvent()),
|
||||
queryMembershipParams, Lists.newArrayList());
|
||||
|
||||
List<JsonObject> expireMemberships = Lists.newArrayList();
|
||||
|
||||
for (JsonObject membershipOrderPosition : membershipOrderPositions) {
|
||||
Instant active = getDateAnswer(membershipOrderPosition, membershipActiveQuestion);
|
||||
if (active.isAfter(InstantHelper.truncate(Instant.now(), ChronoUnit.YEARS))
|
||||
&& InstantHelper.minus(active, membershipfeeOrderDays, ChronoUnit.DAYS)
|
||||
.isBefore(Instant.now())) {
|
||||
expireMemberships.add(membershipOrderPosition);
|
||||
} else {
|
||||
logger.trace("Membership '" + membershipOrderPosition.get("order").getAsString()
|
||||
+ "' not expiring in next " + membershipfeeOrderDays + " days.");
|
||||
}
|
||||
}
|
||||
|
||||
MultiValueMap<String, String> queryMembershipFeeParams = new LinkedMultiValueMap<String, String>();
|
||||
queryMembershipFeeParams.add("ordering", "order__datetime");
|
||||
queryMembershipFeeParams.add("item", membershipFeeItemId);
|
||||
queryMembershipFeeParams.add("order__status__in", "n,e,c");
|
||||
|
||||
List<JsonObject> membershipfeeOrderPositions = fetchAllOrderPositions(
|
||||
String.format("/api/v1/organizers/%s/events/%s/orderpositions/",
|
||||
pretixManager.getOrganizer(), pretixManager.getEvent()),
|
||||
queryMembershipFeeParams, Lists.newArrayList());
|
||||
|
||||
Map<Integer, List<JsonObject>> membershipfeeOrderPositionMap = Maps.newHashMap();
|
||||
|
||||
for (JsonObject membershipfeeOrderPosition : membershipfeeOrderPositions) {
|
||||
int membershipReference = getNumberAnswer(membershipfeeOrderPosition,
|
||||
membershipFeeReferenceQuestion);
|
||||
|
||||
JsonObject membershipFeeOrder = pretixManager
|
||||
.getOrder(membershipfeeOrderPosition.get("order").getAsString());
|
||||
|
||||
Instant membershipFeeOrderDatetime = OffsetDateTime
|
||||
.parse(membershipFeeOrder.get("datetime").getAsString()).toInstant();
|
||||
|
||||
if (membershipFeeOrderDatetime
|
||||
.isAfter(InstantHelper.truncate(Instant.now(), ChronoUnit.YEARS))) {
|
||||
if (!membershipfeeOrderPositionMap.containsKey(membershipReference)) {
|
||||
membershipfeeOrderPositionMap.put(membershipReference, Lists.newArrayList());
|
||||
}
|
||||
|
||||
membershipfeeOrderPositionMap.get(membershipReference)
|
||||
.add(membershipfeeOrderPosition);
|
||||
}
|
||||
}
|
||||
|
||||
for (JsonObject membershipOrderPosition : expireMemberships) {
|
||||
int membershipId = getNumberAnswer(membershipOrderPosition,
|
||||
membershipInternalIdQuestion);
|
||||
Instant active = getDateAnswer(membershipOrderPosition, membershipActiveQuestion);
|
||||
|
||||
if (membershipId == 0) {
|
||||
logger.warn("No membership number found for '"
|
||||
+ membershipOrderPosition.get("order").getAsString() + "'!");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!membershipfeeOrderPositionMap.containsKey(membershipId)
|
||||
|| membershipfeeOrderPositionMap.get(membershipId).isEmpty()) {
|
||||
JsonObject membershipOrder = pretixManager
|
||||
.getOrder(membershipOrderPosition.get("order").getAsString());
|
||||
|
||||
JsonObject membershipFeeOrder = new JsonObject();
|
||||
membershipFeeOrder.add("email", membershipOrder.get("email"));
|
||||
membershipFeeOrder.add("locale", membershipOrder.get("locale"));
|
||||
|
||||
JsonArray membershipFeeOrderPositions = new JsonArray();
|
||||
JsonObject membershipFeeOrderPosition = new JsonObject();
|
||||
|
||||
membershipFeeOrderPosition.addProperty("item", membershipFeeItemId);
|
||||
|
||||
JsonArray membershipFeeOrderPositionAnswers = new JsonArray();
|
||||
JsonObject membershipFeeReferenceAnswer = new JsonObject();
|
||||
membershipFeeReferenceAnswer.addProperty("question",
|
||||
membershipFeeReferenceQuestion);
|
||||
membershipFeeReferenceAnswer.add("options", new JsonArray());
|
||||
membershipFeeReferenceAnswer.add("option_identifiers", new JsonArray());
|
||||
membershipFeeReferenceAnswer.addProperty("answer", membershipId);
|
||||
membershipFeeOrderPositionAnswers.add(membershipFeeReferenceAnswer);
|
||||
|
||||
JsonObject membershipFeeCodeAnswer = new JsonObject();
|
||||
membershipFeeCodeAnswer.addProperty("question",
|
||||
membershipFeeCodeQuestion);
|
||||
membershipFeeCodeAnswer.add("options", new JsonArray());
|
||||
membershipFeeCodeAnswer.add("option_identifiers", new JsonArray());
|
||||
membershipFeeCodeAnswer.addProperty("answer", membershipOrderPosition.get("order").getAsString());
|
||||
membershipFeeOrderPositionAnswers.add(membershipFeeCodeAnswer);
|
||||
|
||||
membershipFeeOrderPosition.add("answers", membershipFeeOrderPositionAnswers);
|
||||
|
||||
membershipFeeOrderPositions.add(membershipFeeOrderPosition);
|
||||
|
||||
membershipFeeOrder.add("locale", membershipOrder.get("locale"));
|
||||
membershipFeeOrder.add("positions", membershipFeeOrderPositions);
|
||||
|
||||
if (membershipOrder.has("payments")
|
||||
&& membershipOrder.getAsJsonArray("payments").size() > 0) {
|
||||
JsonObject payment = membershipOrder.getAsJsonArray("payments").get(0)
|
||||
.getAsJsonObject();
|
||||
membershipFeeOrder.add("payment_provider", payment.get("provider"));
|
||||
}
|
||||
|
||||
membershipFeeOrder.addProperty("send_email", orderSendmail);
|
||||
membershipFeeOrder.addProperty("testmode", orderTestmode);
|
||||
membershipFeeOrder.addProperty("simulate", orderSimulate);
|
||||
|
||||
membershipFeeOrder = pretixManager.createOrder(membershipFeeOrder);
|
||||
|
||||
JsonObject expire = new JsonObject();
|
||||
Instant expires = InstantHelper.minus(InstantHelper.truncate(
|
||||
InstantHelper.plus(Instant.now(), 1, ChronoUnit.YEARS), ChronoUnit.YEARS),
|
||||
1, ChronoUnit.DAYS);
|
||||
expire.addProperty("expires", pretixDateFormat.format(Date.from(expires)));
|
||||
membershipFeeOrder = pretixManager
|
||||
.extendOrder(membershipFeeOrder.get("code").getAsString(), expire);
|
||||
|
||||
logger.debug("Create membership fee order: " + membershipFeeOrder.toString());
|
||||
} else
|
||||
// send reminder mail for membership fee order
|
||||
if (membershipfeeReminderDays > 0 && membershipfeeReminderQuestion > 0
|
||||
&& active.isAfter(InstantHelper.truncate(Instant.now(), ChronoUnit.YEARS))
|
||||
&& InstantHelper.minus(active, membershipfeeReminderDays, ChronoUnit.DAYS)
|
||||
.isBefore(Instant.now())) {
|
||||
|
||||
for (JsonObject membershipfeeOrderPosition : membershipfeeOrderPositionMap
|
||||
.get(membershipId)) {
|
||||
|
||||
JsonObject membershipFeeOrder = pretixManager
|
||||
.getOrder(membershipfeeOrderPosition.get("order").getAsString());
|
||||
|
||||
if (!"c".equals(membershipFeeOrder.get("status").getAsString())) {
|
||||
JsonArray membershipfeeAnswers = new JsonArray();
|
||||
if (membershipfeeOrderPosition.has("answers")) {
|
||||
membershipfeeAnswers = membershipfeeOrderPosition
|
||||
.getAsJsonArray("answers");
|
||||
}
|
||||
|
||||
JsonObject membershipReminderAnswer = getAnswerObject(
|
||||
membershipfeeOrderPosition, membershipfeeReminderQuestion);
|
||||
|
||||
if (membershipReminderAnswer == null) {
|
||||
membershipReminderAnswer = new JsonObject();
|
||||
membershipReminderAnswer.addProperty("question",
|
||||
membershipfeeReminderQuestion);
|
||||
membershipReminderAnswer.add("options", new JsonArray());
|
||||
membershipReminderAnswer.add("option_identifiers", new JsonArray());
|
||||
membershipReminderAnswer.addProperty("answer", "false");
|
||||
membershipfeeAnswers.add(membershipReminderAnswer);
|
||||
}
|
||||
|
||||
if (!membershipReminderAnswer.get("answer").getAsBoolean()) {
|
||||
membershipReminderAnswer.addProperty("answer", "true");
|
||||
|
||||
pretixManager.sendEmail(
|
||||
membershipfeeOrderPosition.get("order").getAsString());
|
||||
|
||||
JsonObject payload = new JsonObject();
|
||||
|
||||
payload.add("answers", membershipfeeAnswers);
|
||||
pretixManager.request(
|
||||
String.format(
|
||||
"/api/v1/organizers/%s/events/%s/orderpositions/%s/",
|
||||
pretixManager.getOrganizer(), pretixManager.getEvent(),
|
||||
membershipfeeOrderPosition.get("id").getAsString()),
|
||||
HttpMethod.PATCH, payload);
|
||||
|
||||
logger.debug("Send reminder for membership fee order: "
|
||||
+ membershipfeeOrderPosition.get("order").getAsString());
|
||||
} else {
|
||||
logger.debug("Reminder for Membership fee order of'"
|
||||
+ membershipfeeOrderPosition.get("order").getAsString()
|
||||
+ "' already created.");
|
||||
}
|
||||
} else {
|
||||
logger.debug("Membership fee order for'"
|
||||
+ membershipfeeOrderPosition.get("order").getAsString()
|
||||
+ "' is canceled, no reminder.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logger.debug("Membership fee order for '"
|
||||
+ membershipOrderPosition.get("order").getAsString()
|
||||
+ "' already created, no reminder.");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public void calculatePrice() {
|
||||
int membershipItemId = systemPropertyManager
|
||||
.getInteger(PretixManager.SYSTEM_PROPERTY_PRETIX_MEMBERSHIP_ITEM, 0);
|
||||
String discountPeriod = systemPropertyManager
|
||||
.get(PretixManager.SYSTEM_PROPERTY_PRETIX_MEMBERSHIP_DISCOUNT_PERIOD, "");
|
||||
|
||||
if (!StringUtils.hasText(discountPeriod) || membershipItemId == 0) {
|
||||
logger.warn("Required system properties for 'calculatePrice' not set!");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
int position = -1;
|
||||
Period period = Period.parse(discountPeriod);
|
||||
|
||||
Period oneYear = Period.ofYears(1);
|
||||
|
||||
long variations = InstantHelper.plus(Instant.ofEpochMilli(0), oneYear).getEpochSecond()
|
||||
/ InstantHelper.plus(Instant.ofEpochMilli(0), period).getEpochSecond();
|
||||
|
||||
Instant compare = InstantHelper.truncate(Instant.now(), ChronoUnit.YEARS);
|
||||
|
||||
while (compare.isBefore(Instant.now())) {
|
||||
compare = InstantHelper.plus(compare, period);
|
||||
position++;
|
||||
}
|
||||
|
||||
JsonObject defaultVariation = new JsonObject();
|
||||
defaultVariation.addProperty("active", true);
|
||||
int defaultVariationId = 0;
|
||||
boolean applyDefault = true;
|
||||
|
||||
for (JsonElement variationElement : pretixManager.getVariations(membershipItemId)) {
|
||||
JsonObject variation = variationElement.getAsJsonObject();
|
||||
JsonObject variationUpdate = new JsonObject();
|
||||
int variationId = variation.get("id").getAsInt();
|
||||
int variationPosition = variation.get("position").getAsInt();
|
||||
|
||||
if (variationPosition < variations) {
|
||||
|
||||
variationUpdate.addProperty("active", false);
|
||||
if (variationPosition == 0) {
|
||||
defaultVariationId = variationId;
|
||||
}
|
||||
|
||||
if (variationPosition == position) {
|
||||
variationUpdate.addProperty("active", true);
|
||||
applyDefault = false;
|
||||
}
|
||||
pretixManager.updateVariation(membershipItemId, variationId, variationUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
if (applyDefault && defaultVariationId > 0) {
|
||||
pretixManager.updateVariation(membershipItemId, defaultVariationId,
|
||||
defaultVariation);
|
||||
}
|
||||
|
||||
} catch (DateTimeParseException e) {
|
||||
logger.error("Error in parsing 'pretix.membership.discount.period'!", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param writer
|
||||
* @param includeInactive
|
||||
* @return
|
||||
*/
|
||||
public JsonArray membershipCsvExport(Writer writer, boolean includeInactive) {
|
||||
String membershipItemId = systemPropertyManager
|
||||
.get(PretixManager.SYSTEM_PROPERTY_PRETIX_MEMBERSHIP_ITEM, "0");
|
||||
|
||||
int membershipActiveQuestion = systemPropertyManager
|
||||
.getInteger(PretixManager.SYSTEM_PROPERTY_PRETIX_MEMBERSHIP_ACTIVE_QUESTION, 0);
|
||||
|
||||
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<String, String>();
|
||||
queryParams.add("item", membershipItemId);
|
||||
queryParams.add("order__status", "p");
|
||||
|
||||
JsonArray members = new JsonArray();
|
||||
|
||||
List<String> answerHeaders = Lists.newArrayList();
|
||||
|
||||
List<JsonObject> orderPositions = fetchAllOrderPositions(
|
||||
String.format("/api/v1/organizers/%s/events/%s/orderpositions/",
|
||||
pretixManager.getOrganizer(), pretixManager.getEvent()),
|
||||
queryParams, Lists.newArrayList());
|
||||
|
||||
for (JsonObject orderPosition : orderPositions) {
|
||||
JsonObject order = pretixManager
|
||||
.request(
|
||||
String.format("/api/v1/organizers/%s/events/%s/orders/%s/",
|
||||
pretixManager.getOrganizer(), pretixManager.getEvent(),
|
||||
orderPosition.get("order").getAsString()),
|
||||
HttpMethod.GET, queryParams)
|
||||
.getAsJsonObject();
|
||||
|
||||
JsonObject member = new JsonObject();
|
||||
|
||||
member.addProperty("email", order.get("email").getAsString());
|
||||
JsonObject answers = new JsonObject();
|
||||
Instant active = null;
|
||||
if (orderPosition.has("answers")) {
|
||||
for (JsonElement answerElement : orderPosition.getAsJsonArray("answers")) {
|
||||
JsonObject answer = answerElement.getAsJsonObject();
|
||||
String question_identifier = answer.get("question_identifier").getAsString();
|
||||
if (!answerHeaders.contains(question_identifier)) {
|
||||
answerHeaders.add(question_identifier);
|
||||
}
|
||||
answers.addProperty(question_identifier, answer.get("answer").getAsString());
|
||||
if (membershipActiveQuestion == answer.get("question").getAsInt()
|
||||
&& answer.has("answer")) {
|
||||
|
||||
Date date;
|
||||
try {
|
||||
date = pretixDateFormat.parse(answer.get("answer").getAsString());
|
||||
active = date.toInstant();
|
||||
} catch (ParseException e) {
|
||||
logger.error("Error on parsing active date for '"
|
||||
+ orderPosition.get("order").getAsString() + "'!", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
member.add("answers", answers);
|
||||
if (includeInactive || active != null
|
||||
&& active.isAfter(InstantHelper.truncate(Instant.now(), ChronoUnit.YEARS))) {
|
||||
members.add(member);
|
||||
}
|
||||
}
|
||||
|
||||
try (CSVPrinter csvPrinter = new CSVPrinter(writer, CSVFormat.DEFAULT)) {
|
||||
List<String> csvHeaders = Lists.newArrayList();
|
||||
csvHeaders.add("email");
|
||||
csvHeaders.addAll(answerHeaders);
|
||||
csvPrinter.printRecord(csvHeaders);
|
||||
|
||||
for (JsonElement memberElement : members) {
|
||||
JsonObject member = memberElement.getAsJsonObject();
|
||||
JsonObject answers = member.getAsJsonObject("answers");
|
||||
List<String> records = Lists.newArrayList();
|
||||
records.add(member.get("email").getAsString());
|
||||
for (String answer : answerHeaders) {
|
||||
if (answers.has(answer)) {
|
||||
records.add(answers.get(answer).getAsString());
|
||||
} else {
|
||||
records.add(null);
|
||||
}
|
||||
}
|
||||
csvPrinter.printRecord(records);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return members;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Scheduled(cron = "${we.bstly.membership.cron:0 0 0 * * * }")
|
||||
public void cron() {
|
||||
generateMembershipIds();
|
||||
activeMemberships();
|
||||
createMembershipExtension();
|
||||
calculatePrice();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param path
|
||||
* @param queryParams
|
||||
* @param result
|
||||
* @return
|
||||
*/
|
||||
protected List<JsonObject> fetchAllOrderPositions(String path,
|
||||
MultiValueMap<String, String> queryParams, List<JsonObject> result) {
|
||||
JsonObject orderPositions = pretixManager.request(path, HttpMethod.GET, queryParams)
|
||||
.getAsJsonObject();
|
||||
|
||||
for (JsonElement element : orderPositions.getAsJsonArray("results")) {
|
||||
JsonObject orderPosition = element.getAsJsonObject();
|
||||
result.add(orderPosition);
|
||||
}
|
||||
|
||||
if (orderPositions.has("next") && !orderPositions.get("next").isJsonNull()) {
|
||||
return fetchAllOrderPositions(orderPositions.get("next").getAsString(), queryParams,
|
||||
result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param orderPosition
|
||||
* @param question
|
||||
* @return
|
||||
*/
|
||||
protected JsonObject getAnswerObject(JsonObject orderPosition, int question) {
|
||||
if (orderPosition.has("answers")) {
|
||||
for (JsonElement answerElement : orderPosition.getAsJsonArray("answers")) {
|
||||
JsonObject answer = answerElement.getAsJsonObject();
|
||||
if (question == answer.get("question").getAsInt()) {
|
||||
return answer;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param orderPosition
|
||||
* @param question
|
||||
* @return
|
||||
*/
|
||||
protected int getNumberAnswer(JsonObject orderPosition, int question) {
|
||||
JsonObject answer = getAnswerObject(orderPosition, question);
|
||||
if (answer != null && answer.has("answer")) {
|
||||
return answer.get("answer").getAsInt();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param orderPosition
|
||||
* @param question
|
||||
* @return
|
||||
*/
|
||||
protected Instant getDateAnswer(JsonObject orderPosition, int question) {
|
||||
JsonObject answer = getAnswerObject(orderPosition, question);
|
||||
if (answer != null && answer.has("answer")) {
|
||||
try {
|
||||
return pretixDateFormat.parse(answer.get("answer").getAsString()).toInstant();
|
||||
} catch (ParseException e) {
|
||||
logger.error("Error on parsing active date for '"
|
||||
+ orderPosition.get("order").getAsString() + "' in question '" + question
|
||||
+ "'!", e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package de.bstly.we.membership.controller;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
import de.bstly.we.controller.BaseController;
|
||||
import de.bstly.we.controller.support.EntityResponseStatusException;
|
||||
import de.bstly.we.membership.businesslogic.MembershipManager;
|
||||
|
||||
/**
|
||||
* @author _bastler@bstly.de
|
||||
*
|
||||
*/
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/membership")
|
||||
public class MembershipController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private MembershipManager membershipManager;
|
||||
|
||||
@Value("${we.bstly.pretix.webhook.key:}")
|
||||
private String WEBHOOK_KEY;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param response
|
||||
*/
|
||||
@PreAuthorize("hasRole('ROLE_ADMIN')")
|
||||
@PostMapping("/cron")
|
||||
public void cron(HttpServletResponse response) {
|
||||
membershipManager.cron();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param response
|
||||
*/
|
||||
@PreAuthorize("hasRole('ROLE_ADMIN')")
|
||||
@PostMapping("/ids")
|
||||
public void generateMembershipIds(HttpServletResponse response) {
|
||||
membershipManager.generateMembershipIds();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param response
|
||||
*/
|
||||
@PreAuthorize("hasRole('ROLE_ADMIN')")
|
||||
@PostMapping("/active")
|
||||
public void activeMemberships(HttpServletResponse response) {
|
||||
membershipManager.activeMemberships();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param response
|
||||
*/
|
||||
@PreAuthorize("hasRole('ROLE_ADMIN')")
|
||||
@PostMapping("/extension")
|
||||
public void createMembershipExtension(HttpServletResponse response) {
|
||||
membershipManager.createMembershipExtension();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param response
|
||||
*/
|
||||
@PreAuthorize("hasRole('ROLE_ADMIN')")
|
||||
@PostMapping("/calculateprice")
|
||||
public void calculatePrice(HttpServletResponse response) {
|
||||
membershipManager.calculatePrice();
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole('ROLE_ADMIN')")
|
||||
@GetMapping("/export")
|
||||
public void getMemberMailList(
|
||||
@RequestParam("includeInactive") Optional<Boolean> includeInactive,
|
||||
HttpServletResponse response) throws IOException {
|
||||
response.setContentType("text/csv");
|
||||
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
|
||||
membershipManager.membershipCsvExport(response.getWriter(),
|
||||
includeInactive.isPresent() && includeInactive.get());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param webhookKey
|
||||
* @param payload
|
||||
*/
|
||||
@PostMapping("/pretix/webhook")
|
||||
public void webhook(@RequestParam("key") String webhookKey, @RequestBody String payload) {
|
||||
if (!StringUtils.hasText(webhookKey) || !webhookKey.equals(WEBHOOK_KEY)) {
|
||||
throw new EntityResponseStatusException(HttpStatus.UNAUTHORIZED);
|
||||
}
|
||||
|
||||
JsonObject event = JsonParser.parseString(payload).getAsJsonObject();
|
||||
|
||||
if (event.has("action")
|
||||
&& "pretix.event.order.paid".equals(event.get("action").getAsString())) {
|
||||
membershipManager.generateMembershipIds();
|
||||
membershipManager.activeMemberships();
|
||||
} else {
|
||||
throw new EntityResponseStatusException(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user