0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-01-06 22:40:14 -05:00

🐛 Fixed members with Stripe trials not receiving paid-members newsletters

no issue

- members who have trial subscriptions added directly via Stripe will have a status of `"trialed"` in their Ghost subscription
- the `paid: true` filter was not taking that into account meaning trial users were not receiving newsletters sent to paid members even though they have a "paid" subscription
This commit is contained in:
Kevin Ansfield 2020-09-02 00:34:26 +01:00 committed by Daniel Lockyer
parent 902b55f338
commit 5aadf1cf00
5 changed files with 48 additions and 15 deletions

View file

@ -209,9 +209,9 @@ const Member = ghostBookshelf.Model.extend({
this.on( this.on(
'members_stripe_customers.customer_id', 'members_stripe_customers.customer_id',
'members_stripe_customers_subscriptions.customer_id' 'members_stripe_customers_subscriptions.customer_id'
).andOn( ).onIn(
'members_stripe_customers_subscriptions.status', 'members_stripe_customers_subscriptions.status',
ghostBookshelf.knex.raw('?', ['active']) ['active', 'trialed']
); );
} }
); );

View file

@ -42,7 +42,7 @@ describe('Members API', function () {
const jsonResponse = res.body; const jsonResponse = res.body;
should.exist(jsonResponse); should.exist(jsonResponse);
should.exist(jsonResponse.members); should.exist(jsonResponse.members);
jsonResponse.members.should.have.length(3); jsonResponse.members.should.have.length(4);
localUtils.API.checkResponse(jsonResponse.members[0], 'member', 'stripe'); localUtils.API.checkResponse(jsonResponse.members[0], 'member', 'stripe');
testUtils.API.isISO8601(jsonResponse.members[0].created_at).should.be.true(); testUtils.API.isISO8601(jsonResponse.members[0].created_at).should.be.true();
@ -51,7 +51,7 @@ describe('Members API', function () {
jsonResponse.meta.pagination.should.have.property('page', 1); jsonResponse.meta.pagination.should.have.property('page', 1);
jsonResponse.meta.pagination.should.have.property('limit', 15); jsonResponse.meta.pagination.should.have.property('limit', 15);
jsonResponse.meta.pagination.should.have.property('pages', 1); jsonResponse.meta.pagination.should.have.property('pages', 1);
jsonResponse.meta.pagination.should.have.property('total', 3); jsonResponse.meta.pagination.should.have.property('total', 4);
jsonResponse.meta.pagination.should.have.property('next', null); jsonResponse.meta.pagination.should.have.property('next', null);
jsonResponse.meta.pagination.should.have.property('prev', null); jsonResponse.meta.pagination.should.have.property('prev', null);
}); });
@ -108,8 +108,9 @@ describe('Members API', function () {
const jsonResponse = res.body; const jsonResponse = res.body;
should.exist(jsonResponse); should.exist(jsonResponse);
should.exist(jsonResponse.members); should.exist(jsonResponse.members);
jsonResponse.members.should.have.length(1); jsonResponse.members.should.have.length(2);
jsonResponse.members[0].email.should.equal('paid@test.com'); jsonResponse.members[0].email.should.equal('paid@test.com');
jsonResponse.members[1].email.should.equal('trialed@test.com');
localUtils.API.checkResponse(jsonResponse, 'members'); localUtils.API.checkResponse(jsonResponse, 'members');
localUtils.API.checkResponse(jsonResponse.members[0], 'member', 'stripe'); localUtils.API.checkResponse(jsonResponse.members[0], 'member', 'stripe');
localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination'); localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
@ -412,8 +413,8 @@ describe('Members API', function () {
should.exist(jsonResponse.total_on_date); should.exist(jsonResponse.total_on_date);
should.exist(jsonResponse.new_today); should.exist(jsonResponse.new_today);
// 3 from fixtures, 2 from above posts, 2 from above import // 4 from fixtures, 2 from above posts, 2 from above import
jsonResponse.total.should.equal(7); jsonResponse.total.should.equal(8);
}); });
}); });
}); });

View file

@ -542,7 +542,7 @@ describe('Members API', function () {
should.exist(jsonResponse.new_today); should.exist(jsonResponse.new_today);
// 3 from fixtures and 6 imported in previous tests // 3 from fixtures and 6 imported in previous tests
jsonResponse.total.should.equal(9); jsonResponse.total.should.equal(10);
}); });
}); });
@ -566,7 +566,7 @@ describe('Members API', function () {
should.exist(jsonResponse.new_today); should.exist(jsonResponse.new_today);
// 3 from fixtures and 6 imported in previous tests // 3 from fixtures and 6 imported in previous tests
jsonResponse.total.should.equal(9); jsonResponse.total.should.equal(10);
}); });
}); });
@ -590,7 +590,7 @@ describe('Members API', function () {
should.exist(jsonResponse.new_today); should.exist(jsonResponse.new_today);
// 3 from fixtures and 6 imported in previous tests // 3 from fixtures and 6 imported in previous tests
jsonResponse.total.should.equal(9); jsonResponse.total.should.equal(10);
}); });
}); });

View file

@ -212,12 +212,13 @@ describe('Member Model', function run() {
it('can use custom query', function (done) { it('can use custom query', function (done) {
Member.findAll().then(function (allResult) { Member.findAll().then(function (allResult) {
allResult.length.should.equal(3); allResult.length.should.equal(4);
return Member.findAll({paid: true}); return Member.findAll({paid: true});
}).then(function (queryResult) { }).then(function (queryResult) {
queryResult.length.should.equal(1); queryResult.length.should.equal(2);
queryResult.models[0].get('email').should.equal('paid@test.com'); queryResult.models[0].get('email').should.equal('paid@test.com');
queryResult.models[1].get('email').should.equal('trialed@test.com');
done(); done();
}).catch(done); }).catch(done);

View file

@ -321,6 +321,11 @@ DataGenerator.Content = {
id: ObjectId.generate(), id: ObjectId.generate(),
email: 'paid@test.com', email: 'paid@test.com',
name: 'Egon Spengler' name: 'Egon Spengler'
},
{
id: ObjectId.generate(),
email: 'trialed@test.com',
name: 'Ray Stantz'
} }
], ],
@ -344,6 +349,13 @@ DataGenerator.Content = {
customer_id: 'cus_HR3tBmNhx4QsZY', customer_id: 'cus_HR3tBmNhx4QsZY',
name: 'Egon Spengler', name: 'Egon Spengler',
email: 'paid@test.com' email: 'paid@test.com'
},
{
id: ObjectId.generate(),
member_id: null, // relation added later
customer_id: 'cus_HR3tBmNhx4QsZZ',
name: 'Ray Stantz',
email: 'trialed@test.com'
} }
], ],
@ -362,6 +374,21 @@ DataGenerator.Content = {
plan_interval: 'month', plan_interval: 'month',
plan_amount: '1000', plan_amount: '1000',
plan_currency: 'usd' plan_currency: 'usd'
},
{
id: ObjectId.generate(),
customer_id: 'cus_HR3tBmNhx4QsZZ',
subscription_id: 'sub_HR3tLNgGAHsa7c',
plan_id: '173e16a1fffa7d232b398e4a9b08d266a456ae8f3d23e5f11cc608ced6730bb9',
status: 'trialed',
cancel_at_period_end: true,
current_period_end: '2025-07-09 19:01:20',
start_date: '2020-06-09 19:01:20',
default_payment_card_last4: '4242',
plan_nickname: 'Monthly',
plan_interval: 'month',
plan_amount: '1000',
plan_currency: 'usd'
} }
], ],
@ -445,6 +472,7 @@ DataGenerator.Content.api_keys[1].integration_id = DataGenerator.Content.integra
DataGenerator.Content.emails[0].post_id = DataGenerator.Content.posts[0].id; DataGenerator.Content.emails[0].post_id = DataGenerator.Content.posts[0].id;
DataGenerator.Content.emails[1].post_id = DataGenerator.Content.posts[1].id; DataGenerator.Content.emails[1].post_id = DataGenerator.Content.posts[1].id;
DataGenerator.Content.members_stripe_customers[0].member_id = DataGenerator.Content.members[2].id; DataGenerator.Content.members_stripe_customers[0].member_id = DataGenerator.Content.members[2].id;
DataGenerator.Content.members_stripe_customers[1].member_id = DataGenerator.Content.members[3].id;
DataGenerator.forKnex = (function () { DataGenerator.forKnex = (function () {
function createBasic(overrides) { function createBasic(overrides) {
@ -910,7 +938,8 @@ DataGenerator.forKnex = (function () {
const members = [ const members = [
createMember(DataGenerator.Content.members[0]), createMember(DataGenerator.Content.members[0]),
createMember(DataGenerator.Content.members[1]), createMember(DataGenerator.Content.members[1]),
createMember(DataGenerator.Content.members[2]) createMember(DataGenerator.Content.members[2]),
createMember(DataGenerator.Content.members[3])
]; ];
const labels = [ const labels = [
@ -925,11 +954,13 @@ DataGenerator.forKnex = (function () {
]; ];
const members_stripe_customers = [ const members_stripe_customers = [
createBasic(DataGenerator.Content.members_stripe_customers[0]) createBasic(DataGenerator.Content.members_stripe_customers[0]),
createBasic(DataGenerator.Content.members_stripe_customers[1])
]; ];
const stripe_customer_subscriptions = [ const stripe_customer_subscriptions = [
createBasic(DataGenerator.Content.members_stripe_customers_subscriptions[0]) createBasic(DataGenerator.Content.members_stripe_customers_subscriptions[0]),
createBasic(DataGenerator.Content.members_stripe_customers_subscriptions[1])
]; ];
return { return {