fix(server-api): cancelSubscription() is no longer called twice when user leaves group

This commit is contained in:
hamboomger
2020-03-31 18:23:08 +03:00
parent 0bc836b490
commit b7448e2cfe
3 changed files with 75 additions and 6 deletions

View File

@@ -2,6 +2,7 @@ import { v4 as generateUUID } from 'uuid';
import { import {
each, each,
} from 'lodash'; } from 'lodash';
import moment from 'moment';
import { import {
generateChallenge, generateChallenge,
checkExistence, checkExistence,
@@ -12,6 +13,7 @@ import {
} from '../../../../helpers/api-integration/v3'; } from '../../../../helpers/api-integration/v3';
import { model as User } from '../../../../../website/server/models/user'; import { model as User } from '../../../../../website/server/models/user';
import payments from '../../../../../website/server/libs/payments/payments'; import payments from '../../../../../website/server/libs/payments/payments';
import { calculateSubscriptionTerminationDate } from '../../../../../website/server/libs/payments/util';
describe('POST /groups/:groupId/leave', () => { describe('POST /groups/:groupId/leave', () => {
const typesOfGroups = { const typesOfGroups = {
@@ -338,4 +340,48 @@ describe('POST /groups/:groupId/leave', () => {
}); });
}); });
}); });
each(typesOfGroups, (groupDetails, groupType) => {
context(`Leaving a group with extraMonths left plan when the group is a ${groupType}`, () => {
const extraMonths = 12;
let groupWithPlan;
let member;
beforeEach(async () => {
const { group, members } = await createAndPopulateGroup({
groupDetails,
members: 1,
upgradeToGroupPlan: true,
});
[member] = members;
groupWithPlan = group;
await member.update({
'purchased.plan.extraMonths': extraMonths,
});
});
it('calculates dateTerminated and sets extraMonths to zero after user leaves the group', async () => {
const userBeforeLeave = await User.findById(member._id).exec();
await member.post(`/groups/${groupWithPlan._id}/leave`);
const userAfterLeave = await User.findById(member._id).exec();
const dateTerminatedBefore = userBeforeLeave.purchased.plan.dateTerminated;
const extraMonthsBefore = userBeforeLeave.purchased.plan.extraMonths;
const dateTerminatedAfter = userAfterLeave.purchased.plan.dateTerminated;
const extraMonthsAfter = userAfterLeave.purchased.plan.extraMonths;
const expectedTerminationDate = calculateSubscriptionTerminationDate(null, {
customerId: payments.constants.GROUP_PLAN_CUSTOMER_ID,
extraMonths,
}, payments.constants);
expect(extraMonthsBefore).to.gte(12);
expect(extraMonthsAfter).to.equal(0);
expect(dateTerminatedBefore).to.be.null;
expect(dateTerminatedAfter).to.exist;
expect(moment(dateTerminatedAfter).diff(expectedTerminationDate, 'days')).to.equal(0);
});
});
});
}); });

View File

@@ -5,6 +5,8 @@ import { v4 as generateUUID } from 'uuid';
import { ApiUser, ApiGroup, ApiChallenge } from '../api-classes'; import { ApiUser, ApiGroup, ApiChallenge } from '../api-classes';
import { requester } from '../requester'; import { requester } from '../requester';
import * as Tasks from '../../../../website/server/models/task'; import * as Tasks from '../../../../website/server/models/task';
import payments from '../../../../website/server/libs/payments/payments';
import { model as User } from '../../../../website/server/models/user';
// Creates a new user and returns it // Creates a new user and returns it
// If you need the user to have specific requirements, // If you need the user to have specific requirements,
@@ -83,14 +85,35 @@ export async function generateGroup (leader, details = {}, update = {}) {
return apiGroup; return apiGroup;
} }
async function _upgradeToGroupPlan (groupLeader, group) {
const groupLeaderModel = await User.findById(groupLeader._id).exec();
// Create subscription
const paymentData = {
user: groupLeaderModel,
groupId: group._id,
sub: {
key: 'basic_3mo',
},
customerId: 'customer-id',
paymentMethod: 'Payment Method',
headers: {
'x-client': 'habitica-web',
'user-agent': '',
},
};
await payments.createSubscription(paymentData);
}
// This is generate group + the ability to create // This is generate group + the ability to create
// real users to populate it. The settings object // real users to populate it. The settings object
// takes in: // takes in:
// members: Number - the number of group members to create. // members: Number - the number of group members to create.
// Defaults to 0. Does not include group leader. // Defaults to 0. Does not include group leader.
// inivtes: Number - the number of users to create and invite to the group. Defaults to 0. // invites: Number - the number of users to create and invite to the group. Defaults to 0.
// groupDetails: Object - how to initialize the group // groupDetails: Object - how to initialize the group
// leaderDetails: Object - defaults for the leader, defaults with a gem balance so the user // leaderDetails: Object - defaults for the leader, defaults with a gem balance so the user
// addGroupPlan: boolean - will add group plan with basic subscription. Defaults to false
// can create the group // can create the group
// //
// Returns an object with // Returns an object with
@@ -101,6 +124,7 @@ export async function generateGroup (leader, details = {}, update = {}) {
export async function createAndPopulateGroup (settings = {}) { export async function createAndPopulateGroup (settings = {}) {
const numberOfMembers = settings.members || 0; const numberOfMembers = settings.members || 0;
const numberOfInvites = settings.invites || 0; const numberOfInvites = settings.invites || 0;
const upgradeToGroupPlan = settings.upgradeToGroupPlan || false;
const { groupDetails } = settings; const { groupDetails } = settings;
const leaderDetails = settings.leaderDetails || { balance: 10 }; const leaderDetails = settings.leaderDetails || { balance: 10 };
@@ -130,6 +154,10 @@ export async function createAndPopulateGroup (settings = {}) {
await Promise.all(invitees.map(invitee => invitee.sync())); await Promise.all(invitees.map(invitee => invitee.sync()));
if (upgradeToGroupPlan) {
await _upgradeToGroupPlan(groupLeader, group);
}
return { return {
groupLeader, groupLeader,
group, group,

View File

@@ -861,11 +861,6 @@ api.leaveGroup = {
if (guildIndex >= 0) user.guilds.splice(guildIndex, 1); if (guildIndex >= 0) user.guilds.splice(guildIndex, 1);
} }
const isMemberOfGroupPlan = await user.isMemberOfGroupPlan();
if (!isMemberOfGroupPlan) {
await payments.cancelGroupSubscriptionForUser(user, group);
}
if (group.hasNotCancelled()) await group.updateGroupPlan(true); if (group.hasNotCancelled()) await group.updateGroupPlan(true);
res.respond(200, {}); res.respond(200, {});
}, },