GroupPlansData.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. const Settings = require('@overleaf/settings')
  2. const fs = require('fs')
  3. const Path = require('path')
  4. // The groups.json file encodes the various group plan options we provide, and
  5. // is used in the app the render the appropriate dialog in the plans page, and
  6. // to generate the appropriate entries in the Settings.plans array.
  7. // It is also used by scripts/recurly/sync_recurly.rb, which will make sure
  8. // Recurly has a plan configured for all the groups, and that the prices are
  9. // up to date with the data in groups.json.
  10. // Alternatively, scripts/recurly/get_recurly_group_prices.rb can be used to
  11. // fetch pricing data and generate a groups.json using the current Recurly
  12. // prices
  13. const data = fs.readFileSync(
  14. Path.join(__dirname, '/../../../templates/plans/groups.json')
  15. )
  16. const groups = JSON.parse(data.toString())
  17. const capitalize = string => string.charAt(0).toUpperCase() + string.slice(1)
  18. // With group accounts in Recurly, we end up with a lot of plans to manage.
  19. // Rather than hand coding them in the settings file, and then needing to keep
  20. // that data in sync with the data in groups.json, we can auto generate the
  21. // group plan entries and append them to Settings.plans at boot time. This is not
  22. // a particularly clean pattern, since it's a little surprising that settings
  23. // are modified at boot-time, but I think it's a better option than trying to
  24. // keep two sources of data in sync.
  25. for (const [usage, planData] of Object.entries(groups)) {
  26. for (const [planCode, currencyData] of Object.entries(planData)) {
  27. // Gather all possible sizes that are set up in at least one currency
  28. const sizes = new Set()
  29. for (const priceData of Object.values(currencyData)) {
  30. for (const size in priceData) {
  31. sizes.add(size)
  32. }
  33. }
  34. const planName =
  35. planCode === 'collaborator' ? 'Standard' : capitalize(planCode)
  36. // Generate plans in settings
  37. for (const size of sizes) {
  38. const plan = {
  39. planCode: `group_${planCode}_${size}_${usage}`,
  40. name:
  41. usage === 'enterprise'
  42. ? `Group ${planName} Plan (${size} licenses)`
  43. : `Group ${planName} Plan (${size} licenses) - ${capitalize(usage)}`,
  44. hideFromUsers: true,
  45. price_in_cents: groups[usage][planCode].USD[size].price_in_cents,
  46. annual: true,
  47. features: Settings.features[planCode],
  48. groupPlan: true,
  49. membersLimit: parseInt(size),
  50. // Add the `membersLimitAddOn` to all group plans
  51. membersLimitAddOn: 'additional-license',
  52. // Unlock flexible licensing for all group plans
  53. canUseFlexibleLicensing: true,
  54. }
  55. Settings.plans.push(plan)
  56. }
  57. }
  58. }
  59. module.exports = groups