Cancel users free group plan when they leave a group (#9543)

* Cancel users free group plan when they leave a group

* Fixed lint
This commit is contained in:
Keith Holliday
2017-11-20 12:34:41 -06:00
committed by GitHub
parent 20a99e526d
commit 5f468d16b7
3 changed files with 76 additions and 12 deletions

View File

@@ -10,6 +10,8 @@ import { v4 as generateUUID } from 'uuid';
import {
each,
} from 'lodash';
import { model as User } from '../../../../../website/server/models/user';
import * as payments from '../../../../../website/server/libs/payments';
describe('POST /groups/:groupId/leave', () => {
let typesOfGroups = {
@@ -264,4 +266,45 @@ describe('POST /groups/:groupId/leave', () => {
expect(userWithNonExistentParty.party).to.eql({});
});
});
context('Leaving a group plan', () => {
it('cancels the free subscription', async () => {
// Create group
let { group, groupLeader, members } = await createAndPopulateGroup({
groupDetails: {
name: 'Test Private Guild',
type: 'guild',
},
members: 1,
});
let leader = groupLeader;
let member = members[0];
let userWithFreePlan = await User.findById(leader._id).exec();
// Create subscription
let paymentData = {
user: userWithFreePlan,
groupId: group._id,
sub: {
key: 'basic_3mo',
},
customerId: 'customer-id',
paymentMethod: 'Payment Method',
headers: {
'x-client': 'habitica-web',
'user-agent': '',
},
};
await payments.createSubscription(paymentData);
await member.sync();
expect(member.purchased.plan.planId).to.equal('group_plan_auto');
expect(member.purchased.plan.dateTerminated).to.not.exist;
// Leave
await member.post(`/groups/${group._id}/leave`);
await member.sync();
expect(member.purchased.plan.dateTerminated).to.exist;
});
});
});

View File

@@ -755,13 +755,20 @@ api.leaveGroup = {
}
await group.leave(user, req.query.keep, req.body.keepChallenges);
if (group.hasNotCancelled()) await group.updateGroupPlan(true);
if (group.hasNotCancelled()) await group.updateGroupPlan(true);
_removeMessagesFromMember(user, group._id);
await user.save();
if (group.type !== 'party') {
let guildIndex = user.guilds.indexOf(group._id);
user.guilds.splice(guildIndex, 1);
}
let isMemberOfGroupPlan = await user.isMemberOfGroupPlan();
if (!isMemberOfGroupPlan) {
await payments.cancelGroupSubscriptionForUser(user, group);
}
res.respond(200, {});
},
};

View File

@@ -275,6 +275,19 @@ schema.methods.daysUserHasMissed = function daysUserHasMissed (now, req = {}) {
return {daysMissed, timezoneOffsetFromUserPrefs};
};
async function getUserGroupData (user) {
const userGroups = user.getGroups();
const groups = await Group
.find({
_id: {$in: userGroups},
})
.select('leaderOnly leader purchased')
.exec();
return groups;
}
// Determine if the user can get gems: some groups restrict their members ability to obtain them.
// User is allowed to buy gems if no group has `leaderOnly.getGems` === true or if
// its the group leader
@@ -286,16 +299,17 @@ schema.methods.canGetGems = async function canObtainGems () {
return true;
}
const userGroups = user.getGroups();
const groups = await Group
.find({
_id: {$in: userGroups},
})
.select('leaderOnly leader purchased')
.exec();
const groups = await getUserGroupData(user);
return groups.every(g => {
return !g.isSubscribed() || g.leader === user._id || g.leaderOnly.getGems !== true;
});
};
schema.methods.isMemberOfGroupPlan = async function isMemberOfGroupPlan () {
const groups = await getUserGroupData(this);
return groups.every(g => {
return g.isSubscribed();
});
};