Commit Graph

127 Commits

Author SHA1 Message Date
Simon Backx
41e0aa17ff Updated offer_id matching logic to use stripe_coupon_id instead of metadata (#390)
refs https://github.com/TryGhost/Team/issues/1519

- Removed offer metadata again from offer (added in one of the previous commits)
- Added `getByStripeCouponId` method in offer repository (required to find an offer based on the stripe_coupon_id)
- Match discounts from Stripe based on the stripe_coupon_id instead of metadata
2022-04-19 11:21:48 +02:00
Simon Backx
f74b00fea6 Stored offer_id in subscriptions (#389)
refs https://github.com/TryGhost/Team/issues/1519

- Added offer repository dependency to member repository (offerAPI didn't work because it creates a new transaction that resulted in a deadlock during tests)
- Store the offer id from the Stripe subscription metadata in the subscription (only if the discount is still active)
- Also added the offer id to the metadata for a Stripe coupon, this will make adding and removing coupons a bit more foolproof
- Prefer the usage of the offer metadata from a coupon if it is present
- When no discount is applied to a subscription, it always sets the offer id to null, even when the metadata still contains the offer
- The offer_id remains stored when a subscription is canceled/expired
2022-04-19 09:15:33 +02:00
Rishabh
f9ce2d9064 Updated default newsletter subscriptions for member
refs https://github.com/TryGhost/Team/issues/1469

Previously, members were subscribed to all available newsletters by default when added. This change updates the default newsletters subscription for member to take into account newsletter preferences for auto opt-in as well as visibility.
2022-04-14 21:10:58 +05:30
Sam Lord
455778662c Email verification for imports based on 30 days of import
refs: https://github.com/TryGhost/Toolbox/issues/293

Things needed to create this:
* MemberSubscriptionEvent now has an import source
* Importer now creates events with this type
* Verification trigger logic changed to use 30 day window of imports
2022-04-13 17:35:30 +01:00
Simon Backx
fab8a182d1 Updated mrr_delta to use stored mrr and consider forever offers (#387)
* Updated member mrr_delta calculation to use stored mrr

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

Simplifies the calculation of MRR deltas, which will make it easier to update MRR to include offers and cancellations in the future.

* Adjusted MRR and MRR delta calculation to consider "forever" duration offers

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

Uses the discount information from Stripe to calculate the MRR (this was the easiest way to include it + also supports manually created discounts from users)
2022-04-13 15:46:43 +02:00
Fabien "egg" O'Carroll
4c7a7027a9 Fixed storage of MRR Events type
This was incorrectly attempting to store the `name` column which was
renamed to `type`
2022-04-12 11:17:39 +01:00
Simon Backx
da4df59ba9 Save MRR to subscriptions (#386)
refs https://github.com/TryGhost/Team/issues/1456

- Sets the `mrr` column correctly when updating a subscription
- We can use this value in the future to have an improved calculation of mrr_delta, but we first need to have the migration in place
- Updated missing cancelled -> canceled
2022-04-12 11:19:09 +02:00
Fabien 'egg' O'Carroll
027332b80e Updated MRR events (#385)
refs https://github.com/TryGhost/Team/issues/1454

Updates the MRR events to store the type column for existing events, this
includes expired events.

---

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

Creates MRR events when the cancelled status of a subscription has changes

---

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

Updates the cancelled MRR Event logic to make a negative MRR delta, this
is behind a flag so everything can be release at once

Co-authored-by: Simon Backx <simon@ghost.org>
2022-04-12 11:06:11 +02:00
Fabien 'egg' O'Carroll
1c017c7b7d Used FOR UPDATE lock for linkSubscription reads (#383)
refs https://github.com/TryGhost/Team/issues/1248
refs https://github.com/TryGhost/Team/issues/1302

This fixes the issue with duplicate subscriptions being inserted because
concurrent calls to linkSubscription did not have rows locked.

It is also required to make sure we do not create duplicate cancellation events.
2022-04-07 15:12:55 +01:00
Rishabh
45080a0ab2 Handled default newsletter subscription for new members
refs https://github.com/TryGhost/Team/issues/1469

When a new member signs up on the site, by default they should get subscribed to all newsletters. A new member can get added via different ways (stripe webhook, admin add, free signup), so this change updates the base member repository which gets used irrespective of how member is added to ensure default newsletters are always included for new member.
If a member already has a custom newsletters list attached, we don't change anything.
2022-04-06 15:41:02 +05:30
Rishabh
b3ed042265 Allowed updating newsletter data for a member
refs https://github.com/TryGhost/Team/issues/1469

- allows editing multiple newsletter subscriptions for a member
2022-04-04 20:07:37 +05:30
Thibaut Patel
8b7d9281d3 Added MemberCancelEvent
refs https://github.com/TryGhost/Team/issues/1302

- This event is triggered on subscription cancellation
2022-03-11 22:44:28 +01:00
Fabien 'egg' O'Carroll
480a22d6ac Fixed visibility changes in product repository (#375)
refs https://github.com/TryGhost/Team/issues/1387

First, this default value didn't make sense as it was written when we
had a boolean visible column, second, we don't need to add defaults here
- this implementation is super tied to the models anyway, so we may as
well rely on the model defaults - if we do pull it out similar to
Offers, then it may make sense to add a default there.

We also update the JSDoc to match the updated data structure.
2022-03-07 14:09:07 +00:00
Fabien "egg" O'Carroll
9658306a19 Allowed Tier visibility to be set via repository
refs https://github.com/TryGhost/Team/issues/1387

This will allow the API to set the visibility property for Tiers.
2022-03-07 11:42:51 +00:00
Hannah Wolfe
3dcf85d5e4 Ensured correct usage of @tryghost/errors everywhere
refs: 23b383bedf

- @tryghost/error constructors take an object, not a string - the expectation is that message, context & help should all be set
- This does the bare minimum and just ensures message is set correctly
2022-02-15 12:30:36 +00:00
Fabien "egg" O'Carroll
d7d7806dcf Protected against null value for subscription.plan
no-issue

This will only occur when Subscriptions have manually been modified in
Stripe to no longer have a single price.
2022-02-09 11:28:26 +02:00
Fabien "egg" O'Carroll
26045ecf24 Added validation to prices for Tiers
refs https://github.com/TryGhost/Team/issues/1319

Rather than allowing our code to attempt to speak with Stripe and error
there, we opt to fail fast and throw validation errors so that our API
will respond with a 422, the existing pattern for validation errors.
2022-02-09 10:16:24 +02:00
Rishabh
972d29cae6 Fixed incorrect id passed while updating setting
no refs

- a typo led to whole setting object passed to setting update method instead of just the id
2022-02-04 18:23:24 +05:30
Sam Lord
bf9070f945 Add API verification trigger with new filter
no issue

Previous API verification trigger didn't work because the way filters work also changed. Re-implemented with a new filter.
2022-02-03 15:02:33 +00:00
Thibaut Patel
90faa71cfe 🐛 Fixed typo in getEventTimeline
refs 13a9962ade

- The typo was half-fixed in the commit 13a9962ade
- This fixes the call, restoring the feature
2022-02-02 13:08:15 +01:00
Fabien 'egg' O'Carroll
73418e8749 Ran Comped subscriptions in transaction (#360)
no-issue

We were incorrectly mixing transactional and non-transactional
operations. An e2e test in Ghost will be merged shortly which caught
this problem.
2022-02-01 17:05:22 +02:00
Thibaut Patel
13a9962ade 🐛 Fixed the order of events returned by getEventTimeline
refs https://github.com/TryGhost/Team/issues/1299

- Convert `created_at` to the right column in each function query
- Renamed the misspelled `getEmailDeliveredEvents` function
- Updated existing unit tests to cover the order
2022-02-01 15:47:15 +01:00
Thibaut Patel
da22b31302 🐛 Added the missing payment_event event in getEventTimeline
refs https://github.com/TryGhost/Team/issues/1297

- The function querying for this event type was simply never called.
2022-02-01 11:14:48 +01:00
Fabien "egg" O'Carroll
f1cb661094 Revert "Removed stripe_prices from Products API"
This reverts commit f7a1aac926.

The stripe_prices was nto used by the HTTP API, but it was used for
Complimentary subscriptions.
2022-01-31 12:52:12 +02:00
Fabien "egg" O'Carroll
72d57c7645 Allowed welcome_page_url to be set on Tier creation
refs https://github.com/TryGhost/Team/issues/1168
2022-01-27 16:35:23 +02:00
Fabien "egg" O'Carroll
c50e6358dc Allow welcome_page_url to be set on Tiers
refs https://github.com/TryGhost/Team/issues/1168
2022-01-27 16:33:17 +02:00
Sam Lord
3c5cf21274 Added email verification trigger package
refs: https://github.com/TryGhost/Toolbox/issues/166

New package handles the email verification workflow to prevent spammers. It currently handles MembersSubscribeEvent to detect potential abuse of the API to add members, and exposes methods for checking the threshold / starting the verification process for use by other areas of the code (at the moment - just member imports).

The import package no longer needs to handle anything related to verification since it can be handled in the wrapper function in Ghost, and the API package doesn't need to do anything other than dispatch the new event.
2022-01-27 10:57:51 +00:00
Thibaut Patel
0acf2f060c Fixed eslint warnings in events.js
no ref

- There were 12 `no-shadow` warnings, renaming the right variables fixed them.
2022-01-25 16:44:29 +01:00
Thibaut Patel
b76c056d33 Removed de-duplication of events in getEventTimeline
refs https://github.com/TryGhost/Team/issues/1277

- When a user signs-up, two events are created, the code was only keeping one of these events.
- This was introduce in commit 58c9c1c649 when the only usage of the function was to extract the 5 most recent events. Any duplication was creating too much noise.
- This was creating issues now that we introduce event filtering. Some `newsletter_event` events would appear from nowhere we we were filtering-out `signup_event` events.
- We removed the deduplication when the `membersActivityFeed` flag is enabled.
2022-01-25 16:38:25 +01:00
Thibaut Patel
d7673bb1ef Moved the event filtering to the database queries
refs https://github.com/TryGhost/Team/issues/1277

- In `getEventTimeline` we filter to only perform the relevant queries, passing to each query function the filters (subset of NQL)
- In each query function, we rewrite the filters to adapt them to the internal data shape.
- We need to do this rewrite to allow API consumers to create filters based on the output on the API instead of the internal data structure.
- Added partial unit tests as there is a lot of repetition between the query functions.
2022-01-25 12:20:34 +01:00
Thibaut Patel
1370682a60 Added a function to parse a NQL subset
refs https://github.com/TryGhost/Team/issues/1277

- This will allow to filter events within `getEventTimeline`
- The subset of NQL has the following rules:
  - Only one level of filters, now parenthesis allowed
  - Only three filter keys allowed
  - No `or` allowed outside of the bracket notation (this is allowed: `type:-[email_opened_event,email_failed_event]` but this isn't: `type:1,data.created_at:1`)
- The return is an object with a NQL filter by allowed filter key
2022-01-24 18:53:14 +01:00
Fabien "egg" O'Carroll
7950de49ac Removed archived Tiers from Portal display
refs https://github.com/TryGhost/Team/issues/1252

Although we filter out archived tiers from being shown in Portal - we
must also persist this information, so that when they are unarchived,
they continue to not be shown in Portal.

Unfortunately this information is stored in a setting, rather than on
the Tier object itself, two things to consider for the future are:
1. Representing the display value on the Tier object in the API
2. Updating the DB tables to allow storing the display value on the Tier
2022-01-24 13:13:48 +02:00
Fabien "egg" O'Carroll
73f8db0e37 Restricted Members from being given archived Tiers
refs https://github.com/TryGhost/Team/issues/1252
2022-01-24 11:45:54 +02:00
Thibaut Patel
c65a9e0bb2 Moved the getEventTimeline filtering in memory
refs https://github.com/TryGhost/Team/issues/1277

- Doing a filtered DB query wasn't a good solution because we query several tables with different shapes.
- Filtering in memory is done with the NQL library
- Removed the side-effect of changing options.filter for each query, now that options.filter will already contain NQL
- The filtering is done in the reduce function to avoid looping one more time over the in-memory events
2022-01-21 17:56:15 +01:00
Thibaut Patel
5ff5301b1d Fixed the getEventTimeline filtering in case there is no defined filter
refs https://github.com/TryGhost/Team/issues/1277

- `(undefined)` isn't valid NQL so we make sure options.filter is defined
2022-01-21 14:03:33 +01:00
Thibaut Patel
3ad8d9ab8b Added the option to filter events from getEventTimeline
refs https://github.com/TryGhost/Team/issues/1277

- Added the pre-existing framework filters to each event query.
- Made sure we aren't modifying the original `options.filter` to avoid side-effects between event queries.
2022-01-21 11:16:24 +01:00
Fabien "egg" O'Carroll
f7a1aac926 Removed stripe_prices from Products API
refs https://github.com/TryGhost/Team/issues/713

This is a hangover from the multiple products feature and is no longer used.
2022-01-20 17:47:50 +02:00
Fabien "egg" O'Carroll
c59a42c87b Added support for the active flag to Products API
refs https://github.com/TryGhost/Team/issues/1252

This will be used to archive and unarchive Tiers. There is a restriction
on archiving "free" Tiers because our current system expects only one,
and it should always be active.
2022-01-20 17:47:50 +02:00
Thibaut Patel
de0dc7a9a0 Added the full related email in email recipient events
refs https://github.com/TryGhost/Team/issues/1277

- Prevents the admin from doing extra api calls to retrieve the email records
2022-01-19 11:47:35 +01:00
Thibaut Patel
83fe60cb66 🐛 Fixed the email recipient events in getEventTimeline
refs https://github.com/TryGhost/Team/issues/1277

- The members weren't included in the serialized version of the new events
- Some properties weren't using the bookshelf `get` method as they should have
2022-01-19 09:55:02 +01:00
Thibaut Patel
a7098aee46 Added members to all member events in getEventTimeline
refs https://github.com/TryGhost/Team/issues/1277

- This makes the three new email recipient events similar to the preexisting events
2022-01-18 19:02:44 +01:00
Thibaut Patel
ae967c449c Added EmailRecipient events to getEventTimeline
refs https://github.com/TryGhost/Team/issues/1277

- Adds 3 new requests to the `email_recipients` table in the `getEventTimeline` method
- This allows to extract new member events from the table: `email_delivered_event`, `email_opened_event`, `email_failed_event`
2022-01-18 15:53:51 +01:00
Rishabh Garg
ca18f140c4 Handled new type column for tiers (#356)
refs https://github.com/TryGhost/Team/issues/1037

Tiers have a new `type` column to differentiate between `free` and `paid` tiers. This change -

- sets type as paid for all new tiers created, as `free` tier is created by default
- excludes any price/stripe data change for free tier
- updates all usages of default product to fetch the first paid product from the products list in DB instead of just the first product it finds.
2022-01-17 23:02:02 +05:30
Fabien "egg" O'Carroll
cacc74f3b4 Added "api" source to MemberSubscribedEvents
refs https://github.com/TryGhost/Team/issues/1275

We want to be able to track where member subscriptions came from, so
that we can use the information to reduce spam imports of members.

We were missing information when members were uploaded via the Admin
API, and setting the source to 'member' be default - this fixes that
both when creating members and when updating their subscription status.
2022-01-14 12:19:43 +02:00
Fabien "egg" O'Carroll
a7588e3c6b Fixed transactions for linkSubscription
no-issue

This was missed when transactions were implemented for this method.
2022-01-10 17:53:30 +02:00
Sam Lord
ba2c0818e0 Use @tryghost/logging instead of injected argument 2021-12-02 14:46:58 +00:00
Fabien O'Carroll
b20f5a8b1f Updated linkSubscription to call method in transaction
no-issue

This was missing the options object which would force the DB call to be
run inside the same transaction as the rest
2021-11-09 11:19:05 +02:00
Fabien O'Carroll
2fcafcc8dc Removed coupons from subscriptions when the price changes
refs https://github.com/TryGhost/Team/issues/1092
refs https://github.com/TryGhost/Team/issues/1135

This was missed in the initial due to the issue tracking the task being
superceded, and the task not being copied across to the superceding
issue.

A new method to remove coupons has been added, as opposed to updating
the existing change subscription price method, because the removal of a
coupon is not the concern of an auxillary stripe service, but a busines
concern that should be explicit in the members-api codebase.
2021-11-09 11:12:13 +02:00
Fabien O'Carroll
8051015bb8 Fixed race condition when linking subscriptions
no-issue

Without forcing linkSubscription to run inside a transaction - it's
possible to have race conditions where it is called twice, and attempt
to insert duplicate rows into the database.
2021-10-18 17:26:34 +02:00
Fabien O'Carroll
c58e83c9d7 Wired up OfferRedemption storage
refs https://github.com/TryGhost/Team/issues/1132

We have to include the Offer on the metadata for the Stripe Checkout -
as Offers with a duration of 'once' will not always be present on the
Subscription after fetching it.

Once we receive the Stripe Checkout webhook we emit an event for
subscription created - the reason we use an event is because this logic
should eventually live in a Payments/Stripe module - and we'd want to
decouple it from the Members module.

The Members module is in charge of writing Offer Redemptions - rather
than the Offers module - because Offer Redemptions are "owned" by a
Member - and merely reference and Offer. Eventually Offer Redemptions
could be replaced by Subscriptions.
2021-10-18 17:26:34 +02:00