0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-02-10 23:36:14 -05:00

Replaced members 'comped' status with 'paid'

refs https://github.com/TryGhost/Team/issues/693

Since we've got rid of the concept of Complimentary with the Custom
Prices work, we're removing the 'comped' status from members. This
involves a migration for existing members, a schema update for the
validation, and a bump to members-api to no longer use the 'comped'
status for new members.

We also update the aggregation of the MemberStatusEvent to consider the
'comped' status as 'paid', and that there are 0 'comped' status events
in the database.

We can consider a migration for this data in the future, either adding
new status events moving from 'comped' to 'paid', or by modifying
existing status events. However both of these are very difficulty to
write a down migration for, and might be best saved for a major version.

- @tryghost/members-api@1.7.0 is the version that includes the required
  changes, however we have already bumped to 1.8.0 in Ghost
This commit is contained in:
Fabien O'Carroll 2021-05-17 14:55:23 +01:00
parent 278ad8eaea
commit 5880edd722
5 changed files with 56 additions and 13 deletions

View file

@ -0,0 +1,46 @@
const logging = require('../../../../../shared/logging');
const {createTransactionalMigration} = require('../../utils.js');
module.exports = createTransactionalMigration(
async function up(knex) {
logging.info('Updating all member "comped" statuses to "paid"');
await knex('members')
.update('status', 'paid')
.where('status', 'comped');
},
async function down(knex) {
const compedMemberIds = (await knex('members')
.select('members.id')
.innerJoin(
'members_stripe_customers',
'members.id',
'members_stripe_customers.member_id'
).innerJoin(
'members_stripe_customers_subscriptions',
function () {
this.on(
'members_stripe_customers.customer_id',
'members_stripe_customers_subscriptions.customer_id'
).onIn(
'members_stripe_customers_subscriptions.status',
['active', 'trialing', 'past_due', 'unpaid']
);
}
).where(
'members_stripe_customers_subscriptions.plan_nickname',
'=',
'Complimentary'
)).map(({id}) => id);
if (compedMemberIds.length === 0) {
logging.info('No Members found with Complimentary subscriptions');
return;
}
logging.info(`Updating ${compedMemberIds.length} Members status from 'paid' -> 'comped'`);
await knex('members')
.update('status', 'comped')
.whereIn('id', compedMemberIds);
}
);

View file

@ -345,7 +345,7 @@ module.exports = {
email: {type: 'string', maxlength: 191, nullable: false, unique: true, validations: {isEmail: true}},
status: {
type: 'string', maxlength: 50, nullable: false, defaultTo: 'free', validations: {
isIn: [['free', 'paid', 'comped']]
isIn: [['free', 'paid']]
}
},
name: {type: 'string', maxlength: 191, nullable: true},
@ -399,12 +399,12 @@ module.exports = {
member_id: {type: 'string', maxlength: 24, nullable: false, references: 'members.id', cascadeDelete: true},
from_status: {
type: 'string', maxlength: 50, nullable: true, validations: {
isIn: [['free', 'paid', 'comped']]
isIn: [['free', 'paid']]
}
},
to_status: {
type: 'string', maxlength: 50, nullable: true, validations: {
isIn: [['free', 'paid', 'comped']]
isIn: [['free', 'paid']]
}
},
created_at: {type: 'dateTime', nullable: false}

View file

@ -17,15 +17,12 @@ const MemberStatusEvent = ghostBookshelf.Model.extend({
return qb.clear('select')
.select(knex.raw('DATE(created_at) as date'))
.select(knex.raw(`SUM(
CASE WHEN to_status='paid' THEN 1
WHEN from_status='paid' THEN -1
ELSE 0 END
CASE WHEN to_status IN ('paid', 'comped') THEN 1
WHEN from_status IN ('paid', 'comped') THEN -1
ELSE 0
END
) as paid_delta`))
.select(knex.raw(`SUM(
CASE WHEN to_status='comped' THEN 1
WHEN from_status='comped' THEN -1
ELSE 0 END
) as comped_delta`))
.select(knex.raw(`0 as comped_delta`))
.select(knex.raw(`SUM(
CASE WHEN to_status='free' THEN 1
WHEN from_status='free' THEN -1

View file

@ -98,7 +98,7 @@ describe('Members API', function () {
const jsonResponse = res.body;
should.exist(jsonResponse);
should.exist(jsonResponse.members);
jsonResponse.members.should.have.length(4);
jsonResponse.members.should.have.length(5);
jsonResponse.members[0].email.should.equal('paid@test.com');
jsonResponse.members[1].email.should.equal('trialing@test.com');
localUtils.API.checkResponse(jsonResponse, 'members');

View file

@ -340,7 +340,7 @@ DataGenerator.Content = {
email: 'comped@test.com',
name: 'Vinz Clortho',
uuid: 'f6f91461-d7d8-4a3f-aa5d-8e582c40b344',
status: 'comped'
status: 'paid'
},
{
id: ObjectId().toHexString(),