use new email template when joining a group plan for customisation of subscription cancellation information (#8637)

* use new email template when subscription is cancelled from joining a group plan

* use new email template when subscription is cancelled from joining a group plan - needs more code, tests

* change from sending new email as a cancel-subscription option to sending as a group plan join email

Uses a new group-member-join email template instead of old group-member-joining because new template includes mandril conditional merge tags.

Also adds tests and comments. Edits some comments for accuracy and typo fixes.

* adapt group-member-join email template for manual cancel message for iOS and Android subscriptions

* save test user so its profile name can be read by calls to sendTxn

* add documentation for the user model cancelSubscription function

* add constants for strings passed to mandrill email templates
This commit is contained in:
Alys
2017-06-07 10:25:37 -07:00
committed by Sabe Jones
parent 2292ba2694
commit 613f51b08d
11 changed files with 289 additions and 27 deletions

View File

@@ -20,6 +20,7 @@ import {
import slack from './slack';
const TECH_ASSISTANCE_EMAIL = nconf.get('EMAILS:TECH_ASSISTANCE_EMAIL');
const JOINED_GROUP_PLAN = 'joined group plan';
let api = {};
@@ -81,8 +82,22 @@ api.addSubscriptionToGroupUsers = async function addSubscriptionToGroupUsers (gr
* @return undefined
*/
api.addSubToGroupUser = async function addSubToGroupUser (member, group) {
// These EMAIL_TEMPLATE constants are used to pass strings into templates that are
// stored externally and so their values must not be changed.
const EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_GOOGLE = 'Google_subscription';
const EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_IOS = 'iOS_subscription';
const EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_GROUP_PLAN = 'group_plan_free_subscription';
const EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_LIFETIME_FREE = 'lifetime_free_subscription';
const EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_NORMAL = 'normal_subscription';
const EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_UNKNOWN = 'unknown_type_of_subscription';
const EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_NONE = 'no_subscription';
// When changing customerIdsToIgnore or paymentMethodsToIgnore, the code blocks below for
// the `group-member-join` email template will probably need to be changed.
let customerIdsToIgnore = [this.constants.GROUP_PLAN_CUSTOMER_ID, this.constants.UNLIMITED_CUSTOMER_ID];
let paymentMethodsToIgnore = [this.constants.GOOGLE_PAYMENT_METHOD, this.constants.IOS_PAYMENT_METHOD];
let previousSubscriptionType = EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_NONE;
let leader = await User.findById(group.leader).exec();
let data = {
user: {},
@@ -125,13 +140,39 @@ api.addSubToGroupUser = async function addSubToGroupUser (member, group) {
{name: 'EMAIL', content: getUserInfo(member, ['email']).email},
{name: 'PAYMENT_METHOD', content: memberPlan.paymentMethod},
{name: 'PURCHASED_PLAN', content: JSON.stringify(memberPlan)},
{name: 'ACTION_NEEDED', content: 'User has joined group plan. Tell them to cancel subscription then give them free sub.'},
{name: 'ACTION_NEEDED', content: 'User has joined group plan and has been told to cancel their subscription then email us. Ensure they do that then give them free sub.'},
// TODO User won't get email instructions if they've opted out of all emails. See if we can make this email an exception and if not, report here whether they've opted out.
]);
}
if ((ignorePaymentPlan || ignoreCustomerId) && !customerHasCancelledGroupPlan) return;
if ((ignorePaymentPlan || ignoreCustomerId) && !customerHasCancelledGroupPlan) {
// member has been added to group plan but their subscription will not be changed
// automatically so they need a special message in the email
if (memberPlan.paymentMethod === this.constants.GOOGLE_PAYMENT_METHOD) {
previousSubscriptionType = EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_GOOGLE;
} else if (memberPlan.paymentMethod === this.constants.IOS_PAYMENT_METHOD) {
previousSubscriptionType = EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_IOS;
} else if (memberPlan.customerId === this.constants.UNLIMITED_CUSTOMER_ID) {
previousSubscriptionType = EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_LIFETIME_FREE;
} else if (memberPlan.customerId === this.constants.GROUP_PLAN_CUSTOMER_ID) {
previousSubscriptionType = EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_GROUP_PLAN;
} else {
// this triggers a generic message in the email template in case we forget
// to update this code for new special cases
previousSubscriptionType = EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_UNKNOWN;
}
txnEmail(member, 'group-member-join', [
{name: 'LEADER', content: leader.profile.name},
{name: 'GROUP_NAME', content: group.name},
{name: 'PREVIOUS_SUBSCRIPTION_TYPE', content: previousSubscriptionType},
]);
return;
}
if (member.hasNotCancelled()) await member.cancelSubscription();
if (member.hasNotCancelled()) {
await member.cancelSubscription({cancellationReason: JOINED_GROUP_PLAN});
previousSubscriptionType = EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_NORMAL;
}
let today = new Date();
plan = member.purchased.plan.toObject();
@@ -164,10 +205,10 @@ api.addSubToGroupUser = async function addSubToGroupUser (member, group) {
data.user = member;
await this.createSubscription(data);
let leader = await User.findById(group.leader).exec();
txnEmail(data.user, 'group-member-joining', [
txnEmail(data.user, 'group-member-join', [
{name: 'LEADER', content: leader.profile.name},
{name: 'GROUP_NAME', content: group.name},
{name: 'PREVIOUS_SUBSCRIPTION_TYPE', content: previousSubscriptionType},
]);
};
@@ -409,17 +450,18 @@ api.createSubscription = async function createSubscription (data) {
});
};
// Sets their subscription to be cancelled later
// Cancels a subscription or group plan, setting termination to happen later
api.cancelSubscription = async function cancelSubscription (data) {
let plan;
let group;
let cancelType = 'unsubscribe';
let groupId;
let emailType = 'cancel-subscription';
let emailType;
let emailMergeData = [];
let sendEmail = true;
// If we are buying a group subscription
if (data.groupId) {
// cancelling a group plan
let groupFields = basicGroupFields.concat(' purchased');
group = await Group.getGroup({user: data.user, groupId: data.groupId, populateLeader: false, groupFields});
@@ -438,15 +480,20 @@ api.cancelSubscription = async function cancelSubscription (data) {
await this.cancelGroupUsersSubscription(group);
} else {
// cancelling a user subscription
plan = data.user.purchased.plan;
emailType = 'cancel-subscription';
// When cancelling because the user joined a group plan, no cancel-subscription email is sent
// because the group-member-join email says the subscription is cancelled.
if (data.cancellationReason && data.cancellationReason === JOINED_GROUP_PLAN) sendEmail = false;
}
let customerId = plan.customerId;
let now = moment();
let defaultRemainingDays = 30;
if (plan.customerId === this.constants.GROUP_PLAN_CUSTOMER_ID) {
defaultRemainingDays = 2;
sendEmail = false; // because group-member-cancel email has already been sent
}
let remaining = data.nextBill ? moment(data.nextBill).diff(new Date(), 'days', true) : defaultRemainingDays;
@@ -469,7 +516,7 @@ api.cancelSubscription = async function cancelSubscription (data) {
await data.user.save();
}
if (customerId !== this.constants.GROUP_PLAN_CUSTOMER_ID) txnEmail(data.user, emailType, emailMergeData);
if (sendEmail) txnEmail(data.user, emailType, emailMergeData);
if (group) {
cancelType = 'group-unsubscribe';