Commit Graph

100 Commits

Author SHA1 Message Date
Kevin Ansfield
ae1ac83fc5
Fixed members import-with-tier alpha creating unexpected invoices (#20695)
ref https://linear.app/tryghost/issue/ONC-199

The `updateSubscriptionItemPrice()` method in our Stripe library used by the importer when moving a subscription over to a Ghost product/price was setting `proration_behavior: 'always_invoice'`. This resulted in invoices being created when changing the subscription (even though no prices were changing as far as the customer is concerned) and in some cases where a customer previously had a one-off discount the customer was incorrectly charged the proration difference because the discount was no longer applied to the new invoice.

- updated `updateSubscriptionItemPrice()` to accept an `options` param allowing the `proration_behavior` property passed to the Stripe API to be overridden on a per-call basis
- updated the `forceStripeSubscriptionToProduct()` method used by the importer to pass an options object with `prorationBehavior: 'none'` when updating the subscription item price so that no invoice and no unexpected charges occur when importing
2024-07-31 11:16:25 +01:00
Daniel Lockyer
29cc3003c7 Fixed misc JSDoc types
- nothing crazy, just fixing minor typing issues that I've come across
2024-05-07 11:44:07 +02:00
Chris Raible
90ebdacabb
🐛 Fixed members importer overwriting name and note if left blank (#19663)
fixes ENG-610

- Previously, when importing an existing member, if the name or note
field is left blank in the CSV file, this would overwrite (re: delete)
the existing name or note in the database.
- This change ensures that the name and note fields are only updated if
they are not blank in the CSV file.
2024-02-06 13:31:34 -08:00
Daniel Lockyer
077652e3f3 Added metrics for measuring members importer
fixes https://linear.app/tryghost/issue/PROD-199/add-metrics-for-members-importer

- we know the members importer is slow but we need metrics to prove it
- this should collect import count, error count + runtime for the
  members importer, so we can analyze the data
2023-12-05 17:07:39 +01:00
Michael Barrett
3a95caf48f
Implement member import with tier (#17506)
refs https://github.com/TryGhost/Product/issues/3629
2023-08-18 15:24:31 +01:00
Michael Barrett
2fe392c312
Added import tier to members import modal (#17492)
refs https://github.com/TryGhost/Product/issues/3629
2023-07-26 09:19:09 +01:00
Sag
9f438972f1
Added search by email for Stripe Customer ID during member import (#17326)
closes https://github.com/TryGhost/Product/issues/3593

- when importing members via CSV, it's now possible to add the value "auto" for the "stripe_customer_id" field. When this option is passed, the importer will search for a Stripe customer based on the email address provided
- if there are multiple Stripe customers with the same email address, the customer with the most recent subscription is returned
2023-07-13 13:20:54 +02:00
Michael Barrett
b49cf14287
🐛 Fixed member import newsletter subscription prefs (#17208)
fixes https://github.com/TryGhost/Product/issues/2947

When an import is performed and a member already exists:
- If `subscribe_to_emails` is set to `true` and the existing member
already has newsletter subscriptions, these are preserved
- If `subscribe_to_emails` is set to `true` and the existing member does
not already have newsletter subscriptions, no new subscriptions are
added in case the member has previously unsubscribed
- If `subscribe_to_emails` is set to `false` the existing member will be
unsubscribed from all newsletters regardless of their preference
2023-07-06 08:45:56 +01:00
Fabien "egg" O'Carroll
104f84f252 Added eslint rule for file naming convention
As discussed with the product team we want to enforce kebab-case file names for
all files, with the exception of files which export a single class, in which
case they should be PascalCase and reflect the class which they export.

This will help find classes faster, and should push better naming for them too.

Some files and packages have been excluded from this linting, specifically when
a library or framework depends on the naming of a file for the functionality
e.g. Ember, knex-migrator, adapter-manager
2023-05-09 12:34:34 -04:00
Chris Raible
af1ff7902e
Fixed member import with created_at in the future (#16580)
closes TryGhost/Team#2793

- if a member is imported with a created_at in the future, the member
will not appear in the members list in admin
- this commit updates created_at to the current date if it is in the
future upon import
2023-04-06 23:01:23 -07:00
Simon Backx
819d0d884c
Improved email verification required checks (#16060)
fixes https://github.com/TryGhost/Team/issues/2366
refs https://ghost.slack.com/archives/C02G9E68C/p1670232405014209

Probem described in issue.

In the old MEGA flow:
- The `email_verification_required` check is now repeated inside the job

In the new email service flow:
- The `email_verification_required` is now checked (didn't happen
before)
- When generating the email batch recipients, we only include members
that were created before the email was created. That way it is
impossible to avoid limit checks by inserting new members between
creating an email and sending an email.
- We don't need to repeat the check inside the job because of the above
changes

Improved handling of large imports:
- When checking `email_verification_required`, we now also check if the
import threshold is reached (a new method is introduced in
vertificationTrigger specifically for this usage). If it is, we start
the verification progress. This is required for long running imports
that only check the verification threshold at the very end.
- This change increases the concurrency of fastq to 3 (refs
https://ghost.slack.com/archives/C02G9E68C/p1670232405014209). So when
running a long import, it is now possible to send emails without having
to wait for the import. Above change makes sure it is not possible to
get around the verification limits.

Refactoring:
- Removed the need to use `updateVerificationTrigger` by making
thresholds getters instead of fixed variables.
- Improved awaiting of members import job in regression test
2023-01-04 11:22:12 +01:00
Simon Backx
6e72767a50
Fixed verification trigger not working for large imports (#15887)
fixes https://github.com/TryGhost/Team/issues/2326

When importing more than 500 members, we didn't testImportThreshold at
the right time. It was called too early because the importing job was
not awaited. This also adds an E2E test for this case.
2022-11-28 18:22:10 +01:00
Naz
cc72e8f599
🐛 Fixed complimentary_plan Member imports
closes https://github.com/TryGhost/Team/issues/2219

- The CSV importer was failing when a "complimentary_plan" flag was present with a "true" value. The root of the issue was the data model change where the "id" of the Tier object is no longer a String but an ObjectID instance. It's a slight departure from previous bookshelf object behavior where 'id' property is always a string that is a stringified ObjectID.
- In the future we should unify the logic across all data access objects to either keep the convention of using a String under id property or switch to ObjectId instances.
2022-11-08 11:47:00 +07:00
Naz
7fe9e06c4d
Fixed rule for import background job detection
refs https://github.com/TryGhost/Team/issues/1076

- The members CSV import would go into background job (longer running and resulting with an email) when it contained a complimentary_plan column.
- With recent members codebase decoupling Ghost does not make any connection to Stripe as "complimentary plan" data is saved purely in native data structures. Making no need for a background job for complimentary plans
2022-10-31 16:31:55 +08:00
Naz
4d26c50e0b
Fixed data type of hasStripeData in member importer
refs https://github.com/TryGhost/Team/issues/1076

- What appeared to be a "boolean" by nature and name, the hasStripeData was holding a result of "find" method - and object or an undefined value
- Fixed the typing, to avoid ambiguity in the future
2022-10-31 16:31:35 +08:00
Halldor Thorhallsson
5a94cc8039
Removed bluebird from misc packages (#15676)
refs: https://github.com/TryGhost/Ghost/issues/14882

- Removed bluebird from members-csv package-json and update-check-service 
- Removing bluebird specific methods in favour of the Ghost sequence method so we can remove the bluebird dependency
2022-10-30 15:16:10 +00:00
Naz
cdd65f25ac
Migrated members importer to use tiers
refs https://github.com/TryGhost/Team/issues/2077

- The "productRepository" methods have been deprecated in favor of "tiers" and "Tiers API".
- The changes migrated usages of  "productRepository.getDefaultProduct" to Tiers API's "readDefaultTier"
2022-10-26 14:26:21 +08:00
Naz
a7f5ee0ad5
Simplified members CSV importer constructor
refs https://github.com/TryGhost/Team/issues/2077

- Passing in the whole "getMembersApi" is just too much state to know about for the importer - it only uses a concept of default tier and members repository, the rest is distracting fluff making it hard to reason about what the importer **has to** know to function
- Passing in two functions breaking up the above state simplifies the constructor API.
- This is also a groundwork before substituting productsRepository for tiersRepository (refed issue objective)
2022-10-25 16:40:28 +08:00
Naz
59209a07a5
Cleaned up leftover "product" variable naming
refs https://github.com/TryGhost/Team/issues/1076

- "product" in the context of members has been deprecated since introduction of "tiers"
2022-10-24 18:06:02 +08:00
Naz
840deaf8d7
Restricted members importer to ignore "products" column
refs https://github.com/TryGhost/Team/issues/1076
refs 70229e4fd3 (diff-b67ecda91b5bd79c598e5c5a9ec2ccf28dbfab6a924b21352273865e07cd7ceaR57)

- The "products" column has not been doing any logic anything since at least 5.20.0 (see refed commit). The concept of columns in the export file was mostly there for analytical/data filtering reasons - so the user could analyze their exports. CSV was never a good suite for relational data that "products" (or now tiers) represent
- The "tiers" column will still be present in the exported CSV file, but there is not going to be any logic attached to it.
- The only columns that can effect the "tiers" state of the member are: "complimentary_plan" (assign default tier to the member) and "stripe_customer_id" (pulls in subscription/tier data from Stripe)
2022-10-24 18:06:02 +08:00
Naz
5d5b77d32f
Fixed comped tier assignment
closes https://github.com/TryGhost/Team/issues/1869

- When there were "archived" tiers in the system the importer incorrectly fetched them instead of only taking "active" ones into account. The "getDefaultProduct" on product repository does exactly that.
- Additionally, reusing the "getDefaultProduct" makes testing the importer slightly less complex.
2022-10-20 17:19:52 +08:00
Naz
b589a66cd4
Fixed broken CSV importer tests
refs 90768e9985

- With introduction of strict field mapping the regression test testing for "imports of not mapped fields" failed.
2022-10-19 18:33:47 +08:00
Naz
90768e9985
Added strict field mapping to member CSV importer
closes https://github.com/TryGhost/Toolbox/issues/430

- The members importer used to  import all fields present in the uploaded CSV if the headers match, even if they're not mapped in the UI. This behavior has lead to have misleading consequences and "hidden" features. For example, if the field was present but intentionally left as "Not imported" in the UI the field would still get imported.
- Having a strict list of supported import fields also allows for manageable long-term maintenance of the CSV Import API and detect/communicate changes when they happen.
- The list of the current default field mapping is:

    email: 'email',
    name: 'name',
    note: 'note',
    subscribed_to_emails: 'subscribed',
    created_at: 'created_at',
    complimentary_plan: 'complimentary_plan',
    stripe_customer_id: 'stripe_customer_id',
    labels: 'labels',
    products: 'products'
2022-10-19 18:10:40 +08:00
Naz
748ef87954
Made running the import outside of job on test env
- Allows to write tests for the importer easier when there is a "subscription" or a "product" present
2022-10-19 18:10:40 +08:00
Naz
9389064ae2
Removed unused error message
no issue

- The job-related code was ripped out form the importer and this message was just an overlooked leftover
2022-10-19 18:10:40 +08:00
Naz
f0b68846cc
Moved header mapping configuration to importer
refs https://github.com/TryGhost/Toolbox/issues/430

- To be able to introduce strict mapping rules (exclude unknown fields) we need to control the CSV header mapping on the importer level. This change moves the configuration up from CSV parser to the importer
- Also adds tests covering correct inserts for specially treated "subscribed_to_emails" field
2022-10-19 18:10:40 +08:00
Naz
8dc630b3a0
Removed cleaned up use of "Job" object
refs https://github.com/TryGhost/Toolbox/issues/430

- Importer code was filled with an unnecessarily complex "job" object that was passed around. It had an "id" property, which confusingly was a path to a file at all times.
- Simplified the logic significantly by keeping and passing around the path to a "prepared" members CSV.
2022-10-19 18:10:40 +08:00
Naz
812973d962
Removed unused concept of "status" in importer job
refs https://github.com/TryGhost/Toolbox/issues/430

- The job "status" is never anything different than "pending" and never leaves the module itself. It's an outdated concept that only takes up lines of code!
2022-10-19 18:10:40 +08:00
Naz
2175d64095
Added future investigation note
refs https://github.com/TryGhost/Toolbox/issues/430

- This is a strange hardcoded value that seems like some legacy leftover concept we could do without or improve
2022-10-19 18:10:40 +08:00
Naz
4300f14d79
Removed hidden row mapping in csv parser
refs https://github.com/TryGhost/Toolbox/issues/430
refs https://github.com/TryGhost/Ghost/issues/14882

- Having an explicit mappings passed into the members CSV parser makes it easier to control and understand the transforms for package clients
- Eventually the parser will receive a strict map with the fields it should parse - skipping all unknown & unmapped fields
2022-10-19 18:10:40 +08:00
Naz
9e20544927
Fixed typo 2022-10-13 09:53:16 +08:00
Naz
71bed4f926
Fixed jsdoc to only mention used parameters
refs https://github.com/TryGhost/Toolbox/issues/430

- It's a minor cleanup while exploring the referenced bug surface area. Fixes distracting "missing parameters" warnings
2022-10-13 09:53:16 +08:00
Rishabh Garg
8a598fe721
🐛 Fixed member importer crash for failed imports (#15560)
refs/closes https://github.com/TryGhost/Team/issues/2004

- for imports, members are created inside a transaction, which causes the member created events to be dispatched.
- its possible that transactions for import can be rolled back if for some reason there is an error down the line while inserting other member properties. The rollback doesn't commit the member to DB, but the event dispatched earlier will still try to create the member created event which fails due to missing member id.
- knex transactions resolve the `executionPromise` both in case of explicit commit or rollback from the user, so just the transaction end check will not be good enough to make sure the member exists in DB
- adds explicit config to knex to reject transaction in case of rollback, which is then caught and event is not dispatched
2022-10-07 19:15:18 +05:30
Simon Backx
99e6f8ddda Moved analytics page to separate component
refs https://github.com/TryGhost/Team/issues/1976
refs https://ghost.slack.com/archives/C02G9E68C/p1664446234131629

- @tracked properties in controllers are persisted, should use components instead
2022-09-29 12:41:16 +02:00
Simon Backx
f9e5d57f0d 🎨 Added number formatting to members import email
refs https://ghost.slack.com/archives/C02G9E68C/p1663318892246929?thread_ts=1663317382.429489&cid=C02G9E68C
2022-09-16 11:13:12 +02:00
Peter Zimon
2769578dbd Various Members importer UX improvements
no refs.

- CSV overview table headings were selectable
- spinner on the last screen was confusing: users might think they had to wait for something to finish, but that's not true
- spacings in import confirmation emails were off
2022-09-16 10:50:54 +02:00
Rishabh Garg
c16abbf085
🐛 Fixed empty error csv file for member imports (#15274)
closes https://github.com/TryGhost/Team/issues/1828

- members importer was sending empty error files in case of invalid rows in CSV, hiding both error and affected rows
- fixes typo in `content` option(was `contents` before) passed to attachment (ref - https://nodemailer.com/message/attachments )
2022-08-24 00:49:30 +05:30
Simon Backx
14a7d1f00f Cleaned up multipleProducts and multipleNewsletters flags 2022-05-25 10:25:02 +02:00
Aileen Nowak
dd702f6ef8 Allow setting context for members importer and use correct source
no issue

When importing members, the members-importer isn't aware of the context and therefore falls back to use `member` as a source in members event table. This makes it impossible to determine imported members from others.
- Added an `context` property to the options in the members-importer constructor
- Checked for `importer` context when creating member events and assigned the source `admin` to it
2022-04-27 15:27:19 -04:00
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
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
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
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 O'Carroll
75d003816e Fixed the importer from overriding properties
refs https://github.com/TryGhost/Team/issues/1202

When importing we were transforming the CSV and add missing columns to
it before storing it in preparation to perform the import. This resulted
in the missing columns being updated for existing members with blank
data.

We've updated the Members CSV parsing library to take an options list of
columns to include, which then allows imports to not include all of the
default columns.
2021-12-01 17:02:30 +02:00
Naz
9cbe5efdf5 Removed checkEmailList flag check
refs https://github.com/TryGhost/Team/issues/906

- The feature is entering GA stage and the flag is no longer needed
2021-08-20 17:28:06 +04:00
Naz
fd7f515055 Changed MembersCSVImporter constructor
refs https://github.com/TryGhost/Team/issues/958

- The import threshold has to become a dynamic number based on external parameters. Because of this it makes most sense to have it as an async function parameter
- There's a package API change for importThreshold constructor paramter becoming a fetchThreshold async funciton parameter
2021-08-18 16:09:33 +04:00
Naz
96b3629280 Exposed originalImportSize from members importer
refs https://github.com/TryGhost/Team/issues/912

- The variable is needed as a datapoint in Ghost when sending stats about what the import size was used
2021-07-28 19:13:48 +04:00
Naz
a90d996f33 Added import threshold check to importer
refs https://github.com/TryGhost/Team/issues/912

- We need a way to check if the import threshold has been reached within the members importer. See more deets in refed issue
2021-07-23 20:29:19 +04:00
Naz
8b45f73079 Removed unused files
refs https://github.com/TryGhost/Team/issues/916
2021-07-22 01:53:21 +12:00
Naz
e9d186ced6 Refactored ghostMailer parameter
refs https://github.com/TryGhost/Team/issues/916

-  The constructor API should have as small of a surface as possible, there's no need to pass around whole ghostMailer instance
2021-07-22 01:53:21 +12:00