package crmdna.sessionpass;
import com.googlecode.objectify.cmd.Query;
import crmdna.client.Client;
import crmdna.common.EmailConfig;
import crmdna.common.Utils;
import crmdna.common.Utils.Currency;
import crmdna.group.Group;
import crmdna.group.PaypalApiCredentialsProp;
import crmdna.mail2.*;
import crmdna.member.MemberEntity;
import crmdna.member.MemberLoader;
import crmdna.member.MemberProp;
import crmdna.payment.Payment;
import crmdna.payment.Payment.PaymentType;
import crmdna.sequence.Sequence;
import crmdna.sequence.Sequence.SequenceType;
import crmdna.user.User;
import crmdna.user.User.ClientLevelPrivilege;
import java.util.*;
import java.util.logging.Logger;
import static crmdna.common.AssertUtils.*;
import static crmdna.common.OfyService.ofy;
public class SessionPass {
public static final String MANUAL_TRANSACTION_ID = "MANUAL";
public static String buySubscription(String client, long groupId, MemberProp memberProp,
int numSessions, Date expiry, double amount, Currency currency,
PaypalApiCredentialsProp paypalProp, String rootUrl, String successCallback,
String errorCallback) {
Client.ensureValid(client);
ensure(numSessions > 0, "numSessions should be positive");
ensure(numSessions < 1000, "numSessions should be less than 1000");
ensureNotNull(expiry, "expiry is null");
ensure(expiry.getTime() > new Date().getTime(), "Expiry should be in future");
ensure(amount >= 0, "Invalid amount [" + amount + "]");
ensureNotNull(currency, "Currency not specified");
Utils.ensureValidEmail(memberProp.contact.email);
SubscriptionEntity subscriptionEntity = new SubscriptionEntity();
subscriptionEntity.subscriptionId =
Sequence.getNext(client, SequenceType.SUBSCRIPTION, 1).get(0);
subscriptionEntity.numSessions = numSessions;
subscriptionEntity.expiryMS = expiry.getTime();
subscriptionEntity.amount = amount;
subscriptionEntity.currency = currency.toString();
subscriptionEntity.memberId = memberProp.memberId;
subscriptionEntity.groupId = groupId;
String paymentName =
"Subscription_" + memberProp.memberId + "_" + Integer.toString(numSessions) + "-passes";
String paymentUrl = Payment
.setExpressCheckoutAndGetPaymentUrl(client, PaymentType.SESSION_PASS,
memberProp.contact.email, paymentName, subscriptionEntity.subscriptionId, paypalProp,
amount, currency.toString(), rootUrl, successCallback, errorCallback);
ofy(client).save().entity(subscriptionEntity).now();
return paymentUrl;
}
public static List<SessionPassProp> allocatePasses(String client, long groupId, long memberId,
int numSessions, Date expiry, double amount, Currency currency, String transactionId,
String login) {
Client.ensureValid(client);
MemberEntity memberEntity = MemberLoader.safeGet(client, memberId, login);
ensure(numSessions > 0, "numSessions should be positive");
ensure(numSessions < 1000, "numSessions should be less than 1000");
ensureNotNull(expiry, "expiry is null");
ensure(expiry.getTime() > new Date().getTime(), "Expiry should be in future");
ensure(amount >= 0, "Invalid amount [" + amount + "]");
ensureNotNull(currency, "Currency not specified");
ensureNotNull(transactionId, "transactionId is null");
ensure(!transactionId.isEmpty(), "transactionId is empty");
Utils.ensureValidEmail(memberEntity.toProp().contact.email);
// TODO: allow only members with account
User.ensureClientLevelPrivilege(client, login, ClientLevelPrivilege.UPDATE_SESSION_PASS);
return allocatePasses(client, groupId, numSessions, expiry.getTime(), memberId,
login.toLowerCase(), amount, currency.toString(), transactionId);
}
public static List<SessionPassProp> allocatePasses(String client, long subscriptionId,
String transactionId) {
Client.ensureValid(client);
SubscriptionProp subscriptionProp =
ofy(client).load().type(SubscriptionEntity.class).id(subscriptionId).now().toProp();
MemberEntity memberEntity =
MemberLoader.safeGet(client, subscriptionProp.memberId, User.SUPER_USER);
ensureNotNull(transactionId, "transactionId is null");
ensure(!transactionId.isEmpty(), "transactionId is empty");
Utils.ensureValidEmail(memberEntity.toProp().contact.email);
return allocatePasses(client, subscriptionProp.groupId, subscriptionProp.numSessions,
subscriptionProp.expiryMS, subscriptionProp.memberId, "MEMBER",
subscriptionProp.amount, subscriptionProp.currency, transactionId);
}
private static List<SessionPassProp> allocatePasses(String client, long groupId,
int numSessions, long expiryMS, long memberId, String purchaseUpdatedBy, double amount,
String currency, String transactionId) {
List<SessionPassEntity> entities = new ArrayList<>(numSessions);
List<Long> ids = Sequence.getNext(client, SequenceType.SESSIONPASS, numSessions);
for (int i = 0; i < numSessions; i++) {
SessionPassEntity entity = new SessionPassEntity();
entity.sessionPassId = ids.get(i);
entity.expiryMS = expiryMS;
entity.memberId = memberId;
entity.purchaseMS = new Date().getTime();
entity.transactionId = transactionId;
entity.used = false;
entity.purchaseUpdatedBy = purchaseUpdatedBy;
entity.amount = amount;
entity.currency = currency;
entities.add(entity);
}
ensureEqual(numSessions, entities.size(), "Incorrect no of entities");
ofy(client).save().entities(entities).now();
List<SessionPassProp> props = new ArrayList<>();
for (SessionPassEntity entity : entities) {
props.add(entity.toProp());
}
sendSubscriptionPurchaseNotification(client, groupId, numSessions, amount, currency,
memberId, expiryMS);
return props;
}
public static int getNumPasses(String client, String email, boolean unusedOnly) {
Client.ensureValid(client);
MemberEntity memberEntity = MemberLoader.getByEmail(client, email);
ensureNotNull(memberEntity);
Query<SessionPassEntity> q =
ofy(client).load().type(SessionPassEntity.class).filter("memberId", memberEntity.getId())
.filter("expiryMS >", System.currentTimeMillis());
if (unusedOnly) {
q = q.filter("used", false);
}
return q.count();
}
public static int getNumRegistered(String client, String sessionDateTime) {
Client.ensureValid(client);
return ofy(client).load().type(SessionPassEntity.class).filter("tags", sessionDateTime).count();
}
public static List<SessionPassProp> getRegistrations(String client, String login,
String sessionDateTime) {
Client.ensureValid(client);
User.ensureClientLevelPrivilege(client, login, ClientLevelPrivilege.UPDATE_SESSION_PASS);
List<SessionPassEntity> entities =
ofy(client).load().type(SessionPassEntity.class).filter("tags", sessionDateTime).list();
List<SessionPassProp> props = new ArrayList<>();
for (SessionPassEntity entity : entities) {
props.add(entity.toProp());
}
return props;
}
public static List<SessionPassProp> getValidPasses(String client, String login) {
Client.ensureValid(client);
User.ensureClientLevelPrivilege(client, login, ClientLevelPrivilege.UPDATE_SESSION_PASS);
MemberEntity memberEntity = MemberLoader.getByEmail(client, login);
ensureNotNull(memberEntity);
List<SessionPassEntity> entities =
ofy(client).load().type(SessionPassEntity.class).filter("memberId", memberEntity.getId())
.list();
List<SessionPassProp> props = new ArrayList<>();
for (SessionPassEntity entity : entities) {
props.add(entity.toProp());
}
return props;
}
public static boolean isRegistered(String client, String email, String sessionDateTime) {
Client.ensureValid(client);
MemberEntity memberEntity = MemberLoader.getByEmail(client, email);
ensureNotNull(memberEntity);
return ofy(client).load().type(SessionPassEntity.class)
.filter("memberId", memberEntity.getId()).filter("tags", sessionDateTime).count() > 0;
}
public static void bookSession(String client, String email, String practiceType,
String sessionDateTime) {
Client.ensureValid(client);
MemberEntity memberEntity = MemberLoader.getByEmail(client, email);
ensureNotNull(memberEntity);
Query<SessionPassEntity> q = ofy(client).load().type(SessionPassEntity.class);
SessionPassEntity sessionPassEntity =
q.filter("memberId", memberEntity.getId()).filter("expiryMS >", System.currentTimeMillis())
.filter("used", false).order("expiryMS").first().safe();
sessionPassEntity.used = true;
sessionPassEntity.tags.add(practiceType);
sessionPassEntity.tags.add(sessionDateTime);
ofy(client).save().entity(sessionPassEntity).now();
}
public static void cancelBooking(String client, long sessionPassId) {
Client.ensureValid(client);
SessionPassEntity sessionPassEntity =
ofy(client).load().type(SessionPassEntity.class).id(sessionPassId).safe();
sessionPassEntity.used = false;
sessionPassEntity.tags.clear();
ofy(client).save().entity(sessionPassEntity).now();
}
public static void sendSubscriptionPurchaseNotification(String client, long groupId,
int numSessions, double amount, String currency, long memberId, long expiryMS) {
try {
MailContentEntity mailContentEntity = MailContent.getByName(client,
MailContent.ReservedMailContentName.RESERVED_SUBSCRIPTION_PURCHASE.toString(), 0);
ensureNotNull(mailContentEntity, "RESERVED_SUBSCRIPTION_PURCHASE MailContent is not present");
MailContentProp mailContentProp = mailContentEntity.toProp();
MemberProp memberProp = MemberLoader.safeGet(client, memberId, User.SUPER_USER).toProp();
EmailConfig emailConfig = Group.getEmailConfig(client, groupId, User.SUPER_USER);
MailMap mailMap = new MailMap();
mailMap.add(memberProp.contact.email, memberProp.contact.firstName,
memberProp.contact.lastName);
mailMap.add(memberProp.contact.email, MailMap.MergeVarID.SUBSCRIPTION_TYPE, numSessions + " Passes");
mailMap.add(memberProp.contact.email, MailMap.MergeVarID.AMOUNT,
currency + " " + String.valueOf(amount));
mailMap.add(memberProp.contact.email, MailMap.MergeVarID.VALIDITY,
(new Date(expiryMS)).toString());
MailSendInput msi = new MailSendInput();
msi.createMember = false;
msi.groupId = groupId;
msi.isTransactionEmail = true;
msi.mailContentId = mailContentProp.mailContentId;
msi.senderEmail = emailConfig.contactEmail;
msi.suppressIfAlreadySent = false;
Mail.send(client, msi, mailMap, User.SUPER_USER);
} catch (Exception ex) {
Logger LOGGER = Logger.getLogger(SessionPass.class.getName());
LOGGER.severe(ex.toString());
}
}
}