mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-15 21:57:22 +01:00
Fix subcriptions remaining time disappearing after cancelling (#10761)
* add hasCancelled method for group/user, prevent cancelling a subscription twice * wip * paypal: do not cancel a subscription twice * make sure hasCancelled and hasNotCancelled return a boolean result
This commit is contained in:
@@ -1932,28 +1932,54 @@ describe('Group Model', () => {
|
||||
|
||||
context('hasNotCancelled', () => {
|
||||
it('returns false if group does not have customer id', () => {
|
||||
expect(party.hasNotCancelled()).to.be.undefined;
|
||||
expect(party.hasNotCancelled()).to.be.false;
|
||||
});
|
||||
|
||||
it('returns true if party does not have plan.dateTerminated', () => {
|
||||
it('returns true if group does not have plan.dateTerminated', () => {
|
||||
party.purchased.plan.customerId = 'test-id';
|
||||
|
||||
expect(party.hasNotCancelled()).to.be.true;
|
||||
});
|
||||
|
||||
it('returns false if party if plan.dateTerminated is after today', () => {
|
||||
it('returns false if group if plan.dateTerminated is after today', () => {
|
||||
party.purchased.plan.customerId = 'test-id';
|
||||
party.purchased.plan.dateTerminated = moment().add(1, 'days').toDate();
|
||||
|
||||
expect(party.hasNotCancelled()).to.be.false;
|
||||
});
|
||||
|
||||
it('returns false if party if plan.dateTerminated is before today', () => {
|
||||
it('returns false if group if plan.dateTerminated is before today', () => {
|
||||
party.purchased.plan.customerId = 'test-id';
|
||||
party.purchased.plan.dateTerminated = moment().subtract(1, 'days').toDate();
|
||||
|
||||
expect(party.hasNotCancelled()).to.be.false;
|
||||
});
|
||||
});
|
||||
|
||||
context('hasCancelled', () => {
|
||||
it('returns false if group does not have customer id', () => {
|
||||
expect(party.hasCancelled()).to.be.false;
|
||||
});
|
||||
|
||||
it('returns false if group does not have plan.dateTerminated', () => {
|
||||
party.purchased.plan.customerId = 'test-id';
|
||||
|
||||
expect(party.hasCancelled()).to.be.false;
|
||||
});
|
||||
|
||||
it('returns true if group if plan.dateTerminated is after today', () => {
|
||||
party.purchased.plan.customerId = 'test-id';
|
||||
party.purchased.plan.dateTerminated = moment().add(1, 'days').toDate();
|
||||
|
||||
expect(party.hasCancelled()).to.be.true;
|
||||
});
|
||||
|
||||
it('returns false if group if plan.dateTerminated is before today', () => {
|
||||
party.purchased.plan.customerId = 'test-id';
|
||||
party.purchased.plan.dateTerminated = moment().subtract(1, 'days').toDate();
|
||||
|
||||
expect(party.hasCancelled()).to.be.false;
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -315,9 +315,8 @@ describe('User Model', () => {
|
||||
user = new User();
|
||||
});
|
||||
|
||||
|
||||
it('returns false if user does not have customer id', () => {
|
||||
expect(user.hasNotCancelled()).to.be.undefined;
|
||||
expect(user.hasNotCancelled()).to.be.false;
|
||||
});
|
||||
|
||||
it('returns true if user does not have plan.dateTerminated', () => {
|
||||
@@ -341,6 +340,38 @@ describe('User Model', () => {
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
context('hasCancelled', () => {
|
||||
let user;
|
||||
beforeEach(() => {
|
||||
user = new User();
|
||||
});
|
||||
|
||||
it('returns false if user does not have customer id', () => {
|
||||
expect(user.hasCancelled()).to.be.false;
|
||||
});
|
||||
|
||||
it('returns false if user does not have plan.dateTerminated', () => {
|
||||
user.purchased.plan.customerId = 'test-id';
|
||||
|
||||
expect(user.hasCancelled()).to.be.false;
|
||||
});
|
||||
|
||||
it('returns true if user if plan.dateTerminated is after today', () => {
|
||||
user.purchased.plan.customerId = 'test-id';
|
||||
user.purchased.plan.dateTerminated = moment().add(1, 'days').toDate();
|
||||
|
||||
expect(user.hasCancelled()).to.be.true;
|
||||
});
|
||||
|
||||
it('returns false if user if plan.dateTerminated is before today', () => {
|
||||
user.purchased.plan.customerId = 'test-id';
|
||||
user.purchased.plan.dateTerminated = moment().subtract(1, 'days').toDate();
|
||||
|
||||
expect(user.hasCancelled()).to.be.false;
|
||||
});
|
||||
});
|
||||
|
||||
context('pre-save hook', () => {
|
||||
it('does not try to award achievements when achievements or items not selected in query', async () => {
|
||||
let user = new User();
|
||||
|
||||
@@ -257,12 +257,18 @@ api.ipn = async function ipnApi (options = {}) {
|
||||
'recurring_payment_failed',
|
||||
'recurring_payment_expired',
|
||||
'subscr_cancel',
|
||||
'subscr_failed'];
|
||||
'subscr_failed',
|
||||
];
|
||||
|
||||
if (ipnAcceptableTypes.indexOf(txn_type) === -1) return;
|
||||
|
||||
// @TODO: Should this request billing date?
|
||||
let user = await User.findOne({ 'purchased.plan.customerId': recurring_payment_id }).exec();
|
||||
if (user) {
|
||||
// If the user has already cancelled the subscription, return
|
||||
// Otherwise the subscription would be cancelled twice resulting in the loss of subscription credits
|
||||
if (user.hasCancelled()) return;
|
||||
|
||||
await payments.cancelSubscription({ user, paymentMethod: this.constants.PAYMENT_METHOD });
|
||||
return;
|
||||
}
|
||||
@@ -274,6 +280,10 @@ api.ipn = async function ipnApi (options = {}) {
|
||||
.exec();
|
||||
|
||||
if (group) {
|
||||
// If the group subscription has already been cancelled the subscription, return
|
||||
// Otherwise the subscription would be cancelled twice resulting in the loss of subscription credits
|
||||
if (group.hasCancelled()) return;
|
||||
|
||||
await payments.cancelSubscription({ groupId: group._id, paymentMethod: this.constants.PAYMENT_METHOD });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1421,7 +1421,12 @@ schema.methods.isSubscribed = function isSubscribed () {
|
||||
|
||||
schema.methods.hasNotCancelled = function hasNotCancelled () {
|
||||
let plan = this.purchased.plan;
|
||||
return this.isSubscribed() && !plan.dateTerminated;
|
||||
return Boolean(this.isSubscribed() && !plan.dateTerminated);
|
||||
};
|
||||
|
||||
schema.methods.hasCancelled = function hasNotCancelled () {
|
||||
let plan = this.purchased.plan;
|
||||
return Boolean(this.isSubscribed() && plan.dateTerminated);
|
||||
};
|
||||
|
||||
schema.methods.updateGroupPlan = async function updateGroupPlan (removingMember) {
|
||||
|
||||
@@ -31,7 +31,12 @@ schema.methods.isSubscribed = function isSubscribed () {
|
||||
|
||||
schema.methods.hasNotCancelled = function hasNotCancelled () {
|
||||
let plan = this.purchased.plan;
|
||||
return this.isSubscribed() && !plan.dateTerminated;
|
||||
return Boolean(this.isSubscribed() && !plan.dateTerminated);
|
||||
};
|
||||
|
||||
schema.methods.hasCancelled = function hasCancelled () {
|
||||
let plan = this.purchased.plan;
|
||||
return Boolean(this.isSubscribed() && plan.dateTerminated);
|
||||
};
|
||||
|
||||
// Get an array of groups ids the user is member of
|
||||
|
||||
Reference in New Issue
Block a user