refs https://github.com/TryGhost/Team/issues/586
On Ghost Boot, as part of configuring Stripe, this populates stripe products and prices for existing stripe customers in the newly created `stripe_prices` and `stripe_products` table, which allows us to map existing customers to default Ghost product and on current prices. The population script on boot is only run if we find -
- A Ghost Product
- No rows in `stripe_products`
- No rows in `stripe_prices`
- One or more rows in `members_stripe_customers_subscriptions`
refs https://github.com/TryGhost/Team/issues/593
- Bumps `stripe` node library major version to v8 - 8.142
- Bumps default Stripe version to latest - '2020-08-27'
- Updated webhook Stripe version to latest - '2020-08-27'
- Removes `@types/stripe` in favor of first-class types support in `stripe` lib directly
- Updates types across files
refs https://github.com/TryGhost/Team/issues/595
For a canceled subscription, the desired MRR delta is to reduce by negative of original amount, but our logic was incorrectly reducing it by double which led to big gap between real MRR and one shown on Dashboard.
- Fixes calculation for MRR change for canceled subscriptions
no-issue
The Admin API uses a Member id rather than email to update
subscriptions, this ensures that we provide an interface that will
continue to work with the Admin API
https://github.com/TryGhost/Team/issues/530
This option will check to see if a subscription is in an unpaid or past
due state, and if so, will cancel the subscription immediately, rather
than cancelling at the period end.
refs https://github.com/TryGhost/Team/issues/530
The RouterController was a grab bag of all controller methods, making it
difficult to mock & test. This adds a MemberController with a smaller
API - making it easier to test.
no-issue
We would like to release @tryghost/members-csv as version 1.0.0 but
lerna will only allow us to release packages which have had changes in
them since their last release. Well, this is a change. And it's solely
for the purpose of allowing us to release 1.0.0. This version is not
tagged, nor is it published to npm.
no-issue
When seeding the database with fake members & stripe data, it's possible
to create stripe plans without a nickname. Similarly some other services
do not have a nickname on their plans. This ensures that we do not error
when working with these plans.
no-issue
If we are to perform the `linkSubscription` method inside of a
transaction, the addition of the paid subscription events would happen
outside of the transaction, and cause errors. This ensures that we pass
the options object (containing the transaction) to the models calls to
add paid subscription events
no-issue
1. We do not want to store payment events for payments of 0 value
2. Stripe webhooks can arrive and be processed "out of order", which can
result in us attempting to add a payment event for a member which
does not yet exist. The change here will 404 in such (edge) cases, so
that Stripe will retry the webhook at a later point, when the Member
has been created, allowing us to store the payment event.
refs https://github.com/TryGhost/Team/issues/469
In order to reduce noise, we want to only display newsletter
subscription events which are not likely to be the result of a member
signup. The approach we've taken is to remove any newsletter
subscription (not unsubscription) event, if when sorted in chronological
order, it is to reside next to a signup event for the same member.
An improvement to this approach might be to add some kind of transaction
id to events which would allow us to group together events which should
be considered to have happened simultaneously.
refs https://github.com/TryGhost/Team/issues/469
Signup events are captured by status changes with no `from_status`, this
means that the member did not have a status (did not exist) before this
change.
refs https://github.com/TryGhost/Team/issues/469
We order the set of all events by created_at, but were not fetching the
individual events with the same order applies, this resulted in
incorrect results.
refs https://github.com/TryGhost/Ghost/issues/12711
We must wait for the stripeSubscriptions relation to be loaded before
attempting to loop through them. As well as this we should use `upsert`
so that we can edit a subscription record by `subscription_id`, rather
than the (internal) `id`
no refs
The member id assigned when creating a new status event on member creation was incorrectly using `data.id` instead of `member.id`, which was undefined causing a validation error.
refs https://github.com/TryGhost/Ghost/issues/12602
* Added Event Repository
** Added method for MRR over time
** Added method for newsletter subscriptions over time
** Added method for gross volume over time
** Added method for status segment size over time
* Captured login events
* Captured newsletter subscription/unsubscription
* Captured email address change events
* Captured paid subscription events
* Captured payment events
* Captured status events
no refs
The data structure for subscriptions object on member has changed in 4.x from` stripe.subscriptions` to direct `subscriptions`, the change here updates parsing of subscriptions data
refs https://github.com/TryGhost/Team/issues/479
* Fixed updating payment method for canceled subscriptions
Stripe considers canceled subscriptions as non-existent, so any attempts
to update them will fail with a 404 not found. Prior to this change we
were attempting to update *all* subscriptions for a customer, including
those which were canceled. This would cause an error and the loop to
break.
* 🐛 Fixed errors for members with multiple active customers
Members with multiple active customers would have their first active
customer found updated with the new payment method. We would then
iterate through *all* active subscription, and attempt to update their
payment method. If a subscription was not owned by the customer that was
just updated, it would error and cause the loop to break out.
* Added ability to update a specific subscription's payment method
In order to remove ambiguity we add the ability to update the payment
method for a specific subscription. This will remove room for errors as
we will not have to worry about if a subscription belong to the customer
or not.
refs https://github.com/TryGhost/Team/issues/475
The subscription object here is a database model rather than an
ISubscription from the stripe library, and we need to 1) use the `get`
method to read attributes and 2) read the `subscription_id` attribute,
as the `id` is our internal one.
no-issue
Fetching relations via the model returns a promise, and this was missing
the `await` keyword. We also need to `get` the subscription_id attribute
as we're working with models rather than subscription objects.