first commit
This commit is contained in:
2
services/web/scripts/plan-prices/.gitignore
vendored
Normal file
2
services/web/scripts/plan-prices/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
node_modules
|
||||
output
|
||||
17
services/web/scripts/plan-prices/README.md
Normal file
17
services/web/scripts/plan-prices/README.md
Normal file
@@ -0,0 +1,17 @@
|
||||
A nodejs tool for reading plans prices from csv files and creating JSON objects.
|
||||
|
||||
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.mjs -f fileName -o outputdir` - generates two json files:
|
||||
|
||||
- `localizedPlanPricing.json` for `/services/web/config/settings.overrides.saas.js`
|
||||
- `groups.json` for `/services/web/app/templates/plans/groups.json`
|
||||
|
||||
The input file can be in `.csv` or `.json` format
|
||||
|
||||
- `.csv` csv format
|
||||
- `.json` json format from the `recurly_prices.mjs --download` script output
|
||||
@@ -0,0 +1,546 @@
|
||||
{
|
||||
"educational": {
|
||||
"professional": {
|
||||
"2": {
|
||||
"AUD": 321,
|
||||
"BRL": 699,
|
||||
"CAD": 314,
|
||||
"CHF": 279,
|
||||
"CLP": 168693,
|
||||
"COP": 552930,
|
||||
"DKK": 1665,
|
||||
"EUR": 258,
|
||||
"GBP": 223,
|
||||
"INR": 6719,
|
||||
"MXN": 4129,
|
||||
"NOK": 2008,
|
||||
"NZD": 321,
|
||||
"PEN": 671,
|
||||
"SEK": 2008,
|
||||
"SGD": 363,
|
||||
"USD": 279
|
||||
},
|
||||
"3": {
|
||||
"AUD": 321,
|
||||
"BRL": 699,
|
||||
"CAD": 314,
|
||||
"CHF": 279,
|
||||
"CLP": 168693,
|
||||
"COP": 552930,
|
||||
"DKK": 1665,
|
||||
"EUR": 258,
|
||||
"GBP": 223,
|
||||
"INR": 6719,
|
||||
"MXN": 4129,
|
||||
"NOK": 2008,
|
||||
"NZD": 321,
|
||||
"PEN": 671,
|
||||
"SEK": 2008,
|
||||
"SGD": 363,
|
||||
"USD": 279
|
||||
},
|
||||
"4": {
|
||||
"AUD": 321,
|
||||
"BRL": 699,
|
||||
"CAD": 314,
|
||||
"CHF": 279,
|
||||
"CLP": 168693,
|
||||
"COP": 552930,
|
||||
"DKK": 1665,
|
||||
"EUR": 258,
|
||||
"GBP": 223,
|
||||
"INR": 6719,
|
||||
"MXN": 4129,
|
||||
"NOK": 2008,
|
||||
"NZD": 321,
|
||||
"PEN": 671,
|
||||
"SEK": 2008,
|
||||
"SGD": 363,
|
||||
"USD": 279
|
||||
},
|
||||
"5": {
|
||||
"AUD": 321,
|
||||
"BRL": 699,
|
||||
"CAD": 314,
|
||||
"CHF": 279,
|
||||
"CLP": 168693,
|
||||
"COP": 552930,
|
||||
"DKK": 1665,
|
||||
"EUR": 258,
|
||||
"GBP": 223,
|
||||
"INR": 6719,
|
||||
"MXN": 4129,
|
||||
"NOK": 2008,
|
||||
"NZD": 321,
|
||||
"PEN": 671,
|
||||
"SEK": 2008,
|
||||
"SGD": 363,
|
||||
"USD": 279
|
||||
},
|
||||
"10": {
|
||||
"AUD": 179,
|
||||
"BRL": 389,
|
||||
"CAD": 175,
|
||||
"CHF": 155,
|
||||
"CLP": 93986,
|
||||
"COP": 308061,
|
||||
"DKK": 927,
|
||||
"EUR": 143,
|
||||
"GBP": 124,
|
||||
"INR": 3743,
|
||||
"MXN": 2300,
|
||||
"NOK": 1118,
|
||||
"NZD": 179,
|
||||
"PEN": 374,
|
||||
"SEK": 1118,
|
||||
"SGD": 202,
|
||||
"USD": 155
|
||||
},
|
||||
"20": {
|
||||
"AUD": 165,
|
||||
"BRL": 359,
|
||||
"CAD": 161,
|
||||
"CHF": 143,
|
||||
"CLP": 86756,
|
||||
"COP": 284364,
|
||||
"DKK": 856,
|
||||
"EUR": 132,
|
||||
"GBP": 114,
|
||||
"INR": 3455,
|
||||
"MXN": 2123,
|
||||
"NOK": 1032,
|
||||
"NZD": 165,
|
||||
"PEN": 345,
|
||||
"SEK": 1032,
|
||||
"SGD": 186,
|
||||
"USD": 143
|
||||
},
|
||||
"50": {
|
||||
"AUD": 151,
|
||||
"BRL": 329,
|
||||
"CAD": 148,
|
||||
"CHF": 131,
|
||||
"CLP": 79526,
|
||||
"COP": 260667,
|
||||
"DKK": 785,
|
||||
"EUR": 121,
|
||||
"GBP": 105,
|
||||
"INR": 3167,
|
||||
"MXN": 1946,
|
||||
"NOK": 946,
|
||||
"NZD": 151,
|
||||
"PEN": 316,
|
||||
"SEK": 946,
|
||||
"SGD": 171,
|
||||
"USD": 131
|
||||
}
|
||||
},
|
||||
"collaborator": {
|
||||
"2": {
|
||||
"AUD": 167,
|
||||
"BRL": 349,
|
||||
"CAD": 160,
|
||||
"CHF": 139,
|
||||
"CLP": 77693,
|
||||
"COP": 272930,
|
||||
"DKK": 839,
|
||||
"EUR": 125,
|
||||
"GBP": 111,
|
||||
"INR": 3219,
|
||||
"MXN": 2029,
|
||||
"NOK": 1014,
|
||||
"NZD": 167,
|
||||
"PEN": 321,
|
||||
"SEK": 1014,
|
||||
"SGD": 181,
|
||||
"USD": 139
|
||||
},
|
||||
"3": {
|
||||
"AUD": 167,
|
||||
"BRL": 349,
|
||||
"CAD": 160,
|
||||
"CHF": 139,
|
||||
"CLP": 77693,
|
||||
"COP": 272930,
|
||||
"DKK": 839,
|
||||
"EUR": 125,
|
||||
"GBP": 111,
|
||||
"INR": 3219,
|
||||
"MXN": 2029,
|
||||
"NOK": 1014,
|
||||
"NZD": 167,
|
||||
"PEN": 321,
|
||||
"SEK": 1014,
|
||||
"SGD": 181,
|
||||
"USD": 139
|
||||
},
|
||||
"4": {
|
||||
"AUD": 167,
|
||||
"BRL": 349,
|
||||
"CAD": 160,
|
||||
"CHF": 139,
|
||||
"CLP": 77693,
|
||||
"COP": 272930,
|
||||
"DKK": 839,
|
||||
"EUR": 125,
|
||||
"GBP": 111,
|
||||
"INR": 3219,
|
||||
"MXN": 2029,
|
||||
"NOK": 1014,
|
||||
"NZD": 167,
|
||||
"PEN": 321,
|
||||
"SEK": 1014,
|
||||
"SGD": 181,
|
||||
"USD": 139
|
||||
},
|
||||
"5": {
|
||||
"AUD": 167,
|
||||
"BRL": 349,
|
||||
"CAD": 160,
|
||||
"CHF": 139,
|
||||
"CLP": 77693,
|
||||
"COP": 272930,
|
||||
"DKK": 839,
|
||||
"EUR": 125,
|
||||
"GBP": 111,
|
||||
"INR": 3219,
|
||||
"MXN": 2029,
|
||||
"NOK": 1014,
|
||||
"NZD": 167,
|
||||
"PEN": 321,
|
||||
"SEK": 1014,
|
||||
"SGD": 181,
|
||||
"USD": 139
|
||||
},
|
||||
"10": {
|
||||
"AUD": 93,
|
||||
"BRL": 194,
|
||||
"CAD": 89,
|
||||
"CHF": 77,
|
||||
"CLP": 43286,
|
||||
"COP": 152061,
|
||||
"DKK": 467,
|
||||
"EUR": 69,
|
||||
"GBP": 62,
|
||||
"INR": 1793,
|
||||
"MXN": 1130,
|
||||
"NOK": 565,
|
||||
"NZD": 93,
|
||||
"PEN": 179,
|
||||
"SEK": 565,
|
||||
"SGD": 101,
|
||||
"USD": 77
|
||||
},
|
||||
"20": {
|
||||
"AUD": 86,
|
||||
"BRL": 179,
|
||||
"CAD": 82,
|
||||
"CHF": 71,
|
||||
"CLP": 39956,
|
||||
"COP": 140364,
|
||||
"DKK": 431,
|
||||
"EUR": 64,
|
||||
"GBP": 57,
|
||||
"INR": 1655,
|
||||
"MXN": 1043,
|
||||
"NOK": 521,
|
||||
"NZD": 86,
|
||||
"PEN": 165,
|
||||
"SEK": 521,
|
||||
"SGD": 93,
|
||||
"USD": 71
|
||||
},
|
||||
"50": {
|
||||
"AUD": 78,
|
||||
"BRL": 164,
|
||||
"CAD": 75,
|
||||
"CHF": 65,
|
||||
"CLP": 36626,
|
||||
"COP": 128667,
|
||||
"DKK": 395,
|
||||
"EUR": 59,
|
||||
"GBP": 52,
|
||||
"INR": 1517,
|
||||
"MXN": 956,
|
||||
"NOK": 478,
|
||||
"NZD": 78,
|
||||
"PEN": 151,
|
||||
"SEK": 478,
|
||||
"SGD": 85,
|
||||
"USD": 65
|
||||
}
|
||||
}
|
||||
},
|
||||
"enterprise": {
|
||||
"professional": {
|
||||
"2": {
|
||||
"AUD": 321,
|
||||
"BRL": 699,
|
||||
"CAD": 314,
|
||||
"CHF": 499,
|
||||
"CLP": 168693,
|
||||
"COP": 552930,
|
||||
"DKK": 1665,
|
||||
"EUR": 258,
|
||||
"GBP": 223,
|
||||
"INR": 6719,
|
||||
"MXN": 4129,
|
||||
"NOK": 2008,
|
||||
"NZD": 321,
|
||||
"PEN": 671,
|
||||
"SEK": 2008,
|
||||
"SGD": 363,
|
||||
"USD": 279
|
||||
},
|
||||
"3": {
|
||||
"AUD": 321,
|
||||
"BRL": 699,
|
||||
"CAD": 314,
|
||||
"CHF": 499,
|
||||
"CLP": 168693,
|
||||
"COP": 552930,
|
||||
"DKK": 1665,
|
||||
"EUR": 258,
|
||||
"GBP": 223,
|
||||
"INR": 6719,
|
||||
"MXN": 4129,
|
||||
"NOK": 2008,
|
||||
"NZD": 321,
|
||||
"PEN": 671,
|
||||
"SEK": 2008,
|
||||
"SGD": 363,
|
||||
"USD": 279
|
||||
},
|
||||
"4": {
|
||||
"AUD": 321,
|
||||
"BRL": 699,
|
||||
"CAD": 314,
|
||||
"CHF": 499,
|
||||
"CLP": 168693,
|
||||
"COP": 552930,
|
||||
"DKK": 1665,
|
||||
"EUR": 258,
|
||||
"GBP": 223,
|
||||
"INR": 6719,
|
||||
"MXN": 4129,
|
||||
"NOK": 2008,
|
||||
"NZD": 321,
|
||||
"PEN": 671,
|
||||
"SEK": 2008,
|
||||
"SGD": 363,
|
||||
"USD": 279
|
||||
},
|
||||
"5": {
|
||||
"AUD": 321,
|
||||
"BRL": 699,
|
||||
"CAD": 314,
|
||||
"CHF": 499,
|
||||
"CLP": 168693,
|
||||
"COP": 552930,
|
||||
"DKK": 1665,
|
||||
"EUR": 258,
|
||||
"GBP": 223,
|
||||
"INR": 6719,
|
||||
"MXN": 4129,
|
||||
"NOK": 2008,
|
||||
"NZD": 321,
|
||||
"PEN": 671,
|
||||
"SEK": 2008,
|
||||
"SGD": 363,
|
||||
"USD": 279
|
||||
},
|
||||
"10": {
|
||||
"AUD": 298,
|
||||
"BRL": 649,
|
||||
"CAD": 291,
|
||||
"CHF": 259,
|
||||
"CLP": 156643,
|
||||
"COP": 513435,
|
||||
"DKK": 1546,
|
||||
"EUR": 239,
|
||||
"GBP": 207,
|
||||
"INR": 6239,
|
||||
"MXN": 3834,
|
||||
"NOK": 1864,
|
||||
"NZD": 298,
|
||||
"PEN": 623,
|
||||
"SEK": 1864,
|
||||
"SGD": 337,
|
||||
"USD": 259
|
||||
},
|
||||
"20": {
|
||||
"AUD": 275,
|
||||
"BRL": 599,
|
||||
"CAD": 269,
|
||||
"CHF": 239,
|
||||
"CLP": 144594,
|
||||
"COP": 473940,
|
||||
"DKK": 1427,
|
||||
"EUR": 221,
|
||||
"GBP": 191,
|
||||
"INR": 5759,
|
||||
"MXN": 3539,
|
||||
"NOK": 1721,
|
||||
"NZD": 275,
|
||||
"PEN": 575,
|
||||
"SEK": 1721,
|
||||
"SGD": 311,
|
||||
"USD": 239
|
||||
},
|
||||
"50": {
|
||||
"AUD": 252,
|
||||
"BRL": 549,
|
||||
"CAD": 246,
|
||||
"CHF": 219,
|
||||
"CLP": 132544,
|
||||
"COP": 400000,
|
||||
"DKK": 1308,
|
||||
"EUR": 202,
|
||||
"GBP": 175,
|
||||
"INR": 5279,
|
||||
"MXN": 3244,
|
||||
"NOK": 1577,
|
||||
"NZD": 252,
|
||||
"PEN": 527,
|
||||
"SEK": 1577,
|
||||
"SGD": 285,
|
||||
"USD": 219
|
||||
}
|
||||
},
|
||||
"collaborator": {
|
||||
"2": {
|
||||
"AUD": 167,
|
||||
"BRL": 349,
|
||||
"CAD": 160,
|
||||
"CHF": 139,
|
||||
"CLP": 77693,
|
||||
"COP": 272930,
|
||||
"DKK": 839,
|
||||
"EUR": 125,
|
||||
"GBP": 111,
|
||||
"INR": 3219,
|
||||
"MXN": 2029,
|
||||
"NOK": 1014,
|
||||
"NZD": 167,
|
||||
"PEN": 321,
|
||||
"SEK": 1014,
|
||||
"SGD": 181,
|
||||
"USD": 139
|
||||
},
|
||||
"3": {
|
||||
"AUD": 167,
|
||||
"BRL": 349,
|
||||
"CAD": 160,
|
||||
"CHF": 139,
|
||||
"CLP": 77693,
|
||||
"COP": 272930,
|
||||
"DKK": 839,
|
||||
"EUR": 125,
|
||||
"GBP": 111,
|
||||
"INR": 3219,
|
||||
"MXN": 2029,
|
||||
"NOK": 1014,
|
||||
"NZD": 167,
|
||||
"PEN": 321,
|
||||
"SEK": 1014,
|
||||
"SGD": 181,
|
||||
"USD": 139
|
||||
},
|
||||
"4": {
|
||||
"AUD": 167,
|
||||
"BRL": 349,
|
||||
"CAD": 160,
|
||||
"CHF": 139,
|
||||
"CLP": 77693,
|
||||
"COP": 272930,
|
||||
"DKK": 839,
|
||||
"EUR": 125,
|
||||
"GBP": 111,
|
||||
"INR": 3219,
|
||||
"MXN": 2029,
|
||||
"NOK": 1014,
|
||||
"NZD": 167,
|
||||
"PEN": 321,
|
||||
"SEK": 1014,
|
||||
"SGD": 181,
|
||||
"USD": 139
|
||||
},
|
||||
"5": {
|
||||
"AUD": 167,
|
||||
"BRL": 349,
|
||||
"CAD": 160,
|
||||
"CHF": 139,
|
||||
"CLP": 77693,
|
||||
"COP": 272930,
|
||||
"DKK": 839,
|
||||
"EUR": 125,
|
||||
"GBP": 111,
|
||||
"INR": 3219,
|
||||
"MXN": 2029,
|
||||
"NOK": 1014,
|
||||
"NZD": 167,
|
||||
"PEN": 321,
|
||||
"SEK": 1014,
|
||||
"SGD": 181,
|
||||
"USD": 139
|
||||
},
|
||||
"10": {
|
||||
"AUD": 155,
|
||||
"BRL": 324,
|
||||
"CAD": 148,
|
||||
"CHF": 129,
|
||||
"CLP": 72143,
|
||||
"COP": 253435,
|
||||
"DKK": 779,
|
||||
"EUR": 116,
|
||||
"GBP": 103,
|
||||
"INR": 2989,
|
||||
"MXN": 1884,
|
||||
"NOK": 941,
|
||||
"NZD": 155,
|
||||
"PEN": 298,
|
||||
"SEK": 941,
|
||||
"SGD": 168,
|
||||
"USD": 129
|
||||
},
|
||||
"20": {
|
||||
"AUD": 143,
|
||||
"BRL": 299,
|
||||
"CAD": 137,
|
||||
"CHF": 119,
|
||||
"CLP": 66594,
|
||||
"COP": 233940,
|
||||
"DKK": 719,
|
||||
"EUR": 107,
|
||||
"GBP": 95,
|
||||
"INR": 2759,
|
||||
"MXN": 1739,
|
||||
"NOK": 869,
|
||||
"NZD": 143,
|
||||
"PEN": 275,
|
||||
"SEK": 869,
|
||||
"SGD": 155,
|
||||
"USD": 119
|
||||
},
|
||||
"50": {
|
||||
"AUD": 131,
|
||||
"BRL": 274,
|
||||
"CAD": 125,
|
||||
"CHF": 109,
|
||||
"CLP": 61044,
|
||||
"COP": 214445,
|
||||
"DKK": 659,
|
||||
"EUR": 98,
|
||||
"GBP": 87,
|
||||
"INR": 2529,
|
||||
"MXN": 1594,
|
||||
"NOK": 796,
|
||||
"NZD": 131,
|
||||
"PEN": 252,
|
||||
"SEK": 796,
|
||||
"SGD": 142,
|
||||
"USD": 109
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
65
services/web/scripts/plan-prices/package-lock.json
generated
Normal file
65
services/web/scripts/plan-prices/package-lock.json
generated
Normal file
@@ -0,0 +1,65 @@
|
||||
{
|
||||
"name": "prices",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "prices",
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"csv": "^6.2.10",
|
||||
"minimist": "^1.2.8"
|
||||
}
|
||||
},
|
||||
"node_modules/csv": {
|
||||
"version": "6.2.10",
|
||||
"resolved": "https://registry.npmjs.org/csv/-/csv-6.2.10.tgz",
|
||||
"integrity": "sha512-aO1dkeMlzWHvtKOdiTeqt7G4SwF/JtJ2fYNOMtlrGiKERD+ASq+QZelGqpFCzHGvZSIhzDtwqRVEgPMkme2BQg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"csv-generate": "^4.2.4",
|
||||
"csv-parse": "^5.3.8",
|
||||
"csv-stringify": "^6.3.2",
|
||||
"stream-transform": "^3.2.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.1.90"
|
||||
}
|
||||
},
|
||||
"node_modules/csv-generate": {
|
||||
"version": "4.2.4",
|
||||
"resolved": "https://registry.npmjs.org/csv-generate/-/csv-generate-4.2.4.tgz",
|
||||
"integrity": "sha512-PvEwuRksnW30I1DlZnVuCVMOiff7ZoUXOCMQJ1c0DPKXQkIC87hWvqJ4ztO70ceQMQER1hp/Lajo8KIy7at1PA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/csv-parse": {
|
||||
"version": "5.3.8",
|
||||
"resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-5.3.8.tgz",
|
||||
"integrity": "sha512-ird8lzMv9I64oqIVIHdaTbT7Yr55n2C/Nv6m1LxO7nddLEeI67468VQ9Ik+r6lwYbK9kTE1oSqAVcVKc/Uqx6g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/csv-stringify": {
|
||||
"version": "6.3.2",
|
||||
"resolved": "https://registry.npmjs.org/csv-stringify/-/csv-stringify-6.3.2.tgz",
|
||||
"integrity": "sha512-dD9gfbxNKa5v90NHiE2Qd6F9I52GtJjGTfowwzqiNDZD/+NPW3h19d2Nvv311a8QUW11rYRobco27nvVAnCrLw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/minimist": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
|
||||
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
|
||||
"dev": true,
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"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
|
||||
}
|
||||
}
|
||||
}
|
||||
15
services/web/scripts/plan-prices/package.json
Normal file
15
services/web/scripts/plan-prices/package.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "prices",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"csv": "^6.2.10",
|
||||
"minimist": "^1.2.8"
|
||||
}
|
||||
}
|
||||
235
services/web/scripts/plan-prices/plans.mjs
Normal file
235
services/web/scripts/plan-prices/plans.mjs
Normal file
@@ -0,0 +1,235 @@
|
||||
// Creates data for localizedPlanPricing object in settings.overrides.saas.js
|
||||
// and group plans object in app/templates/plans/groups.json
|
||||
|
||||
// https://github.com/import-js/eslint-plugin-import/issues/1810
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import * as csv from 'csv/sync'
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import minimist from 'minimist'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
||||
|
||||
function readCSVFile(fileName) {
|
||||
// Pick the csv file
|
||||
const filePath = path.resolve(__dirname, fileName)
|
||||
const input = fs.readFileSync(filePath, 'utf8')
|
||||
const rawRecords = csv.parse(input, { columns: true })
|
||||
return rawRecords
|
||||
}
|
||||
|
||||
function readJSONFile(fileName) {
|
||||
const filePath = path.resolve(__dirname, fileName)
|
||||
const file = fs.readFileSync(filePath)
|
||||
const plans = JSON.parse(file)
|
||||
// convert the plans JSON from recurly to an array of
|
||||
// objects matching the spreadsheet format
|
||||
const result = []
|
||||
for (const plan of plans) {
|
||||
const newRow = { plan_code: plan.code }
|
||||
for (const price of plan.currencies) {
|
||||
newRow[price.currency] = price.unitAmount
|
||||
}
|
||||
result.push(newRow)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// Mapping of [output_keys]:[actual_keys]
|
||||
const plansMap = {
|
||||
student: 'student',
|
||||
personal: 'paid-personal',
|
||||
collaborator: 'collaborator',
|
||||
professional: 'professional',
|
||||
}
|
||||
|
||||
const currencies = [
|
||||
'AUD',
|
||||
'BRL',
|
||||
'CAD',
|
||||
'CHF',
|
||||
'CLP',
|
||||
'COP',
|
||||
'DKK',
|
||||
'EUR',
|
||||
'GBP',
|
||||
'INR',
|
||||
'MXN',
|
||||
'NOK',
|
||||
'NZD',
|
||||
'PEN',
|
||||
'SEK',
|
||||
'SGD',
|
||||
'USD',
|
||||
]
|
||||
|
||||
/**
|
||||
* This is duplicated in:
|
||||
* - services/web/app/src/Features/Subscription/SubscriptionHelper.js
|
||||
* - services/web/modules/subscriptions/frontend/js/pages/plans-new-design/group-member-picker/group-plan-pricing.js
|
||||
*/
|
||||
function roundUpToNearest5Cents(number) {
|
||||
return Math.ceil(number * 20) / 20
|
||||
}
|
||||
|
||||
function generatePlans(workSheetJSON) {
|
||||
// localizedPlanPricing object for settings.overrides.saas.js
|
||||
const localizedPlanPricing = {}
|
||||
|
||||
for (const currency of currencies) {
|
||||
localizedPlanPricing[currency] = {
|
||||
free: {
|
||||
monthly: 0,
|
||||
annual: 0,
|
||||
},
|
||||
}
|
||||
|
||||
for (const [outputKey, actualKey] of Object.entries(plansMap)) {
|
||||
const monthlyPlan = workSheetJSON.find(
|
||||
data => data.plan_code === actualKey
|
||||
)
|
||||
|
||||
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(
|
||||
data => data.plan_code === actualKeyAnnual
|
||||
)
|
||||
|
||||
if (!annualPlan) throw new Error(`Missing plan: ${actualKeyAnnual}`)
|
||||
if (!(currency in annualPlan))
|
||||
throw new Error(
|
||||
`Missing currency "${currency}" for plan "${actualKeyAnnual}"`
|
||||
)
|
||||
|
||||
const monthly = Number(monthlyPlan[currency])
|
||||
const monthlyTimesTwelve = Number(monthlyPlan[currency] * 12)
|
||||
const annual = Number(annualPlan[currency])
|
||||
const annualDividedByTwelve = Number(
|
||||
roundUpToNearest5Cents(annualPlan[currency] / 12)
|
||||
)
|
||||
|
||||
localizedPlanPricing[currency] = {
|
||||
...localizedPlanPricing[currency],
|
||||
[outputKey]: {
|
||||
monthly,
|
||||
monthlyTimesTwelve,
|
||||
annual,
|
||||
annualDividedByTwelve,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
return localizedPlanPricing
|
||||
}
|
||||
|
||||
function generateGroupPlans(workSheetJSON) {
|
||||
// group plans object for app/templates/plans/groups.json
|
||||
const groupPlans = workSheetJSON.filter(data =>
|
||||
data.plan_code.startsWith('group')
|
||||
)
|
||||
|
||||
const sizes = ['2', '3', '4', '5', '10', '20', '50']
|
||||
const additionalLicenseAddOnLegacyPricesFilePath = path.resolve(
|
||||
__dirname,
|
||||
'additional-license-add-on-legacy-prices.json'
|
||||
)
|
||||
const additionalLicenseAddOnLegacyPricesFile = fs.readFileSync(
|
||||
additionalLicenseAddOnLegacyPricesFilePath
|
||||
)
|
||||
const additionalLicenseAddOnLegacyPrices = JSON.parse(
|
||||
additionalLicenseAddOnLegacyPricesFile
|
||||
)
|
||||
|
||||
const result = {}
|
||||
for (const type1 of ['educational', 'enterprise']) {
|
||||
result[type1] = {}
|
||||
for (const type2 of ['professional', 'collaborator']) {
|
||||
result[type1][type2] = {}
|
||||
for (const currency of currencies) {
|
||||
result[type1][type2][currency] = {}
|
||||
for (const size of sizes) {
|
||||
const planCode = `group_${type2}_${size}_${type1}`
|
||||
const plan = groupPlans.find(data => data.plan_code === planCode)
|
||||
|
||||
if (!plan) throw new Error(`Missing plan: ${planCode}`)
|
||||
|
||||
result[type1][type2][currency][size] = {
|
||||
price_in_cents: plan[currency] * 100,
|
||||
}
|
||||
|
||||
const additionalLicenseAddOnLegacyPrice =
|
||||
additionalLicenseAddOnLegacyPrices[type1][type2][size]?.[currency]
|
||||
if (additionalLicenseAddOnLegacyPrice) {
|
||||
Object.assign(result[type1][type2][currency][size], {
|
||||
additional_license_legacy_price_in_cents:
|
||||
additionalLicenseAddOnLegacyPrice * 100,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
const argv = minimist(process.argv.slice(2), {
|
||||
string: ['output', 'file'],
|
||||
alias: { o: 'output', f: 'file' },
|
||||
})
|
||||
|
||||
let input
|
||||
if (argv.file) {
|
||||
const ext = path.extname(argv.file)
|
||||
switch (ext) {
|
||||
case '.csv':
|
||||
input = readCSVFile(argv.file)
|
||||
break
|
||||
case '.json':
|
||||
input = readJSONFile(argv.file)
|
||||
break
|
||||
default:
|
||||
console.log('Invalid file type: must be csv or json')
|
||||
}
|
||||
} else {
|
||||
console.log('usage: node plans.mjs -f <file.csv|file.json> -o <dir>')
|
||||
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 = generatePlans(input)
|
||||
const groupPlans = generateGroupPlans(input)
|
||||
|
||||
if (argv.output) {
|
||||
const dir = argv.output
|
||||
// check if output directory exists
|
||||
if (!fs.existsSync(dir)) {
|
||||
console.log(`Creating output directory ${dir}`)
|
||||
fs.mkdirSync(dir)
|
||||
}
|
||||
// check if output directory is a directory and report error if not
|
||||
if (!fs.lstatSync(dir).isDirectory()) {
|
||||
console.error(`Error: output dir ${dir} is not a directory`)
|
||||
process.exit(1)
|
||||
}
|
||||
writeFile(`${dir}/localizedPlanPricing.json`, formatJS(localizedPlanPricing))
|
||||
writeFile(`${dir}/groups.json`, formatJSON(groupPlans))
|
||||
} else {
|
||||
console.log('LOCALIZED', localizedPlanPricing)
|
||||
console.log('GROUP PLANS', JSON.stringify(groupPlans, null, 2))
|
||||
}
|
||||
|
||||
console.log('Completed!')
|
||||
Reference in New Issue
Block a user