فهرست منبع

Merge pull request #12748 from overleaf/bg-recurly-add-currency

add script for generating recurly prices

GitOrigin-RevId: c7a624af35eba9882798fbaf750e4328604f47fa
Brian Gough 3 سال پیش
والد
کامیت
253f44894a
1فایلهای تغییر یافته به همراه118 افزوده شده و 0 حذف شده
  1. 118 0
      services/web/scripts/recurly/generate_recurly_prices.js

+ 118 - 0
services/web/scripts/recurly/generate_recurly_prices.js

@@ -0,0 +1,118 @@
+// script to generate plan prices for recurly from a csv file
+//
+// Usage:
+//
+// $ node scripts/recurly/generate_recurly_prices.js -f input.csv -o prices.json
+//
+// The input csv file has the following format:
+//
+//     plan_code,USD,EUR,GBP,...
+//     student,9,8,7,...
+//     student-annual,89,79,69,...
+//     group_professional_2_educational,558,516,446,...
+//
+// The output file format is the JSON of the plans returned by recurly, with an
+// extra _addOns property for the addOns associated with that plan.
+//
+// The output can be used as input for the upload script `recurly_prices.js`.
+
+const minimist = require('minimist')
+const csv = require('csv/sync')
+const _ = require('lodash')
+const fs = require('fs')
+
+const argv = minimist(process.argv.slice(2), {
+  string: ['output', 'file'],
+  alias: { o: 'output', f: 'file' },
+  default: { output: '/dev/stdout' },
+})
+
+// All currency codes are 3 uppercase letters
+const CURRENCY_CODE_REGEX = /^[A-Z]{3}$/
+// Group plans have a plan code of the form group_name_size_type, e.g.
+const GROUP_SIZE_REGEX = /group_\w+_([0-9]+)_\w+/
+// Only group plans with more than 4 users can have additional licenses
+const SINGLE_LICENSE_MAX_GROUP_SIZE = 4
+
+// Compute prices for the base plan
+
+function computePrices(plan) {
+  const prices = _.pickBy(plan, (value, key) => CURRENCY_CODE_REGEX.test(key))
+  const result = []
+  for (const currency in prices) {
+    result.push({
+      currency,
+      setupFee: 0,
+      unitAmount: parseInt(prices[currency], 10),
+    })
+  }
+  return result
+}
+
+// Handle prices for license add-ons associated with group plans
+
+function isGroupPlan(plan) {
+  return plan.plan_code.startsWith('group_')
+}
+
+function getGroupSize(plan) {
+  // extract the group size from the plan code group_name_size_type using a regex
+  const match = plan.plan_code.match(GROUP_SIZE_REGEX)
+  if (!match) {
+    throw new Error(`cannot find group size in plan code: ${plan.plan_code}`)
+  }
+  const size = parseInt(match[1], 10)
+  return size
+}
+
+function computeAddOnPrices(prices, size) {
+  // The price of an additional license is the per-user cost of the base plan,
+  // i.e. the price of the plan divided by the group size of the plan
+  return prices.map(price => {
+    return {
+      currency: price.currency,
+      unitAmount: Math.round((100 * price.unitAmount) / size) / 100,
+      unitAmountDecimal: null,
+    }
+  })
+}
+
+// Convert the raw records into the output format
+
+function transformRecordToPlan(record) {
+  const prices = computePrices(record)
+  // The base plan has no add-ons
+  const plan = {
+    code: record.plan_code,
+    currencies: prices,
+  }
+  // Large group plans have an add-on for additional licenses
+  if (isGroupPlan(record)) {
+    const size = getGroupSize(record)
+    if (size > SINGLE_LICENSE_MAX_GROUP_SIZE) {
+      const addOnPrices = computeAddOnPrices(prices, size)
+      plan._addOns = [
+        {
+          code: 'additional-license',
+          currencies: addOnPrices,
+        },
+      ]
+    }
+  }
+  return plan
+}
+
+function generate(inputFile, outputFile) {
+  const input = fs.readFileSync(inputFile, 'utf8')
+  const rawRecords = csv.parse(input, { columns: true })
+  // transform the raw records into the output format
+  const plans = rawRecords.map(transformRecordToPlan)
+  const output = JSON.stringify(plans, null, 2)
+  fs.writeFileSync(outputFile, output)
+}
+
+if (argv.file) {
+  generate(argv.file, argv.output)
+} else {
+  console.log('usage:\n' + '  --file input.csv -o file.json\n')
+}