mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-17 06:37:23 +01:00
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:
@@ -10,6 +10,8 @@ import { v4 as generateUUID } from 'uuid';
|
|||||||
import {
|
import {
|
||||||
each,
|
each,
|
||||||
} from 'lodash';
|
} from 'lodash';
|
||||||
|
import { model as User } from '../../../../../website/server/models/user';
|
||||||
|
import * as payments from '../../../../../website/server/libs/payments';
|
||||||
|
|
||||||
describe('POST /groups/:groupId/leave', () => {
|
describe('POST /groups/:groupId/leave', () => {
|
||||||
let typesOfGroups = {
|
let typesOfGroups = {
|
||||||
@@ -264,4 +266,45 @@ describe('POST /groups/:groupId/leave', () => {
|
|||||||
expect(userWithNonExistentParty.party).to.eql({});
|
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;
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -755,13 +755,20 @@ api.leaveGroup = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await group.leave(user, req.query.keep, req.body.keepChallenges);
|
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);
|
_removeMessagesFromMember(user, group._id);
|
||||||
|
|
||||||
await user.save();
|
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, {});
|
res.respond(200, {});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -275,6 +275,19 @@ schema.methods.daysUserHasMissed = function daysUserHasMissed (now, req = {}) {
|
|||||||
return {daysMissed, timezoneOffsetFromUserPrefs};
|
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.
|
// 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
|
// User is allowed to buy gems if no group has `leaderOnly.getGems` === true or if
|
||||||
// its the group leader
|
// its the group leader
|
||||||
@@ -286,16 +299,17 @@ schema.methods.canGetGems = async function canObtainGems () {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const userGroups = user.getGroups();
|
const groups = await getUserGroupData(user);
|
||||||
|
|
||||||
const groups = await Group
|
|
||||||
.find({
|
|
||||||
_id: {$in: userGroups},
|
|
||||||
})
|
|
||||||
.select('leaderOnly leader purchased')
|
|
||||||
.exec();
|
|
||||||
|
|
||||||
return groups.every(g => {
|
return groups.every(g => {
|
||||||
return !g.isSubscribed() || g.leader === user._id || g.leaderOnly.getGems !== true;
|
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();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user