diff --git a/services/web/scripts/plan-prices/.gitignore b/services/web/scripts/plan-prices/.gitignore index 05c5e72581..1406277934 100644 --- a/services/web/scripts/plan-prices/.gitignore +++ b/services/web/scripts/plan-prices/.gitignore @@ -1,3 +1,2 @@ node_modules output -*.xlsx diff --git a/services/web/scripts/plan-prices/README.md b/services/web/scripts/plan-prices/README.md index 2c60f0957a..5bca9a308a 100644 --- a/services/web/scripts/plan-prices/README.md +++ b/services/web/scripts/plan-prices/README.md @@ -1,19 +1,18 @@ -A nodejs tool for reading plans prices from an Excel file and creating JSON objects. +A nodejs tool for reading plans prices from csv files and creating JSON objects. -Run `npm install` in order to install the `xlsx` dependency. +Run `npm install` in order to install the dependencies. The scripts will put the output results into the `output` folder. ### Create localized and group plan pricing -_Command_ `node plans.js -f fileName -s sheetName -o outputdir` - generates three json files: +_Command_ `node plans.js -f fileName -o outputdir` - generates three json files: - `localizedPlanPricing.json` for `/services/web/config/settings.overrides.saas.js` - `plans.json` for `/services/web/frontend/js/main/plans.js` - `groups.json` for `/services/web/app/templates/plans/groups.json` -The input file can be in `.xls`, `.csv` or `.json` format +The input file can be in `.csv` or `.json` format -- `.xlsx` excel spreadsheet, requires the `-s sheetName` option -- `.csv` csv format, same data as for excel spreadsheet +- `.csv` csv format - `.json` json format from the `recurly_prices.js --download` script output diff --git a/services/web/scripts/plan-prices/package-lock.json b/services/web/scripts/plan-prices/package-lock.json index 154aa323a6..977248e89d 100644 --- a/services/web/scripts/plan-prices/package-lock.json +++ b/services/web/scripts/plan-prices/package-lock.json @@ -10,51 +10,7 @@ "license": "ISC", "devDependencies": { "csv": "^6.2.10", - "minimist": "^1.2.8", - "xlsx": "^0.18.5" - } - }, - "node_modules/adler-32": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.1.tgz", - "integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/cfb": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.2.tgz", - "integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==", - "dev": true, - "dependencies": { - "adler-32": "~1.3.0", - "crc-32": "~1.2.0" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/codepage": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz", - "integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/crc-32": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", - "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", - "dev": true, - "bin": { - "crc32": "bin/crc32.njs" - }, - "engines": { - "node": ">=0.8" + "minimist": "^1.2.8" } }, "node_modules/csv": { @@ -90,15 +46,6 @@ "integrity": "sha512-dD9gfbxNKa5v90NHiE2Qd6F9I52GtJjGTfowwzqiNDZD/+NPW3h19d2Nvv311a8QUW11rYRobco27nvVAnCrLw==", "dev": true }, - "node_modules/frac": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz", - "integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, "node_modules/minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", @@ -108,93 +55,14 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/ssf": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz", - "integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==", - "dev": true, - "dependencies": { - "frac": "~1.1.2" - }, - "engines": { - "node": ">=0.8" - } - }, "node_modules/stream-transform": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/stream-transform/-/stream-transform-3.2.4.tgz", "integrity": "sha512-YoZm/eoh6f/MH7uHkq+NK3fx3JkyXbck7FcTpJavwEUg0aMINqMPkDj5uNW0CoRy7c/2NSJm0HvoyFv6dVauPA==", "dev": true - }, - "node_modules/wmf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz", - "integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/word": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/word/-/word-0.3.0.tgz", - "integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/xlsx": { - "version": "0.18.5", - "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.18.5.tgz", - "integrity": "sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==", - "dev": true, - "dependencies": { - "adler-32": "~1.3.0", - "cfb": "~1.2.1", - "codepage": "~1.15.0", - "crc-32": "~1.2.1", - "ssf": "~0.11.2", - "wmf": "~1.0.1", - "word": "~0.3.0" - }, - "bin": { - "xlsx": "bin/xlsx.njs" - }, - "engines": { - "node": ">=0.8" - } } }, "dependencies": { - "adler-32": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.1.tgz", - "integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==", - "dev": true - }, - "cfb": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.2.tgz", - "integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==", - "dev": true, - "requires": { - "adler-32": "~1.3.0", - "crc-32": "~1.2.0" - } - }, - "codepage": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz", - "integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==", - "dev": true - }, - "crc-32": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", - "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", - "dev": true - }, "csv": { "version": "6.2.10", "resolved": "https://registry.npmjs.org/csv/-/csv-6.2.10.tgz", @@ -225,59 +93,17 @@ "integrity": "sha512-dD9gfbxNKa5v90NHiE2Qd6F9I52GtJjGTfowwzqiNDZD/+NPW3h19d2Nvv311a8QUW11rYRobco27nvVAnCrLw==", "dev": true }, - "frac": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz", - "integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==", - "dev": true - }, "minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true }, - "ssf": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz", - "integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==", - "dev": true, - "requires": { - "frac": "~1.1.2" - } - }, "stream-transform": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/stream-transform/-/stream-transform-3.2.4.tgz", "integrity": "sha512-YoZm/eoh6f/MH7uHkq+NK3fx3JkyXbck7FcTpJavwEUg0aMINqMPkDj5uNW0CoRy7c/2NSJm0HvoyFv6dVauPA==", "dev": true - }, - "wmf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz", - "integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==", - "dev": true - }, - "word": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/word/-/word-0.3.0.tgz", - "integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==", - "dev": true - }, - "xlsx": { - "version": "0.18.5", - "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.18.5.tgz", - "integrity": "sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==", - "dev": true, - "requires": { - "adler-32": "~1.3.0", - "cfb": "~1.2.1", - "codepage": "~1.15.0", - "crc-32": "~1.2.1", - "ssf": "~0.11.2", - "wmf": "~1.0.1", - "word": "~0.3.0" - } } } } diff --git a/services/web/scripts/plan-prices/package.json b/services/web/scripts/plan-prices/package.json index b97b2e93d2..0ceff77b08 100644 --- a/services/web/scripts/plan-prices/package.json +++ b/services/web/scripts/plan-prices/package.json @@ -10,7 +10,6 @@ "license": "ISC", "devDependencies": { "csv": "^6.2.10", - "minimist": "^1.2.8", - "xlsx": "^0.18.5" + "minimist": "^1.2.8" } } diff --git a/services/web/scripts/plan-prices/plans.js b/services/web/scripts/plan-prices/plans.js index 9a8fbb5032..542a07dd35 100644 --- a/services/web/scripts/plan-prices/plans.js +++ b/services/web/scripts/plan-prices/plans.js @@ -1,33 +1,11 @@ // Creates data for localizedPlanPricing object in settings.overrides.saas.js // and plans object in main/plans.js -const xlsx = require('xlsx') const csv = require('csv/sync') const fs = require('fs') const path = require('path') const minimist = require('minimist') -function readXLSXFile(fileName, sheetName) { - // Pick the xlsx file - const filePath = path.resolve(__dirname, fileName) - const file = xlsx.readFile(filePath) - - if (!file.SheetNames.includes(sheetName)) { - console.error( - `Error: sheet '${sheetName}' not found.\n` + - `Valid sheet names are: ${file.SheetNames.join(',')}` - ) - process.exit(1) - } - - const workSheet = Object.values(file.Sheets)[ - file.SheetNames.indexOf(sheetName) - ] - // Convert to JSON - const workSheetJSON = xlsx.utils.sheet_to_json(workSheet) - return workSheetJSON -} - function readCSVFile(fileName) { // Pick the csv file const filePath = path.resolve(__dirname, fileName) @@ -180,6 +158,10 @@ function generatePlans(workSheetJSON) { ) if (!monthlyPlan) throw new Error(`Missing plan: ${actualKey}`) + if (!(currency in monthlyPlan)) + throw new Error( + `Missing currency "${currency}" for plan "${actualKey}"` + ) const actualKeyAnnual = `${actualKey}-annual` const annualPlan = workSheetJSON.find( @@ -187,6 +169,10 @@ function generatePlans(workSheetJSON) { ) if (!annualPlan) throw new Error(`Missing plan: ${actualKeyAnnual}`) + if (!(currency in annualPlan)) + throw new Error( + `Missing currency "${currency}" for plan "${actualKeyAnnual}"` + ) const monthly = buildCurrencyValue(monthlyPlan[currency], currencyDetails) const monthlyTimesTwelve = buildCurrencyValue( @@ -258,8 +244,8 @@ function generateGroupPlans(workSheetJSON) { } const argv = minimist(process.argv.slice(2), { - string: ['output', 'file', 'sheet'], - alias: { o: 'output', f: 'file', s: 'sheet' }, + string: ['output', 'file'], + alias: { o: 'output', f: 'file' }, }) let input @@ -269,30 +255,26 @@ if (argv.file) { case '.csv': input = readCSVFile(argv.file) break - case '.xls': - case '.xlsx': - input = readXLSXFile(argv.file, argv.sheet) - break case '.json': input = readJSONFile(argv.file) break default: - console.log('Invalid file type: must be csv, xls, xlsx, or json') + console.log('Invalid file type: must be csv or json') } } else { - console.log( - 'usage: node plans.js -f [-s ] -o ' - ) + console.log('usage: node plans.js -f -o ') process.exit(1) } // removes quotes from object keys const formatJS = obj => JSON.stringify(obj, null, 2).replace(/"([^"]+)":/g, '$1:') const formatJSON = obj => JSON.stringify(obj, null, 2) + function writeFile(outputFile, data) { console.log(`Writing ${outputFile}`) fs.writeFileSync(outputFile, data) } + const { localizedPlanPricing, plans } = generatePlans(input) const groupPlans = generateGroupPlans(input)