diff --git a/README.md b/README.md index 181148f..06abd79 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ The script to use in this case is `convert-user-to-partner-admin.sql`. The `create-access-codes` script in the `package.json` file is intended to help easily create access codes for a given partner. To run the script, we'll need to: 1. First create a local `.env` file if one doesn't already exist. See the `env.example` file for an example. - 2. Fill in the `URL` variable in the `.env` file. This variable should point to the bloom backend in the environment where the codes are needed (staging or prod) + 2. Fill in the `BLOOM_API_URL` variable in the `.env` file. This variable should point to the bloom backend in the environment where the codes are needed (staging or prod) 3. Next, we'll fill in the `TOKEN` variable in the `.env` file. To do this, send a POST request to `{{host}}/api/auth/signin` with a body including email and password e.g. `{"email": "","password": "%"}`. The credentials MUST belong to a user who is an admin and associated with the partner for whom the codes are being created. The `{{host}}` in the given url must be the same as the 4. From the api response, copy the access token and paste it as the `TOKEN` variable in the `.env` file. 5. Finally, set the `NUMBER_OF_CODES_NEEDED` variable in the `.env` file @@ -65,4 +65,18 @@ This is one potential way to process the output of the above script. 1. Copy and paste the comma separated script output into a Google Sheet. The sheet will contain one cell with the codes separated by commas 2. With the cell highlighted, click on "Data > Split text into columns". This will separate the access codes into separate columns in a single row.m 3. Copy the row with all the codes, click on the cell below, right click and choose "Paste special > Tranposed". This paste command will put an access code on each row. - 4. That's it! Celebrate :) \ No newline at end of file + 4. That's it! Celebrate :) + + ## Upload missing therapy sessions + The upload-therapy-sessions script in the package.json file is intended to help easily upload missing therapy sessions to the db if the zapier integration breaks down between simplybook and the database. + + Before running the script, a csv file with the missing information will need to be created. The csv file format should match the data format of the information in the database. See example file: `simplybook/therapysession.csv` + + To run the script, we'll need to: + +1. First create a local .env file if one doesn't already exist. See the env.example file for an example. +2. Fill in the `SIMPLYBOOK_WEBHOOK_URL` variable in the .env file. This variable should point to the bloom backend simplybook webhook in prod. +3. Next, we'll fill in the AUTH variable in the .env file. Speak to a team member if you're not sure how to do this. +4. Finally, set the CSV_FILE variable in the .env file. This points to the csv file with the missing data. + +Now run the script by using the following command: `yarn upload-therapy-sessions`. The script will add the therapy sessions to the database and decrement the therapy sessions allocated a user. \ No newline at end of file diff --git a/backend/create-access-codes.ts b/backend/create-access-codes.ts index 1194935..0fd5eee 100644 --- a/backend/create-access-codes.ts +++ b/backend/create-access-codes.ts @@ -4,7 +4,7 @@ import 'dotenv/config' * This script is intended to help create access codes for a given partner. * The README will contain more information on how to run the script. */ -const URL = process.env.URL; +const URL = process.env.BLOOM_API_URL; const TOKEN = process.env.TOKEN const NUMBER_OF_CODES_NEEDED = parseInt(process.env.NUMBER_OF_CODES_NEEDED); diff --git a/env.example b/env.example index fa16720..f17f559 100644 --- a/env.example +++ b/env.example @@ -1,3 +1,10 @@ -URL='https://bloom-backend-staging.herokuapp.com/api' +# Create access codes + +BLOOM_API_URL='https://bloom-backend-staging.herokuapp.com/api' TOKEN='' NUMBER_OF_CODES_NEEDED=7 + +# Upload therapy session +SIMPLYBOOK_WEBHOOK_URL='https://bloom-backend-prod.herokuapp.com/api/webhooks/simplybook' +AUTH='' +CSV_FILE='therapysession.csv' \ No newline at end of file diff --git a/package.json b/package.json index 33eb207..5e72989 100644 --- a/package.json +++ b/package.json @@ -5,10 +5,13 @@ "license": "UNLICENSED", "type": "module", "scripts": { - "create-access-codes": "ts-node --esm backend/create-access-codes.ts" + "create-access-codes": "ts-node --esm backend/create-access-codes.ts", + "upload-therapy-sessions": "ts-node --esm simplybook/upload-therapy-sessions.ts" }, "dependencies": { - "dotenv": "^16.0.1" + "dotenv": "^16.0.1", + "fast-csv": "^4.3.6", + "moment": "^2.29.4" }, "devDependencies": { "@types/node": "^16.0.0", diff --git a/simplybook/therapysession.csv b/simplybook/therapysession.csv new file mode 100644 index 0000000..328ccd5 --- /dev/null +++ b/simplybook/therapysession.csv @@ -0,0 +1,2 @@ +createdAt,updatedAt,action,clientEmail,bookingCode,clientTimezone,serviceName,serviceProviderName,serviceProviderEmail,startDateTime,endDateTime,cancelledAt,rescheduledFrom,completedAt,partnerAccessId +2022-03-13 13:49:00+00,2022-03-13 13:49:00+00,NEW_BOOKING,email@gmail.com,,America/Chicago,Therapy in English,email@gmail.com,email@gmail.com,15-03-2022 23:00:00,15-03-2022 00:00:00,,,, diff --git a/simplybook/upload-therapy-sessions.ts b/simplybook/upload-therapy-sessions.ts new file mode 100644 index 0000000..83fceee --- /dev/null +++ b/simplybook/upload-therapy-sessions.ts @@ -0,0 +1,97 @@ +import 'dotenv/config' +import * as fs from 'fs'; +import * as csv from 'fast-csv'; +import moment from 'moment'; +import nodefetch from 'node-fetch'; +import path from 'path'; + +/** + * This script is intended to help update the database with SimplyBook therapy appointments + * that were missed due to a broken zapier. + */ +const URL = process.env.SIMPLYBOOK_WEBHOOK_URL; +const AUTH = process.env.AUTH +const CSV_FILE = process.env.CSV_FILE; + + +const headers = { + 'Content-Type': 'application/json', + 'Authorization': `${AUTH}` +}; + +const checkEnvVarsSet = () => { + if(!URL) throw Error('Please set simplybook webhook URL'); + if(!AUTH) throw Error('Please set auth'); + if(!CSV_FILE) throw Error('Please set the file containing records to upload'); +} + +const readAndProcessFile = () => { + const csvFilePath = path.resolve('simplybook', CSV_FILE); + + fs.createReadStream(path.resolve(csvFilePath)) + .pipe(csv.parse({ headers: true })) + .on('error', error => console.error(error)) + .on('data', therapySessionRow => addTherapyInformation(therapySessionRow)) + .on('end', (rowCount: number) => console.log(`Parsed ${rowCount} rows`)); +}; + +type TherapySessionInfo = { + createdAt: string, + updatedAt: string, + action: string, + clientEmail: string, + bookingCode: string, + clientTimezone: string, + serviceName: string, + serviceProviderName: string, + serviceProviderEmail: string, + startDateTime: string, + endDateTime: string, + cancelledAt: string, + rescheduledFrom: string, + completedAt: string, + partnerAccessId: string +} + +const convertDate = (dateToConvert: string) => { + return moment(dateToConvert, "DD-MM-YYYY hh:mm:ss").toISOString() +} + +const addTherapyInformation = async (row: TherapySessionInfo) => { + + const body = JSON.stringify({ + "client_email": row.clientEmail, + "action": "NEW_BOOKING", + "booking_code": row.bookingCode, + "service_name": "Therapy in English", + "service_provider_name": row.serviceProviderEmail, + "service_provider_email": row.serviceProviderEmail, + "start_date_time": convertDate(row.startDateTime), + "end_date_time": convertDate(row.endDateTime), + "client_timezone": "Unknown" + }); + + const res = await nodefetch(URL, { + method: 'POST', + body, + headers + }); + + const status = res.status; + + if (status === 201){ + console.log(`Succesful`) + + } else { + console.log(`Failed with status ${status}`) + } +} + +const runScript = async () => { + checkEnvVarsSet() + readAndProcessFile() + + process.stdout.write('Script finished, ') +} + +runScript(); \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 9900f17..7f83726 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -19,5 +19,6 @@ "noFallthroughCasesInSwitch": false, "esModuleInterop": true, "allowJs": true, + "moduleResolution":"node", } } diff --git a/yarn.lock b/yarn.lock index eb86302..7602b6a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -307,6 +307,21 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== +axios-cookiejar-support@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/axios-cookiejar-support/-/axios-cookiejar-support-1.0.1.tgz#7b32af7d932508546c68b1fc5ba8f562884162e1" + integrity sha512-IZJxnAJ99XxiLqNeMOqrPbfR7fRyIfaoSLdPUf4AMQEGkH8URs0ghJK/xtqBsD+KsSr3pKl4DEQjCn834pHMig== + dependencies: + is-redirect "^1.0.0" + pify "^5.0.0" + +axios@^0.24.0: + version "0.24.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.24.0.tgz#804e6fa1e4b9c5288501dd9dff56a7a0940d20d6" + integrity sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA== + dependencies: + follow-redirects "^1.14.4" + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -681,6 +696,11 @@ flatted@^3.1.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3" integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg== +follow-redirects@^1.14.4: + version "1.15.1" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.1.tgz#0ca6a452306c9b276e4d3127483e29575e207ad5" + integrity sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA== + form-data@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" @@ -818,6 +838,11 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== +is-redirect@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24" + integrity sha512-cr/SlUEe5zOGmzvj9bUyC4LVvkNVAXu4GytXLNMr1pny+a65MpQ9IJzFHD5vi7FyJgb4qt27+eS3TuQnqB+RQw== + isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -949,6 +974,16 @@ node-fetch@^3.2.6: fetch-blob "^3.1.4" formdata-polyfill "^4.0.10" +node-jsonrpc-client@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/node-jsonrpc-client/-/node-jsonrpc-client-2.0.0.tgz#3a8397f6959f1c7f7794ba7fa2b4c2cad543aa52" + integrity sha512-D+l/MZsta1F0VSqY7n5mSY0jSxdGBTASv/KbiaojMtSNNPXfJAFdP2jnXNcWlVg40bfbkaPQgZ6xua5X2Ufz9A== + dependencies: + axios "^0.24.0" + axios-cookiejar-support "^1.0.1" + tough-cookie "^4.0.0" + uuid "^8.3.2" + once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -995,6 +1030,11 @@ picomatch@^2.3.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +pify@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-5.0.0.tgz#1f5eca3f5e87ebec28cc6d54a0e4aaf00acc127f" + integrity sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA== + prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" @@ -1017,7 +1057,12 @@ progress@^2.0.0: resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== -punycode@^2.1.0: +psl@^1.1.33: + version "1.9.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" + integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== + +punycode@^2.1.0, punycode@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== @@ -1167,6 +1212,15 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +tough-cookie@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.0.0.tgz#d822234eeca882f991f0f908824ad2622ddbece4" + integrity sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg== + dependencies: + psl "^1.1.33" + punycode "^2.1.1" + universalify "^0.1.2" + ts-loader@^9.2.3: version "9.3.0" resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.3.0.tgz#980f4dbfb60e517179e15e10ed98e454b132159f" @@ -1235,6 +1289,11 @@ typescript@^4.3.5: resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.3.tgz#8364b502d5257b540f9de4c40be84c98e23a129d" integrity sha512-WOkT3XYvrpXx4vMMqlD+8R8R37fZkjyLGlxavMc4iB8lrl8L0DeTcHbYgw/v0N/z9wAFsgBhcsF0ruoySS22mA== +universalify@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -1242,6 +1301,11 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" +uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + v8-compile-cache-lib@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf"