Skip to content

Commit fd47724

Browse files
committed
added support for auto gsheet filling
1 parent 54fa282 commit fd47724

File tree

7 files changed

+94
-16
lines changed

7 files changed

+94
-16
lines changed

Dockerfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ ARG GSHEETS_API_KEY
7373
ARG SENDGRID_API_KEY
7474
ARG GROWSURF_API_KEY
7575
ARG GROWSURF_CAMPAIGN_ID
76+
ARG GOOGLE_SERVICE_ACCOUNT_PRIVATE_KEY
7677

7778
# Optimizely
7879
ARG OPTIMIZELY_SDK_KEY
@@ -137,6 +138,7 @@ ENV SENDGRID_API_KEY=$SENDGRID_API_KEY
137138
ENV GROWSURF_API_KEY=$GROWSURF_API_KEY
138139
ENV GROWSURF_CAMPAIGN_ID=$GROWSURF_CAMPAIGN_ID
139140
ENV GSHEETS_API_KEY=$GSHEETS_API_KEY
141+
ENV GOOGLE_SERVICE_ACCOUNT_PRIVATE_KEY=$GOOGLE_SERVICE_ACCOUNT_PRIVATE_KEY
140142

141143
# Optimizely
142144
ENV OPTIMIZELY_SDK_KEY=$OPTIMIZELY_SDK_KEY

build.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ docker build -t $TAG \
5252
--build-arg GSHEETS_API_KEY=$GSHEETS_API_KEY \
5353
--build-arg OPTIMIZELY_SDK_KEY=$OPTIMIZELY_SDK_KEY \
5454
--build-arg COMMUNITY_APP_URL=$COMMUNITY_APP_URL \
55+
--build-arg GOOGLE_SERVICE_ACCOUNT_PRIVATE_KEY=$GOOGLE_SERVICE_ACCOUNT_PRIVATE_KEY \
5556
--build-arg VALID_ISSUERS=$VALID_ISSUERS .
5657

5758
# Copies "node_modules" from the created image, if necessary for caching.

config/custom-environment-variables.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,4 +113,5 @@ module.exports = {
113113
OPTIMIZELY: {
114114
SDK_KEY: 'OPTIMIZELY_SDK_KEY',
115115
},
116+
GOOGLE_SERVICE_ACCOUNT_PRIVATE_KEY: 'GOOGLE_SERVICE_ACCOUNT_PRIVATE_KEY',
116117
};

config/default.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,9 @@ module.exports = {
267267
},
268268

269269
GSHEETS_API_KEY: 'AIzaSyBRdKySN5JNCb2H6ZxJdTTvp3cWU51jiOQ',
270+
GOOGLE_SERVICE_ACCOUNT_EMAIL: 'communityappserviceacc@tc-sheets-to-contentful.iam.gserviceaccount.com',
271+
GOOGLE_SERVICE_ACCOUNT_PRIVATE_KEY: '',
272+
GIG_REFERRALS_SHEET: '1xilx7NxDAvzAzOTbPpvb3lL3RWv1VD5W24OEMAoF9HU',
270273

271274
AUTH_CONFIG: {
272275
AUTH0_URL: 'TC_M2M_AUTH0_URL',

src/server/routes/gSheet.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* eslint-disable max-len */
12
/**
23
* The routes related to GSheets integration
34
*/
@@ -14,6 +15,7 @@ const routes = express.Router();
1415
routes.use(cors());
1516
routes.options('*', cors());
1617

17-
routes.get('/:id', (req, res) => new GSheetService().getSheet(req, res));
18+
routes.get('/:id', (req, res) => new GSheetService().getSheetAPI(req, res));
19+
// routes.post('/:id', (req, res) => new GSheetService().addToSheetAPI(req, res)); // Enable it for API access to gsheets editing when needed
1820

1921
export default routes;

src/server/services/gSheet.js

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export default class GSheetService {
3030
* @param {Object} req the request
3131
* @param {Object} res the response
3232
*/
33-
async getSheet(req, res) {
33+
async getSheetAPI(req, res) {
3434
const { index } = req.query;
3535
const { id } = req.params;
3636
const doc = new GoogleSpreadsheet(id);
@@ -49,4 +49,63 @@ export default class GSheetService {
4949
return res.send((e.response && e.response.data) || { ...e, message: e.message });
5050
}
5151
}
52+
53+
/**
54+
* Adds rows to gsheet by ID
55+
* Needs to be shared with the service account to work
56+
* This is the controler method with req/res objects
57+
* @param {Object} req the request
58+
* @param {Object} res the response
59+
*/
60+
async addToSheetAPI(req, res) {
61+
const { index } = req.query;
62+
const { id } = req.params;
63+
const doc = new GoogleSpreadsheet(id);
64+
try {
65+
// set credentials for working
66+
await doc.useServiceAccountAuth({
67+
client_email: config.GOOGLE_SERVICE_ACCOUNT_EMAIL,
68+
private_key: config.GOOGLE_SERVICE_ACCOUNT_PRIVATE_KEY.replace(new RegExp('\\\\n', 'g'), '\n'),
69+
});
70+
// load doc infos
71+
await doc.loadInfo();
72+
// get 1st sheet
73+
const sheet = doc.sheetsByIndex[index || 0];
74+
const moreRows = await sheet.addRows(req.body);
75+
const rowsJson = JSON.stringify(moreRows, getCircularReplacer());
76+
return res.send({
77+
rows: JSON.parse(rowsJson),
78+
});
79+
} catch (e) {
80+
res.status((e.response && e.response.status) || 500);
81+
return res.send((e.response && e.response.data) || { ...e, message: e.message });
82+
}
83+
}
84+
85+
/**
86+
* Adds rows to gsheet by ID
87+
* Needs to be shared with the service account to work
88+
* @param {string} id the doc id
89+
* @param {Array} paylod the body to send
90+
* @param {string} index sheet index in the doc. Defaults to 0
91+
*/
92+
async addToSheet(id, payload, index = 0) {
93+
const doc = new GoogleSpreadsheet(id);
94+
try {
95+
// set credentials for working
96+
await doc.useServiceAccountAuth({
97+
client_email: config.GOOGLE_SERVICE_ACCOUNT_EMAIL,
98+
private_key: config.GOOGLE_SERVICE_ACCOUNT_PRIVATE_KEY.replace(new RegExp('\\\\n', 'g'), '\n'),
99+
});
100+
// load doc infos
101+
await doc.loadInfo();
102+
// get 1st sheet
103+
const sheet = doc.sheetsByIndex[index || 0];
104+
const moreRows = await sheet.addRows(payload);
105+
const rowsJson = JSON.stringify(moreRows, getCircularReplacer());
106+
return rowsJson;
107+
} catch (e) {
108+
return e;
109+
}
110+
}
52111
}

src/server/services/recruitCRM.js

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { logger } from 'topcoder-react-lib';
99
import Joi from 'joi';
1010
import GrowsurfService from './growsurf';
1111
import { sendEmailDirect } from './sendGrid';
12+
import GSheetService from './gSheet';
1213

1314
const FormData = require('form-data');
1415

@@ -274,37 +275,35 @@ export default class RecruitCRMService {
274275
let isReferred = false;
275276
let referralCookie = req.cookies[config.GROWSURF_COOKIE];
276277
if (referralCookie) referralCookie = JSON.parse(referralCookie);
278+
const tcHandle = _.findIndex(form.custom_fields, { field_id: 2 });
279+
let growRes;
277280
try {
278281
// referral tracking via growsurf
279282
if (referralCookie) {
280283
const gs = new GrowsurfService();
281-
const tcHandle = _.findIndex(form.custom_fields, { field_id: 2 });
282284
// check if candidate exists in growsurf
283285
const existRes = await gs.getParticipantByIdOREmail(form.email);
284286
if (existRes.id) {
285287
// candidate exists in growsurf
286288
// update candidate to set referrer only if it is not set already
287289
if (!existRes.referrer) {
288-
isReferred = true;
289-
const updateRes = await gs.updateParticipant(form.email, JSON.stringify({
290+
growRes = await gs.updateParticipant(form.email, JSON.stringify({
290291
referredBy: referralCookie.referralId,
291292
referralStatus: 'CREDIT_PENDING',
292293
metadata: {
293294
gigID: id,
294295
},
295296
}));
296297
// add referral link to candidate profile in recruitCRM
297-
if (!updateRes.error) {
298+
if (!growRes.error) {
299+
isReferred = true;
298300
form.custom_fields.push({
299-
field_id: 6, value: `https://app.growsurf.com/dashboard/campaign/${config.GROWSURF_CAMPAIGN_ID}/participant/${updateRes.id}`,
301+
field_id: 6, value: `https://app.growsurf.com/dashboard/campaign/${config.GROWSURF_CAMPAIGN_ID}/participant/${growRes.id}`,
300302
});
301-
} else {
302-
notifyKirilAndNick(updateRes);
303303
}
304304
}
305305
} else {
306-
isReferred = true;
307-
const growRes = await gs.addParticipant(JSON.stringify({
306+
growRes = await gs.addParticipant(JSON.stringify({
308307
email: form.email,
309308
referredBy: referralCookie.referralId,
310309
referralStatus: 'CREDIT_PENDING',
@@ -317,11 +316,10 @@ export default class RecruitCRMService {
317316
}));
318317
// add referral link to candidate profile in recruitCRM
319318
if (!growRes.error) {
319+
isReferred = true;
320320
form.custom_fields.push({
321321
field_id: 6, value: `https://app.growsurf.com/dashboard/campaign/${config.GROWSURF_CAMPAIGN_ID}/participant/${growRes.id}`,
322322
});
323-
} else {
324-
notifyKirilAndNick(growRes);
325323
}
326324
}
327325
// finally, clear the cookie
@@ -479,9 +477,21 @@ export default class RecruitCRMService {
479477
return res.send(error);
480478
}
481479
// For new candidates that apply via referral link
482-
// aka triggered referral state step 1 - notify and etc.
483-
if (isNewCandidate && isReferred) {
484-
// console.log('isNewCandidate');
480+
// aka triggered referral state step 1 - notify and etc. housekeeping tasks
481+
if (isNewCandidate && isReferred && !growRes.error) {
482+
// update the tracking sheet
483+
const gs = new GSheetService();
484+
await gs.addToSheet(config.GIG_REFERRALS_SHEET, [[
485+
`${form.first_name} ${form.last_name}`,
486+
form.email,
487+
`https://app.recruitcrm.io/candidate/${candidateData.slug}`,
488+
`https://topcoder.com/members/${form.custom_fields[tcHandle].value}`,
489+
`https://app.growsurf.com/dashboard/campaign/u9frbx/participant/${growRes.referrer.id}`,
490+
`${growRes.referrer.firstName} ${growRes.referrer.lastName}`,
491+
growRes.referrer.email,
492+
`https://topcoder.com/members/${growRes.referrer.metadata.tcHandle}`,
493+
`https://app.recruitcrm.io/job/${id}`,
494+
]]);
485495
}
486496
// respond to API call
487497
const data = await applyResponse.json();

0 commit comments

Comments
 (0)