From 2754bc482522fa55fee1bd13a0899dfb7086c03c Mon Sep 17 00:00:00 2001 From: Cagdas U Date: Thu, 22 Apr 2021 12:14:33 +0300 Subject: [PATCH 01/20] feat: add interview scheduler 1. Add Sequelize schema for Interview model. 2. Add `create-interviews-table` migration. 3. Add ES mapping for interviews. 4. Update existing index/re-index, and import/export scripts for the applied changes. 5. Add/implement the following endpoints. * `PATCH /jobCandidates/:jobCandidateId/requestInterview` * `PATCH /jobCandidates/:jobCandidateId/updateInterview/:round` * `GET /jobCandidates/:jobCandidateId/interviews` * `GET /jobCandidates/:jobCandidateId/interviews/:round` 6. Update the existing JobCandidate endpoints for applied changes. 7. Set up an hourly scheduled job to check & update Completed interviews. 8. Update `TeamService.sendEmail` for the interview scheduling feature. 9. Update POSTMAN collection & environment. 10. Update Swagger. --- README.md | 4 +- app-constants.js | 26 +- app.js | 4 + config/default.js | 15 + config/email_template.config.js | 24 + data/demo-data.json | 2 +- ...coder-bookings-api.postman_collection.json | 15069 +++++++++++----- docs/swagger.yaml | 485 +- ...topcoder-bookings.postman_environment.json | 86 +- local/kafka-client/topics.txt | 3 + .../2021-04-12-create-interviews-table.js | 102 + package-lock.json | 97 +- package.json | 2 +- scripts/data/exportData.js | 11 +- scripts/data/importData.js | 11 +- scripts/es/reIndexAll.js | 11 +- scripts/es/reIndexJobCandidates.js | 13 +- src/bootstrap.js | 7 + src/common/helper.js | 92 +- src/controllers/InterviewController.js | 52 + src/eventHandlers/InterviewEventHandler.js | 62 + src/eventHandlers/index.js | 4 +- src/models/Interview.js | 124 + src/models/JobCandidate.js | 14 +- src/routes/InterviewRoutes.js | 39 + src/services/InterviewService.js | 387 + src/services/JobCandidateService.js | 44 +- src/services/TeamService.js | 27 +- 28 files changed, 11904 insertions(+), 4913 deletions(-) create mode 100644 migrations/2021-04-12-create-interviews-table.js create mode 100644 src/controllers/InterviewController.js create mode 100644 src/eventHandlers/InterviewEventHandler.js create mode 100644 src/models/Interview.js create mode 100644 src/routes/InterviewRoutes.js create mode 100644 src/services/InterviewService.js diff --git a/README.md b/README.md index a15d010c..ca9c5c47 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,9 @@ AUTH0_AUDIENCE_UBAHN= AUTH0_CLIENT_ID= AUTH0_CLIENT_SECRET= - + # necessary if you'll utilize email functionality of interviews + INTERVIEW_INVITATION_SENDGRID_TEMPLATE_ID= + INTERVIEW_INVITATION_SENDER_EMAIL= # Locally deployed services (via docker-compose) ES_HOST=dockerhost:9200 DATABASE_URL=postgres://postgres:postgres@dockerhost:5432/postgres diff --git a/app-constants.js b/app-constants.js index 54ed9b7f..c1a96a60 100644 --- a/app-constants.js +++ b/app-constants.js @@ -39,11 +39,33 @@ const Scopes = { CREATE_WORK_PERIOD: 'create:taas-workPeriods', UPDATE_WORK_PERIOD: 'update:taas-workPeriods', DELETE_WORK_PERIOD: 'delete:taas-workPeriods', - ALL_WORK_PERIOD: 'all:taas-workPeriods' + ALL_WORK_PERIOD: 'all:taas-workPeriods', + // interview + READ_INTERVIEW: 'read:taas-interviews', + CREATE_INTERVIEW: 'create:taas-interviews', + UPDATE_INTERVIEW: 'update:taas-interviews', + ALL_INTERVIEW: 'all:taas-interviews' +} + +// Interview related constants +const Interviews = { + Status: { + Scheduling: 'Scheduling', + Scheduled: 'Scheduled', + RequestedForReschedule: 'Requested for reschedule', + Rescheduled: 'Rescheduled', + Completed: 'Completed', + Cancelled: 'Cancelled' + }, + XaiTemplate: { + '30MinInterview': '30-min-interview', + '60MinInterview': '60-min-interview' + } } module.exports = { UserRoles, FullManagePermissionRoles, - Scopes + Scopes, + Interviews } diff --git a/app.js b/app.js index fc52ee99..7f3d7d85 100644 --- a/app.js +++ b/app.js @@ -9,8 +9,10 @@ const express = require('express') const cors = require('cors') const HttpStatus = require('http-status-codes') const interceptor = require('express-interceptor') +const schedule = require('node-schedule') const logger = require('./src/common/logger') const eventHandlers = require('./src/eventHandlers') +const interviewService = require('./src/services/InterviewService') // setup express app const app = express() @@ -93,6 +95,8 @@ app.use((err, req, res, next) => { const server = app.listen(app.get('port'), () => { logger.info({ component: 'app', message: `Express server listening on port ${app.get('port')}` }) eventHandlers.init() + // schedule updateCompletedInterviews to run every hour + schedule.scheduleJob('0 0 * * * *', interviewService.updateCompletedInterviews) }) if (process.env.NODE_ENV === 'test') { diff --git a/config/default.js b/config/default.js index 8088c1a8..e1c6b14b 100644 --- a/config/default.js +++ b/config/default.js @@ -119,6 +119,13 @@ module.exports = { TAAS_WORK_PERIOD_UPDATE_TOPIC: process.env.TAAS_WORK_PERIOD_UPDATE_TOPIC || 'taas.workperiod.update', // the delete work period entity Kafka message topic TAAS_WORK_PERIOD_DELETE_TOPIC: process.env.TAAS_WORK_PERIOD_DELETE_TOPIC || 'taas.workperiod.delete', + // topics for interview service + // the request interview Kafka message topic + TAAS_INTERVIEW_REQUEST_TOPIC: process.env.TAAS_INTERVIEW_REQUEST_TOPIC || 'taas.interview.requested', + // the interview update Kafka message topic + TAAS_INTERVIEW_UPDATE_TOPIC: process.env.TAAS_INTERVIEW_UPDATE_TOPIC || 'taas.interview.update', + // the interview bulk update Kafka message topic + TAAS_INTERVIEW_BULK_UPDATE_TOPIC: process.env.TAAS_INTERVIEW_BULK_UPDATE_TOPIC || 'taas.interview.bulkUpdate', // the Kafka message topic for sending email EMAIL_TOPIC: process.env.EMAIL_TOPIC || 'external.action.email', @@ -128,10 +135,18 @@ module.exports = { // the emails address for receiving the issue report // REPORT_ISSUE_EMAILS may contain comma-separated list of email which is converted to array REQUEST_EXTENSION_EMAILS: (process.env.REQUEST_EXTENSION_EMAILS || '').split(','), + // the emails address for interview invitation + // INTERVIEW_INVITATION_CC_LIST may contain comma-separated list of email which is converted to array + // scheduler@x.ai should be in the CC list + INTERVIEW_INVITATION_CC_LIST: (process.env.INTERVIEW_INVITATION_CC_LIST || 'scheduler@x.ai').split(','), // SendGrid email template ID for reporting issue REPORT_ISSUE_SENDGRID_TEMPLATE_ID: process.env.REPORT_ISSUE_SENDGRID_TEMPLATE_ID, // SendGrid email template ID for requesting extension REQUEST_EXTENSION_SENDGRID_TEMPLATE_ID: process.env.REQUEST_EXTENSION_SENDGRID_TEMPLATE_ID, + // SendGrid email template ID for interview invitation + INTERVIEW_INVITATION_SENDGRID_TEMPLATE_ID: process.env.INTERVIEW_INVITATION_SENDGRID_TEMPLATE_ID, + // The sender (aka `from`) email for invitation. + INTERVIEW_INVITATION_SENDER_EMAIL: process.env.INTERVIEW_INVITATION_SENDER_EMAIL, // the URL where TaaS App is hosted TAAS_APP_URL: process.env.TAAS_APP_URL || 'https://platform.topcoder-dev.com/taas/myteams' } diff --git a/config/email_template.config.js b/config/email_template.config.js index bc2d803a..7de8ad80 100644 --- a/config/email_template.config.js +++ b/config/email_template.config.js @@ -59,5 +59,29 @@ module.exports = { '{{text}}', recipients: config.REPORT_ISSUE_EMAILS, sendgridTemplateId: config.REQUEST_EXTENSION_SENDGRID_TEMPLATE_ID + }, + + /* Request interview for a job candidate + * + * - interviewType: the x.ai interview type. Example: "30-min-interview" + * - candidateName: Full name of candidate. Example: "John Doe" + * - jobName: The title of the job. Example: "TaaS API Misc Updates" + * - customMessage: if it's needed, a custom message can be added to the end of email. Example: "I would like to invite you for an interview..." + * + * Template (defined in SendGrid): + * Subject: '/{{interviewType}} tech interview with {{candidateName}} for {{jobName}} is requested by the Customer' + * Body: + * 'The customer has requested /{{interviewType}} with {{candidateName}} for {{jobName}}.' + * + 'In a few minutes you will receive an invitation from our scheduling tool. Please proceed with the invitation to agree on timing.' + * + '

{{customMessage}}' + * + * Note, that the template should be defined in SendGrid. + * The subject & body above (identical to actual SendGrid template) is for reference purposes. + * We won't pass subject & body but only substitutions (replacements in template subject/body). + */ + 'interview-invitation': { + from: config.INTERVIEW_INVITATION_SENDER_EMAIL, + cc: config.INTERVIEW_INVITATION_CC_LIST, + sendgridTemplateId: config.INTERVIEW_INVITATION_SENDGRID_TEMPLATE_ID } } diff --git a/data/demo-data.json b/data/demo-data.json index 94bbdbb9..04f2fc6a 100644 --- a/data/demo-data.json +++ b/data/demo-data.json @@ -1 +1 @@ -{"Job":[{"id":"b9887564-3d3d-4c70-8a7b-552576ef2e8d","projectId":111,"externalId":"0","description":"taas-demo-job1","title":"Demo Title","startDate":"2020-09-27T04:17:23.131Z","duration":null,"numPositions":13,"resourceType":"Dummy Resource Type","rateType":"weekly","workload":"full-time","skills":["ee4c50c1-c8c3-475e-b6b6-edbd136a19d6","89139c80-d0a2-47c2-aa16-14589d5afd10","9f2d9127-6a2e-4506-ad76-c4ab63577b09","9515e7ee-83b6-49d1-ba5c-6c59c5a8ef1b","c854ab55-5922-4be1-8ecc-b3bc1f8629af","8456002e-fa2d-44f0-b0e7-86b1c02b6e4c","114b4ec8-805e-4c60-b351-14a955a991a9","213408aa-f16f-46c8-bc57-9e569cee3f11","b37a48db-f775-4e4e-b403-8ad1d234cdea","99b930b5-1b91-4df1-8b17-d9307107bb51","6388a632-c3ad-4525-9a73-66a527c03672","23839f38-6f19-4de9-9d28-f020056bca73","289e42a3-23e9-49be-88e1-6deb93cd8c31","b403f209-63b5-42bc-9b5f-1564416640d8"],"status":"sourcing","isApplicationPageActive":false,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-01-28T19:36:33.409Z","updatedAt":"2021-03-30T19:11:05.033Z"},{"id":"a5b3bf94-a8bf-4c7e-b685-70a29a4d7d6e","projectId":111,"externalId":"0","description":"taas-demo-job2","title":"Dummy title - at most 64 characters","startDate":"2020-09-27T04:17:23.131Z","duration":null,"numPositions":7,"resourceType":"Dummy Resource Type","rateType":"weekly","workload":"full-time","skills":["213408aa-f16f-46c8-bc57-9e569cee3f11","b37a48db-f775-4e4e-b403-8ad1d234cdea","99b930b5-1b91-4df1-8b17-d9307107bb51","6388a632-c3ad-4525-9a73-66a527c03672","23839f38-6f19-4de9-9d28-f020056bca73","289e42a3-23e9-49be-88e1-6deb93cd8c31","b403f209-63b5-42bc-9b5f-1564416640d8"],"status":"in-review","isApplicationPageActive":false,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","createdAt":"2021-01-28T19:36:44.975Z","updatedAt":"2021-01-28T19:38:17.463Z"},{"id":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","projectId":111,"externalId":"0","description":"taas-demo-job3","title":"Dummy title - at most 64 characters","startDate":"2020-09-27T04:17:23.131Z","duration":null,"numPositions":7,"resourceType":"Dummy Resource Type","rateType":"weekly","workload":"full-time","skills":[],"status":"assigned","isApplicationPageActive":false,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","createdAt":"2021-01-28T19:38:23.739Z","updatedAt":"2021-01-28T19:41:10.607Z"},{"id":"84b73f90-0fef-4507-887a-074578e5ef38","projectId":111,"externalId":"0","description":"taas-demo-job4","title":"Dummy title - at most 64 characters","startDate":"2020-09-27T04:17:23.131Z","duration":null,"numPositions":7,"resourceType":"Dummy Resource Type","rateType":"weekly","workload":"full-time","skills":["8456002e-fa2d-44f0-b0e7-86b1c02b6e4c","114b4ec8-805e-4c60-b351-14a955a991a9","213408aa-f16f-46c8-bc57-9e569cee3f11","b37a48db-f775-4e4e-b403-8ad1d234cdea","99b930b5-1b91-4df1-8b17-d9307107bb51","6388a632-c3ad-4525-9a73-66a527c03672"],"status":"closed","isApplicationPageActive":false,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","createdAt":"2021-01-28T19:41:21.892Z","updatedAt":"2021-01-28T19:41:28.849Z"},{"id":"62399aa0-b088-41fe-9e9b-0c8071f1934f","projectId":111,"externalId":"0","description":"taas-demo-job5","title":"Dummy title - at most 64 characters","startDate":"2020-09-27T04:17:23.131Z","duration":null,"numPositions":7,"resourceType":"Dummy Resource Type","rateType":"weekly","workload":"full-time","skills":["b37a48db-f775-4e4e-b403-8ad1d234cdea","99b930b5-1b91-4df1-8b17-d9307107bb51","6388a632-c3ad-4525-9a73-66a527c03672"],"status":"cancelled","isApplicationPageActive":false,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","createdAt":"2021-01-28T19:41:35.098Z","updatedAt":"2021-01-28T19:41:42.124Z"}],"JobCandidate":[{"id":"debadcd8-64bf-4ab8-9cdb-297479eef6f5","jobId":"a5b3bf94-a8bf-4c7e-b685-70a29a4d7d6e","userId":"4dfc6090-4ba8-4387-b5c4-584fcef982ba","status":"open","externalId":null,"resume":null,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-01-28T19:37:05.723Z","updatedAt":"2021-03-30T19:11:05.043Z"},{"id":"7ff45b8f-2b71-4510-b760-8dfa62e79504","jobId":"a5b3bf94-a8bf-4c7e-b685-70a29a4d7d6e","userId":"243517dd-77d7-4f70-8951-0bc66da83076","status":"open","externalId":null,"resume":null,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-01-28T19:37:11.598Z","updatedAt":"2021-03-30T19:11:05.043Z"},{"id":"91d63d5f-01d5-419e-89df-6117ea92f535","jobId":"a5b3bf94-a8bf-4c7e-b685-70a29a4d7d6e","userId":"a2e28bf4-1147-41a6-a39f-e2509306f2a6","status":"open","externalId":null,"resume":null,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-01-28T19:37:18.066Z","updatedAt":"2021-03-30T19:11:05.043Z"},{"id":"257f98d9-45f7-4e13-a6c2-d7e7b6efc9fe","jobId":"a5b3bf94-a8bf-4c7e-b685-70a29a4d7d6e","userId":"b8649393-d32f-4b7f-a156-12e9776acb0e","status":"open","externalId":null,"resume":null,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-01-28T19:37:24.095Z","updatedAt":"2021-03-30T19:11:05.043Z"},{"id":"a01852d0-fa08-410c-b97b-67580ce62215","jobId":"a5b3bf94-a8bf-4c7e-b685-70a29a4d7d6e","userId":"a0a3a5ce-1de6-465d-91b2-518feb299851","status":"open","externalId":null,"resume":null,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-01-28T19:37:29.734Z","updatedAt":"2021-03-30T19:11:05.043Z"},{"id":"2fd7ca69-c8ec-4bf3-a7f3-655fbfe3e7df","jobId":"a5b3bf94-a8bf-4c7e-b685-70a29a4d7d6e","userId":"e6958d77-ffaf-4d24-9cdb-6391506695a4","status":"open","externalId":null,"resume":null,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-01-28T19:37:44.728Z","updatedAt":"2021-03-30T19:11:05.043Z"},{"id":"f0023058-2996-4bba-8c5f-d09a7023be38","jobId":"a5b3bf94-a8bf-4c7e-b685-70a29a4d7d6e","userId":"626bb327-e738-48e3-8f67-1fa2dc677d3c","status":"open","externalId":null,"resume":null,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-01-28T19:37:50.619Z","updatedAt":"2021-03-30T19:11:05.043Z"},{"id":"a189b34d-acde-4633-b18b-f7a34d7c5a74","jobId":"a5b3bf94-a8bf-4c7e-b685-70a29a4d7d6e","userId":"b49a0adb-1565-4de1-9189-a763c77f5ed4","status":"open","externalId":null,"resume":null,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-01-28T19:37:56.456Z","updatedAt":"2021-03-30T19:11:05.043Z"},{"id":"5191a860-4327-4c50-b76b-84beba04519b","jobId":"a5b3bf94-a8bf-4c7e-b685-70a29a4d7d6e","userId":"79ce2a3e-7679-48cf-8ac9-0a8ca4c4b463","status":"shortlist","externalId":null,"resume":null,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","createdAt":"2021-01-28T19:36:51.222Z","updatedAt":"2021-01-28T19:38:02.293Z"},{"id":"e6d9635c-b122-4f69-9285-09fb1ab30106","jobId":"a5b3bf94-a8bf-4c7e-b685-70a29a4d7d6e","userId":"98ec2c16-442e-4b61-8ad1-66123ee37d3c","status":"rejected","externalId":null,"resume":null,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","createdAt":"2021-01-28T19:36:58.774Z","updatedAt":"2021-01-28T19:38:13.553Z"},{"id":"f67b155e-0f09-4fdd-89a7-d79c5e46cac6","jobId":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","userId":"05e988b7-7d54-4c10-ada1-1a04870a88a8","status":"open","externalId":null,"resume":null,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-01-28T19:38:38.332Z","updatedAt":"2021-03-30T19:11:05.043Z"},{"id":"8ffd33d3-4a43-4719-aee4-8e46be1d8f1c","jobId":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","userId":"a2ffdeed-704d-4cf7-b70a-93fcf61de598","status":"open","externalId":null,"resume":null,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-01-28T19:38:43.967Z","updatedAt":"2021-03-30T19:11:05.043Z"},{"id":"2b8ba549-8878-43d6-ad5f-6a66e3b9d6c9","jobId":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","userId":"4709473d-f060-4102-87f8-4d51ff0b34c1","status":"open","externalId":null,"resume":null,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-01-28T19:38:50.106Z","updatedAt":"2021-03-30T19:11:05.043Z"},{"id":"ae5a81ec-5d05-43c4-8253-847d91a54711","jobId":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","userId":"39c7376e-2d5c-4601-bc47-6b60f505814d","status":"open","externalId":null,"resume":null,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-01-28T19:38:55.734Z","updatedAt":"2021-03-30T19:11:05.043Z"},{"id":"85d6649e-2682-4904-9480-a77b72fef27d","jobId":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","userId":"213d2dd9-1fc3-4eda-ad97-2d56e2a84a1e","status":"selected","externalId":null,"resume":null,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"00000000-0000-0000-0000-000000000000","createdAt":"2021-01-28T19:38:30.856Z","updatedAt":"2021-01-28T19:40:27.209Z"},{"id":"922dfce3-4e06-4387-9fdb-64f70675e86b","jobId":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","userId":"dd5adacb-444d-4992-8b7b-0c349be598db","status":"selected","externalId":null,"resume":null,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"00000000-0000-0000-0000-000000000000","createdAt":"2021-01-28T19:39:02.435Z","updatedAt":"2021-01-28T19:40:49.349Z"},{"id":"c26c38e2-a47d-405b-abc6-fe62a739561c","jobId":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","userId":"6d0509c7-5f12-4d84-9a19-8e80ef7ddd66","status":"selected","externalId":null,"resume":null,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"00000000-0000-0000-0000-000000000000","createdAt":"2021-01-28T19:39:08.233Z","updatedAt":"2021-01-28T19:40:53.659Z"},{"id":"7bef2b37-e1ee-4638-bfc1-c911787ac955","jobId":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","userId":"f65e2104-2987-4136-839d-ee4632f0b2e5","status":"selected","externalId":null,"resume":null,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"00000000-0000-0000-0000-000000000000","createdAt":"2021-01-28T19:39:13.469Z","updatedAt":"2021-01-28T19:40:57.999Z"},{"id":"e9716139-1f40-4bf1-9f8a-77ae4bcc621e","jobId":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","userId":"e5e667ad-0950-43c2-8d1d-6e83ad7d1c7e","status":"selected","externalId":null,"resume":null,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"00000000-0000-0000-0000-000000000000","createdAt":"2021-01-28T19:39:19.215Z","updatedAt":"2021-01-28T19:41:01.953Z"},{"id":"a1731d01-eac9-4eff-8e5a-8a3c99bc66e0","jobId":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","userId":"bef43122-426b-4b2b-acdd-9b5b3bd1c0bf","status":"selected","externalId":null,"resume":null,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"00000000-0000-0000-0000-000000000000","createdAt":"2021-01-28T19:39:24.625Z","updatedAt":"2021-01-28T19:41:06.370Z"}],"ResourceBooking":[{"id":"08f5e4b9-1088-496d-91a7-5b22a3583e3c","projectId":111,"userId":"213d2dd9-1fc3-4eda-ad97-2d56e2a84a1e","jobId":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","status":"assigned","startDate":"2021-01-25T19:39:28.000Z","endDate":"2021-01-31T19:39:28.000Z","memberRate":1000,"customerRate":1200,"rateType":"weekly","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","createdAt":"2021-01-28T19:39:30.052Z","updatedAt":"2021-01-28T19:40:25.260Z"},{"id":"7d967fed-9792-4768-98a7-0b644aa84f2e","projectId":111,"userId":"05e988b7-7d54-4c10-ada1-1a04870a88a8","jobId":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","status":"in-review","startDate":"2021-01-25T19:39:34.000Z","endDate":"2021-01-31T19:39:34.000Z","memberRate":1000,"customerRate":1200,"rateType":"weekly","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","createdAt":"2021-01-28T19:39:35.571Z","updatedAt":"2021-01-28T19:40:30.291Z"},{"id":"35e1abd8-1890-4664-bb52-aade382d7b66","projectId":111,"userId":"a2ffdeed-704d-4cf7-b70a-93fcf61de598","jobId":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","status":"closed","startDate":"2021-01-25T19:39:39.000Z","endDate":"2021-01-31T19:39:39.000Z","memberRate":1000,"customerRate":1200,"rateType":"weekly","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","createdAt":"2021-01-28T19:39:41.205Z","updatedAt":"2021-01-28T19:40:34.859Z"},{"id":"a098e8d8-ce5b-47d9-afee-38b050d16745","projectId":111,"userId":"4709473d-f060-4102-87f8-4d51ff0b34c1","jobId":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","status":"cancelled","startDate":"2021-01-25T19:39:45.000Z","endDate":"2021-01-31T19:39:45.000Z","memberRate":1000,"customerRate":1200,"rateType":"weekly","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","createdAt":"2021-01-28T19:39:46.515Z","updatedAt":"2021-01-28T19:40:38.820Z"},{"id":"d38a6223-3f91-4300-9ecb-6e5fee173625","projectId":111,"userId":"39c7376e-2d5c-4601-bc47-6b60f505814d","jobId":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","status":"sourcing","startDate":"2021-01-25T19:39:50.000Z","endDate":"2021-01-31T19:39:50.000Z","memberRate":1000,"customerRate":1200,"rateType":"weekly","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","createdAt":"2021-01-28T19:39:52.063Z","updatedAt":"2021-01-28T19:40:43.021Z"},{"id":"51b45f5d-5df2-46d5-9c3d-8a1323df38dd","projectId":111,"userId":"dd5adacb-444d-4992-8b7b-0c349be598db","jobId":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","status":"assigned","startDate":"2021-01-25T19:39:58.000Z","endDate":"2021-01-31T19:39:58.000Z","memberRate":800,"customerRate":1000,"rateType":"weekly","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","createdAt":"2021-01-28T19:39:59.432Z","updatedAt":"2021-01-28T19:40:47.743Z"},{"id":"0a6799d7-f5d1-456b-8bf1-90619284b295","projectId":111,"userId":"6d0509c7-5f12-4d84-9a19-8e80ef7ddd66","jobId":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","status":"assigned","startDate":"2021-01-25T19:40:03.000Z","endDate":"2021-01-31T19:40:03.000Z","memberRate":2000,"customerRate":2500,"rateType":"weekly","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","createdAt":"2021-01-28T19:40:04.761Z","updatedAt":"2021-01-28T19:40:52.303Z"},{"id":"61f5d474-e41f-490b-ab58-9f983e3d4916","projectId":111,"userId":"f65e2104-2987-4136-839d-ee4632f0b2e5","jobId":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","status":"assigned","startDate":"2000-07-27T04:17:23.131Z","endDate":"2000-09-27T04:17:23.131Z","memberRate":3000,"customerRate":3500,"rateType":"weekly","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","createdAt":"2021-01-28T19:40:09.879Z","updatedAt":"2021-01-28T19:40:56.381Z"},{"id":"dc4477ec-07f8-4c8e-a8fe-ffe38dd290fa","projectId":111,"userId":"e5e667ad-0950-43c2-8d1d-6e83ad7d1c7e","jobId":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","status":"assigned","startDate":"2022-07-27T04:17:23.131Z","endDate":"2022-09-27T04:17:23.131Z","memberRate":1700,"customerRate":1900,"rateType":"weekly","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","createdAt":"2021-01-28T19:40:15.326Z","updatedAt":"2021-01-28T19:41:00.503Z"},{"id":"8173579e-4b3c-418d-a9a1-c999caa38404","projectId":111,"userId":"bef43122-426b-4b2b-acdd-9b5b3bd1c0bf","jobId":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","status":"assigned","startDate":"2020-09-27T04:17:23.131Z","endDate":"2020-09-27T04:17:23.131Z","memberRate":0,"customerRate":0,"rateType":"weekly","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","createdAt":"2021-01-28T19:40:20.627Z","updatedAt":"2021-01-28T19:41:04.919Z"}],"WorkPeriod":[{"id":"80b85cbb-3064-45aa-bb75-9dc010848fc1","resourceBookingId":"dc4477ec-07f8-4c8e-a8fe-ffe38dd290fa","userHandle":"nskumar278","projectId":111,"startDate":"2021-03-07","endDate":"2021-03-13","daysWorked":2,"memberRate":13.13,"customerRate":13.13,"paymentStatus":"pending","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-03-30T19:13:23.714Z","updatedAt":"2021-03-30T19:13:23.714Z"},{"id":"9b0765ef-4e20-4cb2-91f1-ce8d7bcd8062","resourceBookingId":"d38a6223-3f91-4300-9ecb-6e5fee173625","userHandle":"nithyaasworld","projectId":111,"startDate":"2021-03-07","endDate":"2021-03-13","daysWorked":2,"memberRate":13.13,"customerRate":13.13,"paymentStatus":"cancelled","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-03-30T19:14:17.109Z","updatedAt":"2021-03-30T19:14:17.109Z"},{"id":"5796eecf-cc4f-42c2-a25b-7af4710847d6","resourceBookingId":"a098e8d8-ce5b-47d9-afee-38b050d16745","userHandle":"TCConnCopilot","projectId":111,"startDate":"2021-03-14","endDate":"2021-03-20","daysWorked":5,"memberRate":15.13,"customerRate":17.13,"paymentStatus":"completed","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-03-30T19:14:43.498Z","updatedAt":"2021-03-30T19:14:43.498Z"},{"id":"dba9dc5a-afaa-43b2-9b7d-f0f03af81211","resourceBookingId":"a098e8d8-ce5b-47d9-afee-38b050d16745","userHandle":"TCConnCopilot","projectId":111,"startDate":"2021-03-07","endDate":"2021-03-13","daysWorked":5,"memberRate":15.13,"customerRate":17.13,"paymentStatus":"pending","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-03-30T19:14:56.991Z","updatedAt":"2021-03-30T19:14:56.991Z"},{"id":"d694bbea-707d-41d5-a3f4-14884ff6fbf6","resourceBookingId":"8173579e-4b3c-418d-a9a1-c999caa38404","userHandle":"testcat","projectId":111,"startDate":"2021-03-07","endDate":"2021-03-13","daysWorked":1,"memberRate":10.13,"customerRate":18.13,"paymentStatus":"pending","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-03-30T19:15:16.106Z","updatedAt":"2021-03-30T19:15:16.106Z"},{"id":"30ff1dbe-3434-45c7-806b-0c52a41652b5","resourceBookingId":"8173579e-4b3c-418d-a9a1-c999caa38404","userHandle":"testcat","projectId":111,"startDate":"2021-03-14","endDate":"2021-03-20","daysWorked":7,"memberRate":5.13,"customerRate":7.13,"paymentStatus":"completed","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-03-30T19:15:32.338Z","updatedAt":"2021-03-30T19:15:32.338Z"},{"id":"a974b73d-12a3-464e-ac97-a939f10a0726","resourceBookingId":"7d967fed-9792-4768-98a7-0b644aa84f2e","userHandle":"sachin-wipro","projectId":111,"startDate":"2021-03-14","endDate":"2021-03-20","daysWorked":7,"memberRate":5.13,"customerRate":7.13,"paymentStatus":"completed","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-03-30T19:15:54.822Z","updatedAt":"2021-03-30T19:15:54.822Z"},{"id":"db66b486-157b-4c0c-9a6c-03bd46c0f1d1","resourceBookingId":"7d967fed-9792-4768-98a7-0b644aa84f2e","userHandle":"sachin-wipro","projectId":111,"startDate":"2021-03-21","endDate":"2021-03-27","daysWorked":5,"memberRate":2.13,"customerRate":7.13,"paymentStatus":"pending","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-03-30T19:16:12.235Z","updatedAt":"2021-03-30T19:16:12.235Z"},{"id":"ec9195a6-cc81-4c7d-aa7b-5ac80a6926e8","resourceBookingId":"61f5d474-e41f-490b-ab58-9f983e3d4916","userHandle":"sonu628","projectId":111,"startDate":"2021-03-21","endDate":"2021-03-27","daysWorked":5,"memberRate":2.13,"customerRate":7.13,"paymentStatus":"pending","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-03-30T19:16:25.772Z","updatedAt":"2021-03-30T19:16:25.772Z"},{"id":"fd59ab02-75be-4d78-bc48-2ec35af61d41","resourceBookingId":"61f5d474-e41f-490b-ab58-9f983e3d4916","userHandle":"sonu628","projectId":111,"startDate":"2021-03-28","endDate":"2021-04-03","daysWorked":2,"memberRate":2.13,"customerRate":6.13,"paymentStatus":"pending","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-03-30T19:16:43.007Z","updatedAt":"2021-03-30T19:16:43.007Z"},{"id":"4bafda13-3319-4c46-8a31-0b9279a6e633","resourceBookingId":"51b45f5d-5df2-46d5-9c3d-8a1323df38dd","userHandle":"amy_admin","projectId":111,"startDate":"2021-03-28","endDate":"2021-04-03","daysWorked":2,"memberRate":2.13,"customerRate":6.13,"paymentStatus":"pending","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-03-30T19:16:54.483Z","updatedAt":"2021-03-30T19:16:54.483Z"},{"id":"c4dfb0d7-1a3a-4d1a-8fa5-9fc4b555b724","resourceBookingId":"51b45f5d-5df2-46d5-9c3d-8a1323df38dd","userHandle":"amy_admin","projectId":111,"startDate":"2021-04-04","endDate":"2021-04-10","daysWorked":2,"memberRate":2.13,"customerRate":6.13,"paymentStatus":"pending","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-03-30T19:17:07.537Z","updatedAt":"2021-03-30T19:17:07.537Z"},{"id":"0d92396b-040b-43d3-b816-7fdc9d888864","resourceBookingId":"35e1abd8-1890-4664-bb52-aade382d7b66","userHandle":"lakshmiaconnmgr","projectId":111,"startDate":"2021-04-04","endDate":"2021-04-10","daysWorked":2,"memberRate":2.13,"customerRate":6.13,"paymentStatus":"pending","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-03-30T19:17:20.639Z","updatedAt":"2021-03-30T19:17:20.639Z"},{"id":"073e179b-dae7-4dd7-9cb6-a35fd1370fca","resourceBookingId":"35e1abd8-1890-4664-bb52-aade382d7b66","userHandle":"lakshmiaconnmgr","projectId":111,"startDate":"2021-04-11","endDate":"2021-04-17","daysWorked":2,"memberRate":2.13,"customerRate":6.13,"paymentStatus":"cancelled","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-03-30T19:17:36.581Z","updatedAt":"2021-03-30T19:17:36.581Z"},{"id":"03b2d6e3-0448-4fbf-9f17-576b3dd94405","resourceBookingId":"0a6799d7-f5d1-456b-8bf1-90619284b295","userHandle":"aaaa","projectId":111,"startDate":"2021-04-11","endDate":"2021-04-17","daysWorked":4,"memberRate":2.13,"customerRate":6.13,"paymentStatus":"cancelled","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-03-30T19:17:53.085Z","updatedAt":"2021-03-30T19:17:53.085Z"},{"id":"99c1dba2-a70c-4f73-b19b-9e1a66fa5fd5","resourceBookingId":"0a6799d7-f5d1-456b-8bf1-90619284b295","userHandle":"aaaa","projectId":111,"startDate":"2021-04-04","endDate":"2021-04-10","daysWorked":4,"memberRate":2.13,"customerRate":6.13,"paymentStatus":"pending","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-03-30T19:18:10.763Z","updatedAt":"2021-03-30T19:18:10.763Z"},{"id":"854804e0-e698-424c-8cb9-cbbf885db0b6","resourceBookingId":"08f5e4b9-1088-496d-91a7-5b22a3583e3c","userHandle":"ritesh_cs","projectId":111,"startDate":"2021-04-04","endDate":"2021-04-10","daysWorked":4,"memberRate":2.13,"customerRate":6.13,"paymentStatus":"pending","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-03-30T19:18:23.704Z","updatedAt":"2021-03-30T19:18:23.704Z"},{"id":"a2242b3d-026a-493b-b186-ca16587e5701","resourceBookingId":"08f5e4b9-1088-496d-91a7-5b22a3583e3c","userHandle":"ritesh_cs","projectId":111,"startDate":"2021-04-11","endDate":"2021-04-17","daysWorked":6,"memberRate":12.13,"customerRate":16.13,"paymentStatus":"completed","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-03-30T19:18:36.729Z","updatedAt":"2021-03-30T19:18:36.729Z"}]} \ No newline at end of file +{"Job":[{"id":"b9887564-3d3d-4c70-8a7b-552576ef2e8d","projectId":111,"externalId":"0","description":"taas-demo-job1","title":"Demo Title","startDate":"2020-09-27T04:17:23.131Z","duration":null,"numPositions":13,"resourceType":"Dummy Resource Type","rateType":"weekly","workload":"full-time","skills":["ee4c50c1-c8c3-475e-b6b6-edbd136a19d6","89139c80-d0a2-47c2-aa16-14589d5afd10","9f2d9127-6a2e-4506-ad76-c4ab63577b09","9515e7ee-83b6-49d1-ba5c-6c59c5a8ef1b","c854ab55-5922-4be1-8ecc-b3bc1f8629af","8456002e-fa2d-44f0-b0e7-86b1c02b6e4c","114b4ec8-805e-4c60-b351-14a955a991a9","213408aa-f16f-46c8-bc57-9e569cee3f11","b37a48db-f775-4e4e-b403-8ad1d234cdea","99b930b5-1b91-4df1-8b17-d9307107bb51","6388a632-c3ad-4525-9a73-66a527c03672","23839f38-6f19-4de9-9d28-f020056bca73","289e42a3-23e9-49be-88e1-6deb93cd8c31","b403f209-63b5-42bc-9b5f-1564416640d8"],"status":"sourcing","isApplicationPageActive":false,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-01-28T19:36:33.409Z","updatedAt":"2021-03-30T19:11:05.033Z"},{"id":"a5b3bf94-a8bf-4c7e-b685-70a29a4d7d6e","projectId":111,"externalId":"0","description":"taas-demo-job2","title":"Dummy title - at most 64 characters","startDate":"2020-09-27T04:17:23.131Z","duration":null,"numPositions":7,"resourceType":"Dummy Resource Type","rateType":"weekly","workload":"full-time","skills":["213408aa-f16f-46c8-bc57-9e569cee3f11","b37a48db-f775-4e4e-b403-8ad1d234cdea","99b930b5-1b91-4df1-8b17-d9307107bb51","6388a632-c3ad-4525-9a73-66a527c03672","23839f38-6f19-4de9-9d28-f020056bca73","289e42a3-23e9-49be-88e1-6deb93cd8c31","b403f209-63b5-42bc-9b5f-1564416640d8"],"status":"in-review","isApplicationPageActive":false,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","createdAt":"2021-01-28T19:36:44.975Z","updatedAt":"2021-01-28T19:38:17.463Z"},{"id":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","projectId":111,"externalId":"0","description":"taas-demo-job3","title":"Dummy title - at most 64 characters","startDate":"2020-09-27T04:17:23.131Z","duration":null,"numPositions":7,"resourceType":"Dummy Resource Type","rateType":"weekly","workload":"full-time","skills":[],"status":"assigned","isApplicationPageActive":false,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","createdAt":"2021-01-28T19:38:23.739Z","updatedAt":"2021-01-28T19:41:10.607Z"},{"id":"84b73f90-0fef-4507-887a-074578e5ef38","projectId":111,"externalId":"0","description":"taas-demo-job4","title":"Dummy title - at most 64 characters","startDate":"2020-09-27T04:17:23.131Z","duration":null,"numPositions":7,"resourceType":"Dummy Resource Type","rateType":"weekly","workload":"full-time","skills":["8456002e-fa2d-44f0-b0e7-86b1c02b6e4c","114b4ec8-805e-4c60-b351-14a955a991a9","213408aa-f16f-46c8-bc57-9e569cee3f11","b37a48db-f775-4e4e-b403-8ad1d234cdea","99b930b5-1b91-4df1-8b17-d9307107bb51","6388a632-c3ad-4525-9a73-66a527c03672"],"status":"closed","isApplicationPageActive":false,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","createdAt":"2021-01-28T19:41:21.892Z","updatedAt":"2021-01-28T19:41:28.849Z"},{"id":"62399aa0-b088-41fe-9e9b-0c8071f1934f","projectId":111,"externalId":"0","description":"taas-demo-job5","title":"Dummy title - at most 64 characters","startDate":"2020-09-27T04:17:23.131Z","duration":null,"numPositions":7,"resourceType":"Dummy Resource Type","rateType":"weekly","workload":"full-time","skills":["b37a48db-f775-4e4e-b403-8ad1d234cdea","99b930b5-1b91-4df1-8b17-d9307107bb51","6388a632-c3ad-4525-9a73-66a527c03672"],"status":"cancelled","isApplicationPageActive":false,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","createdAt":"2021-01-28T19:41:35.098Z","updatedAt":"2021-01-28T19:41:42.124Z"},{"id":"1324da27-9d7d-47d8-a04e-9fb3f35a67fa","projectId":111,"externalId":"88774632","description":"Dummy Description","title":"Dummy title - at most 64 characters","startDate":"2020-09-27T04:17:23.131Z","duration":1,"numPositions":13,"resourceType":"Dummy Resource Type","rateType":"hourly","workload":"full-time","skills":["23e00d92-207a-4b5b-b3c9-4c5662644941","7d076384-ccf6-4e43-a45d-1b24b1e624aa","cbac57a3-7180-4316-8769-73af64893158","a2b4bc11-c641-4a19-9eb7-33980378f82e"],"status":"in-review","isApplicationPageActive":false,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"00000000-0000-0000-0000-000000000000","createdAt":"2021-04-14T08:46:17.739Z","updatedAt":"2021-04-14T08:46:23.311Z"}],"JobCandidate":[{"id":"debadcd8-64bf-4ab8-9cdb-297479eef6f5","jobId":"a5b3bf94-a8bf-4c7e-b685-70a29a4d7d6e","userId":"4dfc6090-4ba8-4387-b5c4-584fcef982ba","status":"open","externalId":null,"resume":null,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-01-28T19:37:05.723Z","updatedAt":"2021-03-30T19:11:05.043Z","interviews":[]},{"id":"7ff45b8f-2b71-4510-b760-8dfa62e79504","jobId":"a5b3bf94-a8bf-4c7e-b685-70a29a4d7d6e","userId":"243517dd-77d7-4f70-8951-0bc66da83076","status":"open","externalId":null,"resume":null,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-01-28T19:37:11.598Z","updatedAt":"2021-03-30T19:11:05.043Z","interviews":[]},{"id":"91d63d5f-01d5-419e-89df-6117ea92f535","jobId":"a5b3bf94-a8bf-4c7e-b685-70a29a4d7d6e","userId":"a2e28bf4-1147-41a6-a39f-e2509306f2a6","status":"open","externalId":null,"resume":null,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-01-28T19:37:18.066Z","updatedAt":"2021-03-30T19:11:05.043Z","interviews":[]},{"id":"257f98d9-45f7-4e13-a6c2-d7e7b6efc9fe","jobId":"a5b3bf94-a8bf-4c7e-b685-70a29a4d7d6e","userId":"b8649393-d32f-4b7f-a156-12e9776acb0e","status":"open","externalId":null,"resume":null,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-01-28T19:37:24.095Z","updatedAt":"2021-03-30T19:11:05.043Z","interviews":[]},{"id":"a01852d0-fa08-410c-b97b-67580ce62215","jobId":"a5b3bf94-a8bf-4c7e-b685-70a29a4d7d6e","userId":"a0a3a5ce-1de6-465d-91b2-518feb299851","status":"open","externalId":null,"resume":null,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-01-28T19:37:29.734Z","updatedAt":"2021-03-30T19:11:05.043Z","interviews":[]},{"id":"2fd7ca69-c8ec-4bf3-a7f3-655fbfe3e7df","jobId":"a5b3bf94-a8bf-4c7e-b685-70a29a4d7d6e","userId":"e6958d77-ffaf-4d24-9cdb-6391506695a4","status":"open","externalId":null,"resume":null,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-01-28T19:37:44.728Z","updatedAt":"2021-03-30T19:11:05.043Z","interviews":[]},{"id":"f0023058-2996-4bba-8c5f-d09a7023be38","jobId":"a5b3bf94-a8bf-4c7e-b685-70a29a4d7d6e","userId":"626bb327-e738-48e3-8f67-1fa2dc677d3c","status":"open","externalId":null,"resume":null,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-01-28T19:37:50.619Z","updatedAt":"2021-03-30T19:11:05.043Z","interviews":[]},{"id":"a189b34d-acde-4633-b18b-f7a34d7c5a74","jobId":"a5b3bf94-a8bf-4c7e-b685-70a29a4d7d6e","userId":"b49a0adb-1565-4de1-9189-a763c77f5ed4","status":"open","externalId":null,"resume":null,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-01-28T19:37:56.456Z","updatedAt":"2021-03-30T19:11:05.043Z","interviews":[]},{"id":"5191a860-4327-4c50-b76b-84beba04519b","jobId":"a5b3bf94-a8bf-4c7e-b685-70a29a4d7d6e","userId":"79ce2a3e-7679-48cf-8ac9-0a8ca4c4b463","status":"shortlist","externalId":null,"resume":null,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","createdAt":"2021-01-28T19:36:51.222Z","updatedAt":"2021-01-28T19:38:02.293Z","interviews":[]},{"id":"e6d9635c-b122-4f69-9285-09fb1ab30106","jobId":"a5b3bf94-a8bf-4c7e-b685-70a29a4d7d6e","userId":"98ec2c16-442e-4b61-8ad1-66123ee37d3c","status":"rejected","externalId":null,"resume":null,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","createdAt":"2021-01-28T19:36:58.774Z","updatedAt":"2021-01-28T19:38:13.553Z","interviews":[]},{"id":"f67b155e-0f09-4fdd-89a7-d79c5e46cac6","jobId":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","userId":"05e988b7-7d54-4c10-ada1-1a04870a88a8","status":"open","externalId":null,"resume":null,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-01-28T19:38:38.332Z","updatedAt":"2021-03-30T19:11:05.043Z","interviews":[]},{"id":"8ffd33d3-4a43-4719-aee4-8e46be1d8f1c","jobId":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","userId":"a2ffdeed-704d-4cf7-b70a-93fcf61de598","status":"open","externalId":null,"resume":null,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-01-28T19:38:43.967Z","updatedAt":"2021-03-30T19:11:05.043Z","interviews":[]},{"id":"2b8ba549-8878-43d6-ad5f-6a66e3b9d6c9","jobId":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","userId":"4709473d-f060-4102-87f8-4d51ff0b34c1","status":"open","externalId":null,"resume":null,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-01-28T19:38:50.106Z","updatedAt":"2021-03-30T19:11:05.043Z","interviews":[]},{"id":"ae5a81ec-5d05-43c4-8253-847d91a54711","jobId":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","userId":"39c7376e-2d5c-4601-bc47-6b60f505814d","status":"open","externalId":null,"resume":null,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-01-28T19:38:55.734Z","updatedAt":"2021-03-30T19:11:05.043Z","interviews":[]},{"id":"85d6649e-2682-4904-9480-a77b72fef27d","jobId":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","userId":"213d2dd9-1fc3-4eda-ad97-2d56e2a84a1e","status":"selected","externalId":null,"resume":null,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"00000000-0000-0000-0000-000000000000","createdAt":"2021-01-28T19:38:30.856Z","updatedAt":"2021-01-28T19:40:27.209Z","interviews":[]},{"id":"922dfce3-4e06-4387-9fdb-64f70675e86b","jobId":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","userId":"dd5adacb-444d-4992-8b7b-0c349be598db","status":"selected","externalId":null,"resume":null,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"00000000-0000-0000-0000-000000000000","createdAt":"2021-01-28T19:39:02.435Z","updatedAt":"2021-01-28T19:40:49.349Z","interviews":[]},{"id":"c26c38e2-a47d-405b-abc6-fe62a739561c","jobId":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","userId":"6d0509c7-5f12-4d84-9a19-8e80ef7ddd66","status":"selected","externalId":null,"resume":null,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"00000000-0000-0000-0000-000000000000","createdAt":"2021-01-28T19:39:08.233Z","updatedAt":"2021-01-28T19:40:53.659Z","interviews":[]},{"id":"7bef2b37-e1ee-4638-bfc1-c911787ac955","jobId":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","userId":"f65e2104-2987-4136-839d-ee4632f0b2e5","status":"selected","externalId":null,"resume":null,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"00000000-0000-0000-0000-000000000000","createdAt":"2021-01-28T19:39:13.469Z","updatedAt":"2021-01-28T19:40:57.999Z","interviews":[]},{"id":"e9716139-1f40-4bf1-9f8a-77ae4bcc621e","jobId":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","userId":"e5e667ad-0950-43c2-8d1d-6e83ad7d1c7e","status":"selected","externalId":null,"resume":null,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"00000000-0000-0000-0000-000000000000","createdAt":"2021-01-28T19:39:19.215Z","updatedAt":"2021-01-28T19:41:01.953Z","interviews":[]},{"id":"a1731d01-eac9-4eff-8e5a-8a3c99bc66e0","jobId":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","userId":"bef43122-426b-4b2b-acdd-9b5b3bd1c0bf","status":"selected","externalId":null,"resume":null,"createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"00000000-0000-0000-0000-000000000000","createdAt":"2021-01-28T19:39:24.625Z","updatedAt":"2021-01-28T19:41:06.370Z","interviews":[]},{"id":"25787cb2-d876-4883-b533-d5e628d213ce","jobId":"1324da27-9d7d-47d8-a04e-9fb3f35a67fa","userId":"95e7970f-12b4-43b7-ab35-38c34bf033c7","status":"open","externalId":"88774631","resume":"http://example.com","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-04-14T08:46:23.250Z","updatedAt":"2021-04-14T08:46:23.250Z","interviews":[{"id":"81f03238-1ce2-4d3d-80c5-5ecd5e7e94a2","jobCandidateId":"25787cb2-d876-4883-b533-d5e628d213ce","googleCalendarId":"dummyId","customMessage":"This is a custom message","xaiTemplate":"30-min-interview","round":1,"status":"Scheduling","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-04-14T08:46:34.597Z","updatedAt":"2021-04-14T08:46:34.597Z"},{"id":"75363f1d-46c3-4261-9c21-70019f90a61a","jobCandidateId":"25787cb2-d876-4883-b533-d5e628d213ce","googleCalendarId":"dummyId","customMessage":"This is a custom message","xaiTemplate":"30-min-interview","round":2,"status":"Scheduling","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-04-14T08:50:15.109Z","updatedAt":"2021-04-14T08:50:15.109Z"}]}],"ResourceBooking":[{"id":"08f5e4b9-1088-496d-91a7-5b22a3583e3c","projectId":111,"userId":"213d2dd9-1fc3-4eda-ad97-2d56e2a84a1e","jobId":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","status":"assigned","startDate":"2021-01-25T19:39:28.000Z","endDate":"2021-01-31T19:39:28.000Z","memberRate":1000,"customerRate":1200,"rateType":"weekly","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","createdAt":"2021-01-28T19:39:30.052Z","updatedAt":"2021-01-28T19:40:25.260Z"},{"id":"7d967fed-9792-4768-98a7-0b644aa84f2e","projectId":111,"userId":"05e988b7-7d54-4c10-ada1-1a04870a88a8","jobId":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","status":"in-review","startDate":"2021-01-25T19:39:34.000Z","endDate":"2021-01-31T19:39:34.000Z","memberRate":1000,"customerRate":1200,"rateType":"weekly","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","createdAt":"2021-01-28T19:39:35.571Z","updatedAt":"2021-01-28T19:40:30.291Z"},{"id":"35e1abd8-1890-4664-bb52-aade382d7b66","projectId":111,"userId":"a2ffdeed-704d-4cf7-b70a-93fcf61de598","jobId":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","status":"closed","startDate":"2021-01-25T19:39:39.000Z","endDate":"2021-01-31T19:39:39.000Z","memberRate":1000,"customerRate":1200,"rateType":"weekly","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","createdAt":"2021-01-28T19:39:41.205Z","updatedAt":"2021-01-28T19:40:34.859Z"},{"id":"a098e8d8-ce5b-47d9-afee-38b050d16745","projectId":111,"userId":"4709473d-f060-4102-87f8-4d51ff0b34c1","jobId":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","status":"cancelled","startDate":"2021-01-25T19:39:45.000Z","endDate":"2021-01-31T19:39:45.000Z","memberRate":1000,"customerRate":1200,"rateType":"weekly","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","createdAt":"2021-01-28T19:39:46.515Z","updatedAt":"2021-01-28T19:40:38.820Z"},{"id":"d38a6223-3f91-4300-9ecb-6e5fee173625","projectId":111,"userId":"39c7376e-2d5c-4601-bc47-6b60f505814d","jobId":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","status":"sourcing","startDate":"2021-01-25T19:39:50.000Z","endDate":"2021-01-31T19:39:50.000Z","memberRate":1000,"customerRate":1200,"rateType":"weekly","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","createdAt":"2021-01-28T19:39:52.063Z","updatedAt":"2021-01-28T19:40:43.021Z"},{"id":"51b45f5d-5df2-46d5-9c3d-8a1323df38dd","projectId":111,"userId":"dd5adacb-444d-4992-8b7b-0c349be598db","jobId":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","status":"assigned","startDate":"2021-01-25T19:39:58.000Z","endDate":"2021-01-31T19:39:58.000Z","memberRate":800,"customerRate":1000,"rateType":"weekly","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","createdAt":"2021-01-28T19:39:59.432Z","updatedAt":"2021-01-28T19:40:47.743Z"},{"id":"0a6799d7-f5d1-456b-8bf1-90619284b295","projectId":111,"userId":"6d0509c7-5f12-4d84-9a19-8e80ef7ddd66","jobId":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","status":"assigned","startDate":"2021-01-25T19:40:03.000Z","endDate":"2021-01-31T19:40:03.000Z","memberRate":2000,"customerRate":2500,"rateType":"weekly","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","createdAt":"2021-01-28T19:40:04.761Z","updatedAt":"2021-01-28T19:40:52.303Z"},{"id":"61f5d474-e41f-490b-ab58-9f983e3d4916","projectId":111,"userId":"f65e2104-2987-4136-839d-ee4632f0b2e5","jobId":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","status":"assigned","startDate":"2000-07-27T04:17:23.131Z","endDate":"2000-09-27T04:17:23.131Z","memberRate":3000,"customerRate":3500,"rateType":"weekly","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","createdAt":"2021-01-28T19:40:09.879Z","updatedAt":"2021-01-28T19:40:56.381Z"},{"id":"dc4477ec-07f8-4c8e-a8fe-ffe38dd290fa","projectId":111,"userId":"e5e667ad-0950-43c2-8d1d-6e83ad7d1c7e","jobId":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","status":"assigned","startDate":"2022-07-27T04:17:23.131Z","endDate":"2022-09-27T04:17:23.131Z","memberRate":1700,"customerRate":1900,"rateType":"weekly","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","createdAt":"2021-01-28T19:40:15.326Z","updatedAt":"2021-01-28T19:41:00.503Z"},{"id":"8173579e-4b3c-418d-a9a1-c999caa38404","projectId":111,"userId":"bef43122-426b-4b2b-acdd-9b5b3bd1c0bf","jobId":"2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0","status":"assigned","startDate":"2020-09-27T04:17:23.131Z","endDate":"2020-09-27T04:17:23.131Z","memberRate":0,"customerRate":0,"rateType":"weekly","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","createdAt":"2021-01-28T19:40:20.627Z","updatedAt":"2021-01-28T19:41:04.919Z"}],"WorkPeriod":[{"id":"854804e0-e698-424c-8cb9-cbbf885db0b6","resourceBookingId":"08f5e4b9-1088-496d-91a7-5b22a3583e3c","userHandle":"ritesh_cs","projectId":111,"startDate":"2021-04-04","endDate":"2021-04-10","daysWorked":4,"memberRate":2.13,"customerRate":6.13,"paymentStatus":"pending","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-03-30T19:18:23.704Z","updatedAt":"2021-03-30T19:18:23.704Z"},{"id":"a2242b3d-026a-493b-b186-ca16587e5701","resourceBookingId":"08f5e4b9-1088-496d-91a7-5b22a3583e3c","userHandle":"ritesh_cs","projectId":111,"startDate":"2021-04-11","endDate":"2021-04-17","daysWorked":6,"memberRate":12.13,"customerRate":16.13,"paymentStatus":"completed","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-03-30T19:18:36.729Z","updatedAt":"2021-03-30T19:18:36.729Z"},{"id":"99c1dba2-a70c-4f73-b19b-9e1a66fa5fd5","resourceBookingId":"0a6799d7-f5d1-456b-8bf1-90619284b295","userHandle":"aaaa","projectId":111,"startDate":"2021-04-04","endDate":"2021-04-10","daysWorked":4,"memberRate":2.13,"customerRate":6.13,"paymentStatus":"pending","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-03-30T19:18:10.763Z","updatedAt":"2021-03-30T19:18:10.763Z"},{"id":"03b2d6e3-0448-4fbf-9f17-576b3dd94405","resourceBookingId":"0a6799d7-f5d1-456b-8bf1-90619284b295","userHandle":"aaaa","projectId":111,"startDate":"2021-04-11","endDate":"2021-04-17","daysWorked":4,"memberRate":2.13,"customerRate":6.13,"paymentStatus":"cancelled","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-03-30T19:17:53.085Z","updatedAt":"2021-03-30T19:17:53.085Z"},{"id":"0d92396b-040b-43d3-b816-7fdc9d888864","resourceBookingId":"35e1abd8-1890-4664-bb52-aade382d7b66","userHandle":"lakshmiaconnmgr","projectId":111,"startDate":"2021-04-04","endDate":"2021-04-10","daysWorked":2,"memberRate":2.13,"customerRate":6.13,"paymentStatus":"pending","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-03-30T19:17:20.639Z","updatedAt":"2021-03-30T19:17:20.639Z"},{"id":"073e179b-dae7-4dd7-9cb6-a35fd1370fca","resourceBookingId":"35e1abd8-1890-4664-bb52-aade382d7b66","userHandle":"lakshmiaconnmgr","projectId":111,"startDate":"2021-04-11","endDate":"2021-04-17","daysWorked":2,"memberRate":2.13,"customerRate":6.13,"paymentStatus":"cancelled","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-03-30T19:17:36.581Z","updatedAt":"2021-03-30T19:17:36.581Z"},{"id":"4bafda13-3319-4c46-8a31-0b9279a6e633","resourceBookingId":"51b45f5d-5df2-46d5-9c3d-8a1323df38dd","userHandle":"amy_admin","projectId":111,"startDate":"2021-03-28","endDate":"2021-04-03","daysWorked":2,"memberRate":2.13,"customerRate":6.13,"paymentStatus":"pending","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-03-30T19:16:54.483Z","updatedAt":"2021-03-30T19:16:54.483Z"},{"id":"c4dfb0d7-1a3a-4d1a-8fa5-9fc4b555b724","resourceBookingId":"51b45f5d-5df2-46d5-9c3d-8a1323df38dd","userHandle":"amy_admin","projectId":111,"startDate":"2021-04-04","endDate":"2021-04-10","daysWorked":2,"memberRate":2.13,"customerRate":6.13,"paymentStatus":"pending","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-03-30T19:17:07.537Z","updatedAt":"2021-03-30T19:17:07.537Z"},{"id":"ec9195a6-cc81-4c7d-aa7b-5ac80a6926e8","resourceBookingId":"61f5d474-e41f-490b-ab58-9f983e3d4916","userHandle":"sonu628","projectId":111,"startDate":"2021-03-21","endDate":"2021-03-27","daysWorked":5,"memberRate":2.13,"customerRate":7.13,"paymentStatus":"pending","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-03-30T19:16:25.772Z","updatedAt":"2021-03-30T19:16:25.772Z"},{"id":"fd59ab02-75be-4d78-bc48-2ec35af61d41","resourceBookingId":"61f5d474-e41f-490b-ab58-9f983e3d4916","userHandle":"sonu628","projectId":111,"startDate":"2021-03-28","endDate":"2021-04-03","daysWorked":2,"memberRate":2.13,"customerRate":6.13,"paymentStatus":"pending","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-03-30T19:16:43.007Z","updatedAt":"2021-03-30T19:16:43.007Z"},{"id":"a974b73d-12a3-464e-ac97-a939f10a0726","resourceBookingId":"7d967fed-9792-4768-98a7-0b644aa84f2e","userHandle":"sachin-wipro","projectId":111,"startDate":"2021-03-14","endDate":"2021-03-20","daysWorked":7,"memberRate":5.13,"customerRate":7.13,"paymentStatus":"completed","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-03-30T19:15:54.822Z","updatedAt":"2021-03-30T19:15:54.822Z"},{"id":"db66b486-157b-4c0c-9a6c-03bd46c0f1d1","resourceBookingId":"7d967fed-9792-4768-98a7-0b644aa84f2e","userHandle":"sachin-wipro","projectId":111,"startDate":"2021-03-21","endDate":"2021-03-27","daysWorked":5,"memberRate":2.13,"customerRate":7.13,"paymentStatus":"pending","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-03-30T19:16:12.235Z","updatedAt":"2021-03-30T19:16:12.235Z"},{"id":"d694bbea-707d-41d5-a3f4-14884ff6fbf6","resourceBookingId":"8173579e-4b3c-418d-a9a1-c999caa38404","userHandle":"testcat","projectId":111,"startDate":"2021-03-07","endDate":"2021-03-13","daysWorked":1,"memberRate":10.13,"customerRate":18.13,"paymentStatus":"pending","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-03-30T19:15:16.106Z","updatedAt":"2021-03-30T19:15:16.106Z"},{"id":"30ff1dbe-3434-45c7-806b-0c52a41652b5","resourceBookingId":"8173579e-4b3c-418d-a9a1-c999caa38404","userHandle":"testcat","projectId":111,"startDate":"2021-03-14","endDate":"2021-03-20","daysWorked":7,"memberRate":5.13,"customerRate":7.13,"paymentStatus":"completed","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-03-30T19:15:32.338Z","updatedAt":"2021-03-30T19:15:32.338Z"},{"id":"dba9dc5a-afaa-43b2-9b7d-f0f03af81211","resourceBookingId":"a098e8d8-ce5b-47d9-afee-38b050d16745","userHandle":"TCConnCopilot","projectId":111,"startDate":"2021-03-07","endDate":"2021-03-13","daysWorked":5,"memberRate":15.13,"customerRate":17.13,"paymentStatus":"pending","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-03-30T19:14:56.991Z","updatedAt":"2021-03-30T19:14:56.991Z"},{"id":"5796eecf-cc4f-42c2-a25b-7af4710847d6","resourceBookingId":"a098e8d8-ce5b-47d9-afee-38b050d16745","userHandle":"TCConnCopilot","projectId":111,"startDate":"2021-03-14","endDate":"2021-03-20","daysWorked":5,"memberRate":15.13,"customerRate":17.13,"paymentStatus":"completed","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-03-30T19:14:43.498Z","updatedAt":"2021-03-30T19:14:43.498Z"},{"id":"9b0765ef-4e20-4cb2-91f1-ce8d7bcd8062","resourceBookingId":"d38a6223-3f91-4300-9ecb-6e5fee173625","userHandle":"nithyaasworld","projectId":111,"startDate":"2021-03-07","endDate":"2021-03-13","daysWorked":2,"memberRate":13.13,"customerRate":13.13,"paymentStatus":"cancelled","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-03-30T19:14:17.109Z","updatedAt":"2021-03-30T19:14:17.109Z"},{"id":"80b85cbb-3064-45aa-bb75-9dc010848fc1","resourceBookingId":"dc4477ec-07f8-4c8e-a8fe-ffe38dd290fa","userHandle":"nskumar278","projectId":111,"startDate":"2021-03-07","endDate":"2021-03-13","daysWorked":2,"memberRate":13.13,"customerRate":13.13,"paymentStatus":"pending","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":null,"createdAt":"2021-03-30T19:13:23.714Z","updatedAt":"2021-03-30T19:13:23.714Z"}]} \ No newline at end of file diff --git a/docs/Topcoder-bookings-api.postman_collection.json b/docs/Topcoder-bookings-api.postman_collection.json index 33b2da9d..47f830e6 100644 --- a/docs/Topcoder-bookings-api.postman_collection.json +++ b/docs/Topcoder-bookings-api.postman_collection.json @@ -1,6 +1,6 @@ { "info": { - "_postman_id": "488f8826-1016-4c2a-9d72-244c9ad4d9aa", + "_postman_id": "9346a502-7b04-48d4-ab58-c6b866c400d1", "name": "Topcoder-bookings-api", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" }, @@ -1886,6 +1886,78 @@ }, "response": [] }, + { + "name": "get job candidate with m2m (read jobCandidate & interview) - included interviews", + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_m2m_read_jobCandidate_read_interviews}}" + } + ], + "url": { + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "jobCandidates", + "{{jobCandidateId}}" + ] + } + }, + "response": [] + }, + { + "name": "get job candidate with m2m (read jobCandidate & all interview) - included interviews", + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_m2m_read_jobCandidates_all_interviews}}" + } + ], + "url": { + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "jobCandidates", + "{{jobCandidateId}}" + ] + } + }, + "response": [] + }, + { + "name": "get job candidate with m2m (read jobCandidate) - interviews not included", + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_m2m_read_job_candidate}}" + } + ], + "url": { + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "jobCandidates", + "{{jobCandidateId}}" + ] + } + }, + "response": [] + }, { "name": "get job candidate with booking manager from db", "request": { @@ -2095,14 +2167,14 @@ "response": [] }, { - "name": "search job candidates with connect user", + "name": "search job candidates with m2m (read jobCandidate & read interview) - included interviews", "request": { "method": "GET", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_connectUser}}" + "value": "Bearer {{token_m2m_read_jobCandidate_read_interviews}}" } ], "url": { @@ -2160,18 +2232,18 @@ "response": [] }, { - "name": "search job candidates with member", + "name": "search job candidates with m2m (read jobCandidate & all interview) - included interviews", "request": { "method": "GET", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_member}}" + "value": "Bearer {{token_m2m_read_jobCandidates_all_interviews}}" } ], "url": { - "raw": "{{URL}}/jobCandidates?sortBy=id&sortOrder=asc", + "raw": "{{URL}}/jobCandidates", "host": [ "{{URL}}" ], @@ -2191,11 +2263,13 @@ }, { "key": "sortBy", - "value": "id" + "value": "id", + "disabled": true }, { "key": "sortOrder", - "value": "asc" + "value": "asc", + "disabled": true }, { "key": "jobId", @@ -2223,18 +2297,18 @@ "response": [] }, { - "name": "search job candidates with invalid token", + "name": "search job candidates with m2m (read jobCandidate) - interviews not included", "request": { "method": "GET", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer invalid_token" + "value": "Bearer {{token_m2m_read_job_candidate}}" } ], "url": { - "raw": "{{URL}}/jobCandidates?sortBy=id&sortOrder=asc", + "raw": "{{URL}}/jobCandidates", "host": [ "{{URL}}" ], @@ -2254,11 +2328,13 @@ }, { "key": "sortBy", - "value": "id" + "value": "id", + "disabled": true }, { "key": "sortOrder", - "value": "asc" + "value": "asc", + "disabled": true }, { "key": "jobId", @@ -2286,146 +2362,205 @@ "response": [] }, { - "name": "put job candidate with booking manager", + "name": "search job candidates with connect user", "request": { - "method": "PUT", + "method": "GET", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_connectUser}}" } ], - "body": { - "mode": "raw", - "raw": "{\n \"jobId\": \"{{jobId}}\",\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\n \"status\": \"selected\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}", + "raw": "{{URL}}/jobCandidates", "host": [ "{{URL}}" ], "path": [ - "jobCandidates", - "{{jobCandidateId}}" + "jobCandidates" + ], + "query": [ + { + "key": "page", + "value": "1", + "disabled": true + }, + { + "key": "perPage", + "value": "1", + "disabled": true + }, + { + "key": "sortBy", + "value": "id", + "disabled": true + }, + { + "key": "sortOrder", + "value": "asc", + "disabled": true + }, + { + "key": "jobId", + "value": "46225f4c-c2a3-4603-a141-0277e96fabfa", + "disabled": true + }, + { + "key": "userId", + "value": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "disabled": true + }, + { + "key": "status", + "value": "shortlist", + "disabled": true + }, + { + "key": "externalId", + "value": "300234321", + "disabled": true + } ] } }, "response": [] }, { - "name": "put job candidate with m2m update", + "name": "search job candidates with member", "request": { - "method": "PUT", + "method": "GET", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_m2m_update_job_candidate}}" + "value": "Bearer {{token_member}}" } ], - "body": { - "mode": "raw", - "raw": "{\n \"jobId\": \"{{jobIdCreatedByM2M}}\",\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\n \"status\": \"selected\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/jobCandidates/{{jobCandidateIdCreatedByM2M}}", + "raw": "{{URL}}/jobCandidates?sortBy=id&sortOrder=asc", "host": [ "{{URL}}" ], "path": [ - "jobCandidates", - "{{jobCandidateIdCreatedByM2M}}" + "jobCandidates" + ], + "query": [ + { + "key": "page", + "value": "1", + "disabled": true + }, + { + "key": "perPage", + "value": "1", + "disabled": true + }, + { + "key": "sortBy", + "value": "id" + }, + { + "key": "sortOrder", + "value": "asc" + }, + { + "key": "jobId", + "value": "46225f4c-c2a3-4603-a141-0277e96fabfa", + "disabled": true + }, + { + "key": "userId", + "value": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "disabled": true + }, + { + "key": "status", + "value": "shortlist", + "disabled": true + }, + { + "key": "externalId", + "value": "300234321", + "disabled": true + } ] } }, "response": [] }, { - "name": "put job candidate with connect user", + "name": "search job candidates with invalid token", "request": { - "method": "PUT", + "method": "GET", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_connectUser}}" + "value": "Bearer invalid_token" } ], - "body": { - "mode": "raw", - "raw": "{\n \"jobId\": \"{{jobId}}\",\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\n \"status\": \"selected\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}", + "raw": "{{URL}}/jobCandidates?sortBy=id&sortOrder=asc", "host": [ "{{URL}}" ], "path": [ - "jobCandidates", - "{{jobCandidateId}}" - ] - } - }, - "response": [] - }, - { - "name": "put job candidate with member", - "request": { - "method": "PUT", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_member}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"jobId\": \"{{jobId}}\",\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\n \"status\": \"selected\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}", - "host": [ - "{{URL}}" + "jobCandidates" ], - "path": [ - "jobCandidates", - "{{jobCandidateId}}" + "query": [ + { + "key": "page", + "value": "1", + "disabled": true + }, + { + "key": "perPage", + "value": "1", + "disabled": true + }, + { + "key": "sortBy", + "value": "id" + }, + { + "key": "sortOrder", + "value": "asc" + }, + { + "key": "jobId", + "value": "46225f4c-c2a3-4603-a141-0277e96fabfa", + "disabled": true + }, + { + "key": "userId", + "value": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "disabled": true + }, + { + "key": "status", + "value": "shortlist", + "disabled": true + }, + { + "key": "externalId", + "value": "300234321", + "disabled": true + } ] } }, "response": [] }, { - "name": "put job candidate with user id not exist", + "name": "put job candidate with booking manager", "request": { "method": "PUT", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_userId_not_exist}}" + "value": "Bearer {{token_bookingManager}}" } ], "body": { @@ -2451,19 +2586,19 @@ "response": [] }, { - "name": "put job candidate with invalid token", + "name": "put job candidate with m2m update", "request": { "method": "PUT", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer invalid_token" + "value": "Bearer {{token_m2m_update_job_candidate}}" } ], "body": { "mode": "raw", - "raw": "{\n \"jobId\": \"{{jobId}}\",\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\n \"status\": \"selected\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", + "raw": "{\n \"jobId\": \"{{jobIdCreatedByM2M}}\",\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\n \"status\": \"selected\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", "options": { "raw": { "language": "json" @@ -2471,32 +2606,32 @@ } }, "url": { - "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateIdCreatedByM2M}}", "host": [ "{{URL}}" ], "path": [ "jobCandidates", - "{{jobCandidateId}}" + "{{jobCandidateIdCreatedByM2M}}" ] } }, "response": [] }, { - "name": "patch job candidate with booking manager", + "name": "put job candidate with connect user", "request": { - "method": "PATCH", + "method": "PUT", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_connectUser}}" } ], "body": { "mode": "raw", - "raw": "{\n \"status\": \"shortlist\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", + "raw": "{\n \"jobId\": \"{{jobId}}\",\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\n \"status\": \"selected\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", "options": { "raw": { "language": "json" @@ -2517,19 +2652,19 @@ "response": [] }, { - "name": "patch job candidate with m2m update", + "name": "put job candidate with member", "request": { - "method": "PATCH", + "method": "PUT", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_m2m_update_job_candidate}}" + "value": "Bearer {{token_member}}" } ], "body": { "mode": "raw", - "raw": "{\n \"status\": \"shortlist\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", + "raw": "{\n \"jobId\": \"{{jobId}}\",\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\n \"status\": \"selected\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", "options": { "raw": { "language": "json" @@ -2537,32 +2672,32 @@ } }, "url": { - "raw": "{{URL}}/jobCandidates/{{jobCandidateIdCreatedByM2M}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}", "host": [ "{{URL}}" ], "path": [ "jobCandidates", - "{{jobCandidateIdCreatedByM2M}}" + "{{jobCandidateId}}" ] } }, "response": [] }, { - "name": "patch job candidate with connect user", + "name": "put job candidate with user id not exist", "request": { - "method": "PATCH", + "method": "PUT", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_connectUser}}" + "value": "Bearer {{token_userId_not_exist}}" } ], "body": { "mode": "raw", - "raw": "{\n \"status\": \"shortlist\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", + "raw": "{\n \"jobId\": \"{{jobId}}\",\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\n \"status\": \"selected\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", "options": { "raw": { "language": "json" @@ -2583,19 +2718,19 @@ "response": [] }, { - "name": "patch job candidate with member", + "name": "put job candidate with invalid token", "request": { - "method": "PATCH", + "method": "PUT", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_member}}" + "value": "Bearer invalid_token" } ], "body": { "mode": "raw", - "raw": "{\n \"status\": \"shortlist\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", + "raw": "{\n \"jobId\": \"{{jobId}}\",\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\n \"status\": \"selected\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", "options": { "raw": { "language": "json" @@ -2616,14 +2751,14 @@ "response": [] }, { - "name": "patch job candidate with user id not exist", + "name": "patch job candidate with booking manager", "request": { "method": "PATCH", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_userId_not_exist}}" + "value": "Bearer {{token_bookingManager}}" } ], "body": { @@ -2649,14 +2784,14 @@ "response": [] }, { - "name": "patch job candidate with invalid token", + "name": "patch job candidate with m2m update", "request": { "method": "PATCH", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer invalid_token" + "value": "Bearer {{token_m2m_update_job_candidate}}" } ], "body": { @@ -2669,32 +2804,32 @@ } }, "url": { - "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateIdCreatedByM2M}}", "host": [ "{{URL}}" ], "path": [ "jobCandidates", - "{{jobCandidateId}}" + "{{jobCandidateIdCreatedByM2M}}" ] } }, "response": [] }, { - "name": "delete job candidate with member", + "name": "patch job candidate with connect user", "request": { - "method": "DELETE", + "method": "PATCH", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_member}}" + "value": "Bearer {{token_connectUser}}" } ], "body": { "mode": "raw", - "raw": "", + "raw": "{\n \"status\": \"shortlist\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", "options": { "raw": { "language": "json" @@ -2715,19 +2850,19 @@ "response": [] }, { - "name": "delete job candidate with connect user", + "name": "patch job candidate with member", "request": { - "method": "DELETE", + "method": "PATCH", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_connectUser}}" + "value": "Bearer {{token_member}}" } ], "body": { "mode": "raw", - "raw": "", + "raw": "{\n \"status\": \"shortlist\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", "options": { "raw": { "language": "json" @@ -2748,19 +2883,19 @@ "response": [] }, { - "name": "delete job candidate with booking manager", + "name": "patch job candidate with user id not exist", "request": { - "method": "DELETE", + "method": "PATCH", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_userId_not_exist}}" } ], "body": { "mode": "raw", - "raw": "", + "raw": "{\n \"status\": \"shortlist\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", "options": { "raw": { "language": "json" @@ -2781,19 +2916,19 @@ "response": [] }, { - "name": "delete job candidate with m2m delete", + "name": "patch job candidate with invalid token", "request": { - "method": "DELETE", + "method": "PATCH", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_m2m_delete_job_candidate}}" + "value": "Bearer invalid_token" } ], "body": { "mode": "raw", - "raw": "", + "raw": "{\n \"status\": \"shortlist\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", "options": { "raw": { "language": "json" @@ -2801,49 +2936,32 @@ } }, "url": { - "raw": "{{URL}}/jobCandidates/{{jobCandidateIdCreatedByM2M}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}", "host": [ "{{URL}}" ], "path": [ "jobCandidates", - "{{jobCandidateIdCreatedByM2M}}" + "{{jobCandidateId}}" ] } }, "response": [] - } - ] - }, - { - "name": "Resource Bookings", - "item": [ + }, { - "name": "create resource booking with booking manager", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "var data = JSON.parse(responseBody);\r", - "postman.setEnvironmentVariable(\"resourceBookingId\",data.id);" - ], - "type": "text/javascript" - } - } - ], + "name": "delete job candidate with member", "request": { - "method": "POST", + "method": "DELETE", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_member}}" } ], "body": { "mode": "raw", - "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{jobId}}\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\"\r\n}", + "raw": "", "options": { "raw": { "language": "json" @@ -2851,43 +2969,32 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings" + "jobCandidates", + "{{jobCandidateId}}" ] } }, "response": [] }, { - "name": "create resource booking with m2m create", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "var data = JSON.parse(responseBody);\r", - "postman.setEnvironmentVariable(\"resourceBookingIdCreatedByM2M\",data.id);" - ], - "type": "text/javascript" - } - } - ], + "name": "delete job candidate with connect user", "request": { - "method": "POST", + "method": "DELETE", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_m2m_create_resource_booking}}" + "value": "Bearer {{token_connectUser}}" } ], "body": { "mode": "raw", - "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{jobIdCreatedByM2M}}\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\"\r\n}", + "raw": "", "options": { "raw": { "language": "json" @@ -2895,43 +3002,32 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings" + "jobCandidates", + "{{jobCandidateId}}" ] } }, "response": [] }, { - "name": "create resource booking with connect user", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "var data = JSON.parse(responseBody);\r", - "postman.setEnvironmentVariable(\"resourceBookingId\",data.id);" - ], - "type": "text/javascript" - } - } - ], + "name": "delete job candidate with booking manager", "request": { - "method": "POST", + "method": "DELETE", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_connectUser}}" + "value": "Bearer {{token_bookingManager}}" } ], "body": { "mode": "raw", - "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{jobId}}\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\"\r\n}", + "raw": "", "options": { "raw": { "language": "json" @@ -2939,42 +3035,32 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings" + "jobCandidates", + "{{jobCandidateId}}" ] } }, "response": [] }, { - "name": "create resource booking with member", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "" - ], - "type": "text/javascript" - } - } - ], + "name": "delete job candidate with m2m delete", "request": { - "method": "POST", + "method": "DELETE", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_member}}" + "value": "Bearer {{token_m2m_delete_job_candidate}}" } ], "body": { "mode": "raw", - "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{jobId}}\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\"\r\n}", + "raw": "", "options": { "raw": { "language": "json" @@ -2982,42 +3068,209 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings", + "raw": "{{URL}}/jobCandidates/{{jobCandidateIdCreatedByM2M}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings" + "jobCandidates", + "{{jobCandidateIdCreatedByM2M}}" ] } }, "response": [] - }, - { - "name": "create resource booking with user id not exist", - "event": [ - { + } + ] + }, + { + "name": "Interviews", + "item": [ + { + "name": "Before Test", + "item": [ + { + "name": "create job", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200)\r", + " if(pm.response.status === \"OK\"){\r", + " const response = pm.response.json()\r", + " pm.environment.set(\"jobId\", response.id);\r", + " }\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_bookingManager}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"projectId\": {{projectId}},\n \"externalId\": \"88774632\",\n \"description\": \"Dummy Description\",\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\n \"duration\": 1,\n \"numPositions\": 13,\n \"resourceType\": \"Dummy Resource Type\",\n \"rateType\": \"hourly\",\n \"workload\": \"full-time\",\n \"skills\": [\n \"23e00d92-207a-4b5b-b3c9-4c5662644941\",\n \"7d076384-ccf6-4e43-a45d-1b24b1e624aa\",\n \"cbac57a3-7180-4316-8769-73af64893158\",\n \"a2b4bc11-c641-4a19-9eb7-33980378f82e\"\n ],\n \"title\": \"Dummy title - at most 64 characters\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobs", + "host": [ + "{{URL}}" + ], + "path": [ + "jobs" + ] + } + }, + "response": [] + }, + { + "name": "create job candidate", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200)\r", + " if(pm.response.status === \"OK\"){\r", + " const response = pm.response.json()\r", + " pm.environment.set(\"jobCandidateId\", response.id);\r", + " }\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"jobId\": \"{{jobId}}\",\n \"userId\": \"95e7970f-12b4-43b7-ab35-38c34bf033c7\",\n \"externalId\": \"88774631\",\n \"resume\": \"http://example.com\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobCandidates", + "host": [ + "{{URL}}" + ], + "path": [ + "jobCandidates" + ] + } + }, + "response": [] + }, + { + "name": "Create completed interview", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200)\r", + " if(pm.response.status === \"OK\"){\r", + " const response = pm.response.json()\r", + " pm.environment.set(\"completedInterviewJobCandidateId\", response.jobCandidateId);\r", + " pm.environment.set(\"completedInterviewRound\", response.round);\r", + " }\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_bookingManager}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\",\r\n \"status\": \"Completed\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/requestInterview", + "host": [ + "{{URL}}" + ], + "path": [ + "jobCandidates", + "{{jobCandidateId}}", + "requestInterview" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "Request interview", + "event": [ + { "listen": "test", "script": { "exec": [ - "" + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200)\r", + " if(pm.response.status === \"OK\"){\r", + " const response = pm.response.json()\r", + " pm.environment.set(\"interviewRound\", response.round);\r", + " }\r", + "});" ], "type": "text/javascript" } } ], "request": { - "method": "POST", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_userId_not_exist}}" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], "body": { "mode": "raw", - "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{jobId}}\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\",\r\n \"googleCalendarId\": \"dummyId\",\r\n \"customMessage\": \"This is a custom message\",\r\n \"attendeesList\": [\"attendee1@yopmail.com\", \"attendee2@yopmail.com\"],\r\n \"status\": \"Scheduling\"\r\n}", "options": { "raw": { "language": "json" @@ -3025,42 +3278,50 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/requestInterview", "host": [ "{{URL}}" ], "path": [ - "resourceBookings" + "jobCandidates", + "{{jobCandidateId}}", + "requestInterview" ] } }, "response": [] }, { - "name": "create resource booking with invalid token", + "name": "Request interview for the same jobCandidateId - should increment round", "event": [ { "listen": "test", "script": { "exec": [ - "" + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", + " const response = pm.response.json();\r", + " const lastRound = pm.environment.get(\"interviewRound\");\r", + " pm.expect(response.round).to.eq(lastRound + 1);\r", + " pm.environment.set(\"interviewRound\", response.round);\r", + "});" ], "type": "text/javascript" } } ], "request": { - "method": "POST", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer invalid_token" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], "body": { "mode": "raw", - "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{jobId}}\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\",\r\n \"googleCalendarId\": \"dummyId\",\r\n \"customMessage\": \"This is a custom message\",\r\n \"status\": \"Scheduling\"\r\n}", "options": { "raw": { "language": "json" @@ -3068,469 +3329,589 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/requestInterview", "host": [ "{{URL}}" ], "path": [ - "resourceBookings" + "jobCandidates", + "{{jobCandidateId}}", + "requestInterview" ] } }, "response": [] }, { - "name": "get resource booking with booking manager", + "name": "Request interview without status - should take default status", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200)\r", + " if(pm.response.status === \"OK\"){\r", + " const response = pm.response.json()\r", + " pm.environment.set(\"interviewRound\", response.round);\r", + " pm.expect(response.status).to.eq(\"Scheduling\")\r", + " }\r", + "});" + ], + "type": "text/javascript" + } + } + ], "request": { - "method": "GET", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], + "body": { + "mode": "raw", + "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/requestInterview", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resourceBookingId}}" + "jobCandidates", + "{{jobCandidateId}}", + "requestInterview" ] } }, "response": [] }, { - "name": "get resource booking with m2m read", + "name": "Request interview with invalid status", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"\\\"interview.status\\\" must be one of [Scheduling, Scheduled, Requested for reschedule, Rescheduled, Completed, Cancelled]\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], "request": { - "method": "GET", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_m2m_read_resource_booking}}" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], + "body": { + "mode": "raw", + "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\",\r\n \"status\": \"xxxx\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingIdCreatedByM2M}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/requestInterview", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resourceBookingIdCreatedByM2M}}" + "jobCandidates", + "{{jobCandidateId}}", + "requestInterview" ] } }, "response": [] }, { - "name": "get resource booking with booking manager from db", - "request": { - "method": "GET", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } + "name": "Request interview with attendeesList", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", + " const response = pm.response.json()\r", + " pm.expect(response.attendeesList[0]).to.eq(\"attendee1@yopmail.com\")\r", + " pm.expect(response.attendeesList[1]).to.eq(\"attendee2@yopmail.com\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_bookingManager}}", + "type": "text" + } ], + "body": { + "mode": "raw", + "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\",\r\n \"attendeesList\": [\"attendee1@yopmail.com\", \"attendee2@yopmail.com\"]\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}?fromDb=true", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/requestInterview", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resourceBookingId}}" - ], - "query": [ - { - "key": "fromDb", - "value": "true" - } + "jobCandidates", + "{{jobCandidateId}}", + "requestInterview" ] } }, "response": [] }, { - "name": "get resource booking with connect user", + "name": "Request interview with invalid attendeesList", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"\\\"interview.attendeesList\\\" must be an array\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], "request": { - "method": "GET", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_connectUser}}" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], + "body": { + "mode": "raw", + "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\",\r\n \"attendeesList\": \"asddd\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/requestInterview", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resourceBookingId}}" + "jobCandidates", + "{{jobCandidateId}}", + "requestInterview" ] } }, "response": [] }, { - "name": "get resource booking with member", + "name": "Request interview with invalid attendee email", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"\\\"interview.attendeesList[0]\\\" must be a valid email\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], "request": { - "method": "GET", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_member}}" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], + "body": { + "mode": "raw", + "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\",\r\n \"attendeesList\": [\"asdas\"]\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/requestInterview", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resourceBookingId}}" + "jobCandidates", + "{{jobCandidateId}}", + "requestInterview" ] } }, "response": [] }, { - "name": "search resource bookings with booking manager", + "name": "Request interview with round - should not accept", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"\\\"interview.round\\\" is not allowed\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], "request": { - "method": "GET", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], + "body": { + "mode": "raw", + "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\",\r\n \"round\": 1\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { - "raw": "{{URL}}/resourceBookings", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/requestInterview", "host": [ "{{URL}}" ], "path": [ - "resourceBookings" - ], - "query": [ - { - "key": "page", - "value": "1", - "disabled": true - }, - { - "key": "perPage", - "value": "5", - "disabled": true - }, - { - "key": "sortBy", - "value": "id", - "disabled": true - }, - { - "key": "sortOrder", - "value": "desc", - "disabled": true - }, - { - "key": "startDate", - "value": "2020-09-27T04:17:23.131Z", - "disabled": true - }, - { - "key": "endDate", - "value": "2020-09-27T04:17:23.131Z", - "disabled": true - }, - { - "key": "rateType", - "value": "hourly", - "disabled": true - }, - { - "key": "status", - "value": "sourcing", - "disabled": true - }, - { - "key": "projectIds", - "value": "111, 16705", - "disabled": true + "jobCandidates", + "{{jobCandidateId}}", + "requestInterview" + ] + } + }, + "response": [] + }, + { + "name": "Request interview with startTimestamp - should not accept", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"\\\"interview.startTimestamp\\\" is not allowed\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_bookingManager}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\",\r\n \"startTimestamp\": \"2021-04-17\"\r\n}", + "options": { + "raw": { + "language": "json" } + } + }, + "url": { + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/requestInterview", + "host": [ + "{{URL}}" + ], + "path": [ + "jobCandidates", + "{{jobCandidateId}}", + "requestInterview" ] } }, "response": [] }, { - "name": "search resource bookings with m2m all", + "name": "Request interview without xaiTemplate - should fail", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"\\\"interview.xaiTemplate\\\" is required\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], "request": { - "method": "GET", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_m2m_all_resource_booking}}" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], + "body": { + "mode": "raw", + "raw": "{\r\n \"status\": \"Requested\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { - "raw": "{{URL}}/resourceBookings", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/requestInterview", "host": [ "{{URL}}" ], "path": [ - "resourceBookings" - ], - "query": [ - { - "key": "page", - "value": "1", - "disabled": true - }, - { - "key": "perPage", - "value": "5", - "disabled": true - }, - { - "key": "sortBy", - "value": "id", - "disabled": true - }, - { - "key": "sortOrder", - "value": "desc", - "disabled": true - }, - { - "key": "startDate", - "value": "2020-09-27T04:17:23.131Z", - "disabled": true - }, - { - "key": "endDate", - "value": "2020-09-27T04:17:23.131Z", - "disabled": true - }, - { - "key": "rateType", - "value": "hourly", - "disabled": true - }, - { - "key": "status", - "value": "sourcing", - "disabled": true - } + "jobCandidates", + "{{jobCandidateId}}", + "requestInterview" ] } }, "response": [] }, { - "name": "search resource bookings with connect user", + "name": "Request interview with invalid xaiTemplate", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"\\\"interview.xaiTemplate\\\" must be one of [30-min-interview, 60-min-interview]\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], "request": { - "method": "GET", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_connectUser}}" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], + "body": { + "mode": "raw", + "raw": "{\r\n \"xaiTemplate\": \"asdas\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { - "raw": "{{URL}}/resourceBookings?sortOrder=desc", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/requestInterview", "host": [ "{{URL}}" ], "path": [ - "resourceBookings" - ], - "query": [ - { - "key": "page", - "value": "4", - "disabled": true - }, - { - "key": "perPage", - "value": "3", - "disabled": true - }, - { - "key": "sortBy", - "value": "id", - "disabled": true - }, - { - "key": "startDate", - "value": "2020-09-27T04:17:23.131Z", - "disabled": true - }, - { - "key": "endDate", - "value": "2020-09-27T04:17:23.131Z", - "disabled": true - }, - { - "key": "rateType", - "value": "hourly", - "disabled": true - }, - { - "key": "sortOrder", - "value": "desc" - } + "jobCandidates", + "{{jobCandidateId}}", + "requestInterview" ] } }, "response": [] }, { - "name": "search resource bookings with member", + "name": "Request interview with non-existing jobCandidate", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 404', function () {\r", + " pm.response.to.have.status(404);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"The job candidate with id=9105f597-f9d5-49c0-9cbf-9a0cbda47260 doesn't exist.\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], "request": { - "method": "GET", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_member}}" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], + "body": { + "mode": "raw", + "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { - "raw": "{{URL}}/resourceBookings?sortOrder=desc", + "raw": "{{URL}}/jobCandidates/9105f597-f9d5-49c0-9cbf-9a0cbda47260/requestInterview", "host": [ "{{URL}}" ], "path": [ - "resourceBookings" - ], - "query": [ - { - "key": "page", - "value": "4", - "disabled": true - }, - { - "key": "perPage", - "value": "3", - "disabled": true - }, - { - "key": "sortBy", - "value": "id", - "disabled": true - }, - { - "key": "startDate", - "value": "2020-09-27T04:17:23.131Z", - "disabled": true - }, - { - "key": "endDate", - "value": "2020-09-27T04:17:23.131Z", - "disabled": true - }, - { - "key": "rateType", - "value": "hourly", - "disabled": true - }, - { - "key": "sortOrder", - "value": "desc" - } + "jobCandidates", + "9105f597-f9d5-49c0-9cbf-9a0cbda47260", + "requestInterview" ] } }, "response": [] }, { - "name": "search resource bookings with invalid token", + "name": "Request interview with non-existing userId in token", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"Bad Request\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], "request": { - "method": "GET", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer invalid_token" + "value": "Bearer {{token_userId_not_exist}}", + "type": "text" } ], + "body": { + "mode": "raw", + "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { - "raw": "{{URL}}/resourceBookings?sortOrder=desc", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/requestInterview", "host": [ "{{URL}}" ], "path": [ - "resourceBookings" - ], - "query": [ - { - "key": "page", - "value": "4", - "disabled": true - }, - { - "key": "perPage", - "value": "3", - "disabled": true - }, - { - "key": "sortBy", - "value": "id", - "disabled": true - }, - { - "key": "startDate", - "value": "2020-09-27T04:17:23.131Z", - "disabled": true - }, - { - "key": "endDate", - "value": "2020-09-27T04:17:23.131Z", - "disabled": true - }, - { - "key": "rateType", - "value": "hourly", - "disabled": true - }, - { - "key": "sortOrder", - "value": "desc" - } + "jobCandidates", + "{{jobCandidateId}}", + "requestInterview" ] } }, "response": [] }, { - "name": "put resource booking with booking manager", - "request": { - "method": "PUT", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" + "name": "Request interview with administrator", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_administrator}}", + "type": "text" } ], "body": { "mode": "raw", - "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{jobId}}\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"status\": \"assigned\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\"\r\n}", "options": { "raw": { "language": "json" @@ -3538,32 +3919,46 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/requestInterview", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resourceBookingId}}" + "jobCandidates", + "{{jobCandidateId}}", + "requestInterview" ] } }, "response": [] }, { - "name": "put resource booking with m2m update", + "name": "Request interview with booking manager", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", + "});" + ], + "type": "text/javascript" + } + } + ], "request": { - "method": "PUT", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_m2m_update_resource_booking}}" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], "body": { "mode": "raw", - "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{jobIdCreatedByM2M}}\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"status\": \"assigned\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\"\r\n}", "options": { "raw": { "language": "json" @@ -3571,32 +3966,46 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingIdCreatedByM2M}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/requestInterview", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resourceBookingIdCreatedByM2M}}" + "jobCandidates", + "{{jobCandidateId}}", + "requestInterview" ] } }, "response": [] }, { - "name": "put resource booking with connect user", + "name": "Request interview with m2m (all interview scope)", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", + "});" + ], + "type": "text/javascript" + } + } + ], "request": { - "method": "PUT", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_connectUser}}" + "value": "Bearer {{token_m2m_all_interviews}}", + "type": "text" } ], "body": { "mode": "raw", - "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{jobId}}\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"status\": \"assigned\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\"\r\n}", "options": { "raw": { "language": "json" @@ -3604,32 +4013,46 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/requestInterview", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resourceBookingId}}" + "jobCandidates", + "{{jobCandidateId}}", + "requestInterview" ] } }, "response": [] }, { - "name": "put resource booking with member", + "name": "Request interview with m2m (create interview scope)", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", + "});" + ], + "type": "text/javascript" + } + } + ], "request": { - "method": "PUT", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_member}}" + "value": "Bearer {{token_m2m_create_interviews}}", + "type": "text" } ], "body": { "mode": "raw", - "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{jobId}}\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"status\": \"assigned\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\"\r\n}", "options": { "raw": { "language": "json" @@ -3637,32 +4060,48 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/requestInterview", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resourceBookingId}}" + "jobCandidates", + "{{jobCandidateId}}", + "requestInterview" ] } }, "response": [] }, { - "name": "put resource booking with user id not exist", + "name": "Request interview with m2m (read interview scope) - should fail", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 401', function () {\r", + " pm.response.to.have.status(403);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], "request": { - "method": "PUT", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_userId_not_exist}}" + "value": "Bearer {{token_m2m_read_interviews}}", + "type": "text" } ], "body": { "mode": "raw", - "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{jobId}}\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"status\": \"assigned\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\"\r\n}", "options": { "raw": { "language": "json" @@ -3670,32 +4109,48 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/requestInterview", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resourceBookingId}}" + "jobCandidates", + "{{jobCandidateId}}", + "requestInterview" ] } }, "response": [] }, { - "name": "put resource booking with invalid token", + "name": "Request interview with m2m (update interview scope) - should fail", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 401', function () {\r", + " pm.response.to.have.status(403);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], "request": { - "method": "PUT", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer invalid_token" + "value": "Bearer {{token_m2m_update_interviews}}", + "type": "text" } ], "body": { "mode": "raw", - "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{jobId}}\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"status\": \"assigned\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\"\r\n}", "options": { "raw": { "language": "json" @@ -3703,32 +4158,48 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/requestInterview", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resourceBookingId}}" + "jobCandidates", + "{{jobCandidateId}}", + "requestInterview" ] } }, "response": [] }, { - "name": "patch resource booking with booking manager", + "name": "Request interview with connect manager", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 401', function () {\r", + " pm.response.to.have.status(403);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], "request": { "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_connect_manager_pshahcopmanag2}}", + "type": "text" } ], "body": { "mode": "raw", - "raw": "{\r\n \"status\": \"assigned\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\"\r\n}", "options": { "raw": { "language": "json" @@ -3736,32 +4207,48 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/requestInterview", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resourceBookingId}}" + "jobCandidates", + "{{jobCandidateId}}", + "requestInterview" ] } }, "response": [] }, { - "name": "patch resource booking with m2m update", + "name": "Request interview with connect user", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 401', function () {\r", + " pm.response.to.have.status(403);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], "request": { "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_m2m_update_resource_booking}}" + "value": "Bearer {{token_connectUser}}", + "type": "text" } ], "body": { "mode": "raw", - "raw": "{\r\n \"status\": \"assigned\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\"\r\n}", "options": { "raw": { "language": "json" @@ -3769,32 +4256,48 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingIdCreatedByM2M}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/requestInterview", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resourceBookingIdCreatedByM2M}}" + "jobCandidates", + "{{jobCandidateId}}", + "requestInterview" ] } }, "response": [] }, { - "name": "patch resource booking with connect user", + "name": "Request interview with member", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 401', function () {\r", + " pm.response.to.have.status(403);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], "request": { "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_connectUser}}" + "value": "Bearer {{token_member}}", + "type": "text" } ], "body": { "mode": "raw", - "raw": "{\r\n \"status\": \"assigned\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\"\r\n}", "options": { "raw": { "language": "json" @@ -3802,32 +4305,42 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/requestInterview", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resourceBookingId}}" + "jobCandidates", + "{{jobCandidateId}}", + "requestInterview" ] } }, "response": [] }, { - "name": "patch resource booking with member", + "name": "Request interview without token", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 401', function () {\r", + " pm.response.to.have.status(401);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"No token provided.\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], "request": { "method": "PATCH", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_member}}" - } - ], + "header": [], "body": { "mode": "raw", - "raw": "{\r\n \"status\": \"assigned\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\"\r\n}", "options": { "raw": { "language": "json" @@ -3835,32 +4348,48 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/requestInterview", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resourceBookingId}}" + "jobCandidates", + "{{jobCandidateId}}", + "requestInterview" ] } }, "response": [] }, { - "name": "patch resource booking with user id not exist", - "request": { - "method": "PATCH", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_userId_not_exist}}" + "name": "Request interview with invalid token", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 401', function () {\r", + " pm.response.to.have.status(401);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"Invalid Token.\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "value": "Bearer invalid_token", + "type": "text" } ], "body": { "mode": "raw", - "raw": "{\r\n \"status\": \"assigned\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\"\r\n}", "options": { "raw": { "language": "json" @@ -3868,337 +4397,274 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/requestInterview", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resourceBookingId}}" + "jobCandidates", + "{{jobCandidateId}}", + "requestInterview" ] } }, "response": [] }, { - "name": "patch resource booking with invalid token", + "name": "Get interview by round", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200)\r", + "});" + ], + "type": "text/javascript" + } + } + ], "request": { - "method": "PATCH", + "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer invalid_token" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], - "body": { - "mode": "raw", - "raw": "{\r\n \"status\": \"assigned\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/interviews/{{interviewRound}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resourceBookingId}}" + "jobCandidates", + "{{jobCandidateId}}", + "interviews", + "{{interviewRound}}" ] } }, "response": [] }, { - "name": "delete resource booking with member", + "name": "Get interview fromDb by round", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200)\r", + "});" + ], + "type": "text/javascript" + } + } + ], "request": { - "method": "DELETE", + "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_member}}" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/interviews/{{interviewRound}}?fromDb=true", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resourceBookingId}}" + "jobCandidates", + "{{jobCandidateId}}", + "interviews", + "{{interviewRound}}" + ], + "query": [ + { + "key": "fromDb", + "value": "true" + } ] } }, "response": [] }, { - "name": "delete resource booking with connect user", + "name": "Get interview by negative round", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"\\\"round\\\" must be a positive number\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], "request": { - "method": "DELETE", + "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_connectUser}}" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/interviews/-1", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resourceBookingId}}" + "jobCandidates", + "{{jobCandidateId}}", + "interviews", + "-1" ] } }, "response": [] }, { - "name": "delete resource booking with booking manager", + "name": "Get interview by round=0", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"\\\"round\\\" must be a positive number\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], "request": { - "method": "DELETE", + "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/interviews/0", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resourceBookingId}}" + "jobCandidates", + "{{jobCandidateId}}", + "interviews", + "0" ] } }, "response": [] }, { - "name": "delete resource booking with m2m delete", + "name": "Get interview by non-existing round", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 404', function () {\r", + " pm.response.to.have.status(404);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"Interview doesn't exist with round: 999\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], "request": { - "method": "DELETE", + "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_m2m_delete_resource_booking}}" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingIdCreatedByM2M}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/interviews/999", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resourceBookingIdCreatedByM2M}}" + "jobCandidates", + "{{jobCandidateId}}", + "interviews", + "999" ] } }, "response": [] }, { - "name": "delete resource booking with invalid token", + "name": "Get interview with administrator", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", + "});" + ], + "type": "text/javascript" + } + } + ], "request": { - "method": "DELETE", + "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer invalid_token" + "value": "Bearer {{token_administrator}}", + "type": "text" } ], - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/interviews/{{interviewRound}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resourceBookingId}}" + "jobCandidates", + "{{jobCandidateId}}", + "interviews", + "{{interviewRound}}" ] } }, "response": [] - } - ] - }, - { - "name": "Work Periods", - "item": [ + }, { - "name": "Before Test", - "item": [ - { - "name": "create job", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test('Status code is 200', function () {\r", - " pm.response.to.have.status(200);\r", - " if(pm.response.status === \"OK\"){\r", - " const response = pm.response.json()\r", - " pm.environment.set(\"jobId\", response.id);\r", - " }\r", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "value": "Bearer {{token_bookingManager}}", - "type": "text" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"projectId\": {{projectId}},\n \"externalId\": \"1212\",\n \"description\": \"Dummy Description\",\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\n \"duration\": 1,\n \"numPositions\": 13,\n \"resourceType\": \"Dummy Resource Type\",\n \"rateType\": \"hourly\",\n \"workload\": \"full-time\",\n \"skills\": [\n \"23e00d92-207a-4b5b-b3c9-4c5662644941\",\n \"7d076384-ccf6-4e43-a45d-1b24b1e624aa\",\n \"cbac57a3-7180-4316-8769-73af64893158\",\n \"a2b4bc11-c641-4a19-9eb7-33980378f82e\"\n ],\n \"title\": \"Dummy title - at most 64 characters\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{URL}}/jobs", - "host": [ - "{{URL}}" - ], - "path": [ - "jobs" - ] - } - }, - "response": [] - }, - { - "name": "create resource booking", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test('Status code is 200', function () {\r", - " pm.response.to.have.status(200);\r", - " if(pm.response.status === \"OK\"){\r", - " const response = pm.response.json()\r", - " pm.environment.set(\"resourceBookingId\", response.id);\r", - " }\r", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{jobId}}\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{URL}}/resourceBookings", - "host": [ - "{{URL}}" - ], - "path": [ - "resourceBookings" - ] - } - }, - "response": [] - } - ] - }, - { - "name": "create work period with booking manager", - "event": [ + "name": "Get interview with booking manager", + "event": [ { "listen": "test", "script": { "exec": [ "pm.test('Status code is 200', function () {\r", " pm.response.to.have.status(200);\r", - " if(pm.response.status === \"OK\"){\r", - " const response = pm.response.json()\r", - " pm.environment.set(\"workPeriodId\", response.id);\r", - " }\r", "});" ], "type": "text/javascript" @@ -4206,37 +4672,31 @@ } ], "request": { - "method": "POST", + "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], - "body": { - "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/workPeriods", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/interviews/{{interviewRound}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods" + "jobCandidates", + "{{jobCandidateId}}", + "interviews", + "{{interviewRound}}" ] } }, "response": [] }, { - "name": "create work period with m2m create", + "name": "Get interview with m2m (all interview scope)", "event": [ { "listen": "test", @@ -4244,10 +4704,6 @@ "exec": [ "pm.test('Status code is 200', function () {\r", " pm.response.to.have.status(200);\r", - " if(pm.response.status === \"OK\"){\r", - " const response = pm.response.json()\r", - " pm.environment.set(\"workPeriodIdCreatedByM2M\", response.id);\r", - " }\r", "});" ], "type": "text/javascript" @@ -4255,46 +4711,38 @@ } ], "request": { - "method": "POST", + "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_m2m_create_work_period}}" + "value": "Bearer {{token_m2m_all_interviews}}", + "type": "text" } ], - "body": { - "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-14\",\r\n \"endDate\": \"2021-03-20\",\r\n \"daysWorked\": 3,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"cancelled\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/workPeriods", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/interviews/{{interviewRound}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods" + "jobCandidates", + "{{jobCandidateId}}", + "interviews", + "{{interviewRound}}" ] } }, "response": [] }, { - "name": "create work period with connect user", + "name": "Get interview with m2m (read interview scope)", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 403', function () {\r", - " pm.response.to.have.status(403);\r", - " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", "});" ], "type": "text/javascript" @@ -4302,43 +4750,37 @@ } ], "request": { - "method": "POST", + "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_connectUser}}" + "value": "Bearer {{token_m2m_read_interviews}}", + "type": "text" } ], - "body": { - "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-21\",\r\n \"endDate\": \"2021-03-27\",\r\n \"daysWorked\": 3,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"cancelled\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/workPeriods", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/interviews/{{interviewRound}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods" + "jobCandidates", + "{{jobCandidateId}}", + "interviews", + "{{interviewRound}}" ] } }, "response": [] }, { - "name": "create work period with member", + "name": "Get interview with m2m (create interview scope) - should fail", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 403', function () {\r", + "pm.test('Status code is 404', function () {\r", " pm.response.to.have.status(403);\r", " const response = pm.response.json()\r", " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", @@ -4349,46 +4791,40 @@ } ], "request": { - "method": "POST", + "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_member}}" + "value": "Bearer {{token_m2m_create_interviews}}", + "type": "text" } ], - "body": { - "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-21\",\r\n \"endDate\": \"2021-03-27\",\r\n \"daysWorked\": 3,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"cancelled\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/workPeriods", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/interviews/{{interviewRound}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods" + "jobCandidates", + "{{jobCandidateId}}", + "interviews", + "{{interviewRound}}" ] } }, "response": [] }, { - "name": "create work period with user id not exist", + "name": "Get interview with m2m (update interview scope) - should fail", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 400', function () {\r", - " pm.response.to.have.status(400);\r", + "pm.test('Status code is 404', function () {\r", + " pm.response.to.have.status(403);\r", " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"Bad Request\")\r", + " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", "});" ], "type": "text/javascript" @@ -4396,46 +4832,40 @@ } ], "request": { - "method": "POST", + "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_userId_not_exist}}" + "value": "Bearer {{token_m2m_update_interviews}}", + "type": "text" } ], - "body": { - "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-21\",\r\n \"endDate\": \"2021-03-27\",\r\n \"daysWorked\": 3,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"cancelled\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/workPeriods", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/interviews/{{interviewRound}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods" + "jobCandidates", + "{{jobCandidateId}}", + "interviews", + "{{interviewRound}}" ] } }, "response": [] }, { - "name": "create work period with invalid token", + "name": "Get interview with connect manager", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 401', function () {\r", - " pm.response.to.have.status(401);\r", + "pm.test('Status code is 403', function () {\r", + " pm.response.to.have.status(403);\r", " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"Invalid Token.\")\r", + " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", "});" ], "type": "text/javascript" @@ -4443,46 +4873,40 @@ } ], "request": { - "method": "POST", + "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer invalid_token" + "value": "Bearer {{token_connect_manager_pshahcopmanag2}}", + "type": "text" } ], - "body": { - "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-21\",\r\n \"endDate\": \"2021-03-27\",\r\n \"daysWorked\": 3,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"cancelled\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/workPeriods", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/interviews/{{interviewRound}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods" + "jobCandidates", + "{{jobCandidateId}}", + "interviews", + "{{interviewRound}}" ] } }, "response": [] }, { - "name": "create work period with missing parameter 1", + "name": "Get interview with connect user", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 400', function () {\r", - " pm.response.to.have.status(400);\r", + "pm.test('Status code is 403', function () {\r", + " pm.response.to.have.status(403);\r", " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"\\\"workPeriod.resourceBookingId\\\" is required\")\r", + " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", "});" ], "type": "text/javascript" @@ -4490,46 +4914,40 @@ } ], "request": { - "method": "POST", + "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_connectUser}}", + "type": "text" } ], - "body": { - "mode": "raw", - "raw": "{\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/workPeriods", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/interviews/{{interviewRound}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods" + "jobCandidates", + "{{jobCandidateId}}", + "interviews", + "{{interviewRound}}" ] } }, "response": [] }, { - "name": "create work period with missing parameter 2", + "name": "Get interview with member", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 400', function () {\r", - " pm.response.to.have.status(400);\r", + "pm.test('Status code is 403', function () {\r", + " pm.response.to.have.status(403);\r", " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"\\\"workPeriod.endDate\\\" is required\")\r", + " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", "});" ], "type": "text/javascript" @@ -4537,46 +4955,40 @@ } ], "request": { - "method": "POST", + "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_member}}", + "type": "text" } ], - "body": { - "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/workPeriods", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/interviews/{{interviewRound}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods" + "jobCandidates", + "{{jobCandidateId}}", + "interviews", + "{{interviewRound}}" ] } }, "response": [] }, { - "name": "create work period with missing parameter 3", + "name": "Get interview by round without token", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 400', function () {\r", - " pm.response.to.have.status(400);\r", + "pm.test('Status code is 401', function () {\r", + " pm.response.to.have.status(401);\r", " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"\\\"workPeriod.paymentStatus\\\" is required\")\r", + " pm.expect(response.message).to.eq(\"No token provided.\")\r", "});" ], "type": "text/javascript" @@ -4584,46 +4996,34 @@ } ], "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, + "method": "GET", + "header": [], "url": { - "raw": "{{URL}}/workPeriods", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/interviews/1", "host": [ "{{URL}}" ], "path": [ - "workPeriods" + "jobCandidates", + "{{jobCandidateId}}", + "interviews", + "1" ] } }, "response": [] }, { - "name": "create work period with invalid parameter 1", + "name": "Get interview by round with invalid token", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 400', function () {\r", - " pm.response.to.have.status(400);\r", + "pm.test('Status code is 401', function () {\r", + " pm.response.to.have.status(401);\r", " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"\\\"workPeriod.resourceBookingId\\\" must be a valid GUID\")\r", + " pm.expect(response.message).to.eq(\"Invalid Token.\")\r", "});" ], "type": "text/javascript" @@ -4631,46 +5031,38 @@ } ], "request": { - "method": "POST", + "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer invalid_token", + "type": "text" } ], - "body": { - "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"aaa-aaa\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/workPeriods", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/interviews/1", "host": [ "{{URL}}" ], "path": [ - "workPeriods" + "jobCandidates", + "{{jobCandidateId}}", + "interviews", + "1" ] } }, "response": [] }, { - "name": "create work period with invalid parameter 2", + "name": "Update interview", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 400', function () {\r", - " pm.response.to.have.status(400);\r", - " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"\\\"workPeriod.startDate\\\" must be in YYYY-MM-DD format\")\r", + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200)\r", "});" ], "type": "text/javascript" @@ -4678,17 +5070,17 @@ } ], "request": { - "method": "POST", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], "body": { "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"07-03-2021\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "raw": "{\r\n \"googleCalendarId\": \"dummyIdXX\",\r\n \"customMessage\": \"This is the updated message\"\r\n}", "options": { "raw": { "language": "json" @@ -4696,19 +5088,22 @@ } }, "url": { - "raw": "{{URL}}/workPeriods", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/updateInterview/{{interviewRound}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods" + "jobCandidates", + "{{jobCandidateId}}", + "updateInterview", + "{{interviewRound}}" ] } }, "response": [] }, { - "name": "create work period with invalid parameter 3", + "name": "Update interview with empty payload", "event": [ { "listen": "test", @@ -4717,7 +5112,7 @@ "pm.test('Status code is 400', function () {\r", " pm.response.to.have.status(400);\r", " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"startDate should be always Sunday\")\r", + " pm.expect(response.message).to.eq(\"\\\"data\\\" must have at least 1 key\")\r", "});" ], "type": "text/javascript" @@ -4725,17 +5120,17 @@ } ], "request": { - "method": "POST", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], "body": { "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-06\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "raw": "{}", "options": { "raw": { "language": "json" @@ -4743,19 +5138,22 @@ } }, "url": { - "raw": "{{URL}}/workPeriods", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/updateInterview/{{interviewRound}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods" + "jobCandidates", + "{{jobCandidateId}}", + "updateInterview", + "{{interviewRound}}" ] } }, "response": [] }, { - "name": "create work period with invalid parameter 4", + "name": "Update interview with invalid startTimestamp", "event": [ { "listen": "test", @@ -4764,7 +5162,7 @@ "pm.test('Status code is 400', function () {\r", " pm.response.to.have.status(400);\r", " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"endDate should be always the next Saturday\")\r", + " pm.expect(response.message).to.eq(\"\\\"data.startTimestamp\\\" must be a valid date\")\r", "});" ], "type": "text/javascript" @@ -4772,17 +5170,17 @@ } ], "request": { - "method": "POST", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], "body": { "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-14\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "raw": "{\r\n \"startTimestamp\": \"xxx\"\r\n}", "options": { "raw": { "language": "json" @@ -4790,19 +5188,22 @@ } }, "url": { - "raw": "{{URL}}/workPeriods", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/updateInterview/{{interviewRound}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods" + "jobCandidates", + "{{jobCandidateId}}", + "updateInterview", + "{{interviewRound}}" ] } }, "response": [] }, { - "name": "create work period with invalid parameter 5", + "name": "Update interview with past startTimestamp", "event": [ { "listen": "test", @@ -4811,7 +5212,7 @@ "pm.test('Status code is 400', function () {\r", " pm.response.to.have.status(400);\r", " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"\\\"workPeriod.daysWorked\\\" must be a number\")\r", + " pm.expect(response.message).to.eq(\"\\\"data.startTimestamp\\\" must be greater than \\\"now\\\"\")\r", "});" ], "type": "text/javascript" @@ -4819,17 +5220,17 @@ } ], "request": { - "method": "POST", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], "body": { "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": \"aa\",\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "raw": "{\r\n \"startTimestamp\": \"2021-04-01\"\r\n}", "options": { "raw": { "language": "json" @@ -4837,19 +5238,22 @@ } }, "url": { - "raw": "{{URL}}/workPeriods", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/updateInterview/{{interviewRound}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods" + "jobCandidates", + "{{jobCandidateId}}", + "updateInterview", + "{{interviewRound}}" ] } }, "response": [] }, { - "name": "create work period with invalid parameter 6", + "name": "Update interview with invalid status", "event": [ { "listen": "test", @@ -4858,7 +5262,7 @@ "pm.test('Status code is 400', function () {\r", " pm.response.to.have.status(400);\r", " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(`Key (resource_booking_id, start_date, end_date)=(${pm.environment.get('resourceBookingId')}, 2021-03-07, 2021-03-13) already exists.`)\r", + " pm.expect(response.message).to.eq(\"\\\"data.status\\\" must be one of [Scheduling, Scheduled, Requested for reschedule, Rescheduled, Completed, Cancelled]\")\r", "});" ], "type": "text/javascript" @@ -4866,17 +5270,17 @@ } ], "request": { - "method": "POST", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], "body": { "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "raw": "{\r\n \"status\": \"xxx\"\r\n}", "options": { "raw": { "language": "json" @@ -4884,19 +5288,22 @@ } }, "url": { - "raw": "{{URL}}/workPeriods", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/updateInterview/{{interviewRound}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods" + "jobCandidates", + "{{jobCandidateId}}", + "updateInterview", + "{{interviewRound}}" ] } }, "response": [] }, { - "name": "create work period with invalid parameter 7", + "name": "Update interview with invalid xaiTemplate", "event": [ { "listen": "test", @@ -4905,7 +5312,7 @@ "pm.test('Status code is 400', function () {\r", " pm.response.to.have.status(400);\r", " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"\\\"workPeriod.paymentStatus\\\" must be one of [pending, partially-completed, completed, cancelled]\")\r", + " pm.expect(response.message).to.eq(\"\\\"data.xaiTemplate\\\" must be one of [30-min-interview, 60-min-interview]\")\r", "});" ], "type": "text/javascript" @@ -4913,17 +5320,17 @@ } ], "request": { - "method": "POST", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], "body": { "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"paid\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"xxx\"\r\n}", "options": { "raw": { "language": "json" @@ -4931,26 +5338,31 @@ } }, "url": { - "raw": "{{URL}}/workPeriods", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/updateInterview/{{interviewRound}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods" + "jobCandidates", + "{{jobCandidateId}}", + "updateInterview", + "{{interviewRound}}" ] } }, "response": [] }, { - "name": "get work period with booking manager", + "name": "Update interview status to Scheduled without googleCalendarId", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 200', function () {\r", - " pm.response.to.have.status(200);\r", + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"\\\"data.googleCalendarId\\\" is required\")\r", "});" ], "type": "text/javascript" @@ -4958,36 +5370,49 @@ } ], "request": { - "method": "GET", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], + "body": { + "mode": "raw", + "raw": "{\r\n \"startTimestamp\": \"2030-12-12\",\r\n \"status\": \"Scheduled\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/updateInterview/{{interviewRound}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId}}" + "jobCandidates", + "{{jobCandidateId}}", + "updateInterview", + "{{interviewRound}}" ] } }, "response": [] }, { - "name": "get work period with m2m read", + "name": "Update interview status to Scheduled without startTimestamp", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 200', function () {\r", - " pm.response.to.have.status(200);\r", + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"\\\"data.startTimestamp\\\" is required\")\r", "});" ], "type": "text/javascript" @@ -4995,36 +5420,49 @@ } ], "request": { - "method": "GET", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_m2m_read_work_period}}" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], + "body": { + "mode": "raw", + "raw": "{\r\n \"googleCalendarId\": \"sdsds\",\r\n \"status\": \"Scheduled\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodIdCreatedByM2M}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/updateInterview/{{interviewRound}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodIdCreatedByM2M}}" + "jobCandidates", + "{{jobCandidateId}}", + "updateInterview", + "{{interviewRound}}" ] } }, "response": [] }, { - "name": "get work period with booking manager from db", + "name": "Update interview status to Rescheduled without googleCalendarId", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 200', function () {\r", - " pm.response.to.have.status(200);\r", + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"\\\"data.googleCalendarId\\\" is required\")\r", "});" ], "type": "text/javascript" @@ -5032,42 +5470,49 @@ } ], "request": { - "method": "GET", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], + "body": { + "mode": "raw", + "raw": "{\r\n \"startTimestamp\": \"2030-12-12\",\r\n \"status\": \"Rescheduled\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId}}?fromDb=true", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/updateInterview/{{interviewRound}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId}}" - ], - "query": [ - { - "key": "fromDb", - "value": "true" - } + "jobCandidates", + "{{jobCandidateId}}", + "updateInterview", + "{{interviewRound}}" ] } }, "response": [] }, { - "name": "get work period with connect user", + "name": "Update interview status to Rescheduled without startTimestamp", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 200', function () {\r", - " pm.response.to.have.status(200);\r", + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"\\\"data.startTimestamp\\\" is required\")\r", "});" ], "type": "text/javascript" @@ -5075,36 +5520,49 @@ } ], "request": { - "method": "GET", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_connectUser}}" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], + "body": { + "mode": "raw", + "raw": "{\r\n \"googleCalendarId\": \"sdsds\",\r\n \"status\": \"Rescheduled\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/updateInterview/{{interviewRound}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId}}" + "jobCandidates", + "{{jobCandidateId}}", + "updateInterview", + "{{interviewRound}}" ] } }, "response": [] }, { - "name": "get work period with member", + "name": "Update Completed interview without status", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 401', function () {\r", - " pm.response.to.have.status(401);\r", + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"Only the \\\"status\\\" can be updated for Completed interviews.\")\r", "});" ], "type": "text/javascript" @@ -5112,36 +5570,49 @@ } ], "request": { - "method": "GET", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_member}}" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], + "body": { + "mode": "raw", + "raw": "{\r\n \"googleCalendarId\": \"sdsds\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "raw": "{{URL}}/jobCandidates/{{completedInterviewJobCandidateId}}/updateInterview/{{completedInterviewRound}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId}}" + "jobCandidates", + "{{completedInterviewJobCandidateId}}", + "updateInterview", + "{{completedInterviewRound}}" ] } }, "response": [] }, { - "name": "search work periods with booking manager", + "name": "Update Completed interview with additional fields", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 200', function () {\r", - " pm.response.to.have.status(200);\r", + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"Only the \\\"status\\\" can be updated for Completed interviews.\")\r", "});" ], "type": "text/javascript" @@ -5149,85 +5620,40 @@ } ], "request": { - "method": "GET", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], + "body": { + "mode": "raw", + "raw": "{\r\n \"googleCalendarId\": \"sdsds\",\r\n \"status\": \"Scheduling\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { - "raw": "{{URL}}/workPeriods", + "raw": "{{URL}}/jobCandidates/{{completedInterviewJobCandidateId}}/updateInterview/{{completedInterviewRound}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods" - ], - "query": [ - { - "key": "page", - "value": "1", - "disabled": true - }, - { - "key": "perPage", - "value": "5", - "disabled": true - }, - { - "key": "sortBy", - "value": "id", - "disabled": true - }, - { - "key": "sortOrder", - "value": "desc", - "disabled": true - }, - { - "key": "resourceBookingId", - "value": "{{resourceBookingId}}", - "disabled": true - }, - { - "key": "resourceBookingIds", - "value": "{{resourceBookingId}},{{resourceBookingIdCreatedByM2M}}", - "disabled": true - }, - { - "key": "paymentStatus", - "value": "pending", - "disabled": true - }, - { - "key": "startDate", - "value": "2021-03-14", - "disabled": true - }, - { - "key": "endDate", - "value": "2021-03-20", - "disabled": true - }, - { - "key": "userHandle", - "value": "pshah_manager", - "disabled": true - }, - { - "key": "projectId", - "value": "16843", - "disabled": true - } + "jobCandidates", + "{{completedInterviewJobCandidateId}}", + "updateInterview", + "{{completedInterviewRound}}" ] } }, "response": [] }, { - "name": "search work periods with m2m all", + "name": "Update Completed interview with only status", "event": [ { "listen": "test", @@ -5235,6 +5661,8 @@ "exec": [ "pm.test('Status code is 200', function () {\r", " pm.response.to.have.status(200);\r", + " const response = pm.response.json()\r", + " pm.expect(response.status).to.eq(\"Scheduling\")\r", "});" ], "type": "text/javascript" @@ -5242,85 +5670,40 @@ } ], "request": { - "method": "GET", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_m2m_all_work_period}}" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], + "body": { + "mode": "raw", + "raw": "{\r\n \"status\": \"Scheduling\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { - "raw": "{{URL}}/workPeriods", + "raw": "{{URL}}/jobCandidates/{{completedInterviewJobCandidateId}}/updateInterview/{{completedInterviewRound}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods" - ], - "query": [ - { - "key": "page", - "value": "1", - "disabled": true - }, - { - "key": "perPage", - "value": "5", - "disabled": true - }, - { - "key": "sortBy", - "value": "id", - "disabled": true - }, - { - "key": "sortOrder", - "value": "desc", - "disabled": true - }, - { - "key": "resourceBookingId", - "value": "{{resourceBookingId}}", - "disabled": true - }, - { - "key": "resourceBookingIds", - "value": "{{resourceBookingId}},{{resourceBookingIdCreatedByM2M}}", - "disabled": true - }, - { - "key": "paymentStatus", - "value": "pending", - "disabled": true - }, - { - "key": "startDate", - "value": "2021-03-14", - "disabled": true - }, - { - "key": "endDate", - "value": "2021-03-20", - "disabled": true - }, - { - "key": "userHandle", - "value": "pshah_manager", - "disabled": true - }, - { - "key": "projectId", - "value": "16843", - "disabled": true - } + "jobCandidates", + "{{completedInterviewJobCandidateId}}", + "updateInterview", + "{{completedInterviewRound}}" ] } }, "response": [] }, { - "name": "search work periods with connect user", + "name": "Update interview with booking manager", "event": [ { "listen": "test", @@ -5335,172 +5718,47 @@ } ], "request": { - "method": "GET", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_connectUser}}" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], + "body": { + "mode": "raw", + "raw": "{\r\n \"customMessage\": \"sdsds\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { - "raw": "{{URL}}/workPeriods", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/updateInterview/{{interviewRound}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods" - ], - "query": [ - { - "key": "page", - "value": "1", - "disabled": true - }, - { - "key": "perPage", - "value": "5", - "disabled": true - }, - { - "key": "sortBy", - "value": "id", - "disabled": true - }, - { - "key": "sortOrder", - "value": "desc", - "disabled": true - }, - { - "key": "resourceBookingId", - "value": "{{resourceBookingId}}", - "disabled": true - }, - { - "key": "resourceBookingIds", - "value": "{{resourceBookingId}},{{resourceBookingIdCreatedByM2M}}", - "disabled": true - }, - { - "key": "paymentStatus", - "value": "pending", - "disabled": true - }, - { - "key": "startDate", - "value": "2021-03-14", - "disabled": true - }, - { - "key": "endDate", - "value": "2021-03-20", - "disabled": true - }, - { - "key": "userHandle", - "value": "pshah_manager", - "disabled": true - }, - { - "key": "projectId", - "value": "16843", - "disabled": true - } + "jobCandidates", + "{{jobCandidateId}}", + "updateInterview", + "{{interviewRound}}" ] } }, "response": [] }, { - "name": "search work periods with member", - "request": { - "method": "GET", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_member}}" - } - ], - "url": { - "raw": "{{URL}}/workPeriods", - "host": [ - "{{URL}}" - ], - "path": [ - "workPeriods" - ], - "query": [ - { - "key": "page", - "value": "1", - "disabled": true - }, - { - "key": "perPage", - "value": "5", - "disabled": true - }, - { - "key": "sortBy", - "value": "id", - "disabled": true - }, - { - "key": "sortOrder", - "value": "desc", - "disabled": true - }, - { - "key": "resourceBookingId", - "value": "{{resourceBookingId}}", - "disabled": true - }, - { - "key": "resourceBookingIds", - "value": "{{resourceBookingId}},{{resourceBookingIdCreatedByM2M}}", - "disabled": true - }, - { - "key": "paymentStatus", - "value": "pending", - "disabled": true - }, - { - "key": "startDate", - "value": "2021-03-14", - "disabled": true - }, - { - "key": "endDate", - "value": "2021-03-20", - "disabled": true - }, - { - "key": "userHandle", - "value": "pshah_manager", - "disabled": true - }, - { - "key": "projectId", - "value": "16843", - "disabled": true - } - ] - } - }, - "response": [] - }, - { - "name": "search work periods with invalid token", + "name": "Update interview with administrator", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 401', function () {\r", - " pm.response.to.have.status(401);\r", + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", "});" ], "type": "text/javascript" @@ -5508,85 +5766,40 @@ } ], "request": { - "method": "GET", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer invalid_token" + "value": "Bearer {{token_administrator}}", + "type": "text" } ], + "body": { + "mode": "raw", + "raw": "{\r\n \"customMessage\": \"sdsds\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { - "raw": "{{URL}}/workPeriods", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/updateInterview/{{interviewRound}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods" - ], - "query": [ - { - "key": "page", - "value": "1", - "disabled": true - }, - { - "key": "perPage", - "value": "5", - "disabled": true - }, - { - "key": "sortBy", - "value": "id", - "disabled": true - }, - { - "key": "sortOrder", - "value": "desc", - "disabled": true - }, - { - "key": "resourceBookingId", - "value": "{{resourceBookingId}}", - "disabled": true - }, - { - "key": "resourceBookingIds", - "value": "{{resourceBookingId}},{{resourceBookingIdCreatedByM2M}}", - "disabled": true - }, - { - "key": "paymentStatus", - "value": "pending", - "disabled": true - }, - { - "key": "startDate", - "value": "2021-03-14", - "disabled": true - }, - { - "key": "endDate", - "value": "2021-03-20", - "disabled": true - }, - { - "key": "userHandle", - "value": "pshah_manager", - "disabled": true - }, - { - "key": "projectId", - "value": "111", - "disabled": true - } + "jobCandidates", + "{{jobCandidateId}}", + "updateInterview", + "{{interviewRound}}" ] } }, "response": [] }, { - "name": "put work period with booking manager", + "name": "Update interview with m2m (all interview scope)", "event": [ { "listen": "test", @@ -5601,17 +5814,17 @@ } ], "request": { - "method": "PUT", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_m2m_all_interviews}}", + "type": "text" } ], "body": { "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "raw": "{\r\n \"customMessage\": \"sdsds\"\r\n}", "options": { "raw": { "language": "json" @@ -5619,20 +5832,22 @@ } }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/updateInterview/{{interviewRound}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId}}" + "jobCandidates", + "{{jobCandidateId}}", + "updateInterview", + "{{interviewRound}}" ] } }, "response": [] }, { - "name": "put work period with m2m update", + "name": "Update interview with m2m (update interview scope)", "event": [ { "listen": "test", @@ -5647,17 +5862,17 @@ } ], "request": { - "method": "PUT", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_m2m_update_work_period}}" + "value": "Bearer {{token_m2m_update_interviews}}", + "type": "text" } ], "body": { "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-14\",\r\n \"endDate\": \"2021-03-20\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "raw": "{\r\n \"customMessage\": \"sdsds\"\r\n}", "options": { "raw": { "language": "json" @@ -5665,20 +5880,22 @@ } }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodIdCreatedByM2M}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/updateInterview/{{interviewRound}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodIdCreatedByM2M}}" + "jobCandidates", + "{{jobCandidateId}}", + "updateInterview", + "{{interviewRound}}" ] } }, "response": [] }, { - "name": "put work period with connect user", + "name": "Update interview with m2m (read interview scope) - should fail", "event": [ { "listen": "test", @@ -5695,17 +5912,17 @@ } ], "request": { - "method": "PUT", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_connectUser}}" + "value": "Bearer {{token_m2m_read_interviews}}", + "type": "text" } ], "body": { "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-21\",\r\n \"endDate\": \"2021-03-27\",\r\n \"daysWorked\": 3,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"cancelled\"\r\n}", + "raw": "{\r\n \"customMessage\": \"sdsds\"\r\n}", "options": { "raw": { "language": "json" @@ -5713,20 +5930,22 @@ } }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/updateInterview/{{interviewRound}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId}}" + "jobCandidates", + "{{jobCandidateId}}", + "updateInterview", + "{{interviewRound}}" ] } }, "response": [] }, { - "name": "put work period with member", + "name": "Update interview with m2m (create interview scope) - should fail", "event": [ { "listen": "test", @@ -5743,17 +5962,17 @@ } ], "request": { - "method": "PUT", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_member}}" + "value": "Bearer {{token_m2m_create_interviews}}", + "type": "text" } ], "body": { "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-21\",\r\n \"endDate\": \"2021-03-27\",\r\n \"daysWorked\": 3,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"cancelled\"\r\n}", + "raw": "{\r\n \"customMessage\": \"sdsds\"\r\n}", "options": { "raw": { "language": "json" @@ -5761,29 +5980,31 @@ } }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/updateInterview/{{interviewRound}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId}}" + "jobCandidates", + "{{jobCandidateId}}", + "updateInterview", + "{{interviewRound}}" ] } }, "response": [] }, { - "name": "put work period with user id not exist", + "name": "Update interview with connect manager", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 400', function () {\r", - " pm.response.to.have.status(400);\r", + "pm.test('Status code is 403', function () {\r", + " pm.response.to.have.status(403);\r", " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"Bad Request\")\r", + " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", "});" ], "type": "text/javascript" @@ -5791,17 +6012,17 @@ } ], "request": { - "method": "PUT", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_userId_not_exist}}" + "value": "Bearer {{token_connect_manager_pshahcopmanag2}}", + "type": "text" } ], "body": { "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-21\",\r\n \"endDate\": \"2021-03-27\",\r\n \"daysWorked\": 3,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"cancelled\"\r\n}", + "raw": "{\r\n \"customMessage\": \"sdsds\"\r\n}", "options": { "raw": { "language": "json" @@ -5809,29 +6030,31 @@ } }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/updateInterview/{{interviewRound}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId}}" + "jobCandidates", + "{{jobCandidateId}}", + "updateInterview", + "{{interviewRound}}" ] } }, "response": [] }, { - "name": "put work period with invalid token", + "name": "Update interview with connect user", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 401', function () {\r", - " pm.response.to.have.status(401);\r", + "pm.test('Status code is 403', function () {\r", + " pm.response.to.have.status(403);\r", " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"Invalid Token.\")\r", + " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", "});" ], "type": "text/javascript" @@ -5839,17 +6062,17 @@ } ], "request": { - "method": "PUT", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer invalid_token" + "value": "Bearer {{token_connectUser}}", + "type": "text" } ], "body": { "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-21\",\r\n \"endDate\": \"2021-03-27\",\r\n \"daysWorked\": 3,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"cancelled\"\r\n}", + "raw": "{\r\n \"customMessage\": \"sdsds\"\r\n}", "options": { "raw": { "language": "json" @@ -5857,29 +6080,31 @@ } }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/updateInterview/{{interviewRound}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId}}" + "jobCandidates", + "{{jobCandidateId}}", + "updateInterview", + "{{interviewRound}}" ] } }, "response": [] }, { - "name": "put work period with missing parameter 1", + "name": "Update interview with member", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 400', function () {\r", - " pm.response.to.have.status(400);\r", + "pm.test('Status code is 403', function () {\r", + " pm.response.to.have.status(403);\r", " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"\\\"data.resourceBookingId\\\" is required\")\r", + " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", "});" ], "type": "text/javascript" @@ -5887,17 +6112,17 @@ } ], "request": { - "method": "PUT", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_member}}", + "type": "text" } ], "body": { "mode": "raw", - "raw": "{\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "raw": "{\r\n \"customMessage\": \"sdsds\"\r\n}", "options": { "raw": { "language": "json" @@ -5905,29 +6130,31 @@ } }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/updateInterview/{{interviewRound}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId}}" + "jobCandidates", + "{{jobCandidateId}}", + "updateInterview", + "{{interviewRound}}" ] } }, "response": [] }, { - "name": "put work period with missing parameter 2", + "name": "Update interview without token", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 400', function () {\r", - " pm.response.to.have.status(400);\r", + "pm.test('Status code is 401', function () {\r", + " pm.response.to.have.status(401);\r", " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"\\\"data.endDate\\\" is required\")\r", + " pm.expect(response.message).to.eq(\"No token provided.\")\r", "});" ], "type": "text/javascript" @@ -5935,17 +6162,11 @@ } ], "request": { - "method": "PUT", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } - ], + "method": "PATCH", + "header": [], "body": { "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "raw": "{\r\n \"customMessage\": \"sdsds\"\r\n}", "options": { "raw": { "language": "json" @@ -5953,29 +6174,31 @@ } }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/updateInterview/{{interviewRound}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId}}" + "jobCandidates", + "{{jobCandidateId}}", + "updateInterview", + "{{interviewRound}}" ] } }, "response": [] }, { - "name": "put work period with missing parameter 3", + "name": "Update interview with invalid token", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 400', function () {\r", - " pm.response.to.have.status(400);\r", + "pm.test('Status code is 401', function () {\r", + " pm.response.to.have.status(401);\r", " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"\\\"data.paymentStatus\\\" is required\")\r", + " pm.expect(response.message).to.eq(\"Invalid Token.\")\r", "});" ], "type": "text/javascript" @@ -5983,17 +6206,17 @@ } ], "request": { - "method": "PUT", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer invalid_key", + "type": "text" } ], "body": { "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13\r\n}", + "raw": "{\r\n \"customMessage\": \"sdsds\"\r\n}", "options": { "raw": { "language": "json" @@ -6001,29 +6224,29 @@ } }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/updateInterview/{{interviewRound}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId}}" + "jobCandidates", + "{{jobCandidateId}}", + "updateInterview", + "{{interviewRound}}" ] } }, "response": [] }, { - "name": "put work period with invalid parameter 1", + "name": "Search interviews", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 400', function () {\r", - " pm.response.to.have.status(400);\r", - " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"\\\"data.resourceBookingId\\\" must be a valid GUID\")\r", + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200)\r", "});" ], "type": "text/javascript" @@ -6031,38 +6254,57 @@ } ], "request": { - "method": "PUT", + "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], - "body": { - "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"aaa-aaa\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/interviews", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId}}" + "jobCandidates", + "{{jobCandidateId}}", + "interviews" + ], + "query": [ + { + "key": "sortBy", + "value": "createdAt", + "disabled": true + }, + { + "key": "sortOrder", + "value": "desc", + "disabled": true + }, + { + "key": "createdAt", + "value": "2021-04-13T20:28:37.954Z", + "disabled": true + }, + { + "key": "updatedAt", + "value": "2021-04-13T20:28:37.954Z", + "disabled": true + }, + { + "key": "status", + "value": "Scheduling", + "disabled": true + } ] } }, "response": [] }, { - "name": "put work period with invalid parameter 2", + "name": "Search interviews by invalid status", "event": [ { "listen": "test", @@ -6071,7 +6313,7 @@ "pm.test('Status code is 400', function () {\r", " pm.response.to.have.status(400);\r", " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"\\\"data.startDate\\\" must be in YYYY-MM-DD format\")\r", + " pm.expect(response.message).to.eq(\"\\\"criteria.status\\\" must be one of [Scheduling, Scheduled, Requested for reschedule, Rescheduled, Completed, Cancelled]\")\r", "});" ], "type": "text/javascript" @@ -6079,38 +6321,56 @@ } ], "request": { - "method": "PUT", + "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], - "body": { - "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"07-03-2021\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/interviews?status=xxx", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId}}" + "jobCandidates", + "{{jobCandidateId}}", + "interviews" + ], + "query": [ + { + "key": "sortBy", + "value": "createdAt", + "disabled": true + }, + { + "key": "sortOrder", + "value": "desc", + "disabled": true + }, + { + "key": "createdAt", + "value": "2021-04-13T20:28:37.954Z", + "disabled": true + }, + { + "key": "updatedAt", + "value": "2021-04-13T20:28:37.954Z", + "disabled": true + }, + { + "key": "status", + "value": "xxx" + } ] } }, "response": [] }, { - "name": "put work period with invalid parameter 3", + "name": "Search interviews by invalid createdAt", "event": [ { "listen": "test", @@ -6119,7 +6379,7 @@ "pm.test('Status code is 400', function () {\r", " pm.response.to.have.status(400);\r", " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"startDate should be always Sunday\")\r", + " pm.expect(response.message).to.eq(\"\\\"criteria.createdAt\\\" must be a valid date\")\r", "});" ], "type": "text/javascript" @@ -6127,38 +6387,56 @@ } ], "request": { - "method": "PUT", + "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], - "body": { - "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-06\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/interviews?createdAt=xxxx", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId}}" + "jobCandidates", + "{{jobCandidateId}}", + "interviews" + ], + "query": [ + { + "key": "sortBy", + "value": "createdAt", + "disabled": true + }, + { + "key": "sortOrder", + "value": "desc", + "disabled": true + }, + { + "key": "createdAt", + "value": "xxxx" + }, + { + "key": "updatedAt", + "value": "2021-04-13T20:28:37.954Z", + "disabled": true + }, + { + "key": "status", + "value": "Scheduling", + "disabled": true + } ] } }, "response": [] }, { - "name": "put work period with invalid parameter 4", + "name": "Search interviews by invalid updatedAt", "event": [ { "listen": "test", @@ -6167,7 +6445,7 @@ "pm.test('Status code is 400', function () {\r", " pm.response.to.have.status(400);\r", " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"endDate should be always the next Saturday\")\r", + " pm.expect(response.message).to.eq(\"\\\"criteria.updatedAt\\\" must be a valid date\")\r", "});" ], "type": "text/javascript" @@ -6175,38 +6453,56 @@ } ], "request": { - "method": "PUT", + "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], - "body": { - "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-14\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/interviews?updatedAt=xxx", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId}}" + "jobCandidates", + "{{jobCandidateId}}", + "interviews" + ], + "query": [ + { + "key": "sortBy", + "value": "createdAt", + "disabled": true + }, + { + "key": "sortOrder", + "value": "desc", + "disabled": true + }, + { + "key": "createdAt", + "value": "2021-04-13T20:28:37.954Z", + "disabled": true + }, + { + "key": "updatedAt", + "value": "xxx" + }, + { + "key": "status", + "value": "Scheduling", + "disabled": true + } ] } }, "response": [] }, { - "name": "put work period with invalid parameter 5", + "name": "Search interviews by invalid sortOrder", "event": [ { "listen": "test", @@ -6215,7 +6511,7 @@ "pm.test('Status code is 400', function () {\r", " pm.response.to.have.status(400);\r", " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"\\\"data.daysWorked\\\" must be a number\")\r", + " pm.expect(response.message).to.eq(\"\\\"criteria.sortOrder\\\" must be one of [desc, asc]\")\r", "});" ], "type": "text/javascript" @@ -6223,38 +6519,56 @@ } ], "request": { - "method": "PUT", + "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], - "body": { - "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": \"aa\",\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/interviews?sortOrder=xxx", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId}}" + "jobCandidates", + "{{jobCandidateId}}", + "interviews" + ], + "query": [ + { + "key": "sortBy", + "value": "createdAt", + "disabled": true + }, + { + "key": "sortOrder", + "value": "xxx" + }, + { + "key": "createdAt", + "value": "2021-04-13T20:28:37.954Z", + "disabled": true + }, + { + "key": "updatedAt", + "value": "2021-04-13T20:28:37.954Z", + "disabled": true + }, + { + "key": "status", + "value": "Scheduling", + "disabled": true + } ] } }, "response": [] }, { - "name": "put work period with invalid parameter 6", + "name": "Search interviews by invalid sortBy", "event": [ { "listen": "test", @@ -6263,7 +6577,7 @@ "pm.test('Status code is 400', function () {\r", " pm.response.to.have.status(400);\r", " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(`Key (resource_booking_id, start_date, end_date)=(${pm.environment.get('resourceBookingId')}, 2021-03-14, 2021-03-20) already exists.`)\r", + " pm.expect(response.message).to.eq(\"\\\"criteria.sortBy\\\" must be one of [round, createdAt, updatedAt]\")\r", "});" ], "type": "text/javascript" @@ -6271,47 +6585,63 @@ } ], "request": { - "method": "PUT", + "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], - "body": { - "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-14\",\r\n \"endDate\": \"2021-03-20\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/interviews?sortBy=xxx", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId}}" + "jobCandidates", + "{{jobCandidateId}}", + "interviews" + ], + "query": [ + { + "key": "sortBy", + "value": "xxx" + }, + { + "key": "sortOrder", + "value": "desc", + "disabled": true + }, + { + "key": "createdAt", + "value": "2021-04-13T20:28:37.954Z", + "disabled": true + }, + { + "key": "updatedAt", + "value": "2021-04-13T20:28:37.954Z", + "disabled": true + }, + { + "key": "status", + "value": "Scheduling", + "disabled": true + } ] } }, "response": [] }, { - "name": "put work period with invalid parameter 7", + "name": "Search interviews with administrator", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 400', function () {\r", - " pm.response.to.have.status(400);\r", - " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"\\\"data.paymentStatus\\\" must be one of [pending, partially-completed, completed, cancelled]\")\r", + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200)\r", "});" ], "type": "text/javascript" @@ -6319,45 +6649,64 @@ } ], "request": { - "method": "PUT", + "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_administrator}}", + "type": "text" } ], - "body": { - "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"paid\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/interviews", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId}}" + "jobCandidates", + "{{jobCandidateId}}", + "interviews" + ], + "query": [ + { + "key": "sortBy", + "value": "createdAt", + "disabled": true + }, + { + "key": "sortOrder", + "value": "desc", + "disabled": true + }, + { + "key": "createdAt", + "value": "2021-04-13T20:28:37.954Z", + "disabled": true + }, + { + "key": "updatedAt", + "value": "2021-04-13T20:28:37.954Z", + "disabled": true + }, + { + "key": "status", + "value": "Scheduling", + "disabled": true + } ] } }, "response": [] }, { - "name": "patch work period with booking manager", + "name": "Search interviews with booking manager", "event": [ { "listen": "test", "script": { "exec": [ "pm.test('Status code is 200', function () {\r", - " pm.response.to.have.status(200);\r", + " pm.response.to.have.status(200)\r", "});" ], "type": "text/javascript" @@ -6365,45 +6714,64 @@ } ], "request": { - "method": "PATCH", + "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], - "body": { - "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/interviews", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId}}" + "jobCandidates", + "{{jobCandidateId}}", + "interviews" + ], + "query": [ + { + "key": "sortBy", + "value": "createdAt", + "disabled": true + }, + { + "key": "sortOrder", + "value": "desc", + "disabled": true + }, + { + "key": "createdAt", + "value": "2021-04-13T20:28:37.954Z", + "disabled": true + }, + { + "key": "updatedAt", + "value": "2021-04-13T20:28:37.954Z", + "disabled": true + }, + { + "key": "status", + "value": "Scheduling", + "disabled": true + } ] } }, "response": [] }, { - "name": "patch work period with m2m update", + "name": "Search interviews with m2m (all interview scope)", "event": [ { "listen": "test", "script": { "exec": [ "pm.test('Status code is 200', function () {\r", - " pm.response.to.have.status(200);\r", + " pm.response.to.have.status(200)\r", "});" ], "type": "text/javascript" @@ -6411,47 +6779,64 @@ } ], "request": { - "method": "PATCH", + "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_m2m_update_work_period}}" + "value": "Bearer {{token_m2m_all_interviews}}", + "type": "text" } ], - "body": { - "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-14\",\r\n \"endDate\": \"2021-03-20\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodIdCreatedByM2M}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/interviews", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodIdCreatedByM2M}}" + "jobCandidates", + "{{jobCandidateId}}", + "interviews" + ], + "query": [ + { + "key": "sortBy", + "value": "createdAt", + "disabled": true + }, + { + "key": "sortOrder", + "value": "desc", + "disabled": true + }, + { + "key": "createdAt", + "value": "2021-04-13T20:28:37.954Z", + "disabled": true + }, + { + "key": "updatedAt", + "value": "2021-04-13T20:28:37.954Z", + "disabled": true + }, + { + "key": "status", + "value": "Scheduling", + "disabled": true + } ] } }, "response": [] }, { - "name": "patch work period with connect user", + "name": "Search interviews with m2m (read interview scope)", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 403', function () {\r", - " pm.response.to.have.status(403);\r", - " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200)\r", "});" ], "type": "text/javascript" @@ -6459,38 +6844,57 @@ } ], "request": { - "method": "PATCH", + "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_connectUser}}" + "value": "Bearer {{token_m2m_read_interviews}}", + "type": "text" } ], - "body": { - "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-21\",\r\n \"endDate\": \"2021-03-27\",\r\n \"daysWorked\": 3,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"cancelled\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/interviews", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId}}" + "jobCandidates", + "{{jobCandidateId}}", + "interviews" + ], + "query": [ + { + "key": "sortBy", + "value": "createdAt", + "disabled": true + }, + { + "key": "sortOrder", + "value": "desc", + "disabled": true + }, + { + "key": "createdAt", + "value": "2021-04-13T20:28:37.954Z", + "disabled": true + }, + { + "key": "updatedAt", + "value": "2021-04-13T20:28:37.954Z", + "disabled": true + }, + { + "key": "status", + "value": "Scheduling", + "disabled": true + } ] } }, "response": [] }, { - "name": "patch work period with member", + "name": "Search interviews with m2m (create interview scope) - should fail", "event": [ { "listen": "test", @@ -6507,47 +6911,66 @@ } ], "request": { - "method": "PATCH", + "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_member}}" + "value": "Bearer {{token_m2m_create_interviews}}", + "type": "text" } ], - "body": { - "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-21\",\r\n \"endDate\": \"2021-03-27\",\r\n \"daysWorked\": 3,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"cancelled\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/interviews", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId}}" + "jobCandidates", + "{{jobCandidateId}}", + "interviews" + ], + "query": [ + { + "key": "sortBy", + "value": "createdAt", + "disabled": true + }, + { + "key": "sortOrder", + "value": "desc", + "disabled": true + }, + { + "key": "createdAt", + "value": "2021-04-13T20:28:37.954Z", + "disabled": true + }, + { + "key": "updatedAt", + "value": "2021-04-13T20:28:37.954Z", + "disabled": true + }, + { + "key": "status", + "value": "Scheduling", + "disabled": true + } ] } }, "response": [] }, { - "name": "patch work period with user id not exist", + "name": "Search interviews with m2m (update interview scope) - should fail", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 400', function () {\r", - " pm.response.to.have.status(400);\r", + "pm.test('Status code is 403', function () {\r", + " pm.response.to.have.status(403);\r", " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"Bad Request\")\r", + " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", "});" ], "type": "text/javascript" @@ -6555,47 +6978,66 @@ } ], "request": { - "method": "PATCH", + "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_userId_not_exist}}" + "value": "Bearer {{token_m2m_update_interviews}}", + "type": "text" } ], - "body": { - "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-21\",\r\n \"endDate\": \"2021-03-27\",\r\n \"daysWorked\": 3,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"cancelled\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/interviews", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId}}" + "jobCandidates", + "{{jobCandidateId}}", + "interviews" + ], + "query": [ + { + "key": "sortBy", + "value": "createdAt", + "disabled": true + }, + { + "key": "sortOrder", + "value": "desc", + "disabled": true + }, + { + "key": "createdAt", + "value": "2021-04-13T20:28:37.954Z", + "disabled": true + }, + { + "key": "updatedAt", + "value": "2021-04-13T20:28:37.954Z", + "disabled": true + }, + { + "key": "status", + "value": "Scheduling", + "disabled": true + } ] } }, "response": [] }, { - "name": "patch work period with invalid token", + "name": "Search interviews with connect manager", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 401', function () {\r", - " pm.response.to.have.status(401);\r", + "pm.test('Status code is 403', function () {\r", + " pm.response.to.have.status(403);\r", " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"Invalid Token.\")\r", + " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", "});" ], "type": "text/javascript" @@ -6603,47 +7045,66 @@ } ], "request": { - "method": "PATCH", + "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer invalid_token" + "value": "Bearer {{token_connect_manager_pshahcopmanag2}}", + "type": "text" } ], - "body": { - "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-21\",\r\n \"endDate\": \"2021-03-27\",\r\n \"daysWorked\": 3,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"cancelled\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/interviews", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId}}" + "jobCandidates", + "{{jobCandidateId}}", + "interviews" + ], + "query": [ + { + "key": "sortBy", + "value": "createdAt", + "disabled": true + }, + { + "key": "sortOrder", + "value": "desc", + "disabled": true + }, + { + "key": "createdAt", + "value": "2021-04-13T20:28:37.954Z", + "disabled": true + }, + { + "key": "updatedAt", + "value": "2021-04-13T20:28:37.954Z", + "disabled": true + }, + { + "key": "status", + "value": "Scheduling", + "disabled": true + } ] } }, "response": [] }, { - "name": "patch work period with invalid parameter 1", + "name": "Search interviews with connect user", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 400', function () {\r", - " pm.response.to.have.status(400);\r", + "pm.test('Status code is 403', function () {\r", + " pm.response.to.have.status(403);\r", " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"\\\"data.resourceBookingId\\\" must be a valid GUID\")\r", + " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", "});" ], "type": "text/javascript" @@ -6651,47 +7112,66 @@ } ], "request": { - "method": "PATCH", + "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_connectUser}}", + "type": "text" } ], - "body": { - "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"aaa-aaa\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/interviews", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId}}" + "jobCandidates", + "{{jobCandidateId}}", + "interviews" + ], + "query": [ + { + "key": "sortBy", + "value": "createdAt", + "disabled": true + }, + { + "key": "sortOrder", + "value": "desc", + "disabled": true + }, + { + "key": "createdAt", + "value": "2021-04-13T20:28:37.954Z", + "disabled": true + }, + { + "key": "updatedAt", + "value": "2021-04-13T20:28:37.954Z", + "disabled": true + }, + { + "key": "status", + "value": "Scheduling", + "disabled": true + } ] } }, "response": [] }, { - "name": "patch work period with invalid parameter 2", + "name": "Search interviews with member", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 400', function () {\r", - " pm.response.to.have.status(400);\r", + "pm.test('Status code is 403', function () {\r", + " pm.response.to.have.status(403);\r", " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"\\\"data.startDate\\\" must be in YYYY-MM-DD format\")\r", + " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", "});" ], "type": "text/javascript" @@ -6699,47 +7179,66 @@ } ], "request": { - "method": "PATCH", + "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_member}}", + "type": "text" } ], - "body": { - "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"07-03-2021\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/interviews", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId}}" + "jobCandidates", + "{{jobCandidateId}}", + "interviews" + ], + "query": [ + { + "key": "sortBy", + "value": "createdAt", + "disabled": true + }, + { + "key": "sortOrder", + "value": "desc", + "disabled": true + }, + { + "key": "createdAt", + "value": "2021-04-13T20:28:37.954Z", + "disabled": true + }, + { + "key": "updatedAt", + "value": "2021-04-13T20:28:37.954Z", + "disabled": true + }, + { + "key": "status", + "value": "Scheduling", + "disabled": true + } ] } }, "response": [] }, { - "name": "patch work period with invalid parameter 3", + "name": "Search interviews without token", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 400', function () {\r", - " pm.response.to.have.status(400);\r", + "pm.test('Status code is 401', function () {\r", + " pm.response.to.have.status(401);\r", " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"startDate should be always Sunday\")\r", + " pm.expect(response.message).to.eq(\"No token provided.\")\r", "});" ], "type": "text/javascript" @@ -6747,47 +7246,33 @@ } ], "request": { - "method": "PATCH", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-06\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, + "method": "GET", + "header": [], "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/interviews", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId}}" + "jobCandidates", + "{{jobCandidateId}}", + "interviews" ] } }, "response": [] }, { - "name": "patch work period with invalid parameter 4", + "name": "Search interviews with invalid token", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 400', function () {\r", - " pm.response.to.have.status(400);\r", + "pm.test('Status code is 401', function () {\r", + " pm.response.to.have.status(401);\r", " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"endDate should be always the next Saturday\")\r", + " pm.expect(response.message).to.eq(\"Invalid Token.\")\r", "});" ], "type": "text/javascript" @@ -6795,55 +7280,49 @@ } ], "request": { - "method": "PATCH", + "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer invalid_token", + "type": "text" } ], - "body": { - "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-14\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "raw": "{{URL}}/jobCandidates/{{jobCandidateId}}/interviews", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId}}" + "jobCandidates", + "{{jobCandidateId}}", + "interviews" ] } }, "response": [] - }, + } + ] + }, + { + "name": "Resource Bookings", + "item": [ { - "name": "patch work period with invalid parameter 5", + "name": "create resource booking with booking manager", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 400', function () {\r", - " pm.response.to.have.status(400);\r", - " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"\\\"data.daysWorked\\\" must be a number\")\r", - "});" + "var data = JSON.parse(responseBody);\r", + "postman.setEnvironmentVariable(\"resourceBookingId\",data.id);" ], "type": "text/javascript" } } ], "request": { - "method": "PATCH", + "method": "POST", "header": [ { "key": "Authorization", @@ -6853,7 +7332,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": \"aa\",\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{jobId}}\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\"\r\n}", "options": { "raw": { "language": "json" @@ -6861,47 +7340,43 @@ } }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "raw": "{{URL}}/resourceBookings", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId}}" + "resourceBookings" ] } }, "response": [] }, { - "name": "patch work period with invalid parameter 6", + "name": "create resource booking with m2m create", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 400', function () {\r", - " pm.response.to.have.status(400);\r", - " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(`Key (resource_booking_id, start_date, end_date)=(${pm.environment.get('resourceBookingId')}, 2021-03-14, 2021-03-20) already exists.`)\r", - "});" + "var data = JSON.parse(responseBody);\r", + "postman.setEnvironmentVariable(\"resourceBookingIdCreatedByM2M\",data.id);" ], "type": "text/javascript" } } ], "request": { - "method": "PATCH", + "method": "POST", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_m2m_create_resource_booking}}" } ], "body": { "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-14\",\r\n \"endDate\": \"2021-03-20\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{jobIdCreatedByM2M}}\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\"\r\n}", "options": { "raw": { "language": "json" @@ -6909,47 +7384,43 @@ } }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "raw": "{{URL}}/resourceBookings", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId}}" + "resourceBookings" ] } }, "response": [] }, { - "name": "patch work period with invalid parameter 7", + "name": "create resource booking with connect user", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 400', function () {\r", - " pm.response.to.have.status(400);\r", - " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"\\\"data.paymentStatus\\\" must be one of [pending, partially-completed, completed, cancelled]\")\r", - "});" + "var data = JSON.parse(responseBody);\r", + "postman.setEnvironmentVariable(\"resourceBookingId\",data.id);" ], "type": "text/javascript" } } ], "request": { - "method": "PATCH", + "method": "POST", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_connectUser}}" } ], "body": { "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"paid\"\r\n}", + "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{jobId}}\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\"\r\n}", "options": { "raw": { "language": "json" @@ -6957,37 +7428,32 @@ } }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "raw": "{{URL}}/resourceBookings", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId}}" + "resourceBookings" ] } }, "response": [] }, { - "name": "delete work period with member", + "name": "create resource booking with member", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 403', function () {\r", - " pm.response.to.have.status(403);\r", - " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", - "});" + "" ], "type": "text/javascript" } } ], "request": { - "method": "DELETE", + "method": "POST", "header": [ { "key": "Authorization", @@ -6997,7 +7463,7 @@ ], "body": { "mode": "raw", - "raw": "", + "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{jobId}}\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\"\r\n}", "options": { "raw": { "language": "json" @@ -7005,47 +7471,42 @@ } }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "raw": "{{URL}}/resourceBookings", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId}}" + "resourceBookings" ] } }, "response": [] }, { - "name": "delete work period with connect user", + "name": "create resource booking with user id not exist", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 403', function () {\r", - " pm.response.to.have.status(403);\r", - " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", - "});" + "" ], "type": "text/javascript" } } ], "request": { - "method": "DELETE", + "method": "POST", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_connectUser}}" + "value": "Bearer {{token_userId_not_exist}}" } ], "body": { "mode": "raw", - "raw": "", + "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{jobId}}\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\"\r\n}", "options": { "raw": { "language": "json" @@ -7053,45 +7514,42 @@ } }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "raw": "{{URL}}/resourceBookings", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId}}" + "resourceBookings" ] } }, "response": [] }, { - "name": "delete work period with booking manager", + "name": "create resource booking with invalid token", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 204', function () {\r", - " pm.response.to.have.status(204);\r", - "});" + "" ], "type": "text/javascript" } } ], "request": { - "method": "DELETE", + "method": "POST", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer invalid_token" } ], "body": { "mode": "raw", - "raw": "", + "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{jobId}}\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\"\r\n}", "options": { "raw": { "language": "json" @@ -7099,129 +7557,69 @@ } }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "raw": "{{URL}}/resourceBookings", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId}}" + "resourceBookings" ] } }, "response": [] }, { - "name": "delete work period with m2m delete", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test('Status code is 204', function () {\r", - " pm.response.to.have.status(204);\r", - "});" - ], - "type": "text/javascript" - } - } - ], + "name": "get resource booking with booking manager", "request": { - "method": "DELETE", + "method": "GET", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_m2m_delete_work_period}}" + "value": "Bearer {{token_bookingManager}}" } ], - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodIdCreatedByM2M}}", + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodIdCreatedByM2M}}" + "resourceBookings", + "{{resourceBookingId}}" ] } }, "response": [] }, { - "name": "delete work period with invalid token", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test('Status code is 401', function () {\r", - " pm.response.to.have.status(401);\r", - " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"Invalid Token.\")\r", - "});" - ], - "type": "text/javascript" - } - } - ], + "name": "get resource booking with m2m read", "request": { - "method": "DELETE", + "method": "GET", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer invalid_token" + "value": "Bearer {{token_m2m_read_resource_booking}}" } ], - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "raw": "{{URL}}/resourceBookings/{{resourceBookingIdCreatedByM2M}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId}}" + "resourceBookings", + "{{resourceBookingIdCreatedByM2M}}" ] } }, "response": [] }, { - "name": "delete work period not found", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test('Status code is 404', function () {\r", - " pm.response.to.have.status(404);\r", - "});" - ], - "type": "text/javascript" - } - } - ], + "name": "get resource booking with booking manager from db", "request": { - "method": "DELETE", + "method": "GET", "header": [ { "key": "Authorization", @@ -7229,200 +7627,202 @@ "value": "Bearer {{token_bookingManager}}" } ], - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}?fromDb=true", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId}}" + "resourceBookings", + "{{resourceBookingId}}" + ], + "query": [ + { + "key": "fromDb", + "value": "true" + } ] } }, "response": [] - } - ] - }, - { - "name": "Taas Teams", - "item": [ + }, { - "name": "GET /taas-teams", + "name": "get resource booking with connect user", "request": { "method": "GET", "header": [ { "key": "Authorization", - "value": "Bearer {{token_bookingManager}}", - "type": "text" + "type": "text", + "value": "Bearer {{token_connectUser}}" } ], "url": { - "raw": "{{URL}}/taas-teams?perPage=10&page=1&name=*taas*&sortBy=lastActivityAt&sortOrder=desc", + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", "host": [ "{{URL}}" ], "path": [ - "taas-teams" - ], - "query": [ - { - "key": "perPage", - "value": "10" - }, - { - "key": "page", - "value": "1" - }, - { - "key": "name", - "value": "*taas*", - "description": "case-insensitive; support wildcard match" - }, - { - "key": "sortBy", - "value": "lastActivityAt", - "description": "allows: createdAt, updatedAt, lastActivityAt, id, status, name, type, best match" - }, - { - "key": "sortOrder", - "value": "desc", - "description": "allows: asc, desc" - } + "resourceBookings", + "{{resourceBookingId}}" ] } }, "response": [] }, { - "name": "GET /taas-teams with booking manager", + "name": "get resource booking with member", "request": { "method": "GET", "header": [ { "key": "Authorization", - "value": "Bearer {{token_bookingManager}}", - "type": "text" + "type": "text", + "value": "Bearer {{token_member}}" } ], "url": { - "raw": "{{URL}}/taas-teams?perPage=10&page=1&name=*taas*&sortBy=lastActivityAt&sortOrder=desc", + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", "host": [ "{{URL}}" ], "path": [ - "taas-teams" - ], - "query": [ - { - "key": "perPage", - "value": "10" - }, - { - "key": "page", - "value": "1" - }, - { - "key": "name", - "value": "*taas*", - "description": "case-insensitive; support wildcard match" - }, - { - "key": "sortBy", - "value": "lastActivityAt", - "description": "allows: createdAt, updatedAt, lastActivityAt, id, status, name, type, best match" - }, - { - "key": "sortOrder", - "value": "desc", - "description": "allows: asc, desc" - } + "resourceBookings", + "{{resourceBookingId}}" ] } }, "response": [] }, { - "name": "GET /taas-teams with m2m read", + "name": "search resource bookings with booking manager", "request": { "method": "GET", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_m2m_read_taas_team}}" + "value": "Bearer {{token_bookingManager}}" } ], "url": { - "raw": "{{URL}}/taas-teams", + "raw": "{{URL}}/resourceBookings", "host": [ "{{URL}}" ], "path": [ - "taas-teams" - ] - } - }, - "response": [] - }, - { - "name": "GET /taas-teams/:id", - "request": { - "method": "GET", - "header": [ - { - "key": "Authorization", - "value": "Bearer {{token_bookingManager}}", - "type": "text" - } - ], - "url": { - "raw": "{{URL}}/taas-teams/{{projectId}}", - "host": [ - "{{URL}}" + "resourceBookings" ], - "path": [ - "taas-teams", - "{{projectId}}" + "query": [ + { + "key": "page", + "value": "1", + "disabled": true + }, + { + "key": "perPage", + "value": "5", + "disabled": true + }, + { + "key": "sortBy", + "value": "id", + "disabled": true + }, + { + "key": "sortOrder", + "value": "desc", + "disabled": true + }, + { + "key": "startDate", + "value": "2020-09-27T04:17:23.131Z", + "disabled": true + }, + { + "key": "endDate", + "value": "2020-09-27T04:17:23.131Z", + "disabled": true + }, + { + "key": "rateType", + "value": "hourly", + "disabled": true + }, + { + "key": "status", + "value": "sourcing", + "disabled": true + }, + { + "key": "projectIds", + "value": "111, 16705", + "disabled": true + } ] } }, "response": [] }, { - "name": "GET /taas-teams/:id with booking manager", + "name": "search resource bookings with m2m all", "request": { "method": "GET", "header": [ { "key": "Authorization", - "value": "Bearer {{token_bookingManager}}", - "type": "text" + "type": "text", + "value": "Bearer {{token_m2m_all_resource_booking}}" } ], "url": { - "raw": "{{URL}}/taas-teams/:projectId", + "raw": "{{URL}}/resourceBookings", "host": [ "{{URL}}" ], "path": [ - "taas-teams", - ":projectId" + "resourceBookings" ], - "variable": [ + "query": [ { - "key": "projectId", - "value": "16705" + "key": "page", + "value": "1", + "disabled": true + }, + { + "key": "perPage", + "value": "5", + "disabled": true + }, + { + "key": "sortBy", + "value": "id", + "disabled": true + }, + { + "key": "sortOrder", + "value": "desc", + "disabled": true + }, + { + "key": "startDate", + "value": "2020-09-27T04:17:23.131Z", + "disabled": true + }, + { + "key": "endDate", + "value": "2020-09-27T04:17:23.131Z", + "disabled": true + }, + { + "key": "rateType", + "value": "hourly", + "disabled": true + }, + { + "key": "status", + "value": "sourcing", + "disabled": true } ] } @@ -7430,85 +7830,176 @@ "response": [] }, { - "name": "GET /taas-teams/:id with m2m read", + "name": "search resource bookings with connect user", "request": { "method": "GET", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_m2m_read_taas_team}}" + "value": "Bearer {{token_connectUser}}" } ], "url": { - "raw": "{{URL}}/taas-teams/{{projectId}}", + "raw": "{{URL}}/resourceBookings?sortOrder=desc", "host": [ "{{URL}}" ], "path": [ - "taas-teams", - "{{projectId}}" + "resourceBookings" + ], + "query": [ + { + "key": "page", + "value": "4", + "disabled": true + }, + { + "key": "perPage", + "value": "3", + "disabled": true + }, + { + "key": "sortBy", + "value": "id", + "disabled": true + }, + { + "key": "startDate", + "value": "2020-09-27T04:17:23.131Z", + "disabled": true + }, + { + "key": "endDate", + "value": "2020-09-27T04:17:23.131Z", + "disabled": true + }, + { + "key": "rateType", + "value": "hourly", + "disabled": true + }, + { + "key": "sortOrder", + "value": "desc" + } ] } }, "response": [] }, { - "name": "GET /taas-teams/:id/jobs/:jobId", + "name": "search resource bookings with member", "request": { "method": "GET", "header": [ { "key": "Authorization", - "value": "Bearer {{token_bookingManager}}", - "type": "text" + "type": "text", + "value": "Bearer {{token_member}}" } ], "url": { - "raw": "{{URL}}/taas-teams/{{projectId}}/jobs/{{jobId}}", + "raw": "{{URL}}/resourceBookings?sortOrder=desc", "host": [ "{{URL}}" ], "path": [ - "taas-teams", - "{{projectId}}", - "jobs", - "{{jobId}}" + "resourceBookings" + ], + "query": [ + { + "key": "page", + "value": "4", + "disabled": true + }, + { + "key": "perPage", + "value": "3", + "disabled": true + }, + { + "key": "sortBy", + "value": "id", + "disabled": true + }, + { + "key": "startDate", + "value": "2020-09-27T04:17:23.131Z", + "disabled": true + }, + { + "key": "endDate", + "value": "2020-09-27T04:17:23.131Z", + "disabled": true + }, + { + "key": "rateType", + "value": "hourly", + "disabled": true + }, + { + "key": "sortOrder", + "value": "desc" + } ] } }, "response": [] }, { - "name": "GET /taas-teams/:id/jobs/:jobId with booking manager", + "name": "search resource bookings with invalid token", "request": { "method": "GET", "header": [ { "key": "Authorization", - "value": "Bearer {{token_bookingManager}}", - "type": "text" + "type": "text", + "value": "Bearer invalid_token" } ], "url": { - "raw": "{{URL}}/taas-teams/:projectId/jobs/:jobId", + "raw": "{{URL}}/resourceBookings?sortOrder=desc", "host": [ "{{URL}}" ], "path": [ - "taas-teams", - ":projectId", - "jobs", - ":jobId" + "resourceBookings" ], - "variable": [ + "query": [ { - "key": "projectId", - "value": "16705" + "key": "page", + "value": "4", + "disabled": true }, { - "key": "jobId", - "value": "948a25a6-086f-4a96-aad5-9ccd2d3e87b2" + "key": "perPage", + "value": "3", + "disabled": true + }, + { + "key": "sortBy", + "value": "id", + "disabled": true + }, + { + "key": "startDate", + "value": "2020-09-27T04:17:23.131Z", + "disabled": true + }, + { + "key": "endDate", + "value": "2020-09-27T04:17:23.131Z", + "disabled": true + }, + { + "key": "rateType", + "value": "hourly", + "disabled": true + }, + { + "key": "sortOrder", + "value": "desc" } ] } @@ -7516,89 +8007,85 @@ "response": [] }, { - "name": "GET /taas-teams/:id/jobs/:jobId with m2m read", + "name": "put resource booking with booking manager", "request": { - "method": "GET", + "method": "PUT", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_m2m_read_taas_team}}" + "value": "Bearer {{token_bookingManager}}" } ], + "body": { + "mode": "raw", + "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{jobId}}\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"status\": \"assigned\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { - "raw": "{{URL}}/taas-teams/{{projectId}}/jobs/{{jobId}}", + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", "host": [ "{{URL}}" ], "path": [ - "taas-teams", - "{{projectId}}", - "jobs", - "{{jobId}}" + "resourceBookings", + "{{resourceBookingId}}" ] } }, "response": [] }, { - "name": "GET /taas-teams/skills", + "name": "put resource booking with m2m update", "request": { - "method": "GET", + "method": "PUT", "header": [ { "key": "Authorization", - "value": "Bearer {{token_member}}", - "type": "text" + "type": "text", + "value": "Bearer {{token_m2m_update_resource_booking}}" } ], + "body": { + "mode": "raw", + "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{jobIdCreatedByM2M}}\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"status\": \"assigned\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { - "raw": "{{URL}}/taas-teams/skills?perPage=10&page=1&orderBy=name", + "raw": "{{URL}}/resourceBookings/{{resourceBookingIdCreatedByM2M}}", "host": [ "{{URL}}" ], "path": [ - "taas-teams", - "skills" - ], - "query": [ - { - "key": "perPage", - "value": "10" - }, - { - "key": "page", - "value": "1" - }, - { - "key": "orderBy", - "value": "name", - "description": "possible values are defined by /v5/skills" - } + "resourceBookings", + "{{resourceBookingIdCreatedByM2M}}" ] } }, "response": [] }, { - "name": "POST /taas-teams/email - team-issue-report", + "name": "put resource booking with connect user", "request": { - "method": "POST", + "method": "PUT", "header": [ { "key": "Authorization", - "value": "Bearer {{token_member}}", - "type": "text" - }, - { - "key": "Content-Type", - "value": "application/json", - "type": "text" + "type": "text", + "value": "Bearer {{token_connectUser}}" } ], "body": { "mode": "raw", - "raw": "{\n \"template\": \"team-issue-report\",\n \"data\": {\n \"projectName\": \"TaaS Project Name\",\n \"projectId\": 12345,\n \"reportText\": \"I have issue with ...\"\n }\n}", + "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{jobId}}\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"status\": \"assigned\"\r\n}", "options": { "raw": { "language": "json" @@ -7606,37 +8093,32 @@ } }, "url": { - "raw": "{{URL}}/taas-teams/email", + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", "host": [ "{{URL}}" ], "path": [ - "taas-teams", - "email" + "resourceBookings", + "{{resourceBookingId}}" ] } }, "response": [] }, { - "name": "POST /taas-teams/email - member-issue-report", + "name": "put resource booking with member", "request": { - "method": "POST", + "method": "PUT", "header": [ { "key": "Authorization", "type": "text", "value": "Bearer {{token_member}}" - }, - { - "key": "Content-Type", - "type": "text", - "value": "application/json" } ], "body": { "mode": "raw", - "raw": "{\n \"template\": \"member-issue-report\",\n \"data\": {\n \"projectName\": \"TaaS Project Name\",\n \"projectId\": 12345,\n \"userHandle\": \"pshah_manager\",\n \"reportText\": \"I have issue with ...\"\n }\n}", + "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{jobId}}\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"status\": \"assigned\"\r\n}", "options": { "raw": { "language": "json" @@ -7644,37 +8126,32 @@ } }, "url": { - "raw": "{{URL}}/taas-teams/email", + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", "host": [ "{{URL}}" ], "path": [ - "taas-teams", - "email" + "resourceBookings", + "{{resourceBookingId}}" ] } }, "response": [] }, { - "name": "POST /taas-teams/email - extension-request", + "name": "put resource booking with user id not exist", "request": { - "method": "POST", + "method": "PUT", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_member}}" - }, - { - "key": "Content-Type", - "type": "text", - "value": "application/json" + "value": "Bearer {{token_userId_not_exist}}" } ], "body": { "mode": "raw", - "raw": "{\n \"template\": \"extension-request\",\n \"data\": {\n \"projectName\": \"TaaS Project Name\",\n \"projectId\": 12345,\n \"userHandle\": \"pshah_manager\",\n \"reportText\": \"I would like to keep working with this member for 2 months...\"\n }\n}", + "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{jobId}}\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"status\": \"assigned\"\r\n}", "options": { "raw": { "language": "json" @@ -7682,37 +8159,32 @@ } }, "url": { - "raw": "{{URL}}/taas-teams/email", + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", "host": [ "{{URL}}" ], "path": [ - "taas-teams", - "email" + "resourceBookings", + "{{resourceBookingId}}" ] } }, "response": [] }, { - "name": "POST /taas-teams/:id/members", + "name": "put resource booking with invalid token", "request": { - "method": "POST", + "method": "PUT", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_administrator}}" - }, - { - "key": "Content-Type", - "type": "text", - "value": "application/json" + "value": "Bearer invalid_token" } ], "body": { "mode": "raw", - "raw": "{\n \"handles\": [\n \"tester1234\",\n \"non-existing\"\n ],\n \"emails\": [\n \"non-existing@domain.com\",\n \"email@domain.com\"\n ]\n}", + "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{jobId}}\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"status\": \"assigned\"\r\n}", "options": { "raw": { "language": "json" @@ -7720,158 +8192,121 @@ } }, "url": { - "raw": "{{URL}}/taas-teams/:id/members", + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", "host": [ "{{URL}}" ], "path": [ - "taas-teams", - ":id", - "members" - ], - "variable": [ - { - "key": "id", - "value": "16705" - } + "resourceBookings", + "{{resourceBookingId}}" ] } }, "response": [] }, { - "name": "GET /taas-teams/:id/members", + "name": "patch resource booking with booking manager", "request": { - "method": "GET", + "method": "PATCH", "header": [ { "key": "Authorization", "type": "text", "value": "Bearer {{token_bookingManager}}" - }, - { - "key": "Content-Type", - "type": "text", - "value": "application/json" } ], + "body": { + "mode": "raw", + "raw": "{\r\n \"status\": \"assigned\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { - "raw": "{{URL}}/taas-teams/:id/members?role=customer&fields=id,userId,role,createdAt,updatedAt,createdBy,updatedBy,handle,photoURL,workingHourStart,workingHourEnd,timeZone,email", + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", "host": [ "{{URL}}" ], "path": [ - "taas-teams", - ":id", - "members" - ], - "query": [ - { - "key": "role", - "value": "customer" - }, - { - "key": "fields", - "value": "id,userId,role,createdAt,updatedAt,createdBy,updatedBy,handle,photoURL,workingHourStart,workingHourEnd,timeZone,email" - } - ], - "variable": [ - { - "key": "id", - "value": "16705" - } + "resourceBookings", + "{{resourceBookingId}}" ] } }, "response": [] }, { - "name": "GET /taas-teams/:id/invites", + "name": "patch resource booking with m2m update", "request": { - "method": "GET", + "method": "PATCH", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_bookingManager}}" - }, - { - "key": "Content-Type", - "type": "text", - "value": "application/json" + "value": "Bearer {{token_m2m_update_resource_booking}}" } ], + "body": { + "mode": "raw", + "raw": "{\r\n \"status\": \"assigned\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { - "raw": "{{URL}}/taas-teams/:id/invites?fields=createdAt,deletedAt,role,updatedBy,createdBy,id,projectId,userId,email,deletedBy,updatedAt,status", + "raw": "{{URL}}/resourceBookings/{{resourceBookingIdCreatedByM2M}}", "host": [ "{{URL}}" ], "path": [ - "taas-teams", - ":id", - "invites" - ], - "query": [ - { - "key": "fields", - "value": "createdAt,deletedAt,role,updatedBy,createdBy,id,projectId,userId,email,deletedBy,updatedAt,status" - } - ], - "variable": [ - { - "key": "id", - "value": "16705" - } + "resourceBookings", + "{{resourceBookingIdCreatedByM2M}}" ] } }, "response": [] }, { - "name": "DELETE /taas-teams/:id/members/:projectMemberId", + "name": "patch resource booking with connect user", "request": { - "method": "DELETE", + "method": "PATCH", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_bookingManager}}" - }, - { - "key": "Content-Type", - "type": "text", - "value": "application/json" + "value": "Bearer {{token_connectUser}}" } ], + "body": { + "mode": "raw", + "raw": "{\r\n \"status\": \"assigned\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { - "raw": "{{URL}}/taas-teams/:id/members/:projectMemberId", + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", "host": [ "{{URL}}" ], "path": [ - "taas-teams", - ":id", - "members", - ":projectMemberId" - ], - "variable": [ - { - "key": "id", - "value": "16705" - }, - { - "key": "projectMemberId", - "value": "14327" - } + "resourceBookings", + "{{resourceBookingId}}" ] } }, "response": [] }, { - "name": "GET /taas-teams/me", + "name": "patch resource booking with member", "request": { - "method": "GET", + "method": "PATCH", "header": [ { "key": "Authorization", @@ -7879,188 +8314,281 @@ "value": "Bearer {{token_member}}" } ], + "body": { + "mode": "raw", + "raw": "{\r\n \"status\": \"assigned\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { - "raw": "{{URL}}/taas-teams/me", + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", "host": [ "{{URL}}" ], "path": [ - "taas-teams", - "me" + "resourceBookings", + "{{resourceBookingId}}" ] } }, "response": [] - } - ] - }, - { - "name": "health check", - "item": [ + }, { - "name": "health check", + "name": "patch resource booking with user id not exist", "request": { - "method": "GET", - "header": [], + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_userId_not_exist}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"status\": \"assigned\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { - "raw": "{{URL}}/health", + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", "host": [ "{{URL}}" ], "path": [ - "health" + "resourceBookings", + "{{resourceBookingId}}" ] } }, "response": [] - } - ] - }, - { - "name": "Create Demo Data For Team", - "item": [ + }, { - "name": "Get Users", - "item": [ - { - "name": "Get Users", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "var data = JSON.parse(responseBody);", - "", - "pm.test(\"Status code is 200\", function () {", - " pm.response.to.have.status(200);", - "});", - "", - "var demoUsers = 20;", - "", - "pm.test('We need to have at least ' + demoUsers + ' demo userIds. Define them in {{demoUserIdN}} variables.', function () {", - " for (var i = 0; i < demoUsers; i++) {", - " var variableName = \"demoUserId\" + (i + 1);", - " var existentValue = pm.variables.get(variableName);", - " var user = data[i];", - "", - " pm.expect(!!user || !!existentValue).to.be.true;", - "", - " postman.setEnvironmentVariable(variableName, user.id);", - " }", - "});" - ], - "type": "text/javascript" - } + "name": "patch resource booking with invalid token", + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer invalid_token" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"status\": \"assigned\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\"\r\n}", + "options": { + "raw": { + "language": "json" } + } + }, + "url": { + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "host": [ + "{{URL}}" ], - "request": { - "auth": { - "type": "bearer", - "bearer": [ - { - "key": "token", - "value": "{{token_bookingManager}}", - "type": "string" - } - ] - }, - "method": "GET", - "header": [], - "url": { - "raw": "https://api.topcoder-dev.com/v5/users?perPage=20", - "protocol": "https", - "host": [ - "api", - "topcoder-dev", - "com" - ], - "path": [ - "v5", - "users" - ], - "query": [ - { - "key": "perPage", - "value": "20" - } - ] - } - }, - "response": [] + "path": [ + "resourceBookings", + "{{resourceBookingId}}" + ] } - ] + }, + "response": [] }, { - "name": "Create job #1 \"sourcing\"", - "item": [ - { - "name": "create job #1", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "var data = JSON.parse(responseBody);\r", - "\r", - "pm.test(\"Successful POST request\", function () {\r", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);\r", - "});\r", - "\r", - "postman.setEnvironmentVariable(\"demoJobId1\",data.id);" - ], - "type": "text/javascript" - } + "name": "delete resource booking with member", + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_member}}" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" } + } + }, + "url": { + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "host": [ + "{{URL}}" ], - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"projectId\": {{projectId}},\n \"externalId\": \"0\",\n \"description\": \"taas-demo-job1\",\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\n \"duration\": 1,\n \"numPositions\": 13,\n \"resourceType\": \"Dummy Resource Type\",\n \"rateType\": \"weekly\",\n \"workload\": \"full-time\",\n \"skills\": [\n \"ee4c50c1-c8c3-475e-b6b6-edbd136a19d6\",\n \"89139c80-d0a2-47c2-aa16-14589d5afd10\",\n \"9f2d9127-6a2e-4506-ad76-c4ab63577b09\",\n \"9515e7ee-83b6-49d1-ba5c-6c59c5a8ef1b\",\n \"c854ab55-5922-4be1-8ecc-b3bc1f8629af\",\n \"8456002e-fa2d-44f0-b0e7-86b1c02b6e4c\",\n \"114b4ec8-805e-4c60-b351-14a955a991a9\",\n \"213408aa-f16f-46c8-bc57-9e569cee3f11\",\n \"b37a48db-f775-4e4e-b403-8ad1d234cdea\",\n \"99b930b5-1b91-4df1-8b17-d9307107bb51\",\n \"6388a632-c3ad-4525-9a73-66a527c03672\",\n \"23839f38-6f19-4de9-9d28-f020056bca73\",\n \"289e42a3-23e9-49be-88e1-6deb93cd8c31\",\n \"b403f209-63b5-42bc-9b5f-1564416640d8\"\n ],\n \"title\": \"Dummy title - at most 64 characters\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{URL}}/jobs", - "host": [ - "{{URL}}" - ], - "path": [ - "jobs" - ] - } - }, - "response": [] + "path": [ + "resourceBookings", + "{{resourceBookingId}}" + ] } - ] + }, + "response": [] }, { - "name": "Create job #2 \"in-review\"", + "name": "delete resource booking with connect user", + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_connectUser}}" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings", + "{{resourceBookingId}}" + ] + } + }, + "response": [] + }, + { + "name": "delete resource booking with booking manager", + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings", + "{{resourceBookingId}}" + ] + } + }, + "response": [] + }, + { + "name": "delete resource booking with m2m delete", + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_m2m_delete_resource_booking}}" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/resourceBookings/{{resourceBookingIdCreatedByM2M}}", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings", + "{{resourceBookingIdCreatedByM2M}}" + ] + } + }, + "response": [] + }, + { + "name": "delete resource booking with invalid token", + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer invalid_token" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings", + "{{resourceBookingId}}" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "Work Periods", + "item": [ + { + "name": "Before Test", "item": [ { - "name": "create job #2", + "name": "create job", "event": [ { "listen": "test", "script": { "exec": [ - "var data = JSON.parse(responseBody);\r", - "\r", - "pm.test(\"Successful POST request\", function () {\r", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);\r", - "});\r", - "\r", - "postman.setEnvironmentVariable(\"demoJobId2\",data.id);" + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", + " if(pm.response.status === \"OK\"){\r", + " const response = pm.response.json()\r", + " pm.environment.set(\"jobId\", response.id);\r", + " }\r", + "});" ], "type": "text/javascript" } @@ -8071,13 +8599,13 @@ "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], "body": { "mode": "raw", - "raw": "{\n \"projectId\": {{projectId}},\n \"externalId\": \"0\",\n \"description\": \"taas-demo-job2\",\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\n \"duration\": 1,\n \"numPositions\": 7,\n \"resourceType\": \"Dummy Resource Type\",\n \"rateType\": \"weekly\",\n \"workload\": \"full-time\",\n \"skills\": [\n \"213408aa-f16f-46c8-bc57-9e569cee3f11\",\n \"b37a48db-f775-4e4e-b403-8ad1d234cdea\",\n \"99b930b5-1b91-4df1-8b17-d9307107bb51\",\n \"6388a632-c3ad-4525-9a73-66a527c03672\",\n \"23839f38-6f19-4de9-9d28-f020056bca73\",\n \"289e42a3-23e9-49be-88e1-6deb93cd8c31\",\n \"b403f209-63b5-42bc-9b5f-1564416640d8\"\n ],\n \"title\": \"Dummy title - at most 64 characters\"\n}", + "raw": "{\n \"projectId\": {{projectId}},\n \"externalId\": \"1212\",\n \"description\": \"Dummy Description\",\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\n \"duration\": 1,\n \"numPositions\": 13,\n \"resourceType\": \"Dummy Resource Type\",\n \"rateType\": \"hourly\",\n \"workload\": \"full-time\",\n \"skills\": [\n \"23e00d92-207a-4b5b-b3c9-4c5662644941\",\n \"7d076384-ccf6-4e43-a45d-1b24b1e624aa\",\n \"cbac57a3-7180-4316-8769-73af64893158\",\n \"a2b4bc11-c641-4a19-9eb7-33980378f82e\"\n ],\n \"title\": \"Dummy title - at most 64 characters\"\n}", "options": { "raw": { "language": "json" @@ -8097,19 +8625,19 @@ "response": [] }, { - "name": "create job #2 candidate 1", + "name": "create resource booking", "event": [ { "listen": "test", "script": { "exec": [ - "var data = JSON.parse(responseBody);\r", - "\r", - "pm.test(\"Successful POST request\", function () {\r", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);\r", - "});\r", - "\r", - "postman.setEnvironmentVariable(\"demoJob1candidateId1\",data.id);" + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", + " if(pm.response.status === \"OK\"){\r", + " const response = pm.response.json()\r", + " pm.environment.set(\"resourceBookingId\", response.id);\r", + " }\r", + "});" ], "type": "text/javascript" } @@ -8126,7 +8654,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"jobId\": \"{{demoJobId2}}\",\r\n \"userId\": \"{{demoUserId1}}\"\r\n}", + "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{jobId}}\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\"\r\n}", "options": { "raw": { "language": "json" @@ -8134,779 +8662,4740 @@ } }, "url": { - "raw": "{{URL}}/jobCandidates", + "raw": "{{URL}}/resourceBookings", "host": [ "{{URL}}" ], "path": [ - "jobCandidates" + "resourceBookings" ] } }, "response": [] - }, + } + ] + }, + { + "name": "create work period with booking manager", + "event": [ { - "name": "create job #2 candidate 2", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "var data = JSON.parse(responseBody);\r", - "\r", - "pm.test(\"Successful POST request\", function () {\r", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);\r", - "});\r", - "\r", - "postman.setEnvironmentVariable(\"demoJob1candidateId2\",data.id);" - ], - "type": "text/javascript" - } + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", + " if(pm.response.status === \"OK\"){\r", + " const response = pm.response.json()\r", + " pm.environment.set(\"workPeriodId\", response.id);\r", + " }\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "options": { + "raw": { + "language": "json" } + } + }, + "url": { + "raw": "{{URL}}/workPeriods", + "host": [ + "{{URL}}" ], - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } + "path": [ + "workPeriods" + ] + } + }, + "response": [] + }, + { + "name": "create work period with m2m create", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", + " if(pm.response.status === \"OK\"){\r", + " const response = pm.response.json()\r", + " pm.environment.set(\"workPeriodIdCreatedByM2M\", response.id);\r", + " }\r", + "});" ], - "body": { - "mode": "raw", - "raw": "{\r\n \"jobId\": \"{{demoJobId2}}\",\r\n \"userId\": \"{{demoUserId2}}\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{URL}}/jobCandidates", - "host": [ - "{{URL}}" - ], - "path": [ - "jobCandidates" - ] + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_m2m_create_work_period}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-14\",\r\n \"endDate\": \"2021-03-20\",\r\n \"daysWorked\": 3,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"cancelled\"\r\n}", + "options": { + "raw": { + "language": "json" } - }, - "response": [] + } }, - { - "name": "create job #2 candidate 3", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Successful POST request\", function () {", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", - "});" - ], - "type": "text/javascript" - } - } + "url": { + "raw": "{{URL}}/workPeriods", + "host": [ + "{{URL}}" ], - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } + "path": [ + "workPeriods" + ] + } + }, + "response": [] + }, + { + "name": "create work period with connect user", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 403', function () {\r", + " pm.response.to.have.status(403);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", + "});" ], - "body": { - "mode": "raw", - "raw": "{\r\n \"jobId\": \"{{demoJobId2}}\",\r\n \"userId\": \"{{demoUserId3}}\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{URL}}/jobCandidates", - "host": [ - "{{URL}}" - ], - "path": [ - "jobCandidates" - ] + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_connectUser}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-21\",\r\n \"endDate\": \"2021-03-27\",\r\n \"daysWorked\": 3,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"cancelled\"\r\n}", + "options": { + "raw": { + "language": "json" } - }, - "response": [] + } }, - { - "name": "create job #2 candidate 4", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Successful POST request\", function () {", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", - "});" - ], - "type": "text/javascript" - } - } + "url": { + "raw": "{{URL}}/workPeriods", + "host": [ + "{{URL}}" ], - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } + "path": [ + "workPeriods" + ] + } + }, + "response": [] + }, + { + "name": "create work period with member", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 403', function () {\r", + " pm.response.to.have.status(403);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", + "});" ], - "body": { - "mode": "raw", - "raw": "{\r\n \"jobId\": \"{{demoJobId2}}\",\r\n \"userId\": \"{{demoUserId4}}\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{URL}}/jobCandidates", - "host": [ - "{{URL}}" - ], - "path": [ - "jobCandidates" - ] + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_member}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-21\",\r\n \"endDate\": \"2021-03-27\",\r\n \"daysWorked\": 3,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"cancelled\"\r\n}", + "options": { + "raw": { + "language": "json" } - }, - "response": [] + } }, - { - "name": "create job #2 candidate 5", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Successful POST request\", function () {", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", - "});" - ], - "type": "text/javascript" - } - } + "url": { + "raw": "{{URL}}/workPeriods", + "host": [ + "{{URL}}" ], - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"jobId\": \"{{demoJobId2}}\",\r\n \"userId\": \"{{demoUserId5}}\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{URL}}/jobCandidates", - "host": [ - "{{URL}}" - ], - "path": [ - "jobCandidates" - ] - } - }, - "response": [] - }, + "path": [ + "workPeriods" + ] + } + }, + "response": [] + }, + { + "name": "create work period with user id not exist", + "event": [ { - "name": "create job #2 candidate 6", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Successful POST request\", function () {", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"Bad Request\")\r", + "});" ], - "body": { - "mode": "raw", - "raw": "{\r\n \"jobId\": \"{{demoJobId2}}\",\r\n \"userId\": \"{{demoUserId6}}\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{URL}}/jobCandidates", - "host": [ - "{{URL}}" - ], - "path": [ - "jobCandidates" - ] + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_userId_not_exist}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-21\",\r\n \"endDate\": \"2021-03-27\",\r\n \"daysWorked\": 3,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"cancelled\"\r\n}", + "options": { + "raw": { + "language": "json" } - }, - "response": [] + } }, - { - "name": "create job #2 candidate 7", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Successful POST request\", function () {", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", - "});" - ], - "type": "text/javascript" - } - } + "url": { + "raw": "{{URL}}/workPeriods", + "host": [ + "{{URL}}" ], - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } + "path": [ + "workPeriods" + ] + } + }, + "response": [] + }, + { + "name": "create work period with invalid token", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 401', function () {\r", + " pm.response.to.have.status(401);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"Invalid Token.\")\r", + "});" ], - "body": { - "mode": "raw", - "raw": "{\r\n \"jobId\": \"{{demoJobId2}}\",\r\n \"userId\": \"{{demoUserId7}}\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{URL}}/jobCandidates", - "host": [ - "{{URL}}" - ], - "path": [ - "jobCandidates" - ] + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer invalid_token" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-21\",\r\n \"endDate\": \"2021-03-27\",\r\n \"daysWorked\": 3,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"cancelled\"\r\n}", + "options": { + "raw": { + "language": "json" } - }, - "response": [] + } }, + "url": { + "raw": "{{URL}}/workPeriods", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods" + ] + } + }, + "response": [] + }, + { + "name": "create work period with missing parameter 1", + "event": [ { - "name": "create job #2 candidate 8", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Successful POST request\", function () {", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", - "});" - ], - "type": "text/javascript" - } + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"\\\"workPeriod.resourceBookingId\\\" is required\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "options": { + "raw": { + "language": "json" } + } + }, + "url": { + "raw": "{{URL}}/workPeriods", + "host": [ + "{{URL}}" ], - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"jobId\": \"{{demoJobId2}}\",\r\n \"userId\": \"{{demoUserId8}}\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{URL}}/jobCandidates", - "host": [ - "{{URL}}" - ], - "path": [ - "jobCandidates" - ] - } - }, - "response": [] - }, + "path": [ + "workPeriods" + ] + } + }, + "response": [] + }, + { + "name": "create work period with missing parameter 2", + "event": [ { - "name": "create job #2 candidate 9", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Successful POST request\", function () {", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"\\\"workPeriod.endDate\\\" is required\")\r", + "});" ], - "body": { - "mode": "raw", - "raw": "{\r\n \"jobId\": \"{{demoJobId2}}\",\r\n \"userId\": \"{{demoUserId9}}\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{URL}}/jobCandidates", - "host": [ - "{{URL}}" - ], - "path": [ - "jobCandidates" - ] + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "options": { + "raw": { + "language": "json" } - }, - "response": [] + } }, - { - "name": "create job #2 candidate 10", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Successful POST request\", function () {", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", - "});" - ], - "type": "text/javascript" - } - } + "url": { + "raw": "{{URL}}/workPeriods", + "host": [ + "{{URL}}" ], - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } + "path": [ + "workPeriods" + ] + } + }, + "response": [] + }, + { + "name": "create work period with missing parameter 3", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"\\\"workPeriod.paymentStatus\\\" is required\")\r", + "});" ], - "body": { - "mode": "raw", - "raw": "{\r\n \"jobId\": \"{{demoJobId2}}\",\r\n \"userId\": \"{{demoUserId10}}\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{URL}}/jobCandidates", - "host": [ - "{{URL}}" - ], - "path": [ - "jobCandidates" - ] + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13\r\n}", + "options": { + "raw": { + "language": "json" } - }, - "response": [] + } }, + "url": { + "raw": "{{URL}}/workPeriods", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods" + ] + } + }, + "response": [] + }, + { + "name": "create work period with invalid parameter 1", + "event": [ { - "name": "update job #2 candidate 1 to \"shortlist\"", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Successful PATCH request\", function () {", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", - "});" - ], - "type": "text/javascript" - } + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"\\\"workPeriod.resourceBookingId\\\" must be a valid GUID\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"aaa-aaa\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "options": { + "raw": { + "language": "json" } + } + }, + "url": { + "raw": "{{URL}}/workPeriods", + "host": [ + "{{URL}}" ], - "request": { - "method": "PATCH", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"status\": \"shortlist\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{URL}}/jobCandidates/{{demoJob1candidateId1}}", - "host": [ - "{{URL}}" - ], - "path": [ - "jobCandidates", - "{{demoJob1candidateId1}}" - ] - } - }, - "response": [] - }, + "path": [ + "workPeriods" + ] + } + }, + "response": [] + }, + { + "name": "create work period with invalid parameter 2", + "event": [ { - "name": "update job #2 candidate 2 to \"rejected\"", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Successful PATCH request\", function () {", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "PATCH", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"\\\"workPeriod.startDate\\\" must be in YYYY-MM-DD format\")\r", + "});" ], - "body": { - "mode": "raw", - "raw": "{\r\n \"status\": \"rejected\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{URL}}/jobCandidates/{{demoJob1candidateId2}}", - "host": [ - "{{URL}}" - ], - "path": [ - "jobCandidates", - "{{demoJob1candidateId2}}" - ] + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"07-03-2021\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "options": { + "raw": { + "language": "json" } - }, - "response": [] + } }, - { - "name": "update job #2 status to \"in-review\"", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Successful PATCH request\", function () {", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", - "});" - ], - "type": "text/javascript" - } - } + "url": { + "raw": "{{URL}}/workPeriods", + "host": [ + "{{URL}}" ], - "request": { - "method": "PATCH", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"status\": \"in-review\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{URL}}/jobs/{{demoJobId2}}", - "host": [ - "{{URL}}" - ], - "path": [ - "jobs", - "{{demoJobId2}}" - ] - } - }, - "response": [] + "path": [ + "workPeriods" + ] } - ] + }, + "response": [] }, { - "name": "Create job #3 \"assigned\"", - "item": [ + "name": "create work period with invalid parameter 3", + "event": [ { - "name": "create job #3", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "var data = JSON.parse(responseBody);\r", - "\r", - "pm.test(\"Successful POST request\", function () {\r", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);\r", - "});\r", - "\r", - "postman.setEnvironmentVariable(\"demoJobId3\",data.id);" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"startDate should be always Sunday\")\r", + "});" ], - "body": { - "mode": "raw", - "raw": "{\n \"projectId\": {{projectId}},\n \"externalId\": \"0\",\n \"description\": \"taas-demo-job3\",\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\n \"duration\": 1,\n \"numPositions\": 7,\n \"resourceType\": \"Dummy Resource Type\",\n \"rateType\": \"weekly\",\n \"workload\": \"full-time\",\n \"skills\": [],\n \"title\": \"Dummy title - at most 64 characters\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{URL}}/jobs", - "host": [ - "{{URL}}" - ], - "path": [ - "jobs" - ] + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-06\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "options": { + "raw": { + "language": "json" } - }, - "response": [] + } }, - { - "name": "create job #3 candidate 11", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Successful POST request\", function () {", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", - "});" - ], - "type": "text/javascript" - } - } + "url": { + "raw": "{{URL}}/workPeriods", + "host": [ + "{{URL}}" ], - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"jobId\": \"{{demoJobId3}}\",\r\n \"userId\": \"{{demoUserId11}}\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{URL}}/jobCandidates", - "host": [ - "{{URL}}" - ], - "path": [ - "jobCandidates" - ] - } - }, - "response": [] - }, + "path": [ + "workPeriods" + ] + } + }, + "response": [] + }, + { + "name": "create work period with invalid parameter 4", + "event": [ { - "name": "create job #3 candidate 12", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Successful POST request\", function () {", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"endDate should be always the next Saturday\")\r", + "});" ], - "body": { - "mode": "raw", - "raw": "{\r\n \"jobId\": \"{{demoJobId3}}\",\r\n \"userId\": \"{{demoUserId12}}\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{URL}}/jobCandidates", - "host": [ - "{{URL}}" - ], - "path": [ - "jobCandidates" - ] + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-14\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "options": { + "raw": { + "language": "json" } - }, - "response": [] + } }, - { - "name": "create job #3 candidate 13", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Successful POST request\", function () {", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", - "});" - ], - "type": "text/javascript" - } - } + "url": { + "raw": "{{URL}}/workPeriods", + "host": [ + "{{URL}}" ], - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } + "path": [ + "workPeriods" + ] + } + }, + "response": [] + }, + { + "name": "create work period with invalid parameter 5", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"\\\"workPeriod.daysWorked\\\" must be a number\")\r", + "});" ], - "body": { - "mode": "raw", - "raw": "{\r\n \"jobId\": \"{{demoJobId3}}\",\r\n \"userId\": \"{{demoUserId13}}\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{URL}}/jobCandidates", - "host": [ - "{{URL}}" - ], - "path": [ - "jobCandidates" - ] + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": \"aa\",\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "options": { + "raw": { + "language": "json" } - }, - "response": [] + } }, + "url": { + "raw": "{{URL}}/workPeriods", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods" + ] + } + }, + "response": [] + }, + { + "name": "create work period with invalid parameter 6", + "event": [ { - "name": "create job #3 candidate 14", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Successful POST request\", function () {", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", - "});" - ], - "type": "text/javascript" - } + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(`Key (resource_booking_id, start_date, end_date)=(${pm.environment.get('resourceBookingId')}, 2021-03-07, 2021-03-13) already exists.`)\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "options": { + "raw": { + "language": "json" } + } + }, + "url": { + "raw": "{{URL}}/workPeriods", + "host": [ + "{{URL}}" ], - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } - ], - "body": { - "mode": "raw", + "path": [ + "workPeriods" + ] + } + }, + "response": [] + }, + { + "name": "create work period with invalid parameter 7", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"\\\"workPeriod.paymentStatus\\\" must be one of [pending, partially-completed, completed, cancelled]\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"paid\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/workPeriods", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods" + ] + } + }, + "response": [] + }, + { + "name": "get work period with booking manager", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodId}}" + ] + } + }, + "response": [] + }, + { + "name": "get work period with m2m read", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_m2m_read_work_period}}" + } + ], + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodIdCreatedByM2M}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodIdCreatedByM2M}}" + ] + } + }, + "response": [] + }, + { + "name": "get work period with booking manager from db", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodId}}?fromDb=true", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodId}}" + ], + "query": [ + { + "key": "fromDb", + "value": "true" + } + ] + } + }, + "response": [] + }, + { + "name": "get work period with connect user", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_connectUser}}" + } + ], + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodId}}" + ] + } + }, + "response": [] + }, + { + "name": "get work period with member", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 401', function () {\r", + " pm.response.to.have.status(401);\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_member}}" + } + ], + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodId}}" + ] + } + }, + "response": [] + }, + { + "name": "search work periods with booking manager", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "url": { + "raw": "{{URL}}/workPeriods", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods" + ], + "query": [ + { + "key": "page", + "value": "1", + "disabled": true + }, + { + "key": "perPage", + "value": "5", + "disabled": true + }, + { + "key": "sortBy", + "value": "id", + "disabled": true + }, + { + "key": "sortOrder", + "value": "desc", + "disabled": true + }, + { + "key": "resourceBookingId", + "value": "{{resourceBookingId}}", + "disabled": true + }, + { + "key": "resourceBookingIds", + "value": "{{resourceBookingId}},{{resourceBookingIdCreatedByM2M}}", + "disabled": true + }, + { + "key": "paymentStatus", + "value": "pending", + "disabled": true + }, + { + "key": "startDate", + "value": "2021-03-14", + "disabled": true + }, + { + "key": "endDate", + "value": "2021-03-20", + "disabled": true + }, + { + "key": "userHandle", + "value": "pshah_manager", + "disabled": true + }, + { + "key": "projectId", + "value": "16843", + "disabled": true + } + ] + } + }, + "response": [] + }, + { + "name": "search work periods with m2m all", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_m2m_all_work_period}}" + } + ], + "url": { + "raw": "{{URL}}/workPeriods", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods" + ], + "query": [ + { + "key": "page", + "value": "1", + "disabled": true + }, + { + "key": "perPage", + "value": "5", + "disabled": true + }, + { + "key": "sortBy", + "value": "id", + "disabled": true + }, + { + "key": "sortOrder", + "value": "desc", + "disabled": true + }, + { + "key": "resourceBookingId", + "value": "{{resourceBookingId}}", + "disabled": true + }, + { + "key": "resourceBookingIds", + "value": "{{resourceBookingId}},{{resourceBookingIdCreatedByM2M}}", + "disabled": true + }, + { + "key": "paymentStatus", + "value": "pending", + "disabled": true + }, + { + "key": "startDate", + "value": "2021-03-14", + "disabled": true + }, + { + "key": "endDate", + "value": "2021-03-20", + "disabled": true + }, + { + "key": "userHandle", + "value": "pshah_manager", + "disabled": true + }, + { + "key": "projectId", + "value": "16843", + "disabled": true + } + ] + } + }, + "response": [] + }, + { + "name": "search work periods with connect user", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_connectUser}}" + } + ], + "url": { + "raw": "{{URL}}/workPeriods", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods" + ], + "query": [ + { + "key": "page", + "value": "1", + "disabled": true + }, + { + "key": "perPage", + "value": "5", + "disabled": true + }, + { + "key": "sortBy", + "value": "id", + "disabled": true + }, + { + "key": "sortOrder", + "value": "desc", + "disabled": true + }, + { + "key": "resourceBookingId", + "value": "{{resourceBookingId}}", + "disabled": true + }, + { + "key": "resourceBookingIds", + "value": "{{resourceBookingId}},{{resourceBookingIdCreatedByM2M}}", + "disabled": true + }, + { + "key": "paymentStatus", + "value": "pending", + "disabled": true + }, + { + "key": "startDate", + "value": "2021-03-14", + "disabled": true + }, + { + "key": "endDate", + "value": "2021-03-20", + "disabled": true + }, + { + "key": "userHandle", + "value": "pshah_manager", + "disabled": true + }, + { + "key": "projectId", + "value": "16843", + "disabled": true + } + ] + } + }, + "response": [] + }, + { + "name": "search work periods with member", + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_member}}" + } + ], + "url": { + "raw": "{{URL}}/workPeriods", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods" + ], + "query": [ + { + "key": "page", + "value": "1", + "disabled": true + }, + { + "key": "perPage", + "value": "5", + "disabled": true + }, + { + "key": "sortBy", + "value": "id", + "disabled": true + }, + { + "key": "sortOrder", + "value": "desc", + "disabled": true + }, + { + "key": "resourceBookingId", + "value": "{{resourceBookingId}}", + "disabled": true + }, + { + "key": "resourceBookingIds", + "value": "{{resourceBookingId}},{{resourceBookingIdCreatedByM2M}}", + "disabled": true + }, + { + "key": "paymentStatus", + "value": "pending", + "disabled": true + }, + { + "key": "startDate", + "value": "2021-03-14", + "disabled": true + }, + { + "key": "endDate", + "value": "2021-03-20", + "disabled": true + }, + { + "key": "userHandle", + "value": "pshah_manager", + "disabled": true + }, + { + "key": "projectId", + "value": "16843", + "disabled": true + } + ] + } + }, + "response": [] + }, + { + "name": "search work periods with invalid token", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 401', function () {\r", + " pm.response.to.have.status(401);\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer invalid_token" + } + ], + "url": { + "raw": "{{URL}}/workPeriods", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods" + ], + "query": [ + { + "key": "page", + "value": "1", + "disabled": true + }, + { + "key": "perPage", + "value": "5", + "disabled": true + }, + { + "key": "sortBy", + "value": "id", + "disabled": true + }, + { + "key": "sortOrder", + "value": "desc", + "disabled": true + }, + { + "key": "resourceBookingId", + "value": "{{resourceBookingId}}", + "disabled": true + }, + { + "key": "resourceBookingIds", + "value": "{{resourceBookingId}},{{resourceBookingIdCreatedByM2M}}", + "disabled": true + }, + { + "key": "paymentStatus", + "value": "pending", + "disabled": true + }, + { + "key": "startDate", + "value": "2021-03-14", + "disabled": true + }, + { + "key": "endDate", + "value": "2021-03-20", + "disabled": true + }, + { + "key": "userHandle", + "value": "pshah_manager", + "disabled": true + }, + { + "key": "projectId", + "value": "111", + "disabled": true + } + ] + } + }, + "response": [] + }, + { + "name": "put work period with booking manager", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodId}}" + ] + } + }, + "response": [] + }, + { + "name": "put work period with m2m update", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_m2m_update_work_period}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-14\",\r\n \"endDate\": \"2021-03-20\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodIdCreatedByM2M}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodIdCreatedByM2M}}" + ] + } + }, + "response": [] + }, + { + "name": "put work period with connect user", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 403', function () {\r", + " pm.response.to.have.status(403);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_connectUser}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-21\",\r\n \"endDate\": \"2021-03-27\",\r\n \"daysWorked\": 3,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"cancelled\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodId}}" + ] + } + }, + "response": [] + }, + { + "name": "put work period with member", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 403', function () {\r", + " pm.response.to.have.status(403);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_member}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-21\",\r\n \"endDate\": \"2021-03-27\",\r\n \"daysWorked\": 3,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"cancelled\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodId}}" + ] + } + }, + "response": [] + }, + { + "name": "put work period with user id not exist", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"Bad Request\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_userId_not_exist}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-21\",\r\n \"endDate\": \"2021-03-27\",\r\n \"daysWorked\": 3,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"cancelled\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodId}}" + ] + } + }, + "response": [] + }, + { + "name": "put work period with invalid token", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 401', function () {\r", + " pm.response.to.have.status(401);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"Invalid Token.\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer invalid_token" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-21\",\r\n \"endDate\": \"2021-03-27\",\r\n \"daysWorked\": 3,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"cancelled\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodId}}" + ] + } + }, + "response": [] + }, + { + "name": "put work period with missing parameter 1", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"\\\"data.resourceBookingId\\\" is required\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodId}}" + ] + } + }, + "response": [] + }, + { + "name": "put work period with missing parameter 2", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"\\\"data.endDate\\\" is required\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodId}}" + ] + } + }, + "response": [] + }, + { + "name": "put work period with missing parameter 3", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"\\\"data.paymentStatus\\\" is required\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodId}}" + ] + } + }, + "response": [] + }, + { + "name": "put work period with invalid parameter 1", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"\\\"data.resourceBookingId\\\" must be a valid GUID\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"aaa-aaa\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodId}}" + ] + } + }, + "response": [] + }, + { + "name": "put work period with invalid parameter 2", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"\\\"data.startDate\\\" must be in YYYY-MM-DD format\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"07-03-2021\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodId}}" + ] + } + }, + "response": [] + }, + { + "name": "put work period with invalid parameter 3", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"startDate should be always Sunday\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-06\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodId}}" + ] + } + }, + "response": [] + }, + { + "name": "put work period with invalid parameter 4", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"endDate should be always the next Saturday\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-14\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodId}}" + ] + } + }, + "response": [] + }, + { + "name": "put work period with invalid parameter 5", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"\\\"data.daysWorked\\\" must be a number\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": \"aa\",\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodId}}" + ] + } + }, + "response": [] + }, + { + "name": "put work period with invalid parameter 6", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(`Key (resource_booking_id, start_date, end_date)=(${pm.environment.get('resourceBookingId')}, 2021-03-14, 2021-03-20) already exists.`)\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-14\",\r\n \"endDate\": \"2021-03-20\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodId}}" + ] + } + }, + "response": [] + }, + { + "name": "put work period with invalid parameter 7", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"\\\"data.paymentStatus\\\" must be one of [pending, partially-completed, completed, cancelled]\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"paid\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodId}}" + ] + } + }, + "response": [] + }, + { + "name": "patch work period with booking manager", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodId}}" + ] + } + }, + "response": [] + }, + { + "name": "patch work period with m2m update", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_m2m_update_work_period}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-14\",\r\n \"endDate\": \"2021-03-20\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodIdCreatedByM2M}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodIdCreatedByM2M}}" + ] + } + }, + "response": [] + }, + { + "name": "patch work period with connect user", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 403', function () {\r", + " pm.response.to.have.status(403);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_connectUser}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-21\",\r\n \"endDate\": \"2021-03-27\",\r\n \"daysWorked\": 3,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"cancelled\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodId}}" + ] + } + }, + "response": [] + }, + { + "name": "patch work period with member", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 403', function () {\r", + " pm.response.to.have.status(403);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_member}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-21\",\r\n \"endDate\": \"2021-03-27\",\r\n \"daysWorked\": 3,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"cancelled\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodId}}" + ] + } + }, + "response": [] + }, + { + "name": "patch work period with user id not exist", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"Bad Request\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_userId_not_exist}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-21\",\r\n \"endDate\": \"2021-03-27\",\r\n \"daysWorked\": 3,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"cancelled\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodId}}" + ] + } + }, + "response": [] + }, + { + "name": "patch work period with invalid token", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 401', function () {\r", + " pm.response.to.have.status(401);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"Invalid Token.\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer invalid_token" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-21\",\r\n \"endDate\": \"2021-03-27\",\r\n \"daysWorked\": 3,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"cancelled\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodId}}" + ] + } + }, + "response": [] + }, + { + "name": "patch work period with invalid parameter 1", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"\\\"data.resourceBookingId\\\" must be a valid GUID\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"aaa-aaa\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodId}}" + ] + } + }, + "response": [] + }, + { + "name": "patch work period with invalid parameter 2", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"\\\"data.startDate\\\" must be in YYYY-MM-DD format\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"07-03-2021\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodId}}" + ] + } + }, + "response": [] + }, + { + "name": "patch work period with invalid parameter 3", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"startDate should be always Sunday\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-06\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodId}}" + ] + } + }, + "response": [] + }, + { + "name": "patch work period with invalid parameter 4", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"endDate should be always the next Saturday\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-14\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodId}}" + ] + } + }, + "response": [] + }, + { + "name": "patch work period with invalid parameter 5", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"\\\"data.daysWorked\\\" must be a number\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": \"aa\",\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodId}}" + ] + } + }, + "response": [] + }, + { + "name": "patch work period with invalid parameter 6", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(`Key (resource_booking_id, start_date, end_date)=(${pm.environment.get('resourceBookingId')}, 2021-03-14, 2021-03-20) already exists.`)\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-14\",\r\n \"endDate\": \"2021-03-20\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodId}}" + ] + } + }, + "response": [] + }, + { + "name": "patch work period with invalid parameter 7", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"\\\"data.paymentStatus\\\" must be one of [pending, partially-completed, completed, cancelled]\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resourceBookingId}}\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"paid\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodId}}" + ] + } + }, + "response": [] + }, + { + "name": "delete work period with member", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 403', function () {\r", + " pm.response.to.have.status(403);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_member}}" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodId}}" + ] + } + }, + "response": [] + }, + { + "name": "delete work period with connect user", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 403', function () {\r", + " pm.response.to.have.status(403);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_connectUser}}" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodId}}" + ] + } + }, + "response": [] + }, + { + "name": "delete work period with booking manager", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 204', function () {\r", + " pm.response.to.have.status(204);\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodId}}" + ] + } + }, + "response": [] + }, + { + "name": "delete work period with m2m delete", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 204', function () {\r", + " pm.response.to.have.status(204);\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_m2m_delete_work_period}}" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodIdCreatedByM2M}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodIdCreatedByM2M}}" + ] + } + }, + "response": [] + }, + { + "name": "delete work period with invalid token", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 401', function () {\r", + " pm.response.to.have.status(401);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"Invalid Token.\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer invalid_token" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodId}}" + ] + } + }, + "response": [] + }, + { + "name": "delete work period not found", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 404', function () {\r", + " pm.response.to.have.status(404);\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodId}}" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "Taas Teams", + "item": [ + { + "name": "GET /taas-teams", + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_bookingManager}}", + "type": "text" + } + ], + "url": { + "raw": "{{URL}}/taas-teams?perPage=10&page=1&name=*taas*&sortBy=lastActivityAt&sortOrder=desc", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams" + ], + "query": [ + { + "key": "perPage", + "value": "10" + }, + { + "key": "page", + "value": "1" + }, + { + "key": "name", + "value": "*taas*", + "description": "case-insensitive; support wildcard match" + }, + { + "key": "sortBy", + "value": "lastActivityAt", + "description": "allows: createdAt, updatedAt, lastActivityAt, id, status, name, type, best match" + }, + { + "key": "sortOrder", + "value": "desc", + "description": "allows: asc, desc" + } + ] + } + }, + "response": [] + }, + { + "name": "GET /taas-teams with booking manager", + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_bookingManager}}", + "type": "text" + } + ], + "url": { + "raw": "{{URL}}/taas-teams?perPage=10&page=1&name=*taas*&sortBy=lastActivityAt&sortOrder=desc", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams" + ], + "query": [ + { + "key": "perPage", + "value": "10" + }, + { + "key": "page", + "value": "1" + }, + { + "key": "name", + "value": "*taas*", + "description": "case-insensitive; support wildcard match" + }, + { + "key": "sortBy", + "value": "lastActivityAt", + "description": "allows: createdAt, updatedAt, lastActivityAt, id, status, name, type, best match" + }, + { + "key": "sortOrder", + "value": "desc", + "description": "allows: asc, desc" + } + ] + } + }, + "response": [] + }, + { + "name": "GET /taas-teams with m2m read", + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_m2m_read_taas_team}}" + } + ], + "url": { + "raw": "{{URL}}/taas-teams", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams" + ] + } + }, + "response": [] + }, + { + "name": "GET /taas-teams/:id", + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_bookingManager}}", + "type": "text" + } + ], + "url": { + "raw": "{{URL}}/taas-teams/{{projectId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + "{{projectId}}" + ] + } + }, + "response": [] + }, + { + "name": "GET /taas-teams/:id with booking manager", + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_bookingManager}}", + "type": "text" + } + ], + "url": { + "raw": "{{URL}}/taas-teams/:projectId", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + ":projectId" + ], + "variable": [ + { + "key": "projectId", + "value": "16705" + } + ] + } + }, + "response": [] + }, + { + "name": "GET /taas-teams/:id with m2m read", + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_m2m_read_taas_team}}" + } + ], + "url": { + "raw": "{{URL}}/taas-teams/{{projectId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + "{{projectId}}" + ] + } + }, + "response": [] + }, + { + "name": "GET /taas-teams/:id/jobs/:jobId", + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_bookingManager}}", + "type": "text" + } + ], + "url": { + "raw": "{{URL}}/taas-teams/{{projectId}}/jobs/{{jobId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + "{{projectId}}", + "jobs", + "{{jobId}}" + ] + } + }, + "response": [] + }, + { + "name": "GET /taas-teams/:id/jobs/:jobId with booking manager", + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_bookingManager}}", + "type": "text" + } + ], + "url": { + "raw": "{{URL}}/taas-teams/:projectId/jobs/:jobId", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + ":projectId", + "jobs", + ":jobId" + ], + "variable": [ + { + "key": "projectId", + "value": "16705" + }, + { + "key": "jobId", + "value": "948a25a6-086f-4a96-aad5-9ccd2d3e87b2" + } + ] + } + }, + "response": [] + }, + { + "name": "GET /taas-teams/:id/jobs/:jobId with m2m read", + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_m2m_read_taas_team}}" + } + ], + "url": { + "raw": "{{URL}}/taas-teams/{{projectId}}/jobs/{{jobId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + "{{projectId}}", + "jobs", + "{{jobId}}" + ] + } + }, + "response": [] + }, + { + "name": "GET /taas-teams/skills", + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_member}}", + "type": "text" + } + ], + "url": { + "raw": "{{URL}}/taas-teams/skills?perPage=10&page=1&orderBy=name", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + "skills" + ], + "query": [ + { + "key": "perPage", + "value": "10" + }, + { + "key": "page", + "value": "1" + }, + { + "key": "orderBy", + "value": "name", + "description": "possible values are defined by /v5/skills" + } + ] + } + }, + "response": [] + }, + { + "name": "POST /taas-teams/email - team-issue-report", + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_member}}", + "type": "text" + }, + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"template\": \"team-issue-report\",\n \"data\": {\n \"projectName\": \"TaaS Project Name\",\n \"projectId\": 12345,\n \"reportText\": \"I have issue with ...\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-teams/email", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + "email" + ] + } + }, + "response": [] + }, + { + "name": "POST /taas-teams/email - member-issue-report", + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_member}}" + }, + { + "key": "Content-Type", + "type": "text", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"template\": \"member-issue-report\",\n \"data\": {\n \"projectName\": \"TaaS Project Name\",\n \"projectId\": 12345,\n \"userHandle\": \"pshah_manager\",\n \"reportText\": \"I have issue with ...\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-teams/email", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + "email" + ] + } + }, + "response": [] + }, + { + "name": "POST /taas-teams/email - extension-request", + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_member}}" + }, + { + "key": "Content-Type", + "type": "text", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"template\": \"extension-request\",\n \"data\": {\n \"projectName\": \"TaaS Project Name\",\n \"projectId\": 12345,\n \"userHandle\": \"pshah_manager\",\n \"reportText\": \"I would like to keep working with this member for 2 months...\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-teams/email", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + "email" + ] + } + }, + "response": [] + }, + { + "name": "POST /taas-teams/:id/members", + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + }, + { + "key": "Content-Type", + "type": "text", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"handles\": [\n \"tester1234\",\n \"non-existing\"\n ],\n \"emails\": [\n \"non-existing@domain.com\",\n \"email@domain.com\"\n ]\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-teams/:id/members", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + ":id", + "members" + ], + "variable": [ + { + "key": "id", + "value": "16705" + } + ] + } + }, + "response": [] + }, + { + "name": "GET /taas-teams/:id/members", + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + }, + { + "key": "Content-Type", + "type": "text", + "value": "application/json" + } + ], + "url": { + "raw": "{{URL}}/taas-teams/:id/members?role=customer&fields=id,userId,role,createdAt,updatedAt,createdBy,updatedBy,handle,photoURL,workingHourStart,workingHourEnd,timeZone,email", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + ":id", + "members" + ], + "query": [ + { + "key": "role", + "value": "customer" + }, + { + "key": "fields", + "value": "id,userId,role,createdAt,updatedAt,createdBy,updatedBy,handle,photoURL,workingHourStart,workingHourEnd,timeZone,email" + } + ], + "variable": [ + { + "key": "id", + "value": "16705" + } + ] + } + }, + "response": [] + }, + { + "name": "GET /taas-teams/:id/invites", + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + }, + { + "key": "Content-Type", + "type": "text", + "value": "application/json" + } + ], + "url": { + "raw": "{{URL}}/taas-teams/:id/invites?fields=createdAt,deletedAt,role,updatedBy,createdBy,id,projectId,userId,email,deletedBy,updatedAt,status", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + ":id", + "invites" + ], + "query": [ + { + "key": "fields", + "value": "createdAt,deletedAt,role,updatedBy,createdBy,id,projectId,userId,email,deletedBy,updatedAt,status" + } + ], + "variable": [ + { + "key": "id", + "value": "16705" + } + ] + } + }, + "response": [] + }, + { + "name": "DELETE /taas-teams/:id/members/:projectMemberId", + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + }, + { + "key": "Content-Type", + "type": "text", + "value": "application/json" + } + ], + "url": { + "raw": "{{URL}}/taas-teams/:id/members/:projectMemberId", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + ":id", + "members", + ":projectMemberId" + ], + "variable": [ + { + "key": "id", + "value": "16705" + }, + { + "key": "projectMemberId", + "value": "14327" + } + ] + } + }, + "response": [] + }, + { + "name": "GET /taas-teams/me", + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_member}}" + } + ], + "url": { + "raw": "{{URL}}/taas-teams/me", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + "me" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "health check", + "item": [ + { + "name": "health check", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{URL}}/health", + "host": [ + "{{URL}}" + ], + "path": [ + "health" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "Create Demo Data For Team", + "item": [ + { + "name": "Get Users", + "item": [ + { + "name": "Get Users", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var data = JSON.parse(responseBody);", + "", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "var demoUsers = 20;", + "", + "pm.test('We need to have at least ' + demoUsers + ' demo userIds. Define them in {{demoUserIdN}} variables.', function () {", + " for (var i = 0; i < demoUsers; i++) {", + " var variableName = \"demoUserId\" + (i + 1);", + " var existentValue = pm.variables.get(variableName);", + " var user = data[i];", + "", + " pm.expect(!!user || !!existentValue).to.be.true;", + "", + " postman.setEnvironmentVariable(variableName, user.id);", + " }", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{token_bookingManager}}", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "https://api.topcoder-dev.com/v5/users?perPage=20", + "protocol": "https", + "host": [ + "api", + "topcoder-dev", + "com" + ], + "path": [ + "v5", + "users" + ], + "query": [ + { + "key": "perPage", + "value": "20" + } + ] + } + }, + "response": [] + } + ] + }, + { + "name": "Create job #1 \"sourcing\"", + "item": [ + { + "name": "create job #1", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var data = JSON.parse(responseBody);\r", + "\r", + "pm.test(\"Successful POST request\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);\r", + "});\r", + "\r", + "postman.setEnvironmentVariable(\"demoJobId1\",data.id);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"projectId\": {{projectId}},\n \"externalId\": \"0\",\n \"description\": \"taas-demo-job1\",\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\n \"duration\": 1,\n \"numPositions\": 13,\n \"resourceType\": \"Dummy Resource Type\",\n \"rateType\": \"weekly\",\n \"workload\": \"full-time\",\n \"skills\": [\n \"ee4c50c1-c8c3-475e-b6b6-edbd136a19d6\",\n \"89139c80-d0a2-47c2-aa16-14589d5afd10\",\n \"9f2d9127-6a2e-4506-ad76-c4ab63577b09\",\n \"9515e7ee-83b6-49d1-ba5c-6c59c5a8ef1b\",\n \"c854ab55-5922-4be1-8ecc-b3bc1f8629af\",\n \"8456002e-fa2d-44f0-b0e7-86b1c02b6e4c\",\n \"114b4ec8-805e-4c60-b351-14a955a991a9\",\n \"213408aa-f16f-46c8-bc57-9e569cee3f11\",\n \"b37a48db-f775-4e4e-b403-8ad1d234cdea\",\n \"99b930b5-1b91-4df1-8b17-d9307107bb51\",\n \"6388a632-c3ad-4525-9a73-66a527c03672\",\n \"23839f38-6f19-4de9-9d28-f020056bca73\",\n \"289e42a3-23e9-49be-88e1-6deb93cd8c31\",\n \"b403f209-63b5-42bc-9b5f-1564416640d8\"\n ],\n \"title\": \"Dummy title - at most 64 characters\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobs", + "host": [ + "{{URL}}" + ], + "path": [ + "jobs" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "Create job #2 \"in-review\"", + "item": [ + { + "name": "create job #2", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var data = JSON.parse(responseBody);\r", + "\r", + "pm.test(\"Successful POST request\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);\r", + "});\r", + "\r", + "postman.setEnvironmentVariable(\"demoJobId2\",data.id);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"projectId\": {{projectId}},\n \"externalId\": \"0\",\n \"description\": \"taas-demo-job2\",\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\n \"duration\": 1,\n \"numPositions\": 7,\n \"resourceType\": \"Dummy Resource Type\",\n \"rateType\": \"weekly\",\n \"workload\": \"full-time\",\n \"skills\": [\n \"213408aa-f16f-46c8-bc57-9e569cee3f11\",\n \"b37a48db-f775-4e4e-b403-8ad1d234cdea\",\n \"99b930b5-1b91-4df1-8b17-d9307107bb51\",\n \"6388a632-c3ad-4525-9a73-66a527c03672\",\n \"23839f38-6f19-4de9-9d28-f020056bca73\",\n \"289e42a3-23e9-49be-88e1-6deb93cd8c31\",\n \"b403f209-63b5-42bc-9b5f-1564416640d8\"\n ],\n \"title\": \"Dummy title - at most 64 characters\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobs", + "host": [ + "{{URL}}" + ], + "path": [ + "jobs" + ] + } + }, + "response": [] + }, + { + "name": "create job #2 candidate 1", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var data = JSON.parse(responseBody);\r", + "\r", + "pm.test(\"Successful POST request\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);\r", + "});\r", + "\r", + "postman.setEnvironmentVariable(\"demoJob1candidateId1\",data.id);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"jobId\": \"{{demoJobId2}}\",\r\n \"userId\": \"{{demoUserId1}}\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobCandidates", + "host": [ + "{{URL}}" + ], + "path": [ + "jobCandidates" + ] + } + }, + "response": [] + }, + { + "name": "create job #2 candidate 2", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var data = JSON.parse(responseBody);\r", + "\r", + "pm.test(\"Successful POST request\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);\r", + "});\r", + "\r", + "postman.setEnvironmentVariable(\"demoJob1candidateId2\",data.id);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"jobId\": \"{{demoJobId2}}\",\r\n \"userId\": \"{{demoUserId2}}\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobCandidates", + "host": [ + "{{URL}}" + ], + "path": [ + "jobCandidates" + ] + } + }, + "response": [] + }, + { + "name": "create job #2 candidate 3", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Successful POST request\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"jobId\": \"{{demoJobId2}}\",\r\n \"userId\": \"{{demoUserId3}}\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobCandidates", + "host": [ + "{{URL}}" + ], + "path": [ + "jobCandidates" + ] + } + }, + "response": [] + }, + { + "name": "create job #2 candidate 4", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Successful POST request\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"jobId\": \"{{demoJobId2}}\",\r\n \"userId\": \"{{demoUserId4}}\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobCandidates", + "host": [ + "{{URL}}" + ], + "path": [ + "jobCandidates" + ] + } + }, + "response": [] + }, + { + "name": "create job #2 candidate 5", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Successful POST request\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"jobId\": \"{{demoJobId2}}\",\r\n \"userId\": \"{{demoUserId5}}\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobCandidates", + "host": [ + "{{URL}}" + ], + "path": [ + "jobCandidates" + ] + } + }, + "response": [] + }, + { + "name": "create job #2 candidate 6", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Successful POST request\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"jobId\": \"{{demoJobId2}}\",\r\n \"userId\": \"{{demoUserId6}}\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobCandidates", + "host": [ + "{{URL}}" + ], + "path": [ + "jobCandidates" + ] + } + }, + "response": [] + }, + { + "name": "create job #2 candidate 7", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Successful POST request\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"jobId\": \"{{demoJobId2}}\",\r\n \"userId\": \"{{demoUserId7}}\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobCandidates", + "host": [ + "{{URL}}" + ], + "path": [ + "jobCandidates" + ] + } + }, + "response": [] + }, + { + "name": "create job #2 candidate 8", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Successful POST request\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"jobId\": \"{{demoJobId2}}\",\r\n \"userId\": \"{{demoUserId8}}\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobCandidates", + "host": [ + "{{URL}}" + ], + "path": [ + "jobCandidates" + ] + } + }, + "response": [] + }, + { + "name": "create job #2 candidate 9", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Successful POST request\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"jobId\": \"{{demoJobId2}}\",\r\n \"userId\": \"{{demoUserId9}}\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobCandidates", + "host": [ + "{{URL}}" + ], + "path": [ + "jobCandidates" + ] + } + }, + "response": [] + }, + { + "name": "create job #2 candidate 10", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Successful POST request\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"jobId\": \"{{demoJobId2}}\",\r\n \"userId\": \"{{demoUserId10}}\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobCandidates", + "host": [ + "{{URL}}" + ], + "path": [ + "jobCandidates" + ] + } + }, + "response": [] + }, + { + "name": "update job #2 candidate 1 to \"shortlist\"", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Successful PATCH request\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"status\": \"shortlist\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobCandidates/{{demoJob1candidateId1}}", + "host": [ + "{{URL}}" + ], + "path": [ + "jobCandidates", + "{{demoJob1candidateId1}}" + ] + } + }, + "response": [] + }, + { + "name": "update job #2 candidate 2 to \"rejected\"", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Successful PATCH request\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"status\": \"rejected\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobCandidates/{{demoJob1candidateId2}}", + "host": [ + "{{URL}}" + ], + "path": [ + "jobCandidates", + "{{demoJob1candidateId2}}" + ] + } + }, + "response": [] + }, + { + "name": "update job #2 status to \"in-review\"", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Successful PATCH request\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"status\": \"in-review\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobs/{{demoJobId2}}", + "host": [ + "{{URL}}" + ], + "path": [ + "jobs", + "{{demoJobId2}}" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "Create job #3 \"assigned\"", + "item": [ + { + "name": "create job #3", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var data = JSON.parse(responseBody);\r", + "\r", + "pm.test(\"Successful POST request\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);\r", + "});\r", + "\r", + "postman.setEnvironmentVariable(\"demoJobId3\",data.id);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"projectId\": {{projectId}},\n \"externalId\": \"0\",\n \"description\": \"taas-demo-job3\",\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\n \"duration\": 1,\n \"numPositions\": 7,\n \"resourceType\": \"Dummy Resource Type\",\n \"rateType\": \"weekly\",\n \"workload\": \"full-time\",\n \"skills\": [],\n \"title\": \"Dummy title - at most 64 characters\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobs", + "host": [ + "{{URL}}" + ], + "path": [ + "jobs" + ] + } + }, + "response": [] + }, + { + "name": "create job #3 candidate 11", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Successful POST request\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"jobId\": \"{{demoJobId3}}\",\r\n \"userId\": \"{{demoUserId11}}\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobCandidates", + "host": [ + "{{URL}}" + ], + "path": [ + "jobCandidates" + ] + } + }, + "response": [] + }, + { + "name": "create job #3 candidate 12", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Successful POST request\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"jobId\": \"{{demoJobId3}}\",\r\n \"userId\": \"{{demoUserId12}}\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobCandidates", + "host": [ + "{{URL}}" + ], + "path": [ + "jobCandidates" + ] + } + }, + "response": [] + }, + { + "name": "create job #3 candidate 13", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Successful POST request\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"jobId\": \"{{demoJobId3}}\",\r\n \"userId\": \"{{demoUserId13}}\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobCandidates", + "host": [ + "{{URL}}" + ], + "path": [ + "jobCandidates" + ] + } + }, + "response": [] + }, + { + "name": "create job #3 candidate 14", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Successful POST request\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", "raw": "{\r\n \"jobId\": \"{{demoJobId3}}\",\r\n \"userId\": \"{{demoUserId14}}\"\r\n}", "options": { "raw": { @@ -8927,7 +13416,232 @@ "response": [] }, { - "name": "create job #3 candidate 15", + "name": "create job #3 candidate 15", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Successful POST request\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"jobId\": \"{{demoJobId3}}\",\r\n \"userId\": \"{{demoUserId15}}\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobCandidates", + "host": [ + "{{URL}}" + ], + "path": [ + "jobCandidates" + ] + } + }, + "response": [] + }, + { + "name": "create job #3 candidate 16", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Successful POST request\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"jobId\": \"{{demoJobId3}}\",\r\n \"userId\": \"{{demoUserId16}}\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobCandidates", + "host": [ + "{{URL}}" + ], + "path": [ + "jobCandidates" + ] + } + }, + "response": [] + }, + { + "name": "create job #3 candidate 17", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Successful POST request\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"jobId\": \"{{demoJobId3}}\",\r\n \"userId\": \"{{demoUserId17}}\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobCandidates", + "host": [ + "{{URL}}" + ], + "path": [ + "jobCandidates" + ] + } + }, + "response": [] + }, + { + "name": "create job #3 candidate 18", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Successful POST request\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"jobId\": \"{{demoJobId3}}\",\r\n \"userId\": \"{{demoUserId18}}\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobCandidates", + "host": [ + "{{URL}}" + ], + "path": [ + "jobCandidates" + ] + } + }, + "response": [] + }, + { + "name": "create job #3 candidate 19", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Successful POST request\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"jobId\": \"{{demoJobId3}}\",\r\n \"userId\": \"{{demoUserId19}}\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobCandidates", + "host": [ + "{{URL}}" + ], + "path": [ + "jobCandidates" + ] + } + }, + "response": [] + }, + { + "name": "create job #3 candidate 20", "event": [ { "listen": "test", @@ -8952,7 +13666,137 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"jobId\": \"{{demoJobId3}}\",\r\n \"userId\": \"{{demoUserId15}}\"\r\n}", + "raw": "{\r\n \"jobId\": \"{{demoJobId3}}\",\r\n \"userId\": \"{{demoUserId20}}\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobCandidates", + "host": [ + "{{URL}}" + ], + "path": [ + "jobCandidates" + ] + } + }, + "response": [] + }, + { + "name": "create job 3 resource booking 11", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var data = JSON.parse(responseBody);\r", + "\r", + "pm.test(\"Successful POST request\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);\r", + "});\r", + "\r", + "postman.setEnvironmentVariable(\"demoJob3resourceCandiateId11\",data.id);" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const startDate = new Date()", + "startDate.setDate(startDate.getDate() - 3);", + "", + "const endDate = new Date()", + "endDate.setDate(endDate.getDate() + 3);", + "", + "postman.setEnvironmentVariable(\"resourceStartDate\", startDate.toUTCString());", + "postman.setEnvironmentVariable(\"resourceEndDate\", endDate.toUTCString());" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"{{demoUserId11}}\",\r\n \"jobId\": \"{{demoJobId3}}\",\r\n \"startDate\": \"{{resourceStartDate}}\",\r\n \"endDate\": \"{{resourceEndDate}}\",\r\n \"memberRate\": 1000,\r\n \"customerRate\": 1200,\r\n \"rateType\": \"weekly\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/resourceBookings", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings" + ] + } + }, + "response": [] + }, + { + "name": "create job 3 resource booking 12", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var data = JSON.parse(responseBody);\r", + "\r", + "pm.test(\"Successful POST request\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);\r", + "});\r", + "\r", + "postman.setEnvironmentVariable(\"demoJob3resourceCandiateId12\",data.id);" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const startDate = new Date()", + "startDate.setDate(startDate.getDate() - 3);", + "", + "const endDate = new Date()", + "endDate.setDate(endDate.getDate() + 3);", + "", + "postman.setEnvironmentVariable(\"resourceStartDate\", startDate.toUTCString());", + "postman.setEnvironmentVariable(\"resourceEndDate\", endDate.toUTCString());" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"{{demoUserId12}}\",\r\n \"jobId\": \"{{demoJobId3}}\",\r\n \"startDate\": \"{{resourceStartDate}}\",\r\n \"endDate\": \"{{resourceEndDate}}\",\r\n \"memberRate\": 1000,\r\n \"customerRate\": 1200,\r\n \"rateType\": \"weekly\"\r\n}", "options": { "raw": { "language": "json" @@ -8960,27 +13804,47 @@ } }, "url": { - "raw": "{{URL}}/jobCandidates", + "raw": "{{URL}}/resourceBookings", "host": [ "{{URL}}" ], "path": [ - "jobCandidates" + "resourceBookings" ] } }, "response": [] }, { - "name": "create job #3 candidate 16", + "name": "create job 3 resource booking 13", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test(\"Successful POST request\", function () {", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", - "});" + "var data = JSON.parse(responseBody);\r", + "\r", + "pm.test(\"Successful POST request\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);\r", + "});\r", + "\r", + "postman.setEnvironmentVariable(\"demoJob3resourceCandiateId13\",data.id);" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const startDate = new Date()", + "startDate.setDate(startDate.getDate() - 3);", + "", + "const endDate = new Date()", + "endDate.setDate(endDate.getDate() + 3);", + "", + "postman.setEnvironmentVariable(\"resourceStartDate\", startDate.toUTCString());", + "postman.setEnvironmentVariable(\"resourceEndDate\", endDate.toUTCString());" ], "type": "text/javascript" } @@ -8997,7 +13861,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"jobId\": \"{{demoJobId3}}\",\r\n \"userId\": \"{{demoUserId16}}\"\r\n}", + "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"{{demoUserId13}}\",\r\n \"jobId\": \"{{demoJobId3}}\",\r\n \"startDate\": \"{{resourceStartDate}}\",\r\n \"endDate\": \"{{resourceEndDate}}\",\r\n \"memberRate\": 1000,\r\n \"customerRate\": 1200,\r\n \"rateType\": \"weekly\"\r\n}", "options": { "raw": { "language": "json" @@ -9005,27 +13869,47 @@ } }, "url": { - "raw": "{{URL}}/jobCandidates", + "raw": "{{URL}}/resourceBookings", "host": [ "{{URL}}" ], "path": [ - "jobCandidates" + "resourceBookings" ] } }, "response": [] }, { - "name": "create job #3 candidate 17", + "name": "create job 3 resource booking 14", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test(\"Successful POST request\", function () {", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", - "});" + "var data = JSON.parse(responseBody);\r", + "\r", + "pm.test(\"Successful POST request\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);\r", + "});\r", + "\r", + "postman.setEnvironmentVariable(\"demoJob3resourceCandiateId14\",data.id);" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const startDate = new Date()", + "startDate.setDate(startDate.getDate() - 3);", + "", + "const endDate = new Date()", + "endDate.setDate(endDate.getDate() + 3);", + "", + "postman.setEnvironmentVariable(\"resourceStartDate\", startDate.toUTCString());", + "postman.setEnvironmentVariable(\"resourceEndDate\", endDate.toUTCString());" ], "type": "text/javascript" } @@ -9042,7 +13926,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"jobId\": \"{{demoJobId3}}\",\r\n \"userId\": \"{{demoUserId17}}\"\r\n}", + "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"{{demoUserId14}}\",\r\n \"jobId\": \"{{demoJobId3}}\",\r\n \"startDate\": \"{{resourceStartDate}}\",\r\n \"endDate\": \"{{resourceEndDate}}\",\r\n \"memberRate\": 1000,\r\n \"customerRate\": 1200,\r\n \"rateType\": \"weekly\"\r\n}", "options": { "raw": { "language": "json" @@ -9050,27 +13934,47 @@ } }, "url": { - "raw": "{{URL}}/jobCandidates", + "raw": "{{URL}}/resourceBookings", "host": [ "{{URL}}" ], "path": [ - "jobCandidates" + "resourceBookings" ] } }, "response": [] }, { - "name": "create job #3 candidate 18", + "name": "create job 3 resource booking 15", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test(\"Successful POST request\", function () {", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", - "});" + "var data = JSON.parse(responseBody);\r", + "\r", + "pm.test(\"Successful POST request\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);\r", + "});\r", + "\r", + "postman.setEnvironmentVariable(\"demoJob3resourceCandiateId15\",data.id);" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const startDate = new Date()", + "startDate.setDate(startDate.getDate() - 3);", + "", + "const endDate = new Date()", + "endDate.setDate(endDate.getDate() + 3);", + "", + "postman.setEnvironmentVariable(\"resourceStartDate\", startDate.toUTCString());", + "postman.setEnvironmentVariable(\"resourceEndDate\", endDate.toUTCString());" ], "type": "text/javascript" } @@ -9087,7 +13991,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"jobId\": \"{{demoJobId3}}\",\r\n \"userId\": \"{{demoUserId18}}\"\r\n}", + "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"{{demoUserId15}}\",\r\n \"jobId\": \"{{demoJobId3}}\",\r\n \"startDate\": \"{{resourceStartDate}}\",\r\n \"endDate\": \"{{resourceEndDate}}\",\r\n \"memberRate\": 1000,\r\n \"customerRate\": 1200,\r\n \"rateType\": \"weekly\"\r\n}", "options": { "raw": { "language": "json" @@ -9095,27 +13999,47 @@ } }, "url": { - "raw": "{{URL}}/jobCandidates", + "raw": "{{URL}}/resourceBookings", "host": [ "{{URL}}" ], "path": [ - "jobCandidates" + "resourceBookings" ] } }, "response": [] }, { - "name": "create job #3 candidate 19", + "name": "create job 3 resource booking 16", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test(\"Successful POST request\", function () {", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", - "});" + "var data = JSON.parse(responseBody);\r", + "\r", + "pm.test(\"Successful POST request\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);\r", + "});\r", + "\r", + "postman.setEnvironmentVariable(\"demoJob3resourceCandiateId16\",data.id);" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const startDate = new Date()", + "startDate.setDate(startDate.getDate() - 3);", + "", + "const endDate = new Date()", + "endDate.setDate(endDate.getDate() + 3);", + "", + "postman.setEnvironmentVariable(\"resourceStartDate\", startDate.toUTCString());", + "postman.setEnvironmentVariable(\"resourceEndDate\", endDate.toUTCString());" ], "type": "text/javascript" } @@ -9132,7 +14056,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"jobId\": \"{{demoJobId3}}\",\r\n \"userId\": \"{{demoUserId19}}\"\r\n}", + "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"{{demoUserId16}}\",\r\n \"jobId\": \"{{demoJobId3}}\",\r\n \"startDate\": \"{{resourceStartDate}}\",\r\n \"endDate\": \"{{resourceEndDate}}\",\r\n \"memberRate\": 800,\r\n \"customerRate\": 1000,\r\n \"rateType\": \"weekly\"\r\n}", "options": { "raw": { "language": "json" @@ -9140,27 +14064,47 @@ } }, "url": { - "raw": "{{URL}}/jobCandidates", + "raw": "{{URL}}/resourceBookings", "host": [ "{{URL}}" ], "path": [ - "jobCandidates" + "resourceBookings" ] } }, "response": [] }, { - "name": "create job #3 candidate 20", + "name": "create job 3 resource booking 17", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test(\"Successful POST request\", function () {", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", - "});" + "var data = JSON.parse(responseBody);\r", + "\r", + "pm.test(\"Successful POST request\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);\r", + "});\r", + "\r", + "postman.setEnvironmentVariable(\"demoJob3resourceCandiateId17\",data.id);" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const startDate = new Date()", + "startDate.setDate(startDate.getDate() - 3);", + "", + "const endDate = new Date()", + "endDate.setDate(endDate.getDate() + 3);", + "", + "postman.setEnvironmentVariable(\"resourceStartDate\", startDate.toUTCString());", + "postman.setEnvironmentVariable(\"resourceEndDate\", endDate.toUTCString());" ], "type": "text/javascript" } @@ -9177,7 +14121,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"jobId\": \"{{demoJobId3}}\",\r\n \"userId\": \"{{demoUserId20}}\"\r\n}", + "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"{{demoUserId17}}\",\r\n \"jobId\": \"{{demoJobId3}}\",\r\n \"startDate\": \"{{resourceStartDate}}\",\r\n \"endDate\": \"{{resourceEndDate}}\",\r\n \"memberRate\": 2000,\r\n \"customerRate\": 2500,\r\n \"rateType\": \"weekly\"\r\n}", "options": { "raw": { "language": "json" @@ -9185,19 +14129,19 @@ } }, "url": { - "raw": "{{URL}}/jobCandidates", + "raw": "{{URL}}/resourceBookings", "host": [ "{{URL}}" ], "path": [ - "jobCandidates" + "resourceBookings" ] } }, "response": [] }, { - "name": "create job 3 resource booking 11", + "name": "create job 3 resource booking 18", "event": [ { "listen": "test", @@ -9209,7 +14153,7 @@ " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);\r", "});\r", "\r", - "postman.setEnvironmentVariable(\"demoJob3resourceCandiateId11\",data.id);" + "postman.setEnvironmentVariable(\"demoJob3resourceCandiateId18\",data.id);" ], "type": "text/javascript" } @@ -9218,14 +14162,7 @@ "listen": "prerequest", "script": { "exec": [ - "const startDate = new Date()", - "startDate.setDate(startDate.getDate() - 3);", - "", - "const endDate = new Date()", - "endDate.setDate(endDate.getDate() + 3);", - "", - "postman.setEnvironmentVariable(\"resourceStartDate\", startDate.toUTCString());", - "postman.setEnvironmentVariable(\"resourceEndDate\", endDate.toUTCString());" + "" ], "type": "text/javascript" } @@ -9242,7 +14179,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"{{demoUserId11}}\",\r\n \"jobId\": \"{{demoJobId3}}\",\r\n \"startDate\": \"{{resourceStartDate}}\",\r\n \"endDate\": \"{{resourceEndDate}}\",\r\n \"memberRate\": 1000,\r\n \"customerRate\": 1200,\r\n \"rateType\": \"weekly\"\r\n}", + "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"{{demoUserId18}}\",\r\n \"jobId\": \"{{demoJobId3}}\",\r\n \"startDate\": \"2000-07-27T04:17:23.131Z\",\r\n \"endDate\": \"2000-09-27T04:17:23.131Z\",\r\n \"memberRate\": 3000,\r\n \"customerRate\": 3500,\r\n \"rateType\": \"weekly\"\r\n}", "options": { "raw": { "language": "json" @@ -9262,7 +14199,7 @@ "response": [] }, { - "name": "create job 3 resource booking 12", + "name": "create job 3 resource booking 19", "event": [ { "listen": "test", @@ -9274,23 +14211,7 @@ " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);\r", "});\r", "\r", - "postman.setEnvironmentVariable(\"demoJob3resourceCandiateId12\",data.id);" - ], - "type": "text/javascript" - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "const startDate = new Date()", - "startDate.setDate(startDate.getDate() - 3);", - "", - "const endDate = new Date()", - "endDate.setDate(endDate.getDate() + 3);", - "", - "postman.setEnvironmentVariable(\"resourceStartDate\", startDate.toUTCString());", - "postman.setEnvironmentVariable(\"resourceEndDate\", endDate.toUTCString());" + "postman.setEnvironmentVariable(\"demoJob3resourceCandiateId19\",data.id);" ], "type": "text/javascript" } @@ -9307,7 +14228,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"{{demoUserId12}}\",\r\n \"jobId\": \"{{demoJobId3}}\",\r\n \"startDate\": \"{{resourceStartDate}}\",\r\n \"endDate\": \"{{resourceEndDate}}\",\r\n \"memberRate\": 1000,\r\n \"customerRate\": 1200,\r\n \"rateType\": \"weekly\"\r\n}", + "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"{{demoUserId19}}\",\r\n \"jobId\": \"{{demoJobId3}}\",\r\n \"startDate\": \"2022-07-27T04:17:23.131Z\",\r\n \"endDate\": \"2022-09-27T04:17:23.131Z\",\r\n \"memberRate\": 1700,\r\n \"customerRate\": 1900,\r\n \"rateType\": \"weekly\"\r\n}", "options": { "raw": { "language": "json" @@ -9327,7 +14248,7 @@ "response": [] }, { - "name": "create job 3 resource booking 13", + "name": "create job 3 resource booking 20", "event": [ { "listen": "test", @@ -9339,7 +14260,7 @@ " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);\r", "});\r", "\r", - "postman.setEnvironmentVariable(\"demoJob3resourceCandiateId13\",data.id);" + "postman.setEnvironmentVariable(\"demoJob3resourceCandiateId20\",data.id);" ], "type": "text/javascript" } @@ -9362,7 +14283,52 @@ } ], "request": { - "method": "POST", + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"{{demoUserId20}}\",\r\n \"jobId\": \"{{demoJobId3}}\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 0,\r\n \"customerRate\": 0,\r\n \"rateType\": \"weekly\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/resourceBookings", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings" + ] + } + }, + "response": [] + }, + { + "name": "update job 3 resource booking 11 status to \"assigned\"", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Successful PATCH request\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", "header": [ { "key": "Authorization", @@ -9372,7 +14338,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"{{demoUserId13}}\",\r\n \"jobId\": \"{{demoJobId3}}\",\r\n \"startDate\": \"{{resourceStartDate}}\",\r\n \"endDate\": \"{{resourceEndDate}}\",\r\n \"memberRate\": 1000,\r\n \"customerRate\": 1200,\r\n \"rateType\": \"weekly\"\r\n}", + "raw": "{\r\n \"status\": \"assigned\"\r\n}", "options": { "raw": { "language": "json" @@ -9380,54 +14346,35 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings", + "raw": "{{URL}}/resourceBookings/{{demoJob3resourceCandiateId11}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings" + "resourceBookings", + "{{demoJob3resourceCandiateId11}}" ] } }, "response": [] }, { - "name": "create job 3 resource booking 14", + "name": "update job 3 resource booking 12 status to \"in-review\"", "event": [ { "listen": "test", "script": { "exec": [ - "var data = JSON.parse(responseBody);\r", - "\r", - "pm.test(\"Successful POST request\", function () {\r", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);\r", - "});\r", - "\r", - "postman.setEnvironmentVariable(\"demoJob3resourceCandiateId14\",data.id);" - ], - "type": "text/javascript" - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "const startDate = new Date()", - "startDate.setDate(startDate.getDate() - 3);", - "", - "const endDate = new Date()", - "endDate.setDate(endDate.getDate() + 3);", - "", - "postman.setEnvironmentVariable(\"resourceStartDate\", startDate.toUTCString());", - "postman.setEnvironmentVariable(\"resourceEndDate\", endDate.toUTCString());" + "pm.test(\"Successful PATCH request\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", + "});" ], "type": "text/javascript" } } ], "request": { - "method": "POST", + "method": "PATCH", "header": [ { "key": "Authorization", @@ -9437,7 +14384,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"{{demoUserId14}}\",\r\n \"jobId\": \"{{demoJobId3}}\",\r\n \"startDate\": \"{{resourceStartDate}}\",\r\n \"endDate\": \"{{resourceEndDate}}\",\r\n \"memberRate\": 1000,\r\n \"customerRate\": 1200,\r\n \"rateType\": \"weekly\"\r\n}", + "raw": "{\r\n \"status\": \"in-review\"\r\n}", "options": { "raw": { "language": "json" @@ -9445,54 +14392,35 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings", + "raw": "{{URL}}/resourceBookings/{{demoJob3resourceCandiateId12}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings" + "resourceBookings", + "{{demoJob3resourceCandiateId12}}" ] } }, "response": [] }, { - "name": "create job 3 resource booking 15", + "name": "update job 3 resource booking 13 status to \"closed\"", "event": [ { "listen": "test", "script": { "exec": [ - "var data = JSON.parse(responseBody);\r", - "\r", - "pm.test(\"Successful POST request\", function () {\r", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);\r", - "});\r", - "\r", - "postman.setEnvironmentVariable(\"demoJob3resourceCandiateId15\",data.id);" - ], - "type": "text/javascript" - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "const startDate = new Date()", - "startDate.setDate(startDate.getDate() - 3);", - "", - "const endDate = new Date()", - "endDate.setDate(endDate.getDate() + 3);", - "", - "postman.setEnvironmentVariable(\"resourceStartDate\", startDate.toUTCString());", - "postman.setEnvironmentVariable(\"resourceEndDate\", endDate.toUTCString());" + "pm.test(\"Successful PATCH request\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", + "});" ], "type": "text/javascript" } } ], "request": { - "method": "POST", + "method": "PATCH", "header": [ { "key": "Authorization", @@ -9502,7 +14430,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"{{demoUserId15}}\",\r\n \"jobId\": \"{{demoJobId3}}\",\r\n \"startDate\": \"{{resourceStartDate}}\",\r\n \"endDate\": \"{{resourceEndDate}}\",\r\n \"memberRate\": 1000,\r\n \"customerRate\": 1200,\r\n \"rateType\": \"weekly\"\r\n}", + "raw": "{\r\n \"status\": \"closed\"\r\n}", "options": { "raw": { "language": "json" @@ -9510,54 +14438,35 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings", + "raw": "{{URL}}/resourceBookings/{{demoJob3resourceCandiateId13}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings" + "resourceBookings", + "{{demoJob3resourceCandiateId13}}" ] } }, "response": [] }, { - "name": "create job 3 resource booking 16", + "name": "update job 3 resource booking 14 status to \"cancelled\"", "event": [ { "listen": "test", "script": { "exec": [ - "var data = JSON.parse(responseBody);\r", - "\r", - "pm.test(\"Successful POST request\", function () {\r", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);\r", - "});\r", - "\r", - "postman.setEnvironmentVariable(\"demoJob3resourceCandiateId16\",data.id);" - ], - "type": "text/javascript" - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "const startDate = new Date()", - "startDate.setDate(startDate.getDate() - 3);", - "", - "const endDate = new Date()", - "endDate.setDate(endDate.getDate() + 3);", - "", - "postman.setEnvironmentVariable(\"resourceStartDate\", startDate.toUTCString());", - "postman.setEnvironmentVariable(\"resourceEndDate\", endDate.toUTCString());" + "pm.test(\"Successful PATCH request\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", + "});" ], "type": "text/javascript" } } ], "request": { - "method": "POST", + "method": "PATCH", "header": [ { "key": "Authorization", @@ -9567,7 +14476,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"{{demoUserId16}}\",\r\n \"jobId\": \"{{demoJobId3}}\",\r\n \"startDate\": \"{{resourceStartDate}}\",\r\n \"endDate\": \"{{resourceEndDate}}\",\r\n \"memberRate\": 800,\r\n \"customerRate\": 1000,\r\n \"rateType\": \"weekly\"\r\n}", + "raw": "{\r\n \"status\": \"cancelled\"\r\n}", "options": { "raw": { "language": "json" @@ -9575,54 +14484,35 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings", + "raw": "{{URL}}/resourceBookings/{{demoJob3resourceCandiateId14}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings" + "resourceBookings", + "{{demoJob3resourceCandiateId14}}" ] } }, "response": [] }, { - "name": "create job 3 resource booking 17", + "name": "update job 3 resource booking 15 status to \"sourcing\"", "event": [ { "listen": "test", "script": { "exec": [ - "var data = JSON.parse(responseBody);\r", - "\r", - "pm.test(\"Successful POST request\", function () {\r", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);\r", - "});\r", - "\r", - "postman.setEnvironmentVariable(\"demoJob3resourceCandiateId17\",data.id);" - ], - "type": "text/javascript" - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "const startDate = new Date()", - "startDate.setDate(startDate.getDate() - 3);", - "", - "const endDate = new Date()", - "endDate.setDate(endDate.getDate() + 3);", - "", - "postman.setEnvironmentVariable(\"resourceStartDate\", startDate.toUTCString());", - "postman.setEnvironmentVariable(\"resourceEndDate\", endDate.toUTCString());" + "pm.test(\"Successful PATCH request\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", + "});" ], "type": "text/javascript" } } ], "request": { - "method": "POST", + "method": "PATCH", "header": [ { "key": "Authorization", @@ -9632,7 +14522,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"{{demoUserId17}}\",\r\n \"jobId\": \"{{demoJobId3}}\",\r\n \"startDate\": \"{{resourceStartDate}}\",\r\n \"endDate\": \"{{resourceEndDate}}\",\r\n \"memberRate\": 2000,\r\n \"customerRate\": 2500,\r\n \"rateType\": \"weekly\"\r\n}", + "raw": "{\r\n \"status\": \"sourcing\"\r\n}", "options": { "raw": { "language": "json" @@ -9640,47 +14530,35 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings", + "raw": "{{URL}}/resourceBookings/{{demoJob3resourceCandiateId15}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings" + "resourceBookings", + "{{demoJob3resourceCandiateId15}}" ] } }, "response": [] }, { - "name": "create job 3 resource booking 18", + "name": "update job 3 resource booking 16 status to \"assigned\"", "event": [ { "listen": "test", "script": { "exec": [ - "var data = JSON.parse(responseBody);\r", - "\r", - "pm.test(\"Successful POST request\", function () {\r", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);\r", - "});\r", - "\r", - "postman.setEnvironmentVariable(\"demoJob3resourceCandiateId18\",data.id);" - ], - "type": "text/javascript" - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "" + "pm.test(\"Successful PATCH request\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", + "});" ], "type": "text/javascript" } } ], "request": { - "method": "POST", + "method": "PATCH", "header": [ { "key": "Authorization", @@ -9690,7 +14568,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"{{demoUserId18}}\",\r\n \"jobId\": \"{{demoJobId3}}\",\r\n \"startDate\": \"2000-07-27T04:17:23.131Z\",\r\n \"endDate\": \"2000-09-27T04:17:23.131Z\",\r\n \"memberRate\": 3000,\r\n \"customerRate\": 3500,\r\n \"rateType\": \"weekly\"\r\n}", + "raw": "{\r\n \"status\": \"assigned\"\r\n}", "options": { "raw": { "language": "json" @@ -9698,38 +14576,35 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings", + "raw": "{{URL}}/resourceBookings/{{demoJob3resourceCandiateId16}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings" + "resourceBookings", + "{{demoJob3resourceCandiateId16}}" ] } }, "response": [] }, { - "name": "create job 3 resource booking 19", + "name": "update job 3 resource booking 17 status to \"assigned\"", "event": [ { "listen": "test", "script": { "exec": [ - "var data = JSON.parse(responseBody);\r", - "\r", - "pm.test(\"Successful POST request\", function () {\r", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);\r", - "});\r", - "\r", - "postman.setEnvironmentVariable(\"demoJob3resourceCandiateId19\",data.id);" + "pm.test(\"Successful PATCH request\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", + "});" ], "type": "text/javascript" } } ], "request": { - "method": "POST", + "method": "PATCH", "header": [ { "key": "Authorization", @@ -9739,7 +14614,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"{{demoUserId19}}\",\r\n \"jobId\": \"{{demoJobId3}}\",\r\n \"startDate\": \"2022-07-27T04:17:23.131Z\",\r\n \"endDate\": \"2022-09-27T04:17:23.131Z\",\r\n \"memberRate\": 1700,\r\n \"customerRate\": 1900,\r\n \"rateType\": \"weekly\"\r\n}", + "raw": "{\r\n \"status\": \"assigned\"\r\n}", "options": { "raw": { "language": "json" @@ -9747,54 +14622,81 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings", + "raw": "{{URL}}/resourceBookings/{{demoJob3resourceCandiateId17}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings" + "resourceBookings", + "{{demoJob3resourceCandiateId17}}" ] } }, "response": [] }, { - "name": "create job 3 resource booking 20", + "name": "update job 3 resource booking 18 status to \"assigned\"", "event": [ { "listen": "test", "script": { "exec": [ - "var data = JSON.parse(responseBody);\r", - "\r", - "pm.test(\"Successful POST request\", function () {\r", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);\r", - "});\r", - "\r", - "postman.setEnvironmentVariable(\"demoJob3resourceCandiateId20\",data.id);" + "pm.test(\"Successful PATCH request\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", + "});" ], "type": "text/javascript" } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"status\": \"assigned\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } }, + "url": { + "raw": "{{URL}}/resourceBookings/{{demoJob3resourceCandiateId18}}", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings", + "{{demoJob3resourceCandiateId18}}" + ] + } + }, + "response": [] + }, + { + "name": "update job 3 resource booking 19 status to \"assigned\"", + "event": [ { - "listen": "prerequest", + "listen": "test", "script": { "exec": [ - "const startDate = new Date()", - "startDate.setDate(startDate.getDate() - 3);", - "", - "const endDate = new Date()", - "endDate.setDate(endDate.getDate() + 3);", - "", - "postman.setEnvironmentVariable(\"resourceStartDate\", startDate.toUTCString());", - "postman.setEnvironmentVariable(\"resourceEndDate\", endDate.toUTCString());" + "pm.test(\"Successful PATCH request\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", + "});" ], "type": "text/javascript" } } ], "request": { - "method": "POST", + "method": "PATCH", "header": [ { "key": "Authorization", @@ -9804,7 +14706,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"{{demoUserId20}}\",\r\n \"jobId\": \"{{demoJobId3}}\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 0,\r\n \"customerRate\": 0,\r\n \"rateType\": \"weekly\"\r\n}", + "raw": "{\r\n \"status\": \"assigned\"\r\n}", "options": { "raw": { "language": "json" @@ -9812,19 +14714,20 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings", + "raw": "{{URL}}/resourceBookings/{{demoJob3resourceCandiateId19}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings" + "resourceBookings", + "{{demoJob3resourceCandiateId19}}" ] } }, "response": [] }, { - "name": "update job 3 resource booking 11 status to \"assigned\"", + "name": "update job 3 resource booking 20 status to \"assigned\"", "event": [ { "listen": "test", @@ -9857,20 +14760,20 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{demoJob3resourceCandiateId11}}", + "raw": "{{URL}}/resourceBookings/{{demoJob3resourceCandiateId20}}", "host": [ "{{URL}}" ], "path": [ "resourceBookings", - "{{demoJob3resourceCandiateId11}}" + "{{demoJob3resourceCandiateId20}}" ] } }, "response": [] }, { - "name": "update job 3 resource booking 12 status to \"in-review\"", + "name": "update job #3 status to \"assigned\"", "event": [ { "listen": "test", @@ -9895,7 +14798,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"status\": \"in-review\"\r\n}", + "raw": "{\r\n \"status\": \"assigned\"\r\n}", "options": { "raw": { "language": "json" @@ -9903,35 +14806,44 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{demoJob3resourceCandiateId12}}", + "raw": "{{URL}}/jobs/{{demoJobId3}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{demoJob3resourceCandiateId12}}" + "jobs", + "{{demoJobId3}}" ] } }, "response": [] - }, + } + ] + }, + { + "name": "Create job #4 \"closed\"", + "item": [ { - "name": "update job 3 resource booking 13 status to \"closed\"", + "name": "create job #4", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test(\"Successful PATCH request\", function () {", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", - "});" + "var data = JSON.parse(responseBody);\r", + "\r", + "pm.test(\"Successful POST request\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);\r", + "});\r", + "\r", + "postman.setEnvironmentVariable(\"demoJobId4\",data.id);" ], "type": "text/javascript" } } ], "request": { - "method": "PATCH", + "method": "POST", "header": [ { "key": "Authorization", @@ -9941,7 +14853,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"status\": \"closed\"\r\n}", + "raw": "{\n \"projectId\": {{projectId}},\n \"externalId\": \"0\",\n \"description\": \"taas-demo-job4\",\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\n \"duration\": 1,\n \"numPositions\": 7,\n \"resourceType\": \"Dummy Resource Type\",\n \"rateType\": \"weekly\",\n \"workload\": \"full-time\",\n \"skills\": [\n \"8456002e-fa2d-44f0-b0e7-86b1c02b6e4c\",\n \"114b4ec8-805e-4c60-b351-14a955a991a9\",\n \"213408aa-f16f-46c8-bc57-9e569cee3f11\",\n \"b37a48db-f775-4e4e-b403-8ad1d234cdea\",\n \"99b930b5-1b91-4df1-8b17-d9307107bb51\",\n \"6388a632-c3ad-4525-9a73-66a527c03672\"\n ],\n \"title\": \"Dummy title - at most 64 characters\"\n}", "options": { "raw": { "language": "json" @@ -9949,20 +14861,19 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{demoJob3resourceCandiateId13}}", + "raw": "{{URL}}/jobs", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{demoJob3resourceCandiateId13}}" + "jobs" ] } }, "response": [] }, { - "name": "update job 3 resource booking 14 status to \"cancelled\"", + "name": "update job #4 status to \"closed\"", "event": [ { "listen": "test", @@ -9987,7 +14898,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"status\": \"cancelled\"\r\n}", + "raw": "{\r\n \"status\": \"closed\"\r\n}", "options": { "raw": { "language": "json" @@ -9995,35 +14906,44 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{demoJob3resourceCandiateId14}}", + "raw": "{{URL}}/jobs/{{demoJobId4}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{demoJob3resourceCandiateId14}}" + "jobs", + "{{demoJobId4}}" ] } }, "response": [] - }, + } + ] + }, + { + "name": "Create job #5 \"cancelled\"", + "item": [ { - "name": "update job 3 resource booking 15 status to \"sourcing\"", + "name": "create job #5", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test(\"Successful PATCH request\", function () {", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", - "});" + "var data = JSON.parse(responseBody);\r", + "\r", + "pm.test(\"Successful POST request\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);\r", + "});\r", + "\r", + "postman.setEnvironmentVariable(\"demoJobId5\",data.id);" ], "type": "text/javascript" } } ], "request": { - "method": "PATCH", + "method": "POST", "header": [ { "key": "Authorization", @@ -10033,7 +14953,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"status\": \"sourcing\"\r\n}", + "raw": "{\n \"projectId\": {{projectId}},\n \"externalId\": \"0\",\n \"description\": \"taas-demo-job5\",\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\n \"duration\": 1,\n \"numPositions\": 7,\n \"resourceType\": \"Dummy Resource Type\",\n \"rateType\": \"weekly\",\n \"workload\": \"full-time\",\n \"skills\": [\n \"b37a48db-f775-4e4e-b403-8ad1d234cdea\",\n \"99b930b5-1b91-4df1-8b17-d9307107bb51\",\n \"6388a632-c3ad-4525-9a73-66a527c03672\"\n ],\n \"title\": \"Dummy title - at most 64 characters\"\n}", "options": { "raw": { "language": "json" @@ -10041,20 +14961,19 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{demoJob3resourceCandiateId15}}", + "raw": "{{URL}}/jobs", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{demoJob3resourceCandiateId15}}" + "jobs" ] } }, "response": [] }, { - "name": "update job 3 resource booking 16 status to \"assigned\"", + "name": "update job #5 status to \"cancelled\"", "event": [ { "listen": "test", @@ -10079,485 +14998,652 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"status\": \"assigned\"\r\n}", + "raw": "{\r\n \"status\": \"cancelled\"\r\n}", "options": { "raw": { "language": "json" } - } + } + }, + "url": { + "raw": "{{URL}}/jobs/{{demoJobId5}}", + "host": [ + "{{URL}}" + ], + "path": [ + "jobs", + "{{demoJobId5}}" + ] + } + }, + "response": [] + } + ] + } + ] + }, + { + "name": "Test Permission Rules", + "item": [ + { + "name": "Request with Administrator Role", + "item": [ + { + "name": "Jobs", + "item": [ + { + "name": "✔ create job with administrator", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var data = JSON.parse(responseBody);\r", + "postman.setEnvironmentVariable(\"job_id_created_by_administrator\",data.id);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_administrator}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"projectId\": {{projectId}},\n \"externalId\": \"1212\",\n \"description\": \"Dummy Description\",\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\n \"duration\": 1,\n \"numPositions\": 13,\n \"resourceType\": \"Dummy Resource Type\",\n \"rateType\": \"hourly\",\n \"workload\": \"full-time\",\n \"skills\": [\n \"23e00d92-207a-4b5b-b3c9-4c5662644941\",\n \"7d076384-ccf6-4e43-a45d-1b24b1e624aa\",\n \"cbac57a3-7180-4316-8769-73af64893158\",\n \"a2b4bc11-c641-4a19-9eb7-33980378f82e\"\n ],\n \"title\": \"Dummy title - at most 64 characters\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobs", + "host": [ + "{{URL}}" + ], + "path": [ + "jobs" + ] + } + }, + "response": [] + }, + { + "name": "✔ get job with administrator", + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } + ], + "url": { + "raw": "{{URL}}/jobs/{{job_id_created_by_administrator}}", + "host": [ + "{{URL}}" + ], + "path": [ + "jobs", + "{{job_id_created_by_administrator}}" + ] + } + }, + "response": [] + }, + { + "name": "✔ search jobs with administrator", + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } + ], + "url": { + "raw": "{{URL}}/jobs", + "host": [ + "{{URL}}" + ], + "path": [ + "jobs" + ], + "query": [ + { + "key": "page", + "value": "0", + "disabled": true + }, + { + "key": "perPage", + "value": "3", + "disabled": true + }, + { + "key": "sortBy", + "value": "id", + "disabled": true + }, + { + "key": "sortOrder", + "value": "asc", + "disabled": true + }, + { + "key": "projectId", + "value": "21", + "disabled": true + }, + { + "key": "externalId", + "value": "1212", + "disabled": true + }, + { + "key": "description", + "value": "Dummy", + "disabled": true + }, + { + "key": "startDate", + "value": "2020-09-27T04:17:23.131Z", + "disabled": true + }, + { + "key": "resourceType", + "value": "Dummy Resource Type", + "disabled": true + }, + { + "key": "skill", + "value": "3fa85f64-5717-4562-b3fc-2c963f66afa6", + "disabled": true + }, + { + "key": "rateType", + "value": "hourly", + "disabled": true + }, + { + "key": "status", + "value": "sourcing", + "disabled": true + }, + { + "key": "workload", + "value": "full-time", + "disabled": true + }, + { + "key": "title", + "value": "dummy", + "disabled": true + } + ] + } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/resourceBookings/{{demoJob3resourceCandiateId16}}", - "host": [ - "{{URL}}" - ], - "path": [ - "resourceBookings", - "{{demoJob3resourceCandiateId16}}" - ] - } - }, - "response": [] - }, - { - "name": "update job 3 resource booking 17 status to \"assigned\"", - "event": [ { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Successful PATCH request\", function () {", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", - "});" + "name": "✔ put job with administrator", + "request": { + "method": "PUT", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "PATCH", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"status\": \"assigned\"\r\n}", - "options": { - "raw": { - "language": "json" + "body": { + "mode": "raw", + "raw": "{\n \"projectId\": {{projectId}},\n \"externalId\": \"1212\",\n \"description\": \"Dummy Description\",\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\n \"duration\": 1,\n \"numPositions\": 13,\n \"resourceType\": \"Dummy Resource Type\",\n \"rateType\": \"hourly\",\n \"workload\": \"fractional\",\n \"skills\": [\n \"cbac57a3-7180-4316-8769-73af64893158\",\n \"a2b4bc11-c641-4a19-9eb7-33980378f82e\"\n ],\n \"status\": \"sourcing\",\n \"title\": \"Dummy title - at most 64 characters\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobs/{{job_id_created_by_administrator}}", + "host": [ + "{{URL}}" + ], + "path": [ + "jobs", + "{{job_id_created_by_administrator}}" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/resourceBookings/{{demoJob3resourceCandiateId17}}", - "host": [ - "{{URL}}" - ], - "path": [ - "resourceBookings", - "{{demoJob3resourceCandiateId17}}" - ] - } - }, - "response": [] - }, - { - "name": "update job 3 resource booking 18 status to \"assigned\"", - "event": [ { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Successful PATCH request\", function () {", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", - "});" + "name": "✔ patch job with administrator", + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "PATCH", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"status\": \"assigned\"\r\n}", - "options": { - "raw": { - "language": "json" + "body": { + "mode": "raw", + "raw": "{\n \"description\": \"Dummy Description\",\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\n \"duration\": 1,\n \"numPositions\": 13,\n \"resourceType\": \"Dummy Resource Type\",\n \"rateType\": \"hourly\",\n \"workload\": \"fractional\",\n \"skills\": [\n \"cbac57a3-7180-4316-8769-73af64893158\"\n ],\n \"status\": \"sourcing\",\n \"title\": \"Dummy title - at most 64 characters\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobs/{{job_id_created_by_administrator}}", + "host": [ + "{{URL}}" + ], + "path": [ + "jobs", + "{{job_id_created_by_administrator}}" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/resourceBookings/{{demoJob3resourceCandiateId18}}", - "host": [ - "{{URL}}" - ], - "path": [ - "resourceBookings", - "{{demoJob3resourceCandiateId18}}" - ] - } - }, - "response": [] - }, - { - "name": "update job 3 resource booking 19 status to \"assigned\"", - "event": [ { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Successful PATCH request\", function () {", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", - "});" + "name": "✔ delete job with administrator", + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "PATCH", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"status\": \"assigned\"\r\n}", - "options": { - "raw": { - "language": "json" + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobs/{{job_id_created_by_administrator}}", + "host": [ + "{{URL}}" + ], + "path": [ + "jobs", + "{{job_id_created_by_administrator}}" + ] } - } - }, - "url": { - "raw": "{{URL}}/resourceBookings/{{demoJob3resourceCandiateId19}}", - "host": [ - "{{URL}}" - ], - "path": [ - "resourceBookings", - "{{demoJob3resourceCandiateId19}}" - ] + }, + "response": [] } - }, - "response": [] + ] }, { - "name": "update job 3 resource booking 20 status to \"assigned\"", - "event": [ + "name": "Job Candidates", + "item": [ { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Successful PATCH request\", function () {", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", - "});" + "name": "✔ create job candidate with administrator", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var data = JSON.parse(responseBody);\r", + "postman.setEnvironmentVariable(\"job_candidate_id_created_by_administrator\",data.id);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "PATCH", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"status\": \"assigned\"\r\n}", - "options": { - "raw": { - "language": "json" + "body": { + "mode": "raw", + "raw": "{\r\n \"jobId\": \"{{job_id_created_by_administrator}}\",\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobCandidates", + "host": [ + "{{URL}}" + ], + "path": [ + "jobCandidates" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/resourceBookings/{{demoJob3resourceCandiateId20}}", - "host": [ - "{{URL}}" - ], - "path": [ - "resourceBookings", - "{{demoJob3resourceCandiateId20}}" - ] - } - }, - "response": [] - }, - { - "name": "update job #3 status to \"assigned\"", - "event": [ { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Successful PATCH request\", function () {", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", - "});" + "name": "✔ get job candidate with administrator", + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "PATCH", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"status\": \"assigned\"\r\n}", - "options": { - "raw": { - "language": "json" + "url": { + "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_by_administrator}}", + "host": [ + "{{URL}}" + ], + "path": [ + "jobCandidates", + "{{job_candidate_id_created_by_administrator}}" + ] } - } + }, + "response": [] + }, + { + "name": "✔ search job candidates with administrator", + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } + ], + "url": { + "raw": "{{URL}}/jobCandidates", + "host": [ + "{{URL}}" + ], + "path": [ + "jobCandidates" + ], + "query": [ + { + "key": "page", + "value": "1", + "disabled": true + }, + { + "key": "perPage", + "value": "1", + "disabled": true + }, + { + "key": "sortBy", + "value": "id", + "disabled": true + }, + { + "key": "sortOrder", + "value": "asc", + "disabled": true + }, + { + "key": "jobId", + "value": "46225f4c-c2a3-4603-a141-0277e96fabfa", + "disabled": true + }, + { + "key": "userId", + "value": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "disabled": true + }, + { + "key": "status", + "value": "shortlist", + "disabled": true + } + ] + } + }, + "response": [] + }, + { + "name": "✔ put job candidate with administrator", + "request": { + "method": "PUT", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"jobId\": \"{{job_id_created_by_administrator}}\",\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"status\": \"selected\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_by_administrator}}", + "host": [ + "{{URL}}" + ], + "path": [ + "jobCandidates", + "{{job_candidate_id_created_by_administrator}}" + ] + } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/jobs/{{demoJobId3}}", - "host": [ - "{{URL}}" - ], - "path": [ - "jobs", - "{{demoJobId3}}" - ] - } - }, - "response": [] - } - ] - }, - { - "name": "Create job #4 \"closed\"", - "item": [ - { - "name": "create job #4", - "event": [ { - "listen": "test", - "script": { - "exec": [ - "var data = JSON.parse(responseBody);\r", - "\r", - "pm.test(\"Successful POST request\", function () {\r", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);\r", - "});\r", - "\r", - "postman.setEnvironmentVariable(\"demoJobId4\",data.id);" + "name": "✔ patch job candidate with administrator", + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"projectId\": {{projectId}},\n \"externalId\": \"0\",\n \"description\": \"taas-demo-job4\",\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\n \"duration\": 1,\n \"numPositions\": 7,\n \"resourceType\": \"Dummy Resource Type\",\n \"rateType\": \"weekly\",\n \"workload\": \"full-time\",\n \"skills\": [\n \"8456002e-fa2d-44f0-b0e7-86b1c02b6e4c\",\n \"114b4ec8-805e-4c60-b351-14a955a991a9\",\n \"213408aa-f16f-46c8-bc57-9e569cee3f11\",\n \"b37a48db-f775-4e4e-b403-8ad1d234cdea\",\n \"99b930b5-1b91-4df1-8b17-d9307107bb51\",\n \"6388a632-c3ad-4525-9a73-66a527c03672\"\n ],\n \"title\": \"Dummy title - at most 64 characters\"\n}", - "options": { - "raw": { - "language": "json" + "body": { + "mode": "raw", + "raw": "{\r\n \"status\": \"shortlist\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_by_administrator}}", + "host": [ + "{{URL}}" + ], + "path": [ + "jobCandidates", + "{{job_candidate_id_created_by_administrator}}" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/jobs", - "host": [ - "{{URL}}" - ], - "path": [ - "jobs" - ] - } - }, - "response": [] - }, - { - "name": "update job #4 status to \"closed\"", - "event": [ { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Successful PATCH request\", function () {", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", - "});" + "name": "✔ delete job candidate with administrator", + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "PATCH", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"status\": \"closed\"\r\n}", - "options": { - "raw": { - "language": "json" + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_by_administrator}}", + "host": [ + "{{URL}}" + ], + "path": [ + "jobCandidates", + "{{job_candidate_id_created_by_administrator}}" + ] } - } - }, - "url": { - "raw": "{{URL}}/jobs/{{demoJobId4}}", - "host": [ - "{{URL}}" - ], - "path": [ - "jobs", - "{{demoJobId4}}" - ] + }, + "response": [] } - }, - "response": [] - } - ] - }, - { - "name": "Create job #5 \"cancelled\"", - "item": [ + ] + }, { - "name": "create job #5", - "event": [ + "name": "Interviews", + "item": [ { - "listen": "test", - "script": { - "exec": [ - "var data = JSON.parse(responseBody);\r", - "\r", - "pm.test(\"Successful POST request\", function () {\r", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);\r", - "});\r", - "\r", - "postman.setEnvironmentVariable(\"demoJobId5\",data.id);" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"projectId\": {{projectId}},\n \"externalId\": \"0\",\n \"description\": \"taas-demo-job5\",\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\n \"duration\": 1,\n \"numPositions\": 7,\n \"resourceType\": \"Dummy Resource Type\",\n \"rateType\": \"weekly\",\n \"workload\": \"full-time\",\n \"skills\": [\n \"b37a48db-f775-4e4e-b403-8ad1d234cdea\",\n \"99b930b5-1b91-4df1-8b17-d9307107bb51\",\n \"6388a632-c3ad-4525-9a73-66a527c03672\"\n ],\n \"title\": \"Dummy title - at most 64 characters\"\n}", - "options": { - "raw": { - "language": "json" + "name": "Before Test", + "item": [ + { + "name": "create job", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var data = JSON.parse(responseBody);\r", + "postman.setEnvironmentVariable(\"job_id_created_by_administrator\",data.id);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_administrator}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"projectId\": {{projectId}},\n \"externalId\": \"88774632\",\n \"description\": \"Dummy Description\",\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\n \"duration\": 1,\n \"numPositions\": 13,\n \"resourceType\": \"Dummy Resource Type\",\n \"rateType\": \"hourly\",\n \"workload\": \"full-time\",\n \"skills\": [\n \"23e00d92-207a-4b5b-b3c9-4c5662644941\",\n \"7d076384-ccf6-4e43-a45d-1b24b1e624aa\",\n \"cbac57a3-7180-4316-8769-73af64893158\",\n \"a2b4bc11-c641-4a19-9eb7-33980378f82e\"\n ],\n \"title\": \"Dummy title - at most 64 characters\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobs", + "host": [ + "{{URL}}" + ], + "path": [ + "jobs" + ] + } + }, + "response": [] + }, + { + "name": "create job candidate", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var data = JSON.parse(responseBody);\r", + "postman.setEnvironmentVariable(\"job_candidate_id_created_by_administrator\",data.id);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"jobId\": \"{{job_id_created_by_administrator}}\",\r\n \"userId\": \"95e7970f-12b4-43b7-ab35-38c34bf033c7\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobCandidates", + "host": [ + "{{URL}}" + ], + "path": [ + "jobCandidates" + ] + } + }, + "response": [] } - } - }, - "url": { - "raw": "{{URL}}/jobs", - "host": [ - "{{URL}}" - ], - "path": [ - "jobs" ] - } - }, - "response": [] - }, - { - "name": "update job #5 status to \"cancelled\"", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Successful PATCH request\", function () {", - " pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "PATCH", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"status\": \"cancelled\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } }, - "url": { - "raw": "{{URL}}/jobs/{{demoJobId5}}", - "host": [ - "{{URL}}" - ], - "path": [ - "jobs", - "{{demoJobId5}}" - ] - } - }, - "response": [] - } - ] - } - ] - }, - { - "name": "Test Permission Rules", - "item": [ - { - "name": "Request with Administrator Role", - "item": [ - { - "name": "Jobs", - "item": [ { - "name": "✔ create job with administrator", + "name": "✔ request interview with administrator", "event": [ { "listen": "test", "script": { "exec": [ - "var data = JSON.parse(responseBody);\r", - "postman.setEnvironmentVariable(\"job_id_created_by_administrator\",data.id);" + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", + " if(pm.response.status === \"OK\"){\r", + " const response = pm.response.json()\r", + " pm.environment.set(\"interview_round_created_by_administrator\", response.round);\r", + " }\r", + "});" ], "type": "text/javascript" } } ], "request": { - "method": "POST", + "method": "PATCH", "header": [ { "key": "Authorization", @@ -10567,7 +15653,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"projectId\": {{projectId}},\n \"externalId\": \"1212\",\n \"description\": \"Dummy Description\",\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\n \"duration\": 1,\n \"numPositions\": 13,\n \"resourceType\": \"Dummy Resource Type\",\n \"rateType\": \"hourly\",\n \"workload\": \"full-time\",\n \"skills\": [\n \"23e00d92-207a-4b5b-b3c9-4c5662644941\",\n \"7d076384-ccf6-4e43-a45d-1b24b1e624aa\",\n \"cbac57a3-7180-4316-8769-73af64893158\",\n \"a2b4bc11-c641-4a19-9eb7-33980378f82e\"\n ],\n \"title\": \"Dummy title - at most 64 characters\"\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\",\r\n \"googleCalendarId\": \"dummyId\",\r\n \"customMessage\": \"This is a custom message\",\r\n \"status\": \"Scheduling\"\r\n}", "options": { "raw": { "language": "json" @@ -10575,183 +15661,85 @@ } }, "url": { - "raw": "{{URL}}/jobs", + "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_by_administrator}}/requestInterview", "host": [ "{{URL}}" ], "path": [ - "jobs" + "jobCandidates", + "{{job_candidate_id_created_by_administrator}}", + "requestInterview" ] } }, "response": [] }, { - "name": "✔ get job with administrator", - "request": { - "method": "GET", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_administrator}}" + "name": "✔ get interview with administrator", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", + "});" + ], + "type": "text/javascript" } - ], - "url": { - "raw": "{{URL}}/jobs/{{job_id_created_by_administrator}}", - "host": [ - "{{URL}}" - ], - "path": [ - "jobs", - "{{job_id_created_by_administrator}}" - ] } - }, - "response": [] - }, - { - "name": "✔ search jobs with administrator", + ], "request": { "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_administrator}}" + "value": "Bearer {{token_administrator}}", + "type": "text" } ], "url": { - "raw": "{{URL}}/jobs", + "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_by_administrator}}/interviews/{{interview_round_created_by_administrator}}", "host": [ "{{URL}}" ], "path": [ - "jobs" - ], - "query": [ - { - "key": "page", - "value": "0", - "disabled": true - }, - { - "key": "perPage", - "value": "3", - "disabled": true - }, - { - "key": "sortBy", - "value": "id", - "disabled": true - }, - { - "key": "sortOrder", - "value": "asc", - "disabled": true - }, - { - "key": "projectId", - "value": "21", - "disabled": true - }, - { - "key": "externalId", - "value": "1212", - "disabled": true - }, - { - "key": "description", - "value": "Dummy", - "disabled": true - }, - { - "key": "startDate", - "value": "2020-09-27T04:17:23.131Z", - "disabled": true - }, - { - "key": "resourceType", - "value": "Dummy Resource Type", - "disabled": true - }, - { - "key": "skill", - "value": "3fa85f64-5717-4562-b3fc-2c963f66afa6", - "disabled": true - }, - { - "key": "rateType", - "value": "hourly", - "disabled": true - }, - { - "key": "status", - "value": "sourcing", - "disabled": true - }, - { - "key": "workload", - "value": "full-time", - "disabled": true - }, - { - "key": "title", - "value": "dummy", - "disabled": true - } + "jobCandidates", + "{{job_candidate_id_created_by_administrator}}", + "interviews", + "{{interview_round_created_by_administrator}}" ] } }, "response": [] }, { - "name": "✔ put job with administrator", - "request": { - "method": "PUT", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_administrator}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"projectId\": {{projectId}},\n \"externalId\": \"1212\",\n \"description\": \"Dummy Description\",\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\n \"duration\": 1,\n \"numPositions\": 13,\n \"resourceType\": \"Dummy Resource Type\",\n \"rateType\": \"hourly\",\n \"workload\": \"fractional\",\n \"skills\": [\n \"cbac57a3-7180-4316-8769-73af64893158\",\n \"a2b4bc11-c641-4a19-9eb7-33980378f82e\"\n ],\n \"status\": \"sourcing\",\n \"title\": \"Dummy title - at most 64 characters\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{URL}}/jobs/{{job_id_created_by_administrator}}", - "host": [ - "{{URL}}" - ], - "path": [ - "jobs", - "{{job_id_created_by_administrator}}" - ] + "name": "✔ update interview with administrator", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", + "});" + ], + "type": "text/javascript" + } } - }, - "response": [] - }, - { - "name": "✔ patch job with administrator", + ], "request": { "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_administrator}}" + "value": "Bearer {{token_administrator}}", + "type": "text" } ], "body": { "mode": "raw", - "raw": "{\n \"description\": \"Dummy Description\",\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\n \"duration\": 1,\n \"numPositions\": 13,\n \"resourceType\": \"Dummy Resource Type\",\n \"rateType\": \"hourly\",\n \"workload\": \"fractional\",\n \"skills\": [\n \"cbac57a3-7180-4316-8769-73af64893158\"\n ],\n \"status\": \"sourcing\",\n \"title\": \"Dummy title - at most 64 characters\"\n}", + "raw": "{\r\n \"customMessage\": \"updated\"\r\n}", "options": { "raw": { "language": "json" @@ -10759,46 +15747,53 @@ } }, "url": { - "raw": "{{URL}}/jobs/{{job_id_created_by_administrator}}", + "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_by_administrator}}/updateInterview/{{interview_round_created_by_administrator}}", "host": [ "{{URL}}" ], "path": [ - "jobs", - "{{job_id_created_by_administrator}}" + "jobCandidates", + "{{job_candidate_id_created_by_administrator}}", + "updateInterview", + "{{interview_round_created_by_administrator}}" ] } }, "response": [] }, { - "name": "✔ delete job with administrator", + "name": "✔ search interviews with administrator", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", + "});" + ], + "type": "text/javascript" + } + } + ], "request": { - "method": "DELETE", + "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_administrator}}" + "value": "Bearer {{token_administrator}}", + "type": "text" } ], - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/jobs/{{job_id_created_by_administrator}}", + "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_by_administrator}}/interviews", "host": [ "{{URL}}" ], "path": [ - "jobs", - "{{job_id_created_by_administrator}}" + "jobCandidates", + "{{job_candidate_id_created_by_administrator}}", + "interviews" ] } }, @@ -10807,17 +15802,17 @@ ] }, { - "name": "Job Candidates", + "name": "Resource Bookings", "item": [ { - "name": "✔ create job candidate with administrator", + "name": "✔ create resource booking with administrator", "event": [ { "listen": "test", "script": { "exec": [ "var data = JSON.parse(responseBody);\r", - "postman.setEnvironmentVariable(\"job_candidate_id_created_by_administrator\",data.id);" + "postman.setEnvironmentVariable(\"resource_bookings_id_created_by_administrator\",data.id);" ], "type": "text/javascript" } @@ -10834,7 +15829,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"jobId\": \"{{job_id_created_by_administrator}}\",\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\"\r\n}", + "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{job_id_created_by_administrator}}\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\"\r\n}", "options": { "raw": { "language": "json" @@ -10842,19 +15837,19 @@ } }, "url": { - "raw": "{{URL}}/jobCandidates", + "raw": "{{URL}}/resourceBookings", "host": [ "{{URL}}" ], "path": [ - "jobCandidates" + "resourceBookings" ] } }, "response": [] }, { - "name": "✔ get job candidate with administrator", + "name": "✔ get resource booking with administrator", "request": { "method": "GET", "header": [ @@ -10865,20 +15860,20 @@ } ], "url": { - "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_by_administrator}}", + "raw": "{{URL}}/resourceBookings/{{resource_bookings_id_created_by_administrator}}", "host": [ "{{URL}}" ], "path": [ - "jobCandidates", - "{{job_candidate_id_created_by_administrator}}" + "resourceBookings", + "{{resource_bookings_id_created_by_administrator}}" ] } }, "response": [] }, { - "name": "✔ search job candidates with administrator", + "name": "✔ search resource bookings with administrator", "request": { "method": "GET", "header": [ @@ -10889,12 +15884,12 @@ } ], "url": { - "raw": "{{URL}}/jobCandidates", + "raw": "{{URL}}/resourceBookings", "host": [ "{{URL}}" ], "path": [ - "jobCandidates" + "resourceBookings" ], "query": [ { @@ -10904,7 +15899,7 @@ }, { "key": "perPage", - "value": "1", + "value": "5", "disabled": true }, { @@ -10914,22 +15909,32 @@ }, { "key": "sortOrder", - "value": "asc", + "value": "desc", "disabled": true }, { - "key": "jobId", - "value": "46225f4c-c2a3-4603-a141-0277e96fabfa", + "key": "startDate", + "value": "2020-09-27T04:17:23.131Z", "disabled": true }, { - "key": "userId", - "value": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "key": "endDate", + "value": "2020-09-27T04:17:23.131Z", + "disabled": true + }, + { + "key": "rateType", + "value": "hourly", "disabled": true }, { "key": "status", - "value": "shortlist", + "value": "sourcing", + "disabled": true + }, + { + "key": "projectIds", + "value": "111, 16705", "disabled": true } ] @@ -10938,7 +15943,7 @@ "response": [] }, { - "name": "✔ put job candidate with administrator", + "name": "✔ put resource booking with administrator", "request": { "method": "PUT", "header": [ @@ -10950,7 +15955,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"jobId\": \"{{job_id_created_by_administrator}}\",\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"status\": \"selected\"\r\n}", + "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{job_id_created_by_administrator}}\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"status\": \"assigned\"\r\n}", "options": { "raw": { "language": "json" @@ -10958,20 +15963,20 @@ } }, "url": { - "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_by_administrator}}", + "raw": "{{URL}}/resourceBookings/{{resource_bookings_id_created_by_administrator}}", "host": [ "{{URL}}" ], "path": [ - "jobCandidates", - "{{job_candidate_id_created_by_administrator}}" + "resourceBookings", + "{{resource_bookings_id_created_by_administrator}}" ] } }, "response": [] }, { - "name": "✔ patch job candidate with administrator", + "name": "✔ patch resource booking with administrator", "request": { "method": "PATCH", "header": [ @@ -10983,7 +15988,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"status\": \"shortlist\"\r\n}", + "raw": "{\r\n \"status\": \"assigned\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\"\r\n}", "options": { "raw": { "language": "json" @@ -10991,20 +15996,20 @@ } }, "url": { - "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_by_administrator}}", + "raw": "{{URL}}/resourceBookings/{{resource_bookings_id_created_by_administrator}}", "host": [ "{{URL}}" ], "path": [ - "jobCandidates", - "{{job_candidate_id_created_by_administrator}}" + "resourceBookings", + "{{resource_bookings_id_created_by_administrator}}" ] } }, "response": [] }, { - "name": "✔ delete job candidate with administrator", + "name": "✔ delete resource booking with administrator", "request": { "method": "DELETE", "header": [ @@ -11024,13 +16029,13 @@ } }, "url": { - "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_by_administrator}}", + "raw": "{{URL}}/resourceBookings/{{resource_bookings_id_created_by_administrator}}", "host": [ "{{URL}}" ], "path": [ - "jobCandidates", - "{{job_candidate_id_created_by_administrator}}" + "resourceBookings", + "{{resource_bookings_id_created_by_administrator}}" ] } }, @@ -11039,17 +16044,125 @@ ] }, { - "name": "Resource Bookings", + "name": "Work Periods", "item": [ { - "name": "✔ create resource booking with administrator", + "name": "Before Test", + "item": [ + { + "name": "✔ create job with administrator", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", + " if(pm.response.status === \"OK\"){\r", + " const response = pm.response.json()\r", + " pm.environment.set(\"job_id_created_by_administrator\", response.id);\r", + " }\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_administrator}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"projectId\": {{projectId}},\n \"externalId\": \"1212\",\n \"description\": \"Dummy Description\",\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\n \"duration\": 1,\n \"numPositions\": 13,\n \"resourceType\": \"Dummy Resource Type\",\n \"rateType\": \"hourly\",\n \"workload\": \"full-time\",\n \"skills\": [\n \"23e00d92-207a-4b5b-b3c9-4c5662644941\",\n \"7d076384-ccf6-4e43-a45d-1b24b1e624aa\",\n \"cbac57a3-7180-4316-8769-73af64893158\",\n \"a2b4bc11-c641-4a19-9eb7-33980378f82e\"\n ],\n \"title\": \"Dummy title - at most 64 characters\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobs", + "host": [ + "{{URL}}" + ], + "path": [ + "jobs" + ] + } + }, + "response": [] + }, + { + "name": "✔ create resource booking with administrator", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", + " if(pm.response.status === \"OK\"){\r", + " const response = pm.response.json()\r", + " pm.environment.set(\"resource_bookings_id_created_by_administrator\", response.id);\r", + " }\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{job_id_created_by_administrator}}\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/resourceBookings", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "✔ create work period with administrator", "event": [ { "listen": "test", "script": { "exec": [ - "var data = JSON.parse(responseBody);\r", - "postman.setEnvironmentVariable(\"resource_bookings_id_created_by_administrator\",data.id);" + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", + " if(pm.response.status === \"OK\"){\r", + " const response = pm.response.json()\r", + " pm.environment.set(\"workPeriodId_created_by_administrator\", response.id);\r", + " }\r", + "});" ], "type": "text/javascript" } @@ -11066,7 +16179,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{job_id_created_by_administrator}}\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\"\r\n}", + "raw": "{\r\n \"resourceBookingId\": \"{{resource_bookings_id_created_by_administrator}}\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", "options": { "raw": { "language": "json" @@ -11074,19 +16187,19 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings", + "raw": "{{URL}}/workPeriods", "host": [ "{{URL}}" ], "path": [ - "resourceBookings" + "workPeriods" ] } }, "response": [] }, { - "name": "✔ get resource booking with administrator", + "name": "✔ get work period with administrator", "request": { "method": "GET", "header": [ @@ -11097,20 +16210,20 @@ } ], "url": { - "raw": "{{URL}}/resourceBookings/{{resource_bookings_id_created_by_administrator}}", + "raw": "{{URL}}/workPeriods/{{workPeriodId_created_by_administrator}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resource_bookings_id_created_by_administrator}}" + "workPeriods", + "{{workPeriodId_created_by_administrator}}" ] } }, "response": [] }, { - "name": "✔ search resource bookings with administrator", + "name": "✔ search work periods with administrator", "request": { "method": "GET", "header": [ @@ -11121,12 +16234,12 @@ } ], "url": { - "raw": "{{URL}}/resourceBookings", + "raw": "{{URL}}/workPeriods", "host": [ "{{URL}}" ], "path": [ - "resourceBookings" + "workPeriods" ], "query": [ { @@ -11150,28 +16263,38 @@ "disabled": true }, { - "key": "startDate", - "value": "2020-09-27T04:17:23.131Z", + "key": "resourceBookingId", + "value": "{{resource_bookings_id_created_by_administrator}}", "disabled": true }, { - "key": "endDate", - "value": "2020-09-27T04:17:23.131Z", + "key": "resourceBookingIds", + "value": "{{resource_bookings_id_created_by_administrator}},{{resource_bookings_id_created_by_administrator}}", "disabled": true }, { - "key": "rateType", - "value": "hourly", + "key": "paymentStatus", + "value": "pending", "disabled": true }, { - "key": "status", - "value": "sourcing", + "key": "startDate", + "value": "2021-03-07", "disabled": true }, { - "key": "projectIds", - "value": "111, 16705", + "key": "endDate", + "value": "2021-03-13", + "disabled": true + }, + { + "key": "userHandle", + "value": "pshah_manager", + "disabled": true + }, + { + "key": "projectId", + "value": "111", "disabled": true } ] @@ -11180,7 +16303,20 @@ "response": [] }, { - "name": "✔ put resource booking with administrator", + "name": "✔ put work period with administrator", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", + "});" + ], + "type": "text/javascript" + } + } + ], "request": { "method": "PUT", "header": [ @@ -11192,7 +16328,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{job_id_created_by_administrator}}\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"status\": \"assigned\"\r\n}", + "raw": "{\r\n \"resourceBookingId\": \"{{resource_bookings_id_created_by_administrator}}\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", "options": { "raw": { "language": "json" @@ -11200,20 +16336,33 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{resource_bookings_id_created_by_administrator}}", + "raw": "{{URL}}/workPeriods/{{workPeriodId_created_by_administrator}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resource_bookings_id_created_by_administrator}}" + "workPeriods", + "{{workPeriodId_created_by_administrator}}" ] } }, "response": [] }, { - "name": "✔ patch resource booking with administrator", + "name": "✔ patch work period with administrator", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", + "});" + ], + "type": "text/javascript" + } + } + ], "request": { "method": "PATCH", "header": [ @@ -11225,7 +16374,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"status\": \"assigned\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\"\r\n}", + "raw": "{\r\n \"resourceBookingId\": \"{{resource_bookings_id_created_by_administrator}}\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", "options": { "raw": { "language": "json" @@ -11233,20 +16382,33 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{resource_bookings_id_created_by_administrator}}", + "raw": "{{URL}}/workPeriods/{{workPeriodId_created_by_administrator}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resource_bookings_id_created_by_administrator}}" + "workPeriods", + "{{workPeriodId_created_by_administrator}}" ] } }, "response": [] }, { - "name": "✔ delete resource booking with administrator", + "name": "✔ delete work period with administrator", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 204', function () {\r", + " pm.response.to.have.status(204);\r", + "});" + ], + "type": "text/javascript" + } + } + ], "request": { "method": "DELETE", "header": [ @@ -11266,140 +16428,53 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{resource_bookings_id_created_by_administrator}}", + "raw": "{{URL}}/workPeriods/{{workPeriodId_created_by_administrator}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resource_bookings_id_created_by_administrator}}" + "workPeriods", + "{{workPeriodId_created_by_administrator}}" ] } }, "response": [] } ] - }, + } + ] + }, + { + "name": "Request with Topcoder User Role", + "item": [ { - "name": "Work Periods", + "name": "README", "item": [ { - "name": "Before Test", - "item": [ - { - "name": "✔ create job with administrator", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test('Status code is 200', function () {\r", - " pm.response.to.have.status(200);\r", - " if(pm.response.status === \"OK\"){\r", - " const response = pm.response.json()\r", - " pm.environment.set(\"job_id_created_by_administrator\", response.id);\r", - " }\r", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "value": "Bearer {{token_administrator}}", - "type": "text" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"projectId\": {{projectId}},\n \"externalId\": \"1212\",\n \"description\": \"Dummy Description\",\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\n \"duration\": 1,\n \"numPositions\": 13,\n \"resourceType\": \"Dummy Resource Type\",\n \"rateType\": \"hourly\",\n \"workload\": \"full-time\",\n \"skills\": [\n \"23e00d92-207a-4b5b-b3c9-4c5662644941\",\n \"7d076384-ccf6-4e43-a45d-1b24b1e624aa\",\n \"cbac57a3-7180-4316-8769-73af64893158\",\n \"a2b4bc11-c641-4a19-9eb7-33980378f82e\"\n ],\n \"title\": \"Dummy title - at most 64 characters\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{URL}}/jobs", - "host": [ - "{{URL}}" - ], - "path": [ - "jobs" - ] - } - }, - "response": [] - }, - { - "name": "✔ create resource booking with administrator", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test('Status code is 200', function () {\r", - " pm.response.to.have.status(200);\r", - " if(pm.response.status === \"OK\"){\r", - " const response = pm.response.json()\r", - " pm.environment.set(\"resource_bookings_id_created_by_administrator\", response.id);\r", - " }\r", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_administrator}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{job_id_created_by_administrator}}\",\r\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"endDate\": \"2020-09-27T04:17:23.131Z\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{URL}}/resourceBookings", - "host": [ - "{{URL}}" - ], - "path": [ - "resourceBookings" - ] - } - }, - "response": [] + "name": "[STUB] all operations cause 403 error if user is not member of project", + "request": { + "method": "LOCK", + "header": [], + "url": { + "raw": "" } - ] - }, + }, + "response": [] + } + ] + }, + { + "name": "Jobs", + "item": [ { - "name": "✔ create work period with administrator", + "name": "✔ create job with member", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 200', function () {\r", - " pm.response.to.have.status(200);\r", - " if(pm.response.status === \"OK\"){\r", - " const response = pm.response.json()\r", - " pm.environment.set(\"workPeriodId_created_by_administrator\", response.id);\r", - " }\r", - "});" + "var data = JSON.parse(responseBody);\r", + "postman.setEnvironmentVariable(\"job_id_created_by_member\",data.id);" ], "type": "text/javascript" } @@ -11410,13 +16485,13 @@ "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_administrator}}" + "value": "Bearer {{token_member_tester1234}}", + "type": "text" } ], "body": { "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resource_bookings_id_created_by_administrator}}\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "raw": "{\n \"projectId\": {{project_id_16718}},\n \"externalId\": \"1212\",\n \"description\": \"Dummy Description\",\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\n \"duration\": 1,\n \"numPositions\": 13,\n \"resourceType\": \"Dummy Resource Type\",\n \"rateType\": \"hourly\",\n \"workload\": \"full-time\",\n \"skills\": [\n \"23e00d92-207a-4b5b-b3c9-4c5662644941\",\n \"7d076384-ccf6-4e43-a45d-1b24b1e624aa\",\n \"cbac57a3-7180-4316-8769-73af64893158\",\n \"a2b4bc11-c641-4a19-9eb7-33980378f82e\"\n ],\n \"title\": \"Dummy title - at most 64 characters\"\n}", "options": { "raw": { "language": "json" @@ -11424,69 +16499,69 @@ } }, "url": { - "raw": "{{URL}}/workPeriods", + "raw": "{{URL}}/jobs", "host": [ "{{URL}}" ], "path": [ - "workPeriods" + "jobs" ] } }, "response": [] }, { - "name": "✔ get work period with administrator", + "name": "✔ get job with member", "request": { "method": "GET", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_administrator}}" + "value": "Bearer {{token_member_tester1234}}" } ], "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId_created_by_administrator}}", + "raw": "{{URL}}/jobs/{{job_id_created_by_member}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId_created_by_administrator}}" + "jobs", + "{{job_id_created_by_member}}" ] } }, "response": [] }, { - "name": "✔ search work periods with administrator", + "name": "✔ search jobs with member filtering by \"projectId\"", "request": { "method": "GET", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_administrator}}" + "value": "Bearer {{token_member_tester1234}}" } ], "url": { - "raw": "{{URL}}/workPeriods", + "raw": "{{URL}}/jobs?projectId={{project_id_16718}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods" + "jobs" ], "query": [ { "key": "page", - "value": "1", + "value": "0", "disabled": true }, { "key": "perPage", - "value": "5", + "value": "3", "disabled": true }, { @@ -11496,42 +16571,56 @@ }, { "key": "sortOrder", - "value": "desc", + "value": "asc", "disabled": true }, { - "key": "resourceBookingId", - "value": "{{resource_bookings_id_created_by_administrator}}", - "disabled": true + "key": "projectId", + "value": "{{project_id_16718}}" }, { - "key": "resourceBookingIds", - "value": "{{resource_bookings_id_created_by_administrator}},{{resource_bookings_id_created_by_administrator}}", + "key": "externalId", + "value": "1212", "disabled": true }, { - "key": "paymentStatus", - "value": "pending", + "key": "description", + "value": "Dummy", "disabled": true }, { "key": "startDate", - "value": "2021-03-07", + "value": "2020-09-27T04:17:23.131Z", "disabled": true }, { - "key": "endDate", - "value": "2021-03-13", + "key": "resourceType", + "value": "Dummy Resource Type", "disabled": true }, { - "key": "userHandle", - "value": "pshah_manager", + "key": "skill", + "value": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "disabled": true }, { - "key": "projectId", - "value": "111", + "key": "rateType", + "value": "hourly", + "disabled": true + }, + { + "key": "status", + "value": "sourcing", + "disabled": true + }, + { + "key": "workload", + "value": "full-time", + "disabled": true + }, + { + "key": "title", + "value": "dummy", "disabled": true } ] @@ -11540,32 +16629,19 @@ "response": [] }, { - "name": "✔ put work period with administrator", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test('Status code is 200', function () {\r", - " pm.response.to.have.status(200);\r", - "});" - ], - "type": "text/javascript" - } - } - ], + "name": "✔ put job with member", "request": { "method": "PUT", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_administrator}}" + "value": "Bearer {{token_member_tester1234}}" } ], "body": { "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resource_bookings_id_created_by_administrator}}\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "raw": "{\n \"projectId\": {{project_id_16718}},\n \"externalId\": \"1212\",\n \"description\": \"Dummy Description\",\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\n \"duration\": 1,\n \"numPositions\": 13,\n \"resourceType\": \"Dummy Resource Type\",\n \"rateType\": \"hourly\",\n \"workload\": \"fractional\",\n \"skills\": [\n \"cbac57a3-7180-4316-8769-73af64893158\",\n \"a2b4bc11-c641-4a19-9eb7-33980378f82e\"\n ],\n \"status\": \"sourcing\",\n \"title\": \"Dummy title - at most 64 characters\"\n}", "options": { "raw": { "language": "json" @@ -11573,45 +16649,32 @@ } }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId_created_by_administrator}}", + "raw": "{{URL}}/jobs/{{job_id_created_by_member}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId_created_by_administrator}}" + "jobs", + "{{job_id_created_by_member}}" ] } }, "response": [] }, { - "name": "✔ patch work period with administrator", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test('Status code is 200', function () {\r", - " pm.response.to.have.status(200);\r", - "});" - ], - "type": "text/javascript" - } - } - ], + "name": "✔ patch job with member", "request": { "method": "PATCH", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_administrator}}" + "value": "Bearer {{token_member_tester1234}}" } ], "body": { "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resource_bookings_id_created_by_administrator}}\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "raw": "{\n \"description\": \"Dummy Description\",\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\n \"duration\": 1,\n \"numPositions\": 13,\n \"resourceType\": \"Dummy Resource Type\",\n \"rateType\": \"hourly\",\n \"workload\": \"fractional\",\n \"skills\": [\n \"cbac57a3-7180-4316-8769-73af64893158\"\n ],\n \"status\": \"sourcing\",\n \"title\": \"Dummy title - at most 64 characters\"\n}", "options": { "raw": { "language": "json" @@ -11619,40 +16682,27 @@ } }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId_created_by_administrator}}", + "raw": "{{URL}}/jobs/{{job_id_created_by_member}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId_created_by_administrator}}" + "jobs", + "{{job_id_created_by_member}}" ] } }, "response": [] }, { - "name": "✔ delete work period with administrator", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test('Status code is 204', function () {\r", - " pm.response.to.have.status(204);\r", - "});" - ], - "type": "text/javascript" - } - } - ], + "name": "✘ delete job with member", "request": { "method": "DELETE", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_administrator}}" + "value": "Bearer {{token_member_tester1234}}" } ], "body": { @@ -11665,53 +16715,81 @@ } }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId_created_by_administrator}}", + "raw": "{{URL}}/jobs/{{job_id_created_by_member}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId_created_by_administrator}}" + "jobs", + "{{job_id_created_by_member}}" ] } }, "response": [] } ] - } - ] - }, - { - "name": "Request with Topcoder User Role", - "item": [ + }, { - "name": "README", + "name": "Job Candidates", "item": [ { - "name": "[STUB] all operations cause 403 error if user is not member of project", - "request": { - "method": "LOCK", - "header": [], - "url": { - "raw": "" + "name": "Before Test", + "item": [ + { + "name": "create job candidate", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var data = JSON.parse(responseBody);\r", + "postman.setEnvironmentVariable(\"job_candidate_id_created_for_member\",data.id);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"jobId\": \"{{job_id_created_by_member}}\",\r\n \"userId\": \"fe38eed1-af73-41fd-85a2-ac4da1ff09a3\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobCandidates", + "host": [ + "{{URL}}" + ], + "path": [ + "jobCandidates" + ] + } + }, + "response": [] } - }, - "response": [] - } - ] - }, - { - "name": "Jobs", - "item": [ + ] + }, { - "name": "✔ create job with member", + "name": "✘ create job candidate with member", "event": [ { "listen": "test", "script": { "exec": [ "var data = JSON.parse(responseBody);\r", - "postman.setEnvironmentVariable(\"job_id_created_by_member\",data.id);" + "postman.setEnvironmentVariable(\"job_candidate_id_created_by_member\",data.id);" ], "type": "text/javascript" } @@ -11722,13 +16800,13 @@ "header": [ { "key": "Authorization", - "value": "Bearer {{token_member_tester1234}}", - "type": "text" + "type": "text", + "value": "Bearer {{token_member_tester1234}}" } ], "body": { "mode": "raw", - "raw": "{\n \"projectId\": {{project_id_16718}},\n \"externalId\": \"1212\",\n \"description\": \"Dummy Description\",\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\n \"duration\": 1,\n \"numPositions\": 13,\n \"resourceType\": \"Dummy Resource Type\",\n \"rateType\": \"hourly\",\n \"workload\": \"full-time\",\n \"skills\": [\n \"23e00d92-207a-4b5b-b3c9-4c5662644941\",\n \"7d076384-ccf6-4e43-a45d-1b24b1e624aa\",\n \"cbac57a3-7180-4316-8769-73af64893158\",\n \"a2b4bc11-c641-4a19-9eb7-33980378f82e\"\n ],\n \"title\": \"Dummy title - at most 64 characters\"\n}", + "raw": "{\r\n \"jobId\": \"{{job_id_created_by_member}}\",\r\n \"userId\": \"fe38eed1-af73-41fd-85a2-ac4da1ff09a3\"\r\n}", "options": { "raw": { "language": "json" @@ -11736,19 +16814,19 @@ } }, "url": { - "raw": "{{URL}}/jobs", + "raw": "{{URL}}/jobCandidates", "host": [ "{{URL}}" ], "path": [ - "jobs" + "jobCandidates" ] } }, "response": [] }, { - "name": "✔ get job with member", + "name": "✔ get job candidate with member", "request": { "method": "GET", "header": [ @@ -11759,20 +16837,20 @@ } ], "url": { - "raw": "{{URL}}/jobs/{{job_id_created_by_member}}", + "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_for_member}}", "host": [ "{{URL}}" ], "path": [ - "jobs", - "{{job_id_created_by_member}}" + "jobCandidates", + "{{job_candidate_id_created_for_member}}" ] } }, "response": [] }, { - "name": "✔ search jobs with member filtering by \"projectId\"", + "name": "✔ search job candidates with member filtering by \"jobId\"", "request": { "method": "GET", "header": [ @@ -11783,81 +16861,46 @@ } ], "url": { - "raw": "{{URL}}/jobs?projectId={{project_id_16718}}", + "raw": "{{URL}}/jobCandidates?jobId={{job_id_created_by_member}}", "host": [ "{{URL}}" ], "path": [ - "jobs" - ], - "query": [ - { - "key": "page", - "value": "0", - "disabled": true - }, - { - "key": "perPage", - "value": "3", - "disabled": true - }, - { - "key": "sortBy", - "value": "id", - "disabled": true - }, - { - "key": "sortOrder", - "value": "asc", - "disabled": true - }, - { - "key": "projectId", - "value": "{{project_id_16718}}" - }, + "jobCandidates" + ], + "query": [ { - "key": "externalId", - "value": "1212", + "key": "page", + "value": "1", "disabled": true }, { - "key": "description", - "value": "Dummy", + "key": "perPage", + "value": "1", "disabled": true }, { - "key": "startDate", - "value": "2020-09-27T04:17:23.131Z", + "key": "sortBy", + "value": "id", "disabled": true }, { - "key": "resourceType", - "value": "Dummy Resource Type", + "key": "sortOrder", + "value": "asc", "disabled": true }, { - "key": "skill", - "value": "3fa85f64-5717-4562-b3fc-2c963f66afa6", - "disabled": true + "key": "jobId", + "value": "{{job_id_created_by_member}}" }, { - "key": "rateType", - "value": "hourly", + "key": "userId", + "value": "fe38eed1-af73-41fd-85a2-ac4da1ff09a3", "disabled": true }, { "key": "status", - "value": "sourcing", - "disabled": true - }, - { - "key": "workload", - "value": "full-time", - "disabled": true - }, - { - "key": "title", - "value": "dummy", + "value": "shortlist", "disabled": true } ] @@ -11866,7 +16909,7 @@ "response": [] }, { - "name": "✔ put job with member", + "name": "✔ put job candidate with member", "request": { "method": "PUT", "header": [ @@ -11878,7 +16921,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"projectId\": {{project_id_16718}},\n \"externalId\": \"1212\",\n \"description\": \"Dummy Description\",\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\n \"duration\": 1,\n \"numPositions\": 13,\n \"resourceType\": \"Dummy Resource Type\",\n \"rateType\": \"hourly\",\n \"workload\": \"fractional\",\n \"skills\": [\n \"cbac57a3-7180-4316-8769-73af64893158\",\n \"a2b4bc11-c641-4a19-9eb7-33980378f82e\"\n ],\n \"status\": \"sourcing\",\n \"title\": \"Dummy title - at most 64 characters\"\n}", + "raw": "{\r\n \"jobId\": \"{{job_id_created_by_member}}\",\r\n \"userId\": \"fe38eed1-af73-41fd-85a2-ac4da1ff09a3\",\r\n \"status\": \"selected\"\r\n}", "options": { "raw": { "language": "json" @@ -11886,20 +16929,20 @@ } }, "url": { - "raw": "{{URL}}/jobs/{{job_id_created_by_member}}", + "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_for_member}}", "host": [ "{{URL}}" ], "path": [ - "jobs", - "{{job_id_created_by_member}}" + "jobCandidates", + "{{job_candidate_id_created_for_member}}" ] } }, "response": [] }, { - "name": "✔ patch job with member", + "name": "✔ patch job candidate with member", "request": { "method": "PATCH", "header": [ @@ -11911,7 +16954,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"description\": \"Dummy Description\",\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\n \"duration\": 1,\n \"numPositions\": 13,\n \"resourceType\": \"Dummy Resource Type\",\n \"rateType\": \"hourly\",\n \"workload\": \"fractional\",\n \"skills\": [\n \"cbac57a3-7180-4316-8769-73af64893158\"\n ],\n \"status\": \"sourcing\",\n \"title\": \"Dummy title - at most 64 characters\"\n}", + "raw": "{\r\n \"status\": \"shortlist\"\r\n}", "options": { "raw": { "language": "json" @@ -11919,20 +16962,20 @@ } }, "url": { - "raw": "{{URL}}/jobs/{{job_id_created_by_member}}", + "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_for_member}}", "host": [ "{{URL}}" ], "path": [ - "jobs", - "{{job_id_created_by_member}}" + "jobCandidates", + "{{job_candidate_id_created_for_member}}" ] } }, "response": [] }, { - "name": "✘ delete job with member", + "name": "✘ delete job candidate with member", "request": { "method": "DELETE", "header": [ @@ -11952,13 +16995,13 @@ } }, "url": { - "raw": "{{URL}}/jobs/{{job_id_created_by_member}}", + "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_for_member}}", "host": [ "{{URL}}" ], "path": [ - "jobs", - "{{job_id_created_by_member}}" + "jobCandidates", + "{{job_candidate_id_created_for_member}}" ] } }, @@ -11967,11 +17010,55 @@ ] }, { - "name": "Job Candidates", + "name": "Interviews", "item": [ { "name": "Before Test", "item": [ + { + "name": "create job", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var data = JSON.parse(responseBody);\r", + "postman.setEnvironmentVariable(\"job_id_created_for_member\",data.id);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_administrator}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"projectId\": {{projectId}},\n \"externalId\": \"88774632\",\n \"description\": \"Dummy Description\",\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\n \"duration\": 1,\n \"numPositions\": 13,\n \"resourceType\": \"Dummy Resource Type\",\n \"rateType\": \"hourly\",\n \"workload\": \"full-time\",\n \"skills\": [\n \"23e00d92-207a-4b5b-b3c9-4c5662644941\",\n \"7d076384-ccf6-4e43-a45d-1b24b1e624aa\",\n \"cbac57a3-7180-4316-8769-73af64893158\",\n \"a2b4bc11-c641-4a19-9eb7-33980378f82e\"\n ],\n \"title\": \"Dummy title - at most 64 characters\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobs", + "host": [ + "{{URL}}" + ], + "path": [ + "jobs" + ] + } + }, + "response": [] + }, { "name": "create job candidate", "event": [ @@ -11997,7 +17084,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"jobId\": \"{{job_id_created_by_member}}\",\r\n \"userId\": \"fe38eed1-af73-41fd-85a2-ac4da1ff09a3\"\r\n}", + "raw": "{\r\n \"jobId\": \"{{job_id_created_by_administrator}}\",\r\n \"userId\": \"95e7970f-12b4-43b7-ab35-38c34bf033c7\"\r\n}", "options": { "raw": { "language": "json" @@ -12015,35 +17102,87 @@ } }, "response": [] + }, + { + "name": "create interview", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", + " const response = pm.response.json()\r", + " pm.environment.set(\"interview_round_created_for_member\", response.round)\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_administrator}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\",\r\n \"googleCalendarId\": \"dummyId\",\r\n \"customMessage\": \"This is a custom message\",\r\n \"status\": \"Scheduling\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_for_member}}/requestInterview", + "host": [ + "{{URL}}" + ], + "path": [ + "jobCandidates", + "{{job_candidate_id_created_for_member}}", + "requestInterview" + ] + } + }, + "response": [] } ] }, { - "name": "✘ create job candidate with member", + "name": "✘ request interview with member", "event": [ { "listen": "test", "script": { "exec": [ - "var data = JSON.parse(responseBody);\r", - "postman.setEnvironmentVariable(\"job_candidate_id_created_by_member\",data.id);" + "pm.test('Status code is 403', function () {\r", + " pm.response.to.have.status(403);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", + "});" ], "type": "text/javascript" } } ], "request": { - "method": "POST", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_member_tester1234}}" + "value": "Bearer {{token_member}}", + "type": "text" } ], "body": { "mode": "raw", - "raw": "{\r\n \"jobId\": \"{{job_id_created_by_member}}\",\r\n \"userId\": \"fe38eed1-af73-41fd-85a2-ac4da1ff09a3\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\",\r\n \"googleCalendarId\": \"dummyId\",\r\n \"customMessage\": \"This is a custom message\",\r\n \"status\": \"Scheduling\"\r\n}", "options": { "raw": { "language": "json" @@ -12051,147 +17190,89 @@ } }, "url": { - "raw": "{{URL}}/jobCandidates", - "host": [ - "{{URL}}" - ], - "path": [ - "jobCandidates" - ] - } - }, - "response": [] - }, - { - "name": "✔ get job candidate with member", - "request": { - "method": "GET", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_member_tester1234}}" - } - ], - "url": { - "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_for_member}}", + "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_for_member}}/requestInterview", "host": [ "{{URL}}" ], "path": [ "jobCandidates", - "{{job_candidate_id_created_for_member}}" + "{{job_candidate_id_created_for_member}}", + "requestInterview" ] } }, "response": [] }, { - "name": "✔ search job candidates with member filtering by \"jobId\"", - "request": { - "method": "GET", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_member_tester1234}}" + "name": "✘ get interview with member", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 403', function () {\r", + " pm.response.to.have.status(403);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", + "});" + ], + "type": "text/javascript" } - ], - "url": { - "raw": "{{URL}}/jobCandidates?jobId={{job_id_created_by_member}}", - "host": [ - "{{URL}}" - ], - "path": [ - "jobCandidates" - ], - "query": [ - { - "key": "page", - "value": "1", - "disabled": true - }, - { - "key": "perPage", - "value": "1", - "disabled": true - }, - { - "key": "sortBy", - "value": "id", - "disabled": true - }, - { - "key": "sortOrder", - "value": "asc", - "disabled": true - }, - { - "key": "jobId", - "value": "{{job_id_created_by_member}}" - }, - { - "key": "userId", - "value": "fe38eed1-af73-41fd-85a2-ac4da1ff09a3", - "disabled": true - }, - { - "key": "status", - "value": "shortlist", - "disabled": true - } - ] } - }, - "response": [] - }, - { - "name": "✔ put job candidate with member", + ], "request": { - "method": "PUT", + "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_member_tester1234}}" + "value": "Bearer {{token_member}}", + "type": "text" } ], - "body": { - "mode": "raw", - "raw": "{\r\n \"jobId\": \"{{job_id_created_by_member}}\",\r\n \"userId\": \"fe38eed1-af73-41fd-85a2-ac4da1ff09a3\",\r\n \"status\": \"selected\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_for_member}}", + "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_for_member}}/interviews/{{interview_round_created_for_member}}", "host": [ "{{URL}}" ], "path": [ "jobCandidates", - "{{job_candidate_id_created_for_member}}" + "{{job_candidate_id_created_for_member}}", + "interviews", + "{{interview_round_created_for_member}}" ] } }, "response": [] }, { - "name": "✔ patch job candidate with member", + "name": "✘ update interview with member", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 403', function () {\r", + " pm.response.to.have.status(403);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], "request": { "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_member_tester1234}}" + "value": "Bearer {{token_member}}", + "type": "text" } ], "body": { "mode": "raw", - "raw": "{\r\n \"status\": \"shortlist\"\r\n}", + "raw": "{\r\n \"customMessage\": \"updated\"\r\n}", "options": { "raw": { "language": "json" @@ -12199,46 +17280,55 @@ } }, "url": { - "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_for_member}}", + "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_for_member}}/updateInterview/{{interview_round_created_for_member}}", "host": [ "{{URL}}" ], "path": [ "jobCandidates", - "{{job_candidate_id_created_for_member}}" + "{{job_candidate_id_created_for_member}}", + "updateInterview", + "{{interview_round_created_for_member}}" ] } }, "response": [] }, { - "name": "✘ delete job candidate with member", + "name": "✘ search interviews with member", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 403', function () {\r", + " pm.response.to.have.status(403);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], "request": { - "method": "DELETE", + "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_member_tester1234}}" + "value": "Bearer {{token_member}}", + "type": "text" } ], - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_for_member}}", + "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_for_member}}/interviews", "host": [ "{{URL}}" ], "path": [ "jobCandidates", - "{{job_candidate_id_created_for_member}}" + "{{job_candidate_id_created_for_member}}", + "interviews" ] } }, @@ -12691,13 +17781,211 @@ "workPeriods" ] } - }, - "response": [] + }, + "response": [] + } + ] + }, + { + "name": "✘ create work period with member", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 403', function () {\r", + " pm.response.to.have.status(403);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_member_tester1234}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resource_booking_id_created_for_member}}\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/workPeriods", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods" + ] + } + }, + "response": [] + }, + { + "name": "✔ get work period with member", + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_member_tester1234}}" + } + ], + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodId_created_for_member}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodId_created_for_member}}" + ] + } + }, + "response": [] + }, + { + "name": "✔ search work periods with member", + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_member_tester1234}}" + } + ], + "url": { + "raw": "{{URL}}/workPeriods?projectId=16718", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods" + ], + "query": [ + { + "key": "page", + "value": "1", + "disabled": true + }, + { + "key": "perPage", + "value": "5", + "disabled": true + }, + { + "key": "sortBy", + "value": "id", + "disabled": true + }, + { + "key": "sortOrder", + "value": "desc", + "disabled": true + }, + { + "key": "resourceBookingId", + "value": "{{resource_booking_id_created_for_member}}", + "disabled": true + }, + { + "key": "resourceBookingIds", + "value": "{{resource_booking_id_created_for_member}},{{resource_booking_id_created_for_member}}", + "disabled": true + }, + { + "key": "paymentStatus", + "value": "pending", + "disabled": true + }, + { + "key": "startDate", + "value": "2021-03-07", + "disabled": true + }, + { + "key": "endDate", + "value": "2021-03-13", + "disabled": true + }, + { + "key": "userHandle", + "value": "pshah_manager", + "disabled": true + }, + { + "key": "projectId", + "value": "16718" + } + ] + } + }, + "response": [] + }, + { + "name": "✘ put work period with member", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 403', function () {\r", + " pm.response.to.have.status(403);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_member_tester1234}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"resourceBookingId\": \"{{resource_booking_id_created_for_member}}\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/workPeriods/{{workPeriodId_created_for_member}}", + "host": [ + "{{URL}}" + ], + "path": [ + "workPeriods", + "{{workPeriodId_created_for_member}}" + ] } - ] + }, + "response": [] }, { - "name": "✘ create work period with member", + "name": "✘ patch work period with member", "event": [ { "listen": "test", @@ -12714,7 +18002,7 @@ } ], "request": { - "method": "POST", + "method": "PATCH", "header": [ { "key": "Authorization", @@ -12732,21 +18020,37 @@ } }, "url": { - "raw": "{{URL}}/workPeriods", + "raw": "{{URL}}/workPeriods/{{workPeriodId_created_for_member}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods" + "workPeriods", + "{{workPeriodId_created_for_member}}" ] } }, "response": [] }, { - "name": "✔ get work period with member", + "name": "✘ delete work period with member", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 403', function () {\r", + " pm.response.to.have.status(403);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], "request": { - "method": "GET", + "method": "DELETE", "header": [ { "key": "Authorization", @@ -12754,6 +18058,15 @@ "value": "Bearer {{token_member_tester1234}}" } ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { "raw": "{{URL}}/workPeriods/{{workPeriodId_created_for_member}}", "host": [ @@ -12766,35 +18079,129 @@ } }, "response": [] + } + ] + } + ] + }, + { + "name": "Request with Connect Manager Role", + "item": [ + { + "name": "README", + "item": [ + { + "name": "[STUB] all operations except get/search cause 403 error if manager is not member of project", + "request": { + "method": "LOCK", + "header": [], + "url": { + "raw": "" + } + }, + "response": [] + } + ] + }, + { + "name": "Jobs", + "item": [ + { + "name": "✔ create job with connect manager", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var data = JSON.parse(responseBody);\r", + "postman.setEnvironmentVariable(\"job_id_created_by_connect_manager\",data.id);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_connect_manager_pshahcopmanag2}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"projectId\": {{project_id_16843}},\n \"externalId\": \"1212\",\n \"description\": \"Dummy Description\",\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\n \"duration\": 1,\n \"numPositions\": 13,\n \"resourceType\": \"Dummy Resource Type\",\n \"rateType\": \"hourly\",\n \"workload\": \"full-time\",\n \"skills\": [\n \"23e00d92-207a-4b5b-b3c9-4c5662644941\",\n \"7d076384-ccf6-4e43-a45d-1b24b1e624aa\",\n \"cbac57a3-7180-4316-8769-73af64893158\",\n \"a2b4bc11-c641-4a19-9eb7-33980378f82e\"\n ],\n \"title\": \"Dummy title - at most 64 characters\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobs", + "host": [ + "{{URL}}" + ], + "path": [ + "jobs" + ] + } + }, + "response": [] }, { - "name": "✔ search work periods with member", + "name": "✔ get job with connect manager", "request": { "method": "GET", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_member_tester1234}}" + "value": "Bearer {{token_connect_manager_pshahcopmanag2}}" } ], "url": { - "raw": "{{URL}}/workPeriods?projectId=16718", + "raw": "{{URL}}/jobs/{{job_id_created_by_connect_manager}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods" + "jobs", + "{{job_id_created_by_connect_manager}}" + ] + } + }, + "response": [] + }, + { + "name": "✔ search jobs with connect manager", + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_connect_manager_pshahcopmanag2}}" + } + ], + "url": { + "raw": "{{URL}}/jobs", + "host": [ + "{{URL}}" + ], + "path": [ + "jobs" ], "query": [ { "key": "page", - "value": "1", + "value": "0", "disabled": true }, { "key": "perPage", - "value": "5", + "value": "3", "disabled": true }, { @@ -12804,42 +18211,58 @@ }, { "key": "sortOrder", - "value": "desc", + "value": "asc", "disabled": true }, { - "key": "resourceBookingId", - "value": "{{resource_booking_id_created_for_member}}", + "key": "projectId", + "value": "21", "disabled": true }, { - "key": "resourceBookingIds", - "value": "{{resource_booking_id_created_for_member}},{{resource_booking_id_created_for_member}}", + "key": "externalId", + "value": "1212", "disabled": true }, { - "key": "paymentStatus", - "value": "pending", + "key": "description", + "value": "Dummy", "disabled": true }, { "key": "startDate", - "value": "2021-03-07", + "value": "2020-09-27T04:17:23.131Z", "disabled": true }, { - "key": "endDate", - "value": "2021-03-13", + "key": "resourceType", + "value": "Dummy Resource Type", "disabled": true }, { - "key": "userHandle", - "value": "pshah_manager", + "key": "skill", + "value": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "disabled": true }, { - "key": "projectId", - "value": "16718" + "key": "rateType", + "value": "hourly", + "disabled": true + }, + { + "key": "status", + "value": "sourcing", + "disabled": true + }, + { + "key": "workload", + "value": "full-time", + "disabled": true + }, + { + "key": "title", + "value": "dummy", + "disabled": true } ] } @@ -12847,34 +18270,19 @@ "response": [] }, { - "name": "✘ put work period with member", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test('Status code is 403', function () {\r", - " pm.response.to.have.status(403);\r", - " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", - "});" - ], - "type": "text/javascript" - } - } - ], + "name": "✔ put job with connect manager", "request": { "method": "PUT", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_member_tester1234}}" + "value": "Bearer {{token_connect_manager_pshahcopmanag2}}" } ], "body": { "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resource_booking_id_created_for_member}}\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "raw": "{\n \"projectId\": {{project_id_16843}},\n \"externalId\": \"1212\",\n \"description\": \"Dummy Description\",\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\n \"duration\": 1,\n \"numPositions\": 13,\n \"resourceType\": \"Dummy Resource Type\",\n \"rateType\": \"hourly\",\n \"workload\": \"fractional\",\n \"skills\": [\n \"cbac57a3-7180-4316-8769-73af64893158\",\n \"a2b4bc11-c641-4a19-9eb7-33980378f82e\"\n ],\n \"status\": \"sourcing\",\n \"title\": \"Dummy title - at most 64 characters\"\n}", "options": { "raw": { "language": "json" @@ -12882,47 +18290,32 @@ } }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId_created_for_member}}", + "raw": "{{URL}}/jobs/{{job_id_created_by_connect_manager}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId_created_for_member}}" + "jobs", + "{{job_id_created_by_connect_manager}}" ] } }, "response": [] }, { - "name": "✘ patch work period with member", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test('Status code is 403', function () {\r", - " pm.response.to.have.status(403);\r", - " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", - "});" - ], - "type": "text/javascript" - } - } - ], + "name": "✔ patch job with connect manager", "request": { "method": "PATCH", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_member_tester1234}}" + "value": "Bearer {{token_connect_manager_pshahcopmanag2}}" } ], "body": { "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resource_booking_id_created_for_member}}\",\r\n \"startDate\": \"2021-03-07\",\r\n \"endDate\": \"2021-03-13\",\r\n \"daysWorked\": 2,\r\n \"memberRate\": 13.13,\r\n \"customerRate\": 13.13,\r\n \"paymentStatus\": \"pending\"\r\n}", + "raw": "{\n \"description\": \"Dummy Description\",\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\n \"duration\": 1,\n \"numPositions\": 13,\n \"resourceType\": \"Dummy Resource Type\",\n \"rateType\": \"hourly\",\n \"workload\": \"fractional\",\n \"skills\": [\n \"cbac57a3-7180-4316-8769-73af64893158\"\n ],\n \"status\": \"sourcing\",\n \"title\": \"Dummy title - at most 64 characters\"\n}", "options": { "raw": { "language": "json" @@ -12930,42 +18323,27 @@ } }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId_created_for_member}}", + "raw": "{{URL}}/jobs/{{job_id_created_by_connect_manager}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId_created_for_member}}" + "jobs", + "{{job_id_created_by_connect_manager}}" ] } }, "response": [] }, { - "name": "✘ delete work period with member", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test('Status code is 403', function () {\r", - " pm.response.to.have.status(403);\r", - " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", - "});" - ], - "type": "text/javascript" - } - } - ], + "name": "✘ delete job with connect manager", "request": { "method": "DELETE", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_member_tester1234}}" + "value": "Bearer {{token_connect_manager_pshahcopmanag2}}" } ], "body": { @@ -12978,53 +18356,81 @@ } }, "url": { - "raw": "{{URL}}/workPeriods/{{workPeriodId_created_for_member}}", + "raw": "{{URL}}/jobs/{{job_id_created_by_connect_manager}}", "host": [ "{{URL}}" ], "path": [ - "workPeriods", - "{{workPeriodId_created_for_member}}" + "jobs", + "{{job_id_created_by_connect_manager}}" ] } }, "response": [] } ] - } - ] - }, - { - "name": "Request with Connect Manager Role", - "item": [ + }, { - "name": "README", + "name": "Job Candidates", "item": [ { - "name": "[STUB] all operations except get/search cause 403 error if manager is not member of project", - "request": { - "method": "LOCK", - "header": [], - "url": { - "raw": "" + "name": "Before Test", + "item": [ + { + "name": "create job candidate", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var data = JSON.parse(responseBody);\r", + "postman.setEnvironmentVariable(\"job_candidate_id_created_for_connect_manager\",data.id);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"jobId\": \"{{job_id_created_by_connect_manager}}\",\r\n \"userId\": \"fe38eed1-af73-41fd-85a2-ac4da1ff09a3\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobCandidates", + "host": [ + "{{URL}}" + ], + "path": [ + "jobCandidates" + ] + } + }, + "response": [] } - }, - "response": [] - } - ] - }, - { - "name": "Jobs", - "item": [ + ] + }, { - "name": "✔ create job with connect manager", + "name": "✘ create job candidate with connect manager", "event": [ { "listen": "test", "script": { "exec": [ "var data = JSON.parse(responseBody);\r", - "postman.setEnvironmentVariable(\"job_id_created_by_connect_manager\",data.id);" + "postman.setEnvironmentVariable(\"job_candidate_id_created_by_connect_manager\",data.id);" ], "type": "text/javascript" } @@ -13035,13 +18441,13 @@ "header": [ { "key": "Authorization", - "value": "Bearer {{token_connect_manager_pshahcopmanag2}}", - "type": "text" + "type": "text", + "value": "Bearer {{token_connect_manager_pshahcopmanag2}}" } ], "body": { "mode": "raw", - "raw": "{\n \"projectId\": {{project_id_16843}},\n \"externalId\": \"1212\",\n \"description\": \"Dummy Description\",\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\n \"duration\": 1,\n \"numPositions\": 13,\n \"resourceType\": \"Dummy Resource Type\",\n \"rateType\": \"hourly\",\n \"workload\": \"full-time\",\n \"skills\": [\n \"23e00d92-207a-4b5b-b3c9-4c5662644941\",\n \"7d076384-ccf6-4e43-a45d-1b24b1e624aa\",\n \"cbac57a3-7180-4316-8769-73af64893158\",\n \"a2b4bc11-c641-4a19-9eb7-33980378f82e\"\n ],\n \"title\": \"Dummy title - at most 64 characters\"\n}", + "raw": "{\r\n \"jobId\": \"{{job_id_created_by_connect_manager}}\",\r\n \"userId\": \"fe38eed1-af73-41fd-85a2-ac4da1ff09a3\"\r\n}", "options": { "raw": { "language": "json" @@ -13049,19 +18455,19 @@ } }, "url": { - "raw": "{{URL}}/jobs", + "raw": "{{URL}}/jobCandidates", "host": [ "{{URL}}" ], "path": [ - "jobs" + "jobCandidates" ] } }, "response": [] }, { - "name": "✔ get job with connect manager", + "name": "✔ get job candidate with connect manager", "request": { "method": "GET", "header": [ @@ -13072,20 +18478,20 @@ } ], "url": { - "raw": "{{URL}}/jobs/{{job_id_created_by_connect_manager}}", + "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_for_connect_manager}}", "host": [ "{{URL}}" ], "path": [ - "jobs", - "{{job_id_created_by_connect_manager}}" + "jobCandidates", + "{{job_candidate_id_created_for_connect_manager}}" ] } }, "response": [] }, { - "name": "✔ search jobs with connect manager", + "name": "✔ search job candidates with connect manager", "request": { "method": "GET", "header": [ @@ -13096,22 +18502,22 @@ } ], "url": { - "raw": "{{URL}}/jobs", + "raw": "{{URL}}/jobCandidates", "host": [ "{{URL}}" ], "path": [ - "jobs" + "jobCandidates" ], "query": [ { "key": "page", - "value": "0", + "value": "1", "disabled": true }, { "key": "perPage", - "value": "3", + "value": "1", "disabled": true }, { @@ -13125,53 +18531,18 @@ "disabled": true }, { - "key": "projectId", - "value": "21", - "disabled": true - }, - { - "key": "externalId", - "value": "1212", - "disabled": true - }, - { - "key": "description", - "value": "Dummy", - "disabled": true - }, - { - "key": "startDate", - "value": "2020-09-27T04:17:23.131Z", - "disabled": true - }, - { - "key": "resourceType", - "value": "Dummy Resource Type", - "disabled": true - }, - { - "key": "skill", - "value": "3fa85f64-5717-4562-b3fc-2c963f66afa6", + "key": "jobId", + "value": "46225f4c-c2a3-4603-a141-0277e96fabfa", "disabled": true }, { - "key": "rateType", - "value": "hourly", + "key": "userId", + "value": "fe38eed1-af73-41fd-85a2-ac4da1ff09a3", "disabled": true }, { "key": "status", - "value": "sourcing", - "disabled": true - }, - { - "key": "workload", - "value": "full-time", - "disabled": true - }, - { - "key": "title", - "value": "dummy", + "value": "shortlist", "disabled": true } ] @@ -13180,7 +18551,7 @@ "response": [] }, { - "name": "✔ put job with connect manager", + "name": "✔ put job candidate with connect manager", "request": { "method": "PUT", "header": [ @@ -13192,7 +18563,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"projectId\": {{project_id_16843}},\n \"externalId\": \"1212\",\n \"description\": \"Dummy Description\",\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\n \"duration\": 1,\n \"numPositions\": 13,\n \"resourceType\": \"Dummy Resource Type\",\n \"rateType\": \"hourly\",\n \"workload\": \"fractional\",\n \"skills\": [\n \"cbac57a3-7180-4316-8769-73af64893158\",\n \"a2b4bc11-c641-4a19-9eb7-33980378f82e\"\n ],\n \"status\": \"sourcing\",\n \"title\": \"Dummy title - at most 64 characters\"\n}", + "raw": "{\r\n \"jobId\": \"{{job_id_created_by_connect_manager}}\",\r\n \"userId\": \"fe38eed1-af73-41fd-85a2-ac4da1ff09a3\",\r\n \"status\": \"selected\"\r\n}", "options": { "raw": { "language": "json" @@ -13200,20 +18571,20 @@ } }, "url": { - "raw": "{{URL}}/jobs/{{job_id_created_by_connect_manager}}", + "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_for_connect_manager}}", "host": [ "{{URL}}" ], "path": [ - "jobs", - "{{job_id_created_by_connect_manager}}" + "jobCandidates", + "{{job_candidate_id_created_for_connect_manager}}" ] } }, "response": [] }, { - "name": "✔ patch job with connect manager", + "name": "✔ patch job candidate with connect manager", "request": { "method": "PATCH", "header": [ @@ -13225,7 +18596,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"description\": \"Dummy Description\",\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\n \"duration\": 1,\n \"numPositions\": 13,\n \"resourceType\": \"Dummy Resource Type\",\n \"rateType\": \"hourly\",\n \"workload\": \"fractional\",\n \"skills\": [\n \"cbac57a3-7180-4316-8769-73af64893158\"\n ],\n \"status\": \"sourcing\",\n \"title\": \"Dummy title - at most 64 characters\"\n}", + "raw": "{\r\n \"status\": \"shortlist\"\r\n}", "options": { "raw": { "language": "json" @@ -13233,20 +18604,20 @@ } }, "url": { - "raw": "{{URL}}/jobs/{{job_id_created_by_connect_manager}}", + "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_for_connect_manager}}", "host": [ "{{URL}}" ], "path": [ - "jobs", - "{{job_id_created_by_connect_manager}}" + "jobCandidates", + "{{job_candidate_id_created_for_connect_manager}}" ] } }, "response": [] }, { - "name": "✘ delete job with connect manager", + "name": "✘ delete job candidate with connect manager", "request": { "method": "DELETE", "header": [ @@ -13263,29 +18634,73 @@ "raw": { "language": "json" } - } + } + }, + "url": { + "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_for_connect_manager}}", + "host": [ + "{{URL}}" + ], + "path": [ + "jobCandidates", + "{{job_candidate_id_created_for_connect_manager}}" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "Interviews", + "item": [ + { + "name": "Before Test", + "item": [ + { + "name": "create job", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var data = JSON.parse(responseBody);\r", + "postman.setEnvironmentVariable(\"job_id_created_for_connect_manager\",data.id);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_administrator}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"projectId\": {{projectId}},\n \"externalId\": \"88774632\",\n \"description\": \"Dummy Description\",\n \"startDate\": \"2020-09-27T04:17:23.131Z\",\n \"duration\": 1,\n \"numPositions\": 13,\n \"resourceType\": \"Dummy Resource Type\",\n \"rateType\": \"hourly\",\n \"workload\": \"full-time\",\n \"skills\": [\n \"23e00d92-207a-4b5b-b3c9-4c5662644941\",\n \"7d076384-ccf6-4e43-a45d-1b24b1e624aa\",\n \"cbac57a3-7180-4316-8769-73af64893158\",\n \"a2b4bc11-c641-4a19-9eb7-33980378f82e\"\n ],\n \"title\": \"Dummy title - at most 64 characters\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobs", + "host": [ + "{{URL}}" + ], + "path": [ + "jobs" + ] + } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/jobs/{{job_id_created_by_connect_manager}}", - "host": [ - "{{URL}}" - ], - "path": [ - "jobs", - "{{job_id_created_by_connect_manager}}" - ] - } - }, - "response": [] - } - ] - }, - { - "name": "Job Candidates", - "item": [ - { - "name": "Before Test", - "item": [ { "name": "create job candidate", "event": [ @@ -13311,7 +18726,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"jobId\": \"{{job_id_created_by_connect_manager}}\",\r\n \"userId\": \"fe38eed1-af73-41fd-85a2-ac4da1ff09a3\"\r\n}", + "raw": "{\r\n \"jobId\": \"{{job_id_created_by_administrator}}\",\r\n \"userId\": \"95e7970f-12b4-43b7-ab35-38c34bf033c7\"\r\n}", "options": { "raw": { "language": "json" @@ -13329,35 +18744,87 @@ } }, "response": [] + }, + { + "name": "create interview", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", + " const response = pm.response.json()\r", + " pm.environment.set(\"interview_round_created_for_connect_manager\", response.round)\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_administrator}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\",\r\n \"googleCalendarId\": \"dummyId\",\r\n \"customMessage\": \"This is a custom message\",\r\n \"status\": \"Scheduling\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_for_connect_manager}}/requestInterview", + "host": [ + "{{URL}}" + ], + "path": [ + "jobCandidates", + "{{job_candidate_id_created_for_connect_manager}}", + "requestInterview" + ] + } + }, + "response": [] } ] }, { - "name": "✘ create job candidate with connect manager", + "name": "✘ request interview with connect manager", "event": [ { "listen": "test", "script": { "exec": [ - "var data = JSON.parse(responseBody);\r", - "postman.setEnvironmentVariable(\"job_candidate_id_created_by_connect_manager\",data.id);" + "pm.test('Status code is 403', function () {\r", + " pm.response.to.have.status(403);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", + "});" ], "type": "text/javascript" } } ], "request": { - "method": "POST", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_connect_manager_pshahcopmanag2}}" + "value": "Bearer {{token_connect_manager_pshahcopmanag2}}", + "type": "text" } ], "body": { "mode": "raw", - "raw": "{\r\n \"jobId\": \"{{job_id_created_by_connect_manager}}\",\r\n \"userId\": \"fe38eed1-af73-41fd-85a2-ac4da1ff09a3\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\",\r\n \"googleCalendarId\": \"dummyId\",\r\n \"customMessage\": \"This is a custom message\",\r\n \"status\": \"Scheduling\"\r\n}", "options": { "raw": { "language": "json" @@ -13365,148 +18832,89 @@ } }, "url": { - "raw": "{{URL}}/jobCandidates", + "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_for_connect_manager}}/requestInterview", "host": [ "{{URL}}" ], "path": [ - "jobCandidates" + "jobCandidates", + "{{job_candidate_id_created_for_connect_manager}}", + "requestInterview" ] } }, "response": [] }, { - "name": "✔ get job candidate with connect manager", - "request": { - "method": "GET", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_connect_manager_pshahcopmanag2}}" + "name": "✘ get interview with connect manager", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 403', function () {\r", + " pm.response.to.have.status(403);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", + "});" + ], + "type": "text/javascript" } - ], - "url": { - "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_for_connect_manager}}", - "host": [ - "{{URL}}" - ], - "path": [ - "jobCandidates", - "{{job_candidate_id_created_for_connect_manager}}" - ] } - }, - "response": [] - }, - { - "name": "✔ search job candidates with connect manager", + ], "request": { "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_connect_manager_pshahcopmanag2}}" + "value": "Bearer {{token_connect_manager_pshahcopmanag2}}", + "type": "text" } ], "url": { - "raw": "{{URL}}/jobCandidates", + "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_for_connect_manager}}/interviews/{{interview_round_created_for_connect_manager}}", "host": [ "{{URL}}" ], "path": [ - "jobCandidates" - ], - "query": [ - { - "key": "page", - "value": "1", - "disabled": true - }, - { - "key": "perPage", - "value": "1", - "disabled": true - }, - { - "key": "sortBy", - "value": "id", - "disabled": true - }, - { - "key": "sortOrder", - "value": "asc", - "disabled": true - }, - { - "key": "jobId", - "value": "46225f4c-c2a3-4603-a141-0277e96fabfa", - "disabled": true - }, - { - "key": "userId", - "value": "fe38eed1-af73-41fd-85a2-ac4da1ff09a3", - "disabled": true - }, - { - "key": "status", - "value": "shortlist", - "disabled": true - } + "jobCandidates", + "{{job_candidate_id_created_for_connect_manager}}", + "interviews", + "{{interview_round_created_for_connect_manager}}" ] } }, "response": [] }, { - "name": "✔ put job candidate with connect manager", - "request": { - "method": "PUT", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_connect_manager_pshahcopmanag2}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"jobId\": \"{{job_id_created_by_connect_manager}}\",\r\n \"userId\": \"fe38eed1-af73-41fd-85a2-ac4da1ff09a3\",\r\n \"status\": \"selected\"\r\n}", - "options": { - "raw": { - "language": "json" - } + "name": "✘ update interview with connect manager", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 403', function () {\r", + " pm.response.to.have.status(403);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", + "});" + ], + "type": "text/javascript" } - }, - "url": { - "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_for_connect_manager}}", - "host": [ - "{{URL}}" - ], - "path": [ - "jobCandidates", - "{{job_candidate_id_created_for_connect_manager}}" - ] } - }, - "response": [] - }, - { - "name": "✔ patch job candidate with connect manager", + ], "request": { "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_connect_manager_pshahcopmanag2}}" + "value": "Bearer {{token_connect_manager_pshahcopmanag2}}", + "type": "text" } ], "body": { "mode": "raw", - "raw": "{\r\n \"status\": \"shortlist\"\r\n}", + "raw": "{\r\n \"customMessage\": \"updated\"\r\n}", "options": { "raw": { "language": "json" @@ -13514,46 +18922,55 @@ } }, "url": { - "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_for_connect_manager}}", + "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_for_connect_manager}}/updateInterview/{{interview_round_created_for_connect_manager}}", "host": [ "{{URL}}" ], "path": [ "jobCandidates", - "{{job_candidate_id_created_for_connect_manager}}" + "{{job_candidate_id_created_for_connect_manager}}", + "updateInterview", + "{{interview_round_created_for_connect_manager}}" ] } }, "response": [] }, { - "name": "✘ delete job candidate with connect manager", + "name": "✘ search interviews with member", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 403', function () {\r", + " pm.response.to.have.status(403);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"You are not allowed to perform this action!\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], "request": { - "method": "DELETE", + "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_connect_manager_pshahcopmanag2}}" + "value": "Bearer {{token_connect_manager_pshahcopmanag2}}", + "type": "text" } ], - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_for_connect_manager}}", + "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_for_connect_manager}}/interviews", "host": [ "{{URL}}" ], "path": [ "jobCandidates", - "{{job_candidate_id_created_for_connect_manager}}" + "{{job_candidate_id_created_for_connect_manager}}", + "interviews" ] } }, diff --git a/docs/swagger.yaml b/docs/swagger.yaml index bbd145ef..5755210d 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -12,6 +12,7 @@ servers: tags: - name: Jobs - name: JobCandidates + - name: Interviews - name: ResourceBookings - name: Teams - name: WorkPeriods @@ -613,7 +614,7 @@ paths: schema: type: array items: - $ref: "#/components/schemas/JobCandidate" + $ref: "#/components/schemas/JobCandidateInterviewsIncluded" headers: X-Next-Page: @@ -698,7 +699,7 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/JobCandidate" + $ref: "#/components/schemas/JobCandidateInterviewsIncluded" "400": description: Bad request content: @@ -898,6 +899,306 @@ paths: application/json: schema: $ref: "#/components/schemas/Error" + /jobCandidates/{jobCandidateId}/requestInterview: + patch: + tags: + - Interviews + description: | + Request a new interview. + + **Authorization** Topcoder token with create interview scope is allowed + security: + - bearerAuth: [] + parameters: + - in: path + name: jobCandidateId + description: The job candidate id. + required: true + schema: + type: string + format: uuid + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/RequestInterviewBody" + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/Interview" + "400": + description: Bad request + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "401": + description: Not authenticated + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "403": + description: Forbidden + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "404": + description: Not Found + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "500": + description: Internal Server Error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + /jobCandidates/{jobCandidateId}/updateInterview/{round}: + patch: + tags: + - Interviews + description: | + Partially update interview. + + **Authorization** Topcoder token with update interview scope is allowed + security: + - bearerAuth: [] + parameters: + - in: path + name: jobCandidateId + description: The job candidate id. + required: true + schema: + type: string + format: uuid + - in: path + name: round + description: The interview round. + required: true + schema: + type: integer + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/UpdateInterviewRequestBody" + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/Interview" + "400": + description: Bad request + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "401": + description: Not authenticated + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "403": + description: Forbidden + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "404": + description: Not Found + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "500": + description: Internal Server Error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + /jobCandidates/{jobCandidateId}/interviews: + get: + tags: + - Interviews + description: | + Search interviews. + + **Authorization** Topcoder token with read interview scope is allowed + security: + - bearerAuth: [] + parameters: + - in: path + name: jobCandidateId + description: The job candidate id. + required: true + schema: + type: string + format: uuid + - in: query + name: page + required: false + schema: + type: integer + default: 1 + description: The page number. + - in: query + name: perPage + required: false + schema: + type: integer + default: 20 + description: The number of items to list per page. + - in: query + name: sortBy + required: false + schema: + type: string + default: createdAt + enum: ["round", "createdAt", "updatedAt"] + description: The sort by column. + - in: query + name: sortOrder + required: false + schema: + type: string + default: desc + enum: ["desc", "asc"] + - in: query + name: createdAt + required: false + schema: + type: string + format: date-time + description: The creation date/time of interview. + - in: query + name: updatedAt + required: false + schema: + type: string + format: date-time + description: The last update date/time of interview. + - in: query + name: status + required: false + schema: + type: string + enum: ["Requested"] + description: The interview status. + responses: + "200": + description: OK + content: + application/json: + schema: + type: array + items: + $ref: "#/components/schemas/Interview" + "400": + description: Bad request + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "401": + description: Not authenticated + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "403": + description: Forbidden + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "404": + description: Not Found + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "500": + description: Internal Server Error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + /jobCandidates/{jobCandidateId}/interviews/{round}: + get: + tags: + - Interviews + description: | + Get interview by round. + + **Authorization** Topcoder token with read interview scope is allowed + security: + - bearerAuth: [] + parameters: + - in: path + name: jobCandidateId + description: The job candidate id. + required: true + schema: + type: string + format: uuid + - in: path + name: round + description: The interview round. + required: true + schema: + type: integer + - in: query + name: fromDb + description: get data from db or not. + required: false + schema: + type: boolean + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/Interview" + "400": + description: Bad request + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "401": + description: Not authenticated + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "403": + description: Forbidden + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "404": + description: Not Found + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "500": + description: Internal Server Error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" /resourceBookings: post: tags: @@ -2654,6 +2955,67 @@ components: type: string example: "topcoder user" description: "The user who updated the job last time.(Will get the user info from the token)" + JobCandidateInterviewsIncluded: + required: + - id + - jobId + - userId + - status + properties: + id: + type: string + format: uuid + description: "The job id." + jobId: + type: string + format: uuid + description: "The project id." + userId: + type: string + format: uuid + example: "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a" + description: "The user id." + status: + type: string + enum: + [ + "open", + "selected", + "shortlist", + "rejected", + "cancelled", + "interview", + ] + description: "The job candidate status." + externalId: + type: string + example: "1212" + description: "The external id." + resume: + type: string + example: "http://example.com" + description: "The resume link" + interviews: + type: array + description: "Interviews associated to this job candidate." + items: + $ref: "#/components/schemas/Interview" + createdAt: + type: string + format: date-time + description: "The job created date." + createdBy: + type: string + example: "topocder user" + description: "The user who created the job.(Will get the user info from the token)" + updatedAt: + type: string + format: date-time + description: "The job last updated at." + updatedBy: + type: string + example: "topcoder user" + description: "The user who updated the job last time.(Will get the user info from the token)" JobCandidateRequestBody: required: - jobId @@ -2702,6 +3064,125 @@ components: type: string example: "http://example.com" description: "The resume link" + Interview: + required: + - id + - jobCandidateId + - xaiTemplate + - round + - status + - createdAt + - createdBy + properties: + id: + type: string + format: uuid + description: "The interview id." + jobCandidateId: + type: string + format: uuid + description: "The job candidate id." + googleCalendarId: + type: string + example: "dummyId" + description: "The google calendar id." + xaiTemplate: + type: string + example: "30-min-interview" + enum: ["30-min-interview", "60-min-interview"] + description: "The x.ai template name" + customMessage: + type: string + example: "This is a custom message" + description: "The custom message." + round: + type: integer + example: 1 + description: "The interview round." + attendeesList: + type: array + description: "Attendee list for this interview." + items: + type: string + format: email + startTimestamp: + type: string + format: date-time + description: "Interview start time." + status: + type: string + enum: ["Scheduling", "Scheduled", "Requested for reschedule", "Rescheduled", "Completed", "Cancelled"] + description: "The interview status." + createdAt: + type: string + format: date-time + description: "The interview created date." + createdBy: + type: string + format: uuid + description: "The user who created the interview.(Will get the user info from the token)" + updatedAt: + type: string + format: date-time + description: "The interview last updated at." + updatedBy: + type: string + format: uuid + description: "The user who updated the interview last time.(Will get the user info from the token)" + RequestInterviewBody: + required: + - xaiTemplate + properties: + googleCalendarId: + type: string + example: "dummyId" + description: "The google calendar id." + customMessage: + type: string + example: "This is a custom message" + description: "The custom message." + xaiTemplate: + type: string + enum: ["30-min-interview", "60-min-interview"] + example: "30-min-interview" + description: "The x.ai template name" + attendeesList: + type: array + items: + type: string + format: email + status: + type: string + enum: ["Scheduling", "Scheduled", "Requested for reschedule", "Rescheduled", "Completed", "Cancelled"] + default: "Scheduling" + description: "The interview status." + UpdateInterviewRequestBody: + properties: + googleCalendarId: + type: string + example: "dummyId" + description: "The google calendar id." + customMessage: + type: string + example: "This is a custom message" + description: "The custom message." + xaiTemplate: + type: string + enum: ["30-min-interview", "60-min-interview"] + example: "30-min-interview" + description: "The x.ai template name" + attendeesList: + type: array + items: + type: string + format: email + startTimestamp: + type: string + format: date-time + status: + type: string + enum: ["Scheduling", "Scheduled", "Requested for reschedule", "Rescheduled", "Completed", "Cancelled"] + description: "The interview status." JobPatchRequestBody: properties: status: diff --git a/docs/topcoder-bookings.postman_environment.json b/docs/topcoder-bookings.postman_environment.json index f68993a4..ab3a4abf 100644 --- a/docs/topcoder-bookings.postman_environment.json +++ b/docs/topcoder-bookings.postman_environment.json @@ -1,5 +1,5 @@ { - "id": "9f3d832e-2330-4b01-ad24-acdca64aa2d6", + "id": "0babdf5b-d5cb-485e-b270-6da0a644614f", "name": "topcoder-bookings", "values": [ { @@ -261,9 +261,89 @@ "key": "job_candidate_id_created_by_administrator", "value": "", "enabled": true + }, + { + "key": "interviewRound", + "value": "1", + "enabled": true + }, + { + "key": "interview_round_created_by_administrator", + "value": "1", + "enabled": true + }, + { + "key": "job_id_created_for_member", + "value": "", + "enabled": true + }, + { + "key": "job_candidate_id_created_for_member", + "value": "", + "enabled": true + }, + { + "key": "interview_round_created_for_member", + "value": "1", + "enabled": true + }, + { + "key": "job_id_created_for_connect_manager", + "value": "", + "enabled": true + }, + { + "key": "job_candidate_id_created_for_connect_manager", + "value": "", + "enabled": true + }, + { + "key": "interview_round_created_for_connect_manager", + "value": "1", + "enabled": true + }, + { + "key": "completedInterviewJobCandidateId", + "value": "", + "enabled": true + }, + { + "key": "completedInterviewRound", + "value": "", + "enabled": true + }, + { + "key": "token_m2m_create_interviews", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL3RvcGNvZGVyLWRldi5hdXRoMC5jb20vIiwic3ViIjoiZW5qdzE4MTBlRHozWFR3U08yUm4yWTljUVRyc3BuM0JAY2xpZW50cyIsImF1ZCI6Imh0dHBzOi8vbTJtLnRvcGNvZGVyLWRldi5jb20vIiwiaWF0IjoxNTUwOTA2Mzg4LCJleHAiOjIxNDc0ODM2NDgsImF6cCI6ImVuancxODEwZUR6M1hUd1NPMlJuMlk5Y1FUcnNwbjNCIiwic2NvcGUiOiJjcmVhdGU6dGFhcy1pbnRlcnZpZXdzIiwiZ3R5IjoiY2xpZW50LWNyZWRlbnRpYWxzIn0.VD5j8qdgK3ZPctqD-Nb5KKfSeFIuyajc7Q-wQ_kabIk", + "enabled": true + }, + { + "key": "token_m2m_read_interviews", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL3RvcGNvZGVyLWRldi5hdXRoMC5jb20vIiwic3ViIjoiZW5qdzE4MTBlRHozWFR3U08yUm4yWTljUVRyc3BuM0JAY2xpZW50cyIsImF1ZCI6Imh0dHBzOi8vbTJtLnRvcGNvZGVyLWRldi5jb20vIiwiaWF0IjoxNTUwOTA2Mzg4LCJleHAiOjIxNDc0ODM2NDgsImF6cCI6ImVuancxODEwZUR6M1hUd1NPMlJuMlk5Y1FUcnNwbjNCIiwic2NvcGUiOiJyZWFkOnRhYXMtaW50ZXJ2aWV3cyIsImd0eSI6ImNsaWVudC1jcmVkZW50aWFscyJ9.3Gf42TvkegVi9uiIro75G8-2MqkLdeSbuswVRuZf7t4", + "enabled": true + }, + { + "key": "token_m2m_all_interviews", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL3RvcGNvZGVyLWRldi5hdXRoMC5jb20vIiwic3ViIjoiZW5qdzE4MTBlRHozWFR3U08yUm4yWTljUVRyc3BuM0JAY2xpZW50cyIsImF1ZCI6Imh0dHBzOi8vbTJtLnRvcGNvZGVyLWRldi5jb20vIiwiaWF0IjoxNTUwOTA2Mzg4LCJleHAiOjIxNDc0ODM2NDgsImF6cCI6ImVuancxODEwZUR6M1hUd1NPMlJuMlk5Y1FUcnNwbjNCIiwic2NvcGUiOiJhbGw6dGFhcy1pbnRlcnZpZXdzIiwiZ3R5IjoiY2xpZW50LWNyZWRlbnRpYWxzIn0.N79nfsZvGzX01hufnMzGG7wNCBqL8eceSpJnHS0lhqo", + "enabled": true + }, + { + "key": "token_m2m_update_interviews", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL3RvcGNvZGVyLWRldi5hdXRoMC5jb20vIiwic3ViIjoiZW5qdzE4MTBlRHozWFR3U08yUm4yWTljUVRyc3BuM0JAY2xpZW50cyIsImF1ZCI6Imh0dHBzOi8vbTJtLnRvcGNvZGVyLWRldi5jb20vIiwiaWF0IjoxNTUwOTA2Mzg4LCJleHAiOjIxNDc0ODM2NDgsImF6cCI6ImVuancxODEwZUR6M1hUd1NPMlJuMlk5Y1FUcnNwbjNCIiwic2NvcGUiOiJ1cGRhdGU6dGFhcy1pbnRlcnZpZXdzIiwiZ3R5IjoiY2xpZW50LWNyZWRlbnRpYWxzIn0.qGPZrHL9ybzQEq_KlOMM6VfIPJttTVGa7KpVLNDdMHI", + "enabled": true + }, + { + "key": "token_m2m_read_jobCandidate_read_interviews", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL3RvcGNvZGVyLWRldi5hdXRoMC5jb20vIiwic3ViIjoiZW5qdzE4MTBlRHozWFR3U08yUm4yWTljUVRyc3BuM0JAY2xpZW50cyIsImF1ZCI6Imh0dHBzOi8vbTJtLnRvcGNvZGVyLWRldi5jb20vIiwiaWF0IjoxNTUwOTA2Mzg4LCJleHAiOjIxNDc0ODM2NDgsImF6cCI6ImVuancxODEwZUR6M1hUd1NPMlJuMlk5Y1FUcnNwbjNCIiwic2NvcGUiOiJyZWFkOnRhYXMtam9iQ2FuZGlkYXRlcyByZWFkOnRhYXMtaW50ZXJ2aWV3cyIsImd0eSI6ImNsaWVudC1jcmVkZW50aWFscyJ9._HP8XEoY8eLQRK7K0jgqVPvTGrMS6OwutDU-nCPdopE", + "enabled": true + }, + { + "key": "token_m2m_read_jobCandidates_all_interviews", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL3RvcGNvZGVyLWRldi5hdXRoMC5jb20vIiwic3ViIjoiZW5qdzE4MTBlRHozWFR3U08yUm4yWTljUVRyc3BuM0JAY2xpZW50cyIsImF1ZCI6Imh0dHBzOi8vbTJtLnRvcGNvZGVyLWRldi5jb20vIiwiaWF0IjoxNTUwOTA2Mzg4LCJleHAiOjIxNDc0ODM2NDgsImF6cCI6ImVuancxODEwZUR6M1hUd1NPMlJuMlk5Y1FUcnNwbjNCIiwic2NvcGUiOiJyZWFkOnRhYXMtam9iQ2FuZGlkYXRlcyBhbGw6dGFhcy1pbnRlcnZpZXdzIiwiZ3R5IjoiY2xpZW50LWNyZWRlbnRpYWxzIn0.XQj74JSHp98XKxa1eZnMMpHxGpHeZAHVhLvFAN7gHBY", + "enabled": true } ], "_postman_variable_scope": "environment", - "_postman_exported_at": "2021-03-30T00:44:02.221Z", - "_postman_exported_using": "Postman/8.0.9" + "_postman_exported_at": "2021-04-18T22:46:43.185Z", + "_postman_exported_using": "Postman/8.2.3" } \ No newline at end of file diff --git a/local/kafka-client/topics.txt b/local/kafka-client/topics.txt index 49e4d614..7d3710b0 100644 --- a/local/kafka-client/topics.txt +++ b/local/kafka-client/topics.txt @@ -10,4 +10,7 @@ taas.job.delete taas.jobcandidate.delete taas.resourcebooking.delete taas.workperiod.delete +taas.interview.requested +taas.interview.update +taas.interview.bulkUpdate external.action.email diff --git a/migrations/2021-04-12-create-interviews-table.js b/migrations/2021-04-12-create-interviews-table.js new file mode 100644 index 00000000..53eaab1a --- /dev/null +++ b/migrations/2021-04-12-create-interviews-table.js @@ -0,0 +1,102 @@ +'use strict'; + +const config = require('config') +const _ = require('lodash') +const { Interviews } = require('../app-constants') + +// allowed status values +const statuses = _.values(Interviews.Status) + +/** + * Create `interviews` table & relations. + */ +module.exports = { + up: async (queryInterface, Sequelize) => { + const table = { schema: config.DB_SCHEMA_NAME, tableName: 'interviews' } + await queryInterface.createTable(table, { + id: { + type: Sequelize.UUID, + primaryKey: true, + allowNull: false, + defaultValue: Sequelize.UUIDV4 + }, + jobCandidateId: { + field: 'job_candidate_id', + type: Sequelize.UUID, + allowNull: false, + references: { + model: { + tableName: 'job_candidates', + schema: config.DB_SCHEMA_NAME + }, + key: 'id' + } + }, + googleCalendarId: { + field: 'google_calendar_id', + type: Sequelize.STRING(255) + }, + customMessage: { + field: 'custom_message', + type: Sequelize.TEXT + }, + xaiTemplate: { + field: 'xai_template', + type: Sequelize.STRING(255), + allowNull: false + }, + round: { + type: Sequelize.INTEGER, + allowNull: false + }, + startTimestamp: { + field: 'start_timestamp', + type: Sequelize.DATE + }, + attendeesList: { + field: 'attendees_list', + type: Sequelize.ARRAY(Sequelize.STRING) + }, + status: { + type: Sequelize.ENUM(statuses), + allowNull: false + }, + createdBy: { + field: 'created_by', + type: Sequelize.UUID, + allowNull: false + }, + updatedBy: { + field: 'updated_by', + type: Sequelize.UUID + }, + createdAt: { + field: 'created_at', + type: Sequelize.DATE + }, + updatedAt: { + field: 'updated_at', + type: Sequelize.DATE + }, + deletedAt: { + field: 'deleted_at', + type: Sequelize.DATE + } + }, { schema: config.DB_SCHEMA_NAME }) + }, + + down: async (queryInterface, Sequelize) => { + const table = { schema: config.DB_SCHEMA_NAME, tableName: 'interviews' } + const statusTypeName = `${table.schema}.enum_${table.tableName}_status` + const transaction = await queryInterface.sequelize.transaction() + try { + await queryInterface.dropTable(table, { transaction }) + // drop enum type for status column + await queryInterface.sequelize.query(`DROP TYPE ${statusTypeName}`, { transaction }) + await transaction.commit() + } catch (err) { + await transaction.rollback() + throw err + } + } +}; diff --git a/package-lock.json b/package-lock.json index 225069c1..8bb49b0d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1500,6 +1500,15 @@ "write-file-atomic": "^3.0.0" } }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -1891,6 +1900,15 @@ "vary": "^1" } }, + "cron-parser": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-3.3.0.tgz", + "integrity": "sha512-Tz5WxSrDVhR7YVuLuUxhXoMGHCWoe8I7g8APkyRZNaINXHQ3zcfK97av6hBYy9ue4sOLI7ZH7SeQqi/t4jR+5A==", + "requires": { + "is-nan": "^1.3.0", + "luxon": "^1.25.0" + } + }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", @@ -3098,6 +3116,16 @@ "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", "dev": true }, + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, "get-package-type": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", @@ -3201,25 +3229,6 @@ "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", "dev": true }, - "handlebars": { - "version": "4.7.6", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz", - "integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==", - "requires": { - "minimist": "^1.2.5", - "neo-async": "^2.6.0", - "source-map": "^0.6.1", - "uglify-js": "^3.1.4", - "wordwrap": "^1.0.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } - } - }, "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -3693,6 +3702,15 @@ "integrity": "sha512-T/S49scO8plUiAOA2DBTBG3JHpn1yiw0kRp6dgiZ0v2/6twi5eiB0rHtHFH9ZIrvlWc6+4O+m4zg5+Z833aXgw==", "dev": true }, + "is-nan": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + } + }, "is-negative-zero": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", @@ -4567,6 +4585,11 @@ } } }, + "long-timeout": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/long-timeout/-/long-timeout-0.1.1.tgz", + "integrity": "sha1-lyHXiLR+C8taJMLivuGg2lXatRQ=" + }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -4609,6 +4632,11 @@ "es5-ext": "~0.10.2" } }, + "luxon": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.26.0.tgz", + "integrity": "sha512-+V5QIQ5f6CDXQpWNICELwjwuHdqeJM1UenlZWx5ujcRMc9venvluCjFb4t5NYLhb6IhkbMVOxzVuOqkgMxee2A==" + }, "make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -4963,11 +4991,6 @@ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" }, - "neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" - }, "next-tick": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", @@ -5018,6 +5041,16 @@ "process-on-spawn": "^1.0.0" } }, + "node-schedule": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/node-schedule/-/node-schedule-2.0.0.tgz", + "integrity": "sha512-cHc9KEcfiuXxYDU+HjsBVo2FkWL1jRAUoczFoMIzRBpOA4p/NRHuuLs85AWOLgKsHtSPjN8csvwIxc2SqMv+CQ==", + "requires": { + "cron-parser": "^3.1.0", + "long-timeout": "0.1.1", + "sorted-array-functions": "^1.3.0" + } + }, "nodemon": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.4.tgz", @@ -6773,6 +6806,11 @@ } } }, + "sorted-array-functions": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/sorted-array-functions/-/sorted-array-functions-1.3.0.tgz", + "integrity": "sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA==" + }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -7411,12 +7449,6 @@ "is-typedarray": "^1.0.0" } }, - "uglify-js": { - "version": "3.12.8", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.12.8.tgz", - "integrity": "sha512-fvBeuXOsvqjecUtF/l1dwsrrf5y2BCUk9AOJGzGcm6tE7vegku5u/YvqjyDaAGr422PLoLnrxg3EnRvTqsdC1w==", - "optional": true - }, "umzug": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/umzug/-/umzug-2.3.0.tgz", @@ -7814,11 +7846,6 @@ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==" }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" - }, "workerpool": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.0.0.tgz", diff --git a/package.json b/package.json index 86ab71ce..4dd34c36 100644 --- a/package.json +++ b/package.json @@ -44,11 +44,11 @@ "express": "^4.17.1", "express-interceptor": "^1.2.0", "get-parameter-names": "^0.3.0", - "handlebars": "^4.7.6", "http-status": "^1.4.2", "http-status-codes": "^2.1.4", "joi": "^17.2.1", "lodash": "^4.17.20", + "node-schedule": "^2.0.0", "pg": "^8.4.0", "pg-hstore": "^2.3.3", "prompt-confirm": "^2.0.4", diff --git a/scripts/data/exportData.js b/scripts/data/exportData.js index 858988d7..2de176a1 100644 --- a/scripts/data/exportData.js +++ b/scripts/data/exportData.js @@ -2,12 +2,21 @@ * Export data to a json file */ const config = require('config') +const { Interview } = require('../../src/models') const logger = require('../../src/common/logger') const helper = require('../../src/common/helper') +const jobCandidateModelOpts = { + modelName: 'JobCandidate', + include: [{ + model: Interview, + as: 'interviews' + }] +} + const filePath = helper.getParamFromCliArgs() || config.DEFAULT_DATA_FILE_PATH const userPrompt = `WARNING: are you sure you want to export all data in the database to a json file with the path ${filePath}? This will overwrite the file.` -const dataModels = ['Job', 'JobCandidate', 'ResourceBooking', 'WorkPeriod'] +const dataModels = ['Job', jobCandidateModelOpts, 'ResourceBooking', 'WorkPeriod'] async function exportData () { await helper.promptUser(userPrompt, async () => { diff --git a/scripts/data/importData.js b/scripts/data/importData.js index f1770196..d4e7d2c7 100644 --- a/scripts/data/importData.js +++ b/scripts/data/importData.js @@ -2,12 +2,21 @@ * Import data from a json file into the db and index it in Elasticsearch */ const config = require('config') +const { Interview } = require('../../src/models') const logger = require('../../src/common/logger') const helper = require('../../src/common/helper') +const jobCandidateModelOpts = { + modelName: 'JobCandidate', + include: [{ + model: Interview, + as: 'interviews' + }] +} + const filePath = helper.getParamFromCliArgs() || config.DEFAULT_DATA_FILE_PATH const userPrompt = `WARNING: this would remove existing data. Are you sure you want to import data from a json file with the path ${filePath}?` -const dataModels = ['Job', 'JobCandidate', 'ResourceBooking', 'WorkPeriod'] +const dataModels = ['Job', jobCandidateModelOpts, 'ResourceBooking', 'WorkPeriod'] async function importData () { await helper.promptUser(userPrompt, async () => { diff --git a/scripts/es/reIndexAll.js b/scripts/es/reIndexAll.js index 215efaa2..4f6ef52d 100644 --- a/scripts/es/reIndexAll.js +++ b/scripts/es/reIndexAll.js @@ -2,16 +2,25 @@ * Reindex all data in Elasticsearch using data from database */ const config = require('config') +const { Interview } = require('../../src/models') const logger = require('../../src/common/logger') const helper = require('../../src/common/helper') const userPrompt = 'WARNING: this would remove existent data! Are you sure want to reindex all indices?' +const jobCandidateModelOpts = { + modelName: 'JobCandidate', + include: [{ + model: Interview, + as: 'interviews' + }] +} + async function indexAll () { await helper.promptUser(userPrompt, async () => { try { await helper.indexBulkDataToES('Job', config.get('esConfig.ES_INDEX_JOB'), logger) - await helper.indexBulkDataToES('JobCandidate', config.get('esConfig.ES_INDEX_JOB_CANDIDATE'), logger) + await helper.indexBulkDataToES(jobCandidateModelOpts, config.get('esConfig.ES_INDEX_JOB_CANDIDATE'), logger) await helper.indexBulkDataToES('ResourceBooking', config.get('esConfig.ES_INDEX_RESOURCE_BOOKING'), logger) await helper.indexBulkDataToES('WorkPeriod', config.get('esConfig.ES_INDEX_WORK_PERIOD'), logger) process.exit(0) diff --git a/scripts/es/reIndexJobCandidates.js b/scripts/es/reIndexJobCandidates.js index 7e0aec22..585416a5 100644 --- a/scripts/es/reIndexJobCandidates.js +++ b/scripts/es/reIndexJobCandidates.js @@ -2,6 +2,7 @@ * Reindex JobCandidates data in Elasticsearch using data from database */ const config = require('config') +const { Interview } = require('../../src/models') const logger = require('../../src/common/logger') const helper = require('../../src/common/helper') @@ -10,11 +11,19 @@ const index = config.get('esConfig.ES_INDEX_JOB_CANDIDATE') const reIndexAllJobCandidatesPrompt = `WARNING: this would remove existent data! Are you sure you want to reindex the index ${index}?` const reIndexJobCandidatePrompt = `WARNING: this would remove existent data! Are you sure you want to reindex the document with id ${jobCandidateId} in index ${index}?` +const jobCandidateModelOpts = { + modelName: 'JobCandidate', + include: [{ + model: Interview, + as: 'interviews' + }] +} + async function reIndexJobCandidates () { if (jobCandidateId === null) { await helper.promptUser(reIndexAllJobCandidatesPrompt, async () => { try { - await helper.indexBulkDataToES('JobCandidate', index, logger) + await helper.indexBulkDataToES(jobCandidateModelOpts, index, logger) process.exit(0) } catch (err) { logger.logFullError(err, { component: 'reIndexJobCandidates' }) @@ -24,7 +33,7 @@ async function reIndexJobCandidates () { } else { await helper.promptUser(reIndexJobCandidatePrompt, async () => { try { - await helper.indexDataToEsById(jobCandidateId, 'JobCandidate', index, logger) + await helper.indexDataToEsById(jobCandidateId, jobCandidateModelOpts, index, logger) process.exit(0) } catch (err) { logger.logFullError(err, { component: 'reIndexJobCandidates' }) diff --git a/src/bootstrap.js b/src/bootstrap.js index a85bdec4..c814ec02 100644 --- a/src/bootstrap.js +++ b/src/bootstrap.js @@ -1,8 +1,13 @@ const fs = require('fs') const Joi = require('joi') const path = require('path') +const _ = require('lodash') +const { Interviews } = require('../app-constants') const logger = require('./common/logger') +const allowedInterviewStatuses = _.values(Interviews.Status) +const allowedXAITemplate = _.values(Interviews.XaiTemplate) + Joi.page = () => Joi.number().integer().min(1).default(1) Joi.perPage = () => Joi.number().integer().min(1).default(20) Joi.rateType = () => Joi.string().valid('hourly', 'daily', 'weekly', 'monthly') @@ -11,6 +16,8 @@ Joi.workload = () => Joi.string().valid('full-time', 'fractional') Joi.jobCandidateStatus = () => Joi.string().valid('open', 'selected', 'shortlist', 'rejected', 'cancelled', 'interview') Joi.title = () => Joi.string().max(128) Joi.paymentStatus = () => Joi.string().valid('pending', 'partially-completed', 'completed', 'cancelled') +Joi.xaiTemplate = () => Joi.string().valid(...allowedXAITemplate) +Joi.interviewStatus = () => Joi.string().valid(...allowedInterviewStatuses) // Empty string is not allowed by Joi by default and must be enabled with allow(''). // See https://joi.dev/api/?v=17.3.0#string fro details why it's like this. // In many cases we would like to allow empty string to make it easier to create UI for editing data. diff --git a/src/common/helper.js b/src/common/helper.js index da86c854..89c3f4c2 100644 --- a/src/common/helper.js +++ b/src/common/helper.js @@ -12,6 +12,7 @@ const HttpStatus = require('http-status-codes') const _ = require('lodash') const request = require('superagent') const elasticsearch = require('@elastic/elasticsearch') +const { ResponseError: ESResponseError } = require('@elastic/elasticsearch/lib/errors') const errors = require('../common/errors') const logger = require('./logger') const models = require('../models') @@ -82,6 +83,24 @@ esIndexPropertyMapping[config.get('esConfig.ES_INDEX_JOB_CANDIDATE')] = { status: { type: 'keyword' }, externalId: { type: 'keyword' }, resume: { type: 'text' }, + interviews: { + type: 'nested', + properties: { + id: { type: 'keyword' }, + jobCandidateId: { type: 'keyword' }, + googleCalendarId: { type: 'keyword' }, + customMessage: { type: 'text' }, + xaiTemplate: { type: 'keyword' }, + startTimestamp: { type: 'date' }, + attendeesList: [], + round: { type: 'integer' }, + status: { type: 'keyword' }, + createdAt: { type: 'date' }, + createdBy: { type: 'keyword' }, + updatedAt: { type: 'date' }, + updatedBy: { type: 'keyword' } + } + }, createdAt: { type: 'date' }, createdBy: { type: 'keyword' }, updatedAt: { type: 'date' }, @@ -231,11 +250,14 @@ function getBulksFromDocuments (data) { /** * Index records in bulk -* @param {Object} modelName the model name in db +* @param {Object | String} modelOpts the model name in db, or model options * @param {Object} indexName the index name * @param {Object} logger the logger object */ -async function indexBulkDataToES (modelName, indexName, logger) { +async function indexBulkDataToES (modelOpts, indexName, logger) { + const modelName = _.isString(modelOpts) ? modelOpts : modelOpts.modelName + const include = _.get(modelOpts, 'include', []) + logger.info({ component: 'indexBulkDataToES', message: `Reindexing of ${modelName}s started!` }) const esClient = getESClient() @@ -250,14 +272,13 @@ async function indexBulkDataToES (modelName, indexName, logger) { // get data from db logger.info({ component: 'indexBulkDataToES', message: 'Getting data from database' }) const model = models[modelName] - const data = await model.findAll({ - raw: true - }) - if (_.isEmpty(data)) { + const data = await model.findAll({ include }) + const rawObjects = _.map(data, r => r.toJSON()) + if (_.isEmpty(rawObjects)) { logger.info({ component: 'indexBulkDataToES', message: `No data in database for ${modelName}` }) return } - const bulks = getBulksFromDocuments(data) + const bulks = getBulksFromDocuments(rawObjects) const startTime = Date.now() let doneCount = 0 @@ -281,19 +302,22 @@ async function indexBulkDataToES (modelName, indexName, logger) { /** * Index job by id - * @param {Object} modelName the model name in db + * @param {Object | String} modelOpts the model name in db, or model options * @param {Object} indexName the index name * @param {string} id the job id * @param {Object} logger the logger object */ -async function indexDataToEsById (id, modelName, indexName, logger) { +async function indexDataToEsById (id, modelOpts, indexName, logger) { + const modelName = _.isString(modelOpts) ? modelOpts : modelOpts.modelName + const include = _.get(modelOpts, 'include', []) + logger.info({ component: 'indexDataToEsById', message: `Reindexing of ${modelName} with id ${id} started!` }) const esClient = getESClient() logger.info({ component: 'indexDataToEsById', message: 'Getting data from database' }) const model = models[modelName] - const data = await model.findById(id) + const data = await model.findById(id, include) logger.info({ component: 'indexDataToEsById', message: 'Indexing data into Elasticsearch' }) await esClient.index({ index: indexName, @@ -327,7 +351,10 @@ async function importData (pathToFile, dataModels, logger) { const jsonData = JSON.parse(fs.readFileSync(pathToFile).toString()) for (let index = 0; index < dataModels.length; index += 1) { - const modelName = dataModels[index] + const modelOpts = dataModels[index] + const modelName = _.isString(modelOpts) ? modelOpts : modelOpts.modelName + const include = _.get(modelOpts, 'include', []) + currentModelName = modelName const model = models[modelName] const modelRecords = jsonData[modelName] @@ -335,7 +362,7 @@ async function importData (pathToFile, dataModels, logger) { if (modelRecords && modelRecords.length > 0) { logger.info({ component: 'importData', message: `Importing data for model: ${modelName}` }) - await model.bulkCreate(modelRecords, { transaction }) + await model.bulkCreate(modelRecords, { include, transaction }) logger.info({ component: 'importData', message: `Records imported for model: ${modelName} = ${modelRecords.length}` }) } else { logger.info({ component: 'importData', message: `No records to import for model: ${modelName}` }) @@ -368,8 +395,15 @@ async function importData (pathToFile, dataModels, logger) { } // after importing, index data + const jobCandidateModelOpts = { + modelName: 'JobCandidate', + include: [{ + model: models.Interview, + as: 'interviews' + }] + } await indexBulkDataToES('Job', config.get('esConfig.ES_INDEX_JOB'), logger) - await indexBulkDataToES('JobCandidate', config.get('esConfig.ES_INDEX_JOB_CANDIDATE'), logger) + await indexBulkDataToES(jobCandidateModelOpts, config.get('esConfig.ES_INDEX_JOB_CANDIDATE'), logger) await indexBulkDataToES('ResourceBooking', config.get('esConfig.ES_INDEX_RESOURCE_BOOKING'), logger) } @@ -384,12 +418,13 @@ async function exportData (pathToFile, dataModels, logger) { const allModelsRecords = {} for (let index = 0; index < dataModels.length; index += 1) { - const modelName = dataModels[index] - const modelRecords = await models[modelName].findAll({ - raw: true - }) - allModelsRecords[modelName] = modelRecords - logger.info({ component: 'exportData', message: `Records loaded for model: ${modelName} = ${modelRecords.length}` }) + const modelOpts = dataModels[index] + const modelName = _.isString(modelOpts) ? modelOpts : modelOpts.modelName + const include = _.get(modelOpts, 'include', []) + const modelRecords = await models[modelName].findAll({ include }) + const rawRecords = _.map(modelRecords, r => r.toJSON()) + allModelsRecords[modelName] = rawRecords + logger.info({ component: 'exportData', message: `Records loaded for model: ${modelName} = ${rawRecords.length}` }) } fs.writeFileSync(pathToFile, JSON.stringify(allModelsRecords)) @@ -677,7 +712,7 @@ async function postEvent (topic, payload, options = {}) { * @returns {Boolean} the result */ function isDocumentMissingException (err) { - if (err.statusCode === 404) { + if (err.statusCode === 404 && err instanceof ESResponseError) { return true } return false @@ -755,6 +790,8 @@ async function getUserById (userId, enrich) { if (enrich) { user.skills = (res.body.skills || []).map((skillObj) => _.pick(skillObj.skill, ['id', 'name'])) + const attributes = _.get(res, 'body.attributes', []) + user.attributes = _.map(attributes, attr => _.pick(attr, ['id', 'value', 'attribute.id', 'attribute.name'])) } return user @@ -1144,6 +1181,18 @@ async function deleteProjectMember (currentUser, projectId, projectMemberId) { } } +/** + * Gets requested attribute value from user's attributes array. + * @param {Object} user The enriched (i.e. includes attributes) user object from users API. (check getUserById, getUserByExternalId functions) + * @param {String} attributeName Requested attribute name, e.g. "email" + * @returns attribute value + */ +function getUserAttributeValue (user, attributeName) { + const attributes = _.get(user, 'attributes', []) + const targetAttribute = _.find(attributes, a => a.attribute.name === attributeName) + return _.get(targetAttribute, 'value') +} + module.exports = { getParamFromCliArgs, promptUser, @@ -1186,5 +1235,6 @@ module.exports = { createProjectMember, listProjectMembers, listProjectMemberInvites, - deleteProjectMember + deleteProjectMember, + getUserAttributeValue } diff --git a/src/controllers/InterviewController.js b/src/controllers/InterviewController.js new file mode 100644 index 00000000..d9ae8e44 --- /dev/null +++ b/src/controllers/InterviewController.js @@ -0,0 +1,52 @@ +/** + * Controller for Interview endpoints + */ +const service = require('../services/InterviewService') +const helper = require('../common/helper') + +/** + * Get interview by round + * @param req the request + * @param res the response + */ +async function getInterviewByRound (req, res) { + const { jobCandidateId, round } = req.params + res.send(await service.getInterviewByRound(req.authUser, jobCandidateId, round, req.query.fromDb)) +} + +/** + * Request interview + * @param req the request + * @param res the response + */ +async function requestInterview (req, res) { + res.send(await service.requestInterview(req.authUser, req.params.jobCandidateId, req.body)) +} + +/** + * Patch (partially update) interview + * @param req the request + * @param res the response + */ +async function partiallyUpdateInterview (req, res) { + const { jobCandidateId, round } = req.params + res.send(await service.partiallyUpdateInterview(req.authUser, jobCandidateId, round, req.body)) +} + +/** + * Search interviews + * @param req the request + * @param res the response + */ +async function searchInterviews (req, res) { + const result = await service.searchInterviews(req.authUser, req.params.jobCandidateId, req.query) + helper.setResHeaders(req, res, result) + res.send(result.result) +} + +module.exports = { + getInterviewByRound, + requestInterview, + partiallyUpdateInterview, + searchInterviews +} diff --git a/src/eventHandlers/InterviewEventHandler.js b/src/eventHandlers/InterviewEventHandler.js new file mode 100644 index 00000000..ee503ee5 --- /dev/null +++ b/src/eventHandlers/InterviewEventHandler.js @@ -0,0 +1,62 @@ +/* + * Handle events for Interview. + */ + +const models = require('../models') +const logger = require('../common/logger') +const helper = require('../common/helper') +const teamService = require('../services/TeamService') + +/** + * Once we request Interview for a JobCandidate, the invitation emails to be sent out. + * + * @param {Object} payload the event payload + * @returns {undefined} + */ +async function sendInvitationEmail (payload) { + const interview = payload.value + // get job candidate user details + const jobCandidate = await models.JobCandidate.findById(interview.jobCandidateId) + const jobCandidateUser = await helper.getUserById(jobCandidate.userId, true) + const jobCandidateUserEmail = helper.getUserAttributeValue(jobCandidateUser, 'email') + // get customer details + const job = await jobCandidate.getJob() + const customerUser = await helper.getUserByExternalId(job.externalId, true) + const customerUserEmail = helper.getUserAttributeValue(customerUser, 'email') + if (jobCandidateUserEmail && customerUserEmail) { + teamService.sendEmail({}, { + template: 'interview-invitation', + recipients: [jobCandidateUserEmail, customerUserEmail], + cc: interview.attendeesList, + data: { + interviewType: interview.xaiTemplate, + jobName: job.title, + candidateName: `${jobCandidateUser.firstName} ${jobCandidateUser.lastName}`, + customMessage: interview.customMessage + } + }) + } else { + // one (or both) of the emails are missing due to some reason + // for e.g. some users' externalIds may be set to null or similar + // log error + logger.error({ + component: 'InterviewEventHandler', + context: 'sendInvitationEmail', + message: 'Couldn\'t sent invitation emails. Insufficient details.' + }) + } +} + +/** + * Process interview request event. + * + * @param {Object} payload the event payload + * @returns {undefined} + */ +async function processRequest (payload) { + await sendInvitationEmail(payload) +} + +module.exports = { + processRequest +} diff --git a/src/eventHandlers/index.js b/src/eventHandlers/index.js index f4089ea0..cbfc4d33 100644 --- a/src/eventHandlers/index.js +++ b/src/eventHandlers/index.js @@ -7,13 +7,15 @@ const eventDispatcher = require('../common/eventDispatcher') const JobEventHandler = require('./JobEventHandler') const JobCandidateEventHandler = require('./JobCandidateEventHandler') const ResourceBookingEventHandler = require('./ResourceBookingEventHandler') +const InterviewEventHandler = require('./InterviewEventHandler') const logger = require('../common/logger') const TopicOperationMapping = { [config.TAAS_JOB_UPDATE_TOPIC]: JobEventHandler.processUpdate, [config.TAAS_JOB_CANDIDATE_CREATE_TOPIC]: JobCandidateEventHandler.processCreate, [config.TAAS_RESOURCE_BOOKING_CREATE_TOPIC]: ResourceBookingEventHandler.processCreate, - [config.TAAS_RESOURCE_BOOKING_UPDATE_TOPIC]: ResourceBookingEventHandler.processUpdate + [config.TAAS_RESOURCE_BOOKING_UPDATE_TOPIC]: ResourceBookingEventHandler.processUpdate, + [config.TAAS_INTERVIEW_REQUEST_TOPIC]: InterviewEventHandler.processRequest } /** diff --git a/src/models/Interview.js b/src/models/Interview.js new file mode 100644 index 00000000..424251a3 --- /dev/null +++ b/src/models/Interview.js @@ -0,0 +1,124 @@ +const { Sequelize, Model } = require('sequelize') +const config = require('config') +const _ = require('lodash') +const { Interviews } = require('../../app-constants') +const errors = require('../common/errors') + +// allowed status values +const statuses = _.values(Interviews.Status) + +module.exports = (sequelize) => { + class Interview extends Model { + /** + * Create association between models + * @param {Object} models the database models + */ + static associate (models) { + Interview.belongsTo(models.JobCandidate, { foreignKey: 'jobCandidateId' }) + } + + /** + * Get interview by id + * @param {String} id the interview id + * @returns {Interview} the Interview instance + */ + static async findById (id) { + const interview = await Interview.findOne({ + where: { + id + } + }) + if (!interview) { + throw new errors.NotFoundError(`id: ${id} "Interview" doesn't exist.`) + } + return interview + } + } + Interview.init( + { + id: { + type: Sequelize.UUID, + primaryKey: true, + allowNull: false, + defaultValue: Sequelize.UUIDV4 + }, + jobCandidateId: { + field: 'job_candidate_id', + type: Sequelize.UUID, + allowNull: false + }, + googleCalendarId: { + field: 'google_calendar_id', + type: Sequelize.STRING(255) + }, + customMessage: { + field: 'custom_message', + type: Sequelize.TEXT + }, + xaiTemplate: { + field: 'xai_template', + type: Sequelize.STRING(255), + allowNull: false + }, + round: { + type: Sequelize.INTEGER, + allowNull: false + }, + startTimestamp: { + field: 'start_timestamp', + type: Sequelize.DATE + }, + attendeesList: { + field: 'attendees_list', + type: Sequelize.ARRAY(Sequelize.STRING) + }, + status: { + type: Sequelize.ENUM(statuses), + allowNull: false + }, + createdBy: { + field: 'created_by', + type: Sequelize.UUID, + allowNull: false + }, + updatedBy: { + field: 'updated_by', + type: Sequelize.UUID + }, + createdAt: { + field: 'created_at', + type: Sequelize.DATE + }, + updatedAt: { + field: 'updated_at', + type: Sequelize.DATE + }, + deletedAt: { + field: 'deleted_at', + type: Sequelize.DATE + } + }, + { + schema: config.DB_SCHEMA_NAME, + sequelize, + tableName: 'interviews', + paranoid: true, + deletedAt: 'deletedAt', + createdAt: 'createdAt', + updatedAt: 'updatedAt', + timestamps: true, + defaultScope: { + attributes: { + exclude: ['deletedAt'] + } + }, + hooks: { + afterCreate: (interview) => { + delete interview.dataValues.deletedAt + } + } + } + ) + + return Interview +} diff --git a/src/models/JobCandidate.js b/src/models/JobCandidate.js index 00e83991..819b9177 100644 --- a/src/models/JobCandidate.js +++ b/src/models/JobCandidate.js @@ -11,18 +11,21 @@ module.exports = (sequelize) => { static associate (models) { JobCandidate._models = models JobCandidate.belongsTo(models.Job, { foreignKey: 'jobId' }) + JobCandidate.hasMany(models.Interview, { foreignKey: 'jobCandidateId', as: 'interviews' }) } /** * Get job candidate by id * @param {String} id the job candidate id + * @param {Array} include include options * @returns {JobCandidate} the JobCandidate instance */ - static async findById (id) { + static async findById (id, include = []) { const jobCandidate = await JobCandidate.findOne({ where: { id - } + }, + include }) if (!jobCandidate) { throw new errors.NotFoundError(`id: ${id} "JobCandidate" doesn't exists.`) @@ -98,6 +101,13 @@ module.exports = (sequelize) => { hooks: { afterCreate: (jobCandidate) => { delete jobCandidate.dataValues.deletedAt + }, + afterDestroy: async (jobCandidate) => { + // cascade (soft) delete interviews associated with this jobCandidate + const jobCandidateId = jobCandidate.id + await sequelize.models.Interview.destroy({ + where: { jobCandidateId } + }) } } } diff --git a/src/routes/InterviewRoutes.js b/src/routes/InterviewRoutes.js new file mode 100644 index 00000000..e8f8e960 --- /dev/null +++ b/src/routes/InterviewRoutes.js @@ -0,0 +1,39 @@ +/** + * Contains interview routes + */ +const constants = require('../../app-constants') + +module.exports = { + '/jobCandidates/:jobCandidateId/requestInterview': { + patch: { + controller: 'InterviewController', + method: 'requestInterview', + auth: 'jwt', + scopes: [constants.Scopes.CREATE_INTERVIEW, constants.Scopes.ALL_INTERVIEW] + } + }, + '/jobCandidates/:jobCandidateId/updateInterview/:round': { + patch: { + controller: 'InterviewController', + method: 'partiallyUpdateInterview', + auth: 'jwt', + scopes: [constants.Scopes.UPDATE_INTERVIEW, constants.Scopes.ALL_INTERVIEW] + } + }, + '/jobCandidates/:jobCandidateId/interviews': { + get: { + controller: 'InterviewController', + method: 'searchInterviews', + auth: 'jwt', + scopes: [constants.Scopes.READ_INTERVIEW, constants.Scopes.ALL_INTERVIEW] + } + }, + '/jobCandidates/:jobCandidateId/interviews/:round': { + get: { + controller: 'InterviewController', + method: 'getInterviewByRound', + auth: 'jwt', + scopes: [constants.Scopes.READ_INTERVIEW, constants.Scopes.ALL_INTERVIEW] + } + } +} diff --git a/src/services/InterviewService.js b/src/services/InterviewService.js new file mode 100644 index 00000000..2afad72e --- /dev/null +++ b/src/services/InterviewService.js @@ -0,0 +1,387 @@ +/** + * This service provides operations of Interview. + */ + +const _ = require('lodash') +const Joi = require('joi') +const config = require('config') +const { Op, ForeignKeyConstraintError } = require('sequelize') +const { v4: uuid } = require('uuid') +const { Interviews: InterviewConstants } = require('../../app-constants') +const helper = require('../common/helper') +const logger = require('../common/logger') +const errors = require('../common/errors') +const models = require('../models') + +const Interview = models.Interview +const esClient = helper.getESClient() + +/** + * Ensures user is permitted for the operation. + * + * @param {Object} currentUser the user who perform this operation. + * @throws {errors.ForbiddenError} + */ +function ensureUserIsPermitted (currentUser) { + const isUserPermitted = currentUser.hasManagePermission || currentUser.isMachine + if (isUserPermitted !== true) { + throw new errors.ForbiddenError('You are not allowed to perform this action!') + } +} + +/** + * Handles common sequelize errors + * @param {Object} err error + * @param {String} jobCandidateId the job candidate id + */ +function handleSequelizeError (err, jobCandidateId) { + // jobCandidateId doesn't exist - gracefully handle + if (err instanceof ForeignKeyConstraintError) { + throw new errors.NotFoundError( + `The job candidate with id=${jobCandidateId} doesn't exist.` + ) + } + // another type of sequelize error - extract the details and throw + const errDetail = _.get(err, 'original.detail') + if (errDetail) { + throw new errors.BadRequestError(errDetail) + } +} + +/** + * Get interview by round + * @param {Object} currentUser the user who perform this operation. + * @param {String} jobCandidateId the job candidate id + * @param {Number} round the interview round + * @param {Boolean} fromDb flag if query db for data or not + * @returns {Object} the interview + */ +async function getInterviewByRound (currentUser, jobCandidateId, round, fromDb = false) { + // check permission + ensureUserIsPermitted(currentUser) + if (!fromDb) { + try { + // get job candidate from ES + const jobCandidateES = await esClient.get({ + index: config.esConfig.ES_INDEX_JOB_CANDIDATE, + id: jobCandidateId + }) + // extract interviews from ES object + const jobCandidateInterviews = _.get(jobCandidateES, 'body._source.interviews', []) + // find interview by round + const interview = _.find(jobCandidateInterviews, interview => interview.round === round) + if (interview) { + return interview + } + // if reaches here, the interview with this round is not found + throw new errors.NotFoundError(`Interview doesn't exist with round: ${round}`) + } catch (err) { + if (helper.isDocumentMissingException(err)) { + throw new errors.NotFoundError(`id: ${jobCandidateId} "JobCandidate" not found`) + } + logger.logFullError(err, { component: 'InterviewService', context: 'getInterviewByRound' }) + throw err + } + } + // either ES query failed or `fromDb` is set - fallback to DB + logger.info({ component: 'InterviewService', context: 'getInterview', message: 'try to query db for data' }) + + const interview = await Interview.findOne({ + where: { jobCandidateId, round } + }) + // throw NotFound error if doesn't exist + if (!!interview !== true) { + throw new errors.NotFoundError(`Interview doesn't exist with jobCandidateId: ${jobCandidateId} and round: ${round}`) + } + + return interview.dataValues +} + +getInterviewByRound.schema = Joi.object().keys({ + currentUser: Joi.object().required(), + jobCandidateId: Joi.string().uuid().required(), + round: Joi.number().integer().positive().required(), + fromDb: Joi.boolean() +}).required() + +/** + * Request interview + * @param {Object} currentUser the user who perform this operation + * @param {String} jobCandidateId the job candidate id + * @param {Object} interview the interview to be created + * @returns {Object} the created/requested interview + */ +async function requestInterview (currentUser, jobCandidateId, interview) { + // check permission + ensureUserIsPermitted(currentUser) + + interview.id = uuid() + interview.jobCandidateId = jobCandidateId + interview.createdBy = await helper.getUserId(currentUser.userId) + + // find the round count + const round = await Interview.count({ + where: { jobCandidateId } + }) + interview.round = round + 1 + + // create + try { + const created = await Interview.create(interview) + await helper.postEvent(config.TAAS_INTERVIEW_REQUEST_TOPIC, created.toJSON()) + return created.dataValues + } catch (err) { + // gracefully handle if one of the common sequelize errors + handleSequelizeError(err, jobCandidateId) + // if reaches here, it's not one of the common errors handled in `handleSequelizeError` + throw err + } +} + +requestInterview.schema = Joi.object().keys({ + currentUser: Joi.object().required(), + jobCandidateId: Joi.string().uuid().required(), + interview: Joi.object().keys({ + googleCalendarId: Joi.string().allow(null), + customMessage: Joi.string().allow(null), + xaiTemplate: Joi.xaiTemplate().required(), + attendeesList: Joi.array().items(Joi.string().email()).allow(null), + status: Joi.interviewStatus().default(InterviewConstants.Status.Scheduling) + }).required() +}).required() + +/** + * Patch (partially update) interview + * @param {Object} currentUser the user who perform this operation + * @param {String} jobCandidateId the job candidate id + * @param {Number} round the interview round + * @param {Object} data object containing patched fields + * @returns {Object} the patched interview object + */ +async function partiallyUpdateInterview (currentUser, jobCandidateId, round, data) { + // check permission + ensureUserIsPermitted(currentUser) + + const interview = await Interview.findOne({ + where: { + jobCandidateId, round + } + }) + // throw NotFound error if doesn't exist + if (!!interview !== true) { + throw new errors.NotFoundError(`Interview doesn't exist with jobCandidateId: ${jobCandidateId} and round: ${round}`) + } + + const oldValue = interview.toJSON() + + // only status can be updated for Completed interviews + if (oldValue.status === InterviewConstants.Status.Completed) { + const updatedFields = _.keys(data) + if (updatedFields.length !== 1 || !_.includes(updatedFields, 'status')) { + throw new errors.BadRequestError('Only the "status" can be updated for Completed interviews.') + } + } + + data.updatedBy = await helper.getUserId(currentUser.userId) + try { + const updated = await interview.update(data) + await helper.postEvent(config.TAAS_INTERVIEW_UPDATE_TOPIC, updated.toJSON(), { oldValue: oldValue }) + return updated.dataValues + } catch (err) { + // gracefully handle if one of the common sequelize errors + handleSequelizeError(err, jobCandidateId) + // if reaches here, it's not one of the common errors handled in `handleSequelizeError` + throw err + } +} + +partiallyUpdateInterview.schema = Joi.object().keys({ + currentUser: Joi.object().required(), + jobCandidateId: Joi.string().uuid().required(), + round: Joi.number().integer().positive().required(), + data: Joi.object().keys({ + googleCalendarId: Joi.string().when('status', { + is: [InterviewConstants.Status.Scheduled, InterviewConstants.Status.Rescheduled], + then: Joi.required(), + otherwise: Joi.allow(null) + }), + customMessage: Joi.string().allow(null), + xaiTemplate: Joi.xaiTemplate(), + startTimestamp: Joi.date().greater('now').when('status', { + is: [InterviewConstants.Status.Scheduled, InterviewConstants.Status.Rescheduled], + then: Joi.required(), + otherwise: Joi.allow(null) + }), + attendeesList: Joi.array().items(Joi.string().email()).allow(null), + status: Joi.interviewStatus() + }).required().min(1) // at least one key - i.e. don't allow empty object +}).required() + +/** + * List interviews + * @param {Object} currentUser the user who perform this operation. + * @param {String} jobCandidateId the job candidate id + * @param {Object} criteria the search criteria + * @returns {Object} the search result, contain total/page/perPage and result array + */ +async function searchInterviews (currentUser, jobCandidateId, criteria) { + // check permission + ensureUserIsPermitted(currentUser) + + const { page, perPage } = criteria + + try { + // construct query for nested search + const esQueryBody = { + _source: false, + query: { + nested: { + path: 'interviews', + query: { + bool: { + must: [] + } + }, + inner_hits: { + size: 100 // max. inner_hits size + } + } + } + } + // add filtering terms + // jobCandidateId + esQueryBody.query.nested.query.bool.must.push({ + term: { + 'interviews.jobCandidateId': { + value: jobCandidateId + } + } + }) + // criteria + _.each(_.pick(criteria, ['status', 'createdAt', 'updatedAt']), (value, key) => { + const innerKey = `interviews.${key}` + esQueryBody.query.nested.query.bool.must.push({ + term: { + [innerKey]: { + value + } + } + }) + }) + // search + const { body } = await esClient.search({ + index: config.esConfig.ES_INDEX_JOB_CANDIDATE, + body: esQueryBody + }) + // get jobCandidate hit from body - there's always one jobCandidate hit as we search via jobCandidateId + // extract inner interview hits from jobCandidate + const interviewHits = _.get(body, 'hits.hits[0].inner_hits.interviews.hits.hits', []) + const interviews = _.map(interviewHits, '_source') + + // we need to sort & paginate interviews manually + // as it's not possible with ES query on nested type + // (ES applies pagination & sorting on parent documents, not on the nested objects) + + // sort + const sortedInterviews = _.orderBy(interviews, criteria.sortBy, criteria.sortOrder) + // paginate + const start = (page - 1) * perPage + const end = start + perPage + const paginatedInterviews = _.slice(sortedInterviews, start, end) + + return { + total: sortedInterviews.length, + page, + perPage, + result: paginatedInterviews + } + } catch (err) { + logger.logFullError(err, { component: 'InterviewService', context: 'searchInterviews' }) + } + logger.info({ component: 'InterviewService', context: 'searchInterviews', message: 'fallback to DB query' }) + const filter = { + [Op.and]: [{ jobCandidateId }] + } + // apply filtering based on criteria + _.each(_.pick(criteria, ['status', 'createdAt', 'updatedAt']), (value, key) => { + filter[Op.and].push({ [key]: value }) + }) + const interviews = await Interview.findAll({ + where: filter, + offset: ((page - 1) * perPage), + limit: perPage, + order: [[criteria.sortBy, criteria.sortOrder]] + }) + return { + fromDb: true, + total: interviews.length, + page, + perPage, + result: _.map(interviews, interview => interview.dataValues) + } +} + +searchInterviews.schema = Joi.object().keys({ + currentUser: Joi.object().required(), + jobCandidateId: Joi.string().uuid().required(), + criteria: Joi.object().keys({ + page: Joi.page(), + perPage: Joi.perPage(), + sortBy: Joi.string().valid('round', 'createdAt', 'updatedAt').default('createdAt'), + sortOrder: Joi.string().valid('desc', 'asc').default('desc'), + createdAt: Joi.date(), + updatedAt: Joi.date(), + status: Joi.interviewStatus() + }).required() +}).required() + +/** + * Updates the status of completed (based on startTimestamp) interviews. + * If the startTimestamp of an interview is less than (or equal) the (currentDateTime - 1 hour) + * it's considered as completed. + */ +async function updateCompletedInterviews () { + logger.info({ component: 'InterviewService', context: 'updateCompletedInterviews', message: 'Running the scheduled job...' }) + const oneHourAgo = new Date(Date.now() - 60 * 60 * 1000) + const [affectedCount, updatedRows] = await Interview.update( + // '00000000-0000-0000-0000-000000000000' - to indicate it's updated by the system job + { status: InterviewConstants.Status.Completed, updatedBy: '00000000-0000-0000-0000-000000000000' }, + { + where: { + status: [InterviewConstants.Status.Scheduled, InterviewConstants.Status.Rescheduled], + startTimestamp: { + [Op.lte]: oneHourAgo + } + }, + returning: true + } + ) + + // post event if there are affected/updated interviews + if (affectedCount > 0) { + // payload format: + // { + // jobCandidateId: { interviewId: { affectedFields }, interviewId2: { affectedFields }, ... }, + // jobCandidateId2: { interviewId: { affectedFields }, interviewId2: { affectedFields }, ... }, + // ... + // } + const bulkUpdatePayload = {} + // construct payload + _.forEach(updatedRows, row => { + const interview = row.toJSON() + const affectedFields = _.pick(interview, ['status', 'updatedBy', 'updatedAt']) + _.set(bulkUpdatePayload, [interview.jobCandidateId, interview.id], affectedFields) + }) + // post event + await helper.postEvent(config.TAAS_INTERVIEW_BULK_UPDATE_TOPIC, bulkUpdatePayload) + } + logger.info({ component: 'InterviewService', context: 'updateCompletedInterviews', message: `Completed running. Updated ${affectedCount} interviews.` }) +} + +module.exports = { + getInterviewByRound, + requestInterview, + partiallyUpdateInterview, + searchInterviews, + updateCompletedInterviews +} diff --git a/src/services/JobCandidateService.js b/src/services/JobCandidateService.js index 0dec8a18..392d0af6 100644 --- a/src/services/JobCandidateService.js +++ b/src/services/JobCandidateService.js @@ -8,6 +8,7 @@ const config = require('config') const HttpStatus = require('http-status-codes') const { Op } = require('sequelize') const { v4: uuid } = require('uuid') +const { Scopes } = require('../../app-constants') const helper = require('../common/helper') const logger = require('../common/logger') const errors = require('../common/errors') @@ -31,6 +32,24 @@ async function _checkUserPermissionForGetJobCandidate (currentUser, jobId) { } } +/** + * Returns field omit list, based on user access level. + * + * @param {Object} currentUser the user who perform this operation. + * @returns {Array} the field list to omit from the jobCandidate object + */ +function getJobCandidateOmitList (currentUser) { + // check M2M scopes for Interviews + if (currentUser.isMachine) { + const interviewsAllowedScopes = [Scopes.READ_INTERVIEW, Scopes.ALL_INTERVIEW] + if (!currentUser.scopes || !helper.checkIfExists(interviewsAllowedScopes, currentUser.scopes)) { + return ['interviews'] + } + return [] + } + return currentUser.hasManagePermission ? [] : ['interviews'] +} + /** * Get jobCandidate by id * @param {Object} currentUser the user who perform this operation. @@ -39,6 +58,7 @@ async function _checkUserPermissionForGetJobCandidate (currentUser, jobId) { * @returns {Object} the jobCandidate */ async function getJobCandidate (currentUser, id, fromDb = false) { + const omitList = getJobCandidateOmitList(currentUser) if (!fromDb) { try { const jobCandidate = await esClient.get({ @@ -49,7 +69,7 @@ async function getJobCandidate (currentUser, id, fromDb = false) { await _checkUserPermissionForGetJobCandidate(currentUser, jobCandidate.body._source.jobId) // check user permisson const jobCandidateRecord = { id: jobCandidate.body._id, ...jobCandidate.body._source } - return jobCandidateRecord + return _.omit(jobCandidateRecord, omitList) } catch (err) { if (helper.isDocumentMissingException(err)) { throw new errors.NotFoundError(`id: ${id} "JobCandidate" not found`) @@ -61,7 +81,13 @@ async function getJobCandidate (currentUser, id, fromDb = false) { } } logger.info({ component: 'JobCandidateService', context: 'getJobCandidate', message: 'try to query db for data' }) - const jobCandidate = await JobCandidate.findById(id) + // include interviews if user has permission + const include = [] + const hasInterviewPermision = !_.includes(omitList, 'interviews') + if (hasInterviewPermision) { + include.push({ model: models.Interview, as: 'interviews' }) + } + const jobCandidate = await JobCandidate.findById(id, include) await _checkUserPermissionForGetJobCandidate(currentUser, jobCandidate.jobId) // check user permission @@ -215,6 +241,7 @@ async function searchJobCandidates (currentUser, criteria) { await JobService.getJob(currentUser, criteria.jobId) // check whether user can access the job associated with the jobCandidate } + const omitList = getJobCandidateOmitList(currentUser) const page = criteria.page > 0 ? criteria.page : 1 const perPage = criteria.perPage > 0 ? criteria.perPage : 20 if (!criteria.sortBy) { @@ -260,7 +287,7 @@ async function searchJobCandidates (currentUser, criteria) { result: _.map(body.hits.hits, (hit) => { const obj = _.cloneDeep(hit._source) obj.id = hit._id - return obj + return _.omit(obj, omitList) }) } } catch (err) { @@ -271,8 +298,17 @@ async function searchJobCandidates (currentUser, criteria) { _.each(_.pick(criteria, ['jobId', 'userId', 'status', 'externalId']), (value, key) => { filter[Op.and].push({ [key]: value }) }) + + // include interviews if user has permission + const include = [] + const hasInterviewPermision = !_.includes(omitList, 'interviews') + if (hasInterviewPermision) { + include.push({ model: models.Interview, as: 'interviews' }) + } + const jobCandidates = await JobCandidate.findAll({ where: filter, + include, offset: ((page - 1) * perPage), limit: perPage, order: [[criteria.sortBy, criteria.sortOrder]] @@ -282,7 +318,7 @@ async function searchJobCandidates (currentUser, criteria) { total: jobCandidates.length, page, perPage, - result: _.map(jobCandidates, jobCandidate => jobCandidate.dataValues) + result: _.map(jobCandidates, jobCandidate => _.omit(jobCandidate.dataValues, omitList)) } } diff --git a/src/services/TeamService.js b/src/services/TeamService.js index 0519543e..459e6228 100644 --- a/src/services/TeamService.js +++ b/src/services/TeamService.js @@ -5,7 +5,6 @@ const _ = require('lodash') const Joi = require('joi') const dateFNS = require('date-fns') -const Handlebars = require('handlebars') const config = require('config') const emailTemplateConfig = require('../../config/email_template.config') const helper = require('../common/helper') @@ -16,9 +15,9 @@ const ResourceBookingService = require('./ResourceBookingService') const emailTemplates = _.mapValues(emailTemplateConfig, (template) => { return { - subjectTemplate: Handlebars.compile(template.subject), - bodyTemplate: Handlebars.compile(template.body), + from: template.from, recipients: template.recipients, + cc: template.cc, sendgridTemplateId: template.sendgridTemplateId } }) @@ -316,14 +315,21 @@ getTeamJob.schema = Joi.object().keys({ */ async function sendEmail (currentUser, data) { const template = emailTemplates[data.template] + + const dataCC = data.cc || [] + const templateCC = template.cc || [] + const dataRecipients = data.recipients || [] + const templateRecipients = template.recipients || [] + await helper.postEvent(config.EMAIL_TOPIC, { - data: { - subject: template.subjectTemplate(data.data), - body: template.bodyTemplate(data.data) - }, + data: data.data, // substitutions sendgrid_template_id: template.sendgridTemplateId, version: 'v3', - recipients: template.recipients + // override template if coming data already have the 'from' address + from: data.from || template.from, + // create a set of uniq. recipients & CCs, from both coming data & template + recipients: _.uniq([...dataRecipients, ...templateRecipients]), + cc: _.uniq([...dataCC, ...templateCC]) }) } @@ -331,7 +337,10 @@ sendEmail.schema = Joi.object().keys({ currentUser: Joi.object().required(), data: Joi.object().keys({ template: Joi.string().valid(...Object.keys(emailTemplates)).required(), - data: Joi.object().required() + data: Joi.object().required(), + from: Joi.string().email(), + recipients: Joi.array().items(Joi.string().email()).allow(null), + cc: Joi.array().items(Joi.string().email()).allow(null) }).required() }).required() From 8e2a5a04cd68bfca9690aa322a559cce1f550303 Mon Sep 17 00:00:00 2001 From: Cagdas U Date: Tue, 27 Apr 2021 23:08:01 +0300 Subject: [PATCH 02/20] feat(interview-scheduler): frontend integration 1. Update x.ai template names. 2. Update resourceBooking & jobCandidate statuses. 3. Add migrations for the above updates. 4. Update `interview-invitation` email template. --- app-constants.js | 5 +- config/default.js | 2 +- config/email_template.config.js | 26 +++- data/demo-data.json | 30 ++-- ...coder-bookings-api.postman_collection.json | 144 +++++++++--------- docs/swagger.yaml | 50 +++--- ...esource-booking-placed-status-migration.js | 18 +++ ...7-job-candidate-placed-status-migration.js | 18 +++ ...job-candidate-selected-status-migration.js | 18 +++ ...ndidate-rejected-other-status-migration.js | 22 +++ scripts/recruit-crm-job-import/index.js | 2 +- src/bootstrap.js | 6 +- src/common/helper.js | 5 + src/eventHandlers/InterviewEventHandler.js | 55 ++++--- .../ResourceBookingEventHandler.js | 56 +++---- src/services/InterviewService.js | 10 +- src/services/PaymentService.js | 4 +- src/services/ResourceBookingService.js | 2 +- src/services/TeamService.js | 12 +- 19 files changed, 310 insertions(+), 175 deletions(-) create mode 100644 migrations/2021-04-27-172352-resource-booking-placed-status-migration.js create mode 100644 migrations/2021-04-27-172407-job-candidate-placed-status-migration.js create mode 100644 migrations/2021-04-27-172422-job-candidate-selected-status-migration.js create mode 100644 migrations/2021-04-27-172437-job-candidate-rejected-other-status-migration.js diff --git a/app-constants.js b/app-constants.js index 71f9dce1..37217f99 100644 --- a/app-constants.js +++ b/app-constants.js @@ -62,9 +62,10 @@ const Interviews = { Completed: 'Completed', Cancelled: 'Cancelled' }, + // key: template name in x.ai, value: duration XaiTemplate: { - '30MinInterview': '30-min-interview', - '60MinInterview': '60-min-interview' + '30-minutes': 30, + '60-minutes': 60 } } diff --git a/config/default.js b/config/default.js index 8db522af..56ad8263 100644 --- a/config/default.js +++ b/config/default.js @@ -153,7 +153,7 @@ module.exports = { // SendGrid email template ID for interview invitation INTERVIEW_INVITATION_SENDGRID_TEMPLATE_ID: process.env.INTERVIEW_INVITATION_SENDGRID_TEMPLATE_ID, // The sender (aka `from`) email for invitation. - INTERVIEW_INVITATION_SENDER_EMAIL: process.env.INTERVIEW_INVITATION_SENDER_EMAIL, + INTERVIEW_INVITATION_SENDER_EMAIL: process.env.INTERVIEW_INVITATION_SENDER_EMAIL || 'scheduler@topcoder.com', // the URL where TaaS App is hosted TAAS_APP_URL: process.env.TAAS_APP_URL || 'https://platform.topcoder-dev.com/taas/myteams', // environment variables for Payment Service diff --git a/config/email_template.config.js b/config/email_template.config.js index 7de8ad80..01775ad8 100644 --- a/config/email_template.config.js +++ b/config/email_template.config.js @@ -63,17 +63,31 @@ module.exports = { /* Request interview for a job candidate * - * - interviewType: the x.ai interview type. Example: "30-min-interview" + * - interviewType: the x.ai interview type. Example: "30-minutes" + * - interviewRound: the round of the interview. Example: 2 + * - interviewDuration: duration of the interview, in minutes. Example: 30 + * - interviewerList: The list of interviewer email addresses. Example: "first@attendee.com, second@attendee.com" + * - candidateId: the id of the jobCandidate. Example: "cc562545-7b75-48bf-87e7-50b3c57e41b1" * - candidateName: Full name of candidate. Example: "John Doe" * - jobName: The title of the job. Example: "TaaS API Misc Updates" - * - customMessage: if it's needed, a custom message can be added to the end of email. Example: "I would like to invite you for an interview..." * * Template (defined in SendGrid): - * Subject: '/{{interviewType}} tech interview with {{candidateName}} for {{jobName}} is requested by the Customer' + * Subject: '{{interviewType}} tech interview with {{candidateName}} for {{jobName}} is requested by the Customer' * Body: - * 'The customer has requested /{{interviewType}} with {{candidateName}} for {{jobName}}.' - * + 'In a few minutes you will receive an invitation from our scheduling tool. Please proceed with the invitation to agree on timing.' - * + '

{{customMessage}}' + * 'Hello! + *

+ * Congratulations, you have been selected to participate in a Topcoder Gig Work Interview! + *

+ * Please monitor your email for a response to this where you can coordinate your availability. + *

+ * Interviewee: {{candidateName}}
+ * Interviewer(s): {{interviewerList}}
+ * Interview Length: {{interviewDuration}} minutes + *

+ * /{{interviewType}} + *

+ * Topcoder Info:
+ * Note: "id: {{candidateId}}, round: {{interviewRound}}"' * * Note, that the template should be defined in SendGrid. * The subject & body above (identical to actual SendGrid template) is for reference purposes. diff --git a/data/demo-data.json b/data/demo-data.json index 2947b5d3..5736c839 100644 --- a/data/demo-data.json +++ b/data/demo-data.json @@ -269,7 +269,7 @@ "id": "5191a860-4327-4c50-b76b-84beba04519b", "jobId": "a5b3bf94-a8bf-4c7e-b685-70a29a4d7d6e", "userId": "79ce2a3e-7679-48cf-8ac9-0a8ca4c4b463", - "status": "shortlist", + "status": "selected", "externalId": null, "resume": null, "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", @@ -282,7 +282,7 @@ "id": "e6d9635c-b122-4f69-9285-09fb1ab30106", "jobId": "a5b3bf94-a8bf-4c7e-b685-70a29a4d7d6e", "userId": "98ec2c16-442e-4b61-8ad1-66123ee37d3c", - "status": "rejected", + "status": "rejected - other", "externalId": null, "resume": null, "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", @@ -347,7 +347,7 @@ "id": "85d6649e-2682-4904-9480-a77b72fef27d", "jobId": "2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0", "userId": "213d2dd9-1fc3-4eda-ad97-2d56e2a84a1e", - "status": "selected", + "status": "placed", "externalId": null, "resume": null, "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", @@ -360,7 +360,7 @@ "id": "922dfce3-4e06-4387-9fdb-64f70675e86b", "jobId": "2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0", "userId": "dd5adacb-444d-4992-8b7b-0c349be598db", - "status": "selected", + "status": "placed", "externalId": null, "resume": null, "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", @@ -373,7 +373,7 @@ "id": "c26c38e2-a47d-405b-abc6-fe62a739561c", "jobId": "2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0", "userId": "6d0509c7-5f12-4d84-9a19-8e80ef7ddd66", - "status": "selected", + "status": "placed", "externalId": null, "resume": null, "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", @@ -386,7 +386,7 @@ "id": "7bef2b37-e1ee-4638-bfc1-c911787ac955", "jobId": "2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0", "userId": "f65e2104-2987-4136-839d-ee4632f0b2e5", - "status": "selected", + "status": "placed", "externalId": null, "resume": null, "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", @@ -399,7 +399,7 @@ "id": "e9716139-1f40-4bf1-9f8a-77ae4bcc621e", "jobId": "2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0", "userId": "e5e667ad-0950-43c2-8d1d-6e83ad7d1c7e", - "status": "selected", + "status": "placed", "externalId": null, "resume": null, "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", @@ -412,7 +412,7 @@ "id": "a1731d01-eac9-4eff-8e5a-8a3c99bc66e0", "jobId": "2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0", "userId": "bef43122-426b-4b2b-acdd-9b5b3bd1c0bf", - "status": "selected", + "status": "placed", "externalId": null, "resume": null, "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", @@ -425,7 +425,7 @@ "id": "25787cb2-d876-4883-b533-d5e628d213ce", "jobId": "1324da27-9d7d-47d8-a04e-9fb3f35a67fa", "userId": "95e7970f-12b4-43b7-ab35-38c34bf033c7", - "status": "open", + "status": "interview", "externalId": "88774631", "resume": "http://example.com", "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", @@ -468,7 +468,7 @@ "projectId": 111, "userId": "213d2dd9-1fc3-4eda-ad97-2d56e2a84a1e", "jobId": "2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0", - "status": "assigned", + "status": "placed", "startDate": "2021-01-25", "endDate": "2021-01-31", "memberRate": 1000, @@ -500,7 +500,7 @@ "projectId": 111, "userId": "6d0509c7-5f12-4d84-9a19-8e80ef7ddd66", "jobId": "2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0", - "status": "assigned", + "status": "placed", "startDate": "2021-02-27", "endDate": "2021-03-15", "memberRate": 2000, @@ -532,7 +532,7 @@ "projectId": 111, "userId": "dd5adacb-444d-4992-8b7b-0c349be598db", "jobId": "2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0", - "status": "assigned", + "status": "placed", "startDate": "2021-03-18", "endDate": "2021-05-28", "memberRate": 800, @@ -548,7 +548,7 @@ "projectId": 111, "userId": "f65e2104-2987-4136-839d-ee4632f0b2e5", "jobId": "2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0", - "status": "assigned", + "status": "placed", "startDate": "2000-03-27", "endDate": "2000-04-27", "memberRate": 3000, @@ -564,7 +564,7 @@ "projectId": 111, "userId": "bef43122-426b-4b2b-acdd-9b5b3bd1c0bf", "jobId": "2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0", - "status": "assigned", + "status": "placed", "startDate": "2020-04-27", "endDate": "2020-05-27", "memberRate": 0, @@ -612,7 +612,7 @@ "projectId": 111, "userId": "e5e667ad-0950-43c2-8d1d-6e83ad7d1c7e", "jobId": "2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0", - "status": "assigned", + "status": "placed", "startDate": "2021-07-27", "endDate": "2021-09-27", "memberRate": 1700, diff --git a/docs/Topcoder-bookings-api.postman_collection.json b/docs/Topcoder-bookings-api.postman_collection.json index f40394d5..704ad61d 100644 --- a/docs/Topcoder-bookings-api.postman_collection.json +++ b/docs/Topcoder-bookings-api.postman_collection.json @@ -1,6 +1,6 @@ { "info": { - "_postman_id": "f26164a2-4129-4e0a-89fb-75c6756b4a79", + "_postman_id": "059739c9-5726-44b6-876d-6d87940c9aff", "name": "Topcoder-bookings-api", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" }, @@ -2088,7 +2088,7 @@ }, { "key": "status", - "value": "shortlist", + "value": "selected", "disabled": true }, { @@ -2153,7 +2153,7 @@ }, { "key": "status", - "value": "shortlist", + "value": "selected", "disabled": true }, { @@ -2218,7 +2218,7 @@ }, { "key": "status", - "value": "shortlist", + "value": "selected", "disabled": true }, { @@ -2283,7 +2283,7 @@ }, { "key": "status", - "value": "shortlist", + "value": "selected", "disabled": true }, { @@ -2348,7 +2348,7 @@ }, { "key": "status", - "value": "shortlist", + "value": "selected", "disabled": true }, { @@ -2413,7 +2413,7 @@ }, { "key": "status", - "value": "shortlist", + "value": "selected", "disabled": true }, { @@ -2476,7 +2476,7 @@ }, { "key": "status", - "value": "shortlist", + "value": "selected", "disabled": true }, { @@ -2539,7 +2539,7 @@ }, { "key": "status", - "value": "shortlist", + "value": "selected", "disabled": true }, { @@ -2763,7 +2763,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"status\": \"shortlist\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", + "raw": "{\n \"status\": \"selected\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", "options": { "raw": { "language": "json" @@ -2796,7 +2796,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"status\": \"shortlist\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", + "raw": "{\n \"status\": \"selected\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", "options": { "raw": { "language": "json" @@ -2829,7 +2829,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"status\": \"shortlist\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", + "raw": "{\n \"status\": \"selected\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", "options": { "raw": { "language": "json" @@ -2862,7 +2862,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"status\": \"shortlist\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", + "raw": "{\n \"status\": \"selected\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", "options": { "raw": { "language": "json" @@ -2895,7 +2895,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"status\": \"shortlist\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", + "raw": "{\n \"status\": \"selected\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", "options": { "raw": { "language": "json" @@ -2928,7 +2928,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"status\": \"shortlist\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", + "raw": "{\n \"status\": \"selected\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", "options": { "raw": { "language": "json" @@ -3217,7 +3217,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\",\r\n \"status\": \"Completed\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-minutes\",\r\n \"status\": \"Completed\"\r\n}", "options": { "raw": { "language": "json" @@ -3270,7 +3270,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\",\r\n \"googleCalendarId\": \"dummyId\",\r\n \"customMessage\": \"This is a custom message\",\r\n \"attendeesList\": [\"attendee1@yopmail.com\", \"attendee2@yopmail.com\"],\r\n \"status\": \"Scheduling\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-minutes\",\r\n \"googleCalendarId\": \"dummyId\",\r\n \"customMessage\": \"This is a custom message\",\r\n \"attendeesList\": [\"attendee1@yopmail.com\", \"attendee2@yopmail.com\"],\r\n \"status\": \"Scheduling\"\r\n}", "options": { "raw": { "language": "json" @@ -3321,7 +3321,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\",\r\n \"googleCalendarId\": \"dummyId\",\r\n \"customMessage\": \"This is a custom message\",\r\n \"status\": \"Scheduling\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-minutes\",\r\n \"googleCalendarId\": \"dummyId\",\r\n \"customMessage\": \"This is a custom message\",\r\n \"status\": \"Scheduling\"\r\n}", "options": { "raw": { "language": "json" @@ -3373,7 +3373,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-minutes\"\r\n}", "options": { "raw": { "language": "json" @@ -3422,7 +3422,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\",\r\n \"status\": \"xxxx\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-minutes\",\r\n \"status\": \"xxxx\"\r\n}", "options": { "raw": { "language": "json" @@ -3472,7 +3472,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\",\r\n \"attendeesList\": [\"attendee1@yopmail.com\", \"attendee2@yopmail.com\"]\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-minutes\",\r\n \"attendeesList\": [\"attendee1@yopmail.com\", \"attendee2@yopmail.com\"]\r\n}", "options": { "raw": { "language": "json" @@ -3521,7 +3521,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\",\r\n \"attendeesList\": \"asddd\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-minutes\",\r\n \"attendeesList\": \"asddd\"\r\n}", "options": { "raw": { "language": "json" @@ -3570,7 +3570,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\",\r\n \"attendeesList\": [\"asdas\"]\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-minutes\",\r\n \"attendeesList\": [\"asdas\"]\r\n}", "options": { "raw": { "language": "json" @@ -3619,7 +3619,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\",\r\n \"round\": 1\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-minutes\",\r\n \"round\": 1\r\n}", "options": { "raw": { "language": "json" @@ -3668,7 +3668,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\",\r\n \"startTimestamp\": \"2021-04-17\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-minutes\",\r\n \"startTimestamp\": \"2021-04-17\"\r\n}", "options": { "raw": { "language": "json" @@ -3748,7 +3748,7 @@ "pm.test('Status code is 400', function () {\r", " pm.response.to.have.status(400);\r", " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"\\\"interview.xaiTemplate\\\" must be one of [30-min-interview, 60-min-interview]\")\r", + " pm.expect(response.message).to.eq(\"\\\"interview.xaiTemplate\\\" must be one of [30-minutes, 60-minutes]\")\r", "});" ], "type": "text/javascript" @@ -3815,7 +3815,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-minutes\"\r\n}", "options": { "raw": { "language": "json" @@ -3864,7 +3864,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-minutes\"\r\n}", "options": { "raw": { "language": "json" @@ -3911,7 +3911,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-minutes\"\r\n}", "options": { "raw": { "language": "json" @@ -3958,7 +3958,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-minutes\"\r\n}", "options": { "raw": { "language": "json" @@ -4005,7 +4005,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-minutes\"\r\n}", "options": { "raw": { "language": "json" @@ -4052,7 +4052,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-minutes\"\r\n}", "options": { "raw": { "language": "json" @@ -4101,7 +4101,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-minutes\"\r\n}", "options": { "raw": { "language": "json" @@ -4150,7 +4150,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-minutes\"\r\n}", "options": { "raw": { "language": "json" @@ -4199,7 +4199,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-minutes\"\r\n}", "options": { "raw": { "language": "json" @@ -4248,7 +4248,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-minutes\"\r\n}", "options": { "raw": { "language": "json" @@ -4297,7 +4297,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-minutes\"\r\n}", "options": { "raw": { "language": "json" @@ -4340,7 +4340,7 @@ "header": [], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-minutes\"\r\n}", "options": { "raw": { "language": "json" @@ -4389,7 +4389,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-minutes\"\r\n}", "options": { "raw": { "language": "json" @@ -5312,7 +5312,7 @@ "pm.test('Status code is 400', function () {\r", " pm.response.to.have.status(400);\r", " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"\\\"data.xaiTemplate\\\" must be one of [30-min-interview, 60-min-interview]\")\r", + " pm.expect(response.message).to.eq(\"\\\"data.xaiTemplate\\\" must be one of [30-minutes, 60-minutes]\")\r", "});" ], "type": "text/javascript" @@ -8467,7 +8467,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{jobId}}\",\r\n \"startDate\": \"2020-09-26\",\r\n \"endDate\": \"2020-11-29\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"status\": \"assigned\",\r\n \"billingAccountId\": 80000071\r\n}", + "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{jobId}}\",\r\n \"startDate\": \"2020-09-26\",\r\n \"endDate\": \"2020-11-29\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"status\": \"placed\",\r\n \"billingAccountId\": 80000071\r\n}", "options": { "raw": { "language": "json" @@ -8603,7 +8603,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{jobIdCreatedByM2M}}\",\r\n \"startDate\": \"2020-12-27\",\r\n \"endDate\": \"2021-01-10\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"status\": \"assigned\",\r\n \"billingAccountId\": 80000071\r\n}", + "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{jobIdCreatedByM2M}}\",\r\n \"startDate\": \"2020-12-27\",\r\n \"endDate\": \"2021-01-10\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"status\": \"placed\",\r\n \"billingAccountId\": 80000071\r\n}", "options": { "raw": { "language": "json" @@ -8741,7 +8741,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{jobId}}\",\r\n \"startDate\": \"2020-09-27\",\r\n \"endDate\": \"2020-09-28\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"status\": \"assigned\",\r\n \"billingAccountId\": 80000071\r\n}", + "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{jobId}}\",\r\n \"startDate\": \"2020-09-27\",\r\n \"endDate\": \"2020-09-28\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"status\": \"placed\",\r\n \"billingAccountId\": 80000071\r\n}", "options": { "raw": { "language": "json" @@ -8789,7 +8789,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{jobId}}\",\r\n \"startDate\": \"2020-09-27\",\r\n \"endDate\": \"2020-09-28\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"status\": \"assigned\",\r\n \"billingAccountId\": 80000071\r\n}", + "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{jobId}}\",\r\n \"startDate\": \"2020-09-27\",\r\n \"endDate\": \"2020-09-28\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"status\": \"placed\",\r\n \"billingAccountId\": 80000071\r\n}", "options": { "raw": { "language": "json" @@ -8837,7 +8837,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{jobId}}\",\r\n \"startDate\": \"2020-09-27\",\r\n \"endDate\": \"2020-09-28\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"status\": \"assigned\",\r\n \"billingAccountId\": 80000071\r\n}", + "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{jobId}}\",\r\n \"startDate\": \"2020-09-27\",\r\n \"endDate\": \"2020-09-28\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"status\": \"placed\",\r\n \"billingAccountId\": 80000071\r\n}", "options": { "raw": { "language": "json" @@ -8885,7 +8885,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{jobId}}\",\r\n \"startDate\": \"2020-09-27\",\r\n \"endDate\": \"2020-09-28\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"status\": \"assigned\",\r\n \"billingAccountId\": 80000071\r\n}", + "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{jobId}}\",\r\n \"startDate\": \"2020-09-27\",\r\n \"endDate\": \"2020-09-28\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"status\": \"placed\",\r\n \"billingAccountId\": 80000071\r\n}", "options": { "raw": { "language": "json" @@ -8931,7 +8931,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"status\": \"assigned\",\r\n \"startDate\": \"2020-09-30\",\r\n \"endDate\": \"2020-11-28\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"billingAccountId\": 80000071\r\n}", + "raw": "{\r\n \"status\": \"placed\",\r\n \"startDate\": \"2020-09-30\",\r\n \"endDate\": \"2020-11-28\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"billingAccountId\": 80000071\r\n}", "options": { "raw": { "language": "json" @@ -8977,7 +8977,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"status\": \"assigned\",\r\n \"startDate\": \"2020-12-30\",\r\n \"endDate\": \"2021-02-10\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"billingAccountId\": 80000071\r\n}", + "raw": "{\r\n \"status\": \"placed\",\r\n \"startDate\": \"2020-12-30\",\r\n \"endDate\": \"2021-02-10\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"billingAccountId\": 80000071\r\n}", "options": { "raw": { "language": "json" @@ -9025,7 +9025,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"status\": \"assigned\",\r\n \"startDate\": \"2020-09-27\",\r\n \"endDate\": \"2020-09-28\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"billingAccountId\": 80000071\r\n}", + "raw": "{\r\n \"status\": \"placed\",\r\n \"startDate\": \"2020-09-27\",\r\n \"endDate\": \"2020-09-28\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"billingAccountId\": 80000071\r\n}", "options": { "raw": { "language": "json" @@ -9073,7 +9073,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"status\": \"assigned\",\r\n \"startDate\": \"2020-09-27\",\r\n \"endDate\": \"2020-09-28\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"billingAccountId\": 80000071\r\n}", + "raw": "{\r\n \"status\": \"placed\",\r\n \"startDate\": \"2020-09-27\",\r\n \"endDate\": \"2020-09-28\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"billingAccountId\": 80000071\r\n}", "options": { "raw": { "language": "json" @@ -9121,7 +9121,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"status\": \"assigned\",\r\n \"startDate\": \"2020-09-27\",\r\n \"endDate\": \"2020-09-28\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"billingAccountId\": 80000071\r\n}", + "raw": "{\r\n \"status\": \"placed\",\r\n \"startDate\": \"2020-09-27\",\r\n \"endDate\": \"2020-09-28\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"billingAccountId\": 80000071\r\n}", "options": { "raw": { "language": "json" @@ -9169,7 +9169,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"status\": \"assigned\",\r\n \"startDate\": \"2020-09-27\",\r\n \"endDate\": \"2020-09-27\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"billingAccountId\": 80000071\r\n}", + "raw": "{\r\n \"status\": \"placed\",\r\n \"startDate\": \"2020-09-27\",\r\n \"endDate\": \"2020-09-27\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"billingAccountId\": 80000071\r\n}", "options": { "raw": { "language": "json" @@ -19214,7 +19214,7 @@ }, { "key": "status", - "value": "shortlist", + "value": "selected", "disabled": true } ] @@ -19235,7 +19235,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"jobId\": \"{{job_id_created_by_administrator}}\",\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"status\": \"selected\"\r\n}", + "raw": "{\r\n \"jobId\": \"{{job_id_created_by_administrator}}\",\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"status\": \"placed\"\r\n}", "options": { "raw": { "language": "json" @@ -19268,7 +19268,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"status\": \"shortlist\"\r\n}", + "raw": "{\r\n \"status\": \"selected\"\r\n}", "options": { "raw": { "language": "json" @@ -19449,7 +19449,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\",\r\n \"googleCalendarId\": \"dummyId\",\r\n \"customMessage\": \"This is a custom message\",\r\n \"status\": \"Scheduling\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-minutes\",\r\n \"googleCalendarId\": \"dummyId\",\r\n \"customMessage\": \"This is a custom message\",\r\n \"status\": \"Scheduling\"\r\n}", "options": { "raw": { "language": "json" @@ -19805,7 +19805,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{job_id_created_by_administrator}}\",\r\n \"startDate\": \"2020-09-27\",\r\n \"endDate\": \"2020-09-27\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"status\": \"assigned\",\r\n \"billingAccountId\": 80000071\r\n}", + "raw": "{\r\n \"projectId\": {{projectId}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{job_id_created_by_administrator}}\",\r\n \"startDate\": \"2020-09-27\",\r\n \"endDate\": \"2020-09-27\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"status\": \"placed\",\r\n \"billingAccountId\": 80000071\r\n}", "options": { "raw": { "language": "json" @@ -19838,7 +19838,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"status\": \"assigned\",\r\n \"startDate\": \"2020-09-27\",\r\n \"endDate\": \"2020-09-27\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"billingAccountId\": 80000071\r\n}", + "raw": "{\r\n \"status\": \"placed\",\r\n \"startDate\": \"2020-09-27\",\r\n \"endDate\": \"2020-09-27\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"billingAccountId\": 80000071\r\n}", "options": { "raw": { "language": "json" @@ -21158,7 +21158,7 @@ }, { "key": "status", - "value": "shortlist", + "value": "selected", "disabled": true } ] @@ -21179,7 +21179,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"jobId\": \"{{job_id_created_by_member}}\",\r\n \"userId\": \"fe38eed1-af73-41fd-85a2-ac4da1ff09a3\",\r\n \"status\": \"selected\"\r\n}", + "raw": "{\r\n \"jobId\": \"{{job_id_created_by_member}}\",\r\n \"userId\": \"fe38eed1-af73-41fd-85a2-ac4da1ff09a3\",\r\n \"status\": \"placed\"\r\n}", "options": { "raw": { "language": "json" @@ -21212,7 +21212,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"status\": \"shortlist\"\r\n}", + "raw": "{\r\n \"status\": \"selected\"\r\n}", "options": { "raw": { "language": "json" @@ -21389,7 +21389,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\",\r\n \"googleCalendarId\": \"dummyId\",\r\n \"customMessage\": \"This is a custom message\",\r\n \"status\": \"Scheduling\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-minutes\",\r\n \"googleCalendarId\": \"dummyId\",\r\n \"customMessage\": \"This is a custom message\",\r\n \"status\": \"Scheduling\"\r\n}", "options": { "raw": { "language": "json" @@ -21440,7 +21440,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\",\r\n \"googleCalendarId\": \"dummyId\",\r\n \"customMessage\": \"This is a custom message\",\r\n \"status\": \"Scheduling\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-minutes\",\r\n \"googleCalendarId\": \"dummyId\",\r\n \"customMessage\": \"This is a custom message\",\r\n \"status\": \"Scheduling\"\r\n}", "options": { "raw": { "language": "json" @@ -21845,7 +21845,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"projectId\": {{project_id_16718}},\r\n \"userId\": \"fe38eed1-af73-41fd-85a2-ac4da1ff09a3\",\r\n \"jobId\": \"{{job_id_created_by_member}}\",\r\n \"startDate\": \"2020-09-27\",\r\n \"endDate\": \"2020-09-27\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"status\": \"assigned\",\r\n \"billingAccountId\": 80000071\r\n}", + "raw": "{\r\n \"projectId\": {{project_id_16718}},\r\n \"userId\": \"fe38eed1-af73-41fd-85a2-ac4da1ff09a3\",\r\n \"jobId\": \"{{job_id_created_by_member}}\",\r\n \"startDate\": \"2020-09-27\",\r\n \"endDate\": \"2020-09-27\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"status\": \"placed\",\r\n \"billingAccountId\": 80000071\r\n}", "options": { "raw": { "language": "json" @@ -21878,7 +21878,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"status\": \"assigned\",\r\n \"startDate\": \"2020-09-27\",\r\n \"endDate\": \"2020-09-27\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"billingAccountId\": 80000071\r\n}", + "raw": "{\r\n \"status\": \"placed\",\r\n \"startDate\": \"2020-09-27\",\r\n \"endDate\": \"2020-09-27\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"billingAccountId\": 80000071\r\n}", "options": { "raw": { "language": "json" @@ -23313,7 +23313,7 @@ }, { "key": "status", - "value": "shortlist", + "value": "selected", "disabled": true } ] @@ -23334,7 +23334,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"jobId\": \"{{job_id_created_by_connect_manager}}\",\r\n \"userId\": \"fe38eed1-af73-41fd-85a2-ac4da1ff09a3\",\r\n \"status\": \"selected\"\r\n}", + "raw": "{\r\n \"jobId\": \"{{job_id_created_by_connect_manager}}\",\r\n \"userId\": \"fe38eed1-af73-41fd-85a2-ac4da1ff09a3\",\r\n \"status\": \"placed\"\r\n}", "options": { "raw": { "language": "json" @@ -23367,7 +23367,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"status\": \"shortlist\"\r\n}", + "raw": "{\r\n \"status\": \"selected\"\r\n}", "options": { "raw": { "language": "json" @@ -23544,7 +23544,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\",\r\n \"googleCalendarId\": \"dummyId\",\r\n \"customMessage\": \"This is a custom message\",\r\n \"status\": \"Scheduling\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-minutes\",\r\n \"googleCalendarId\": \"dummyId\",\r\n \"customMessage\": \"This is a custom message\",\r\n \"status\": \"Scheduling\"\r\n}", "options": { "raw": { "language": "json" @@ -23595,7 +23595,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-min-interview\",\r\n \"googleCalendarId\": \"dummyId\",\r\n \"customMessage\": \"This is a custom message\",\r\n \"status\": \"Scheduling\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"30-minutes\",\r\n \"googleCalendarId\": \"dummyId\",\r\n \"customMessage\": \"This is a custom message\",\r\n \"status\": \"Scheduling\"\r\n}", "options": { "raw": { "language": "json" @@ -23996,7 +23996,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"projectId\": {{project_id_16843}},\r\n \"userId\": \"fe38eed1-af73-41fd-85a2-ac4da1ff09a3\",\r\n \"jobId\": \"{{job_id_created_by_connect_manager}}\",\r\n \"startDate\": \"2020-09-27\",\r\n \"endDate\": \"2020-09-27\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"status\": \"assigned\",\r\n \"billingAccountId\": 80000071\r\n}", + "raw": "{\r\n \"projectId\": {{project_id_16843}},\r\n \"userId\": \"fe38eed1-af73-41fd-85a2-ac4da1ff09a3\",\r\n \"jobId\": \"{{job_id_created_by_connect_manager}}\",\r\n \"startDate\": \"2020-09-27\",\r\n \"endDate\": \"2020-09-27\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"status\": \"placed\",\r\n \"billingAccountId\": 80000071\r\n}", "options": { "raw": { "language": "json" @@ -24029,7 +24029,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"status\": \"assigned\",\r\n \"startDate\": \"2020-09-27\",\r\n \"endDate\": \"2020-09-27\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"billingAccountId\": 80000071\r\n}", + "raw": "{\r\n \"status\": \"placed\",\r\n \"startDate\": \"2020-09-27\",\r\n \"endDate\": \"2020-09-27\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"billingAccountId\": 80000071\r\n}", "options": { "raw": { "language": "json" diff --git a/docs/swagger.yaml b/docs/swagger.yaml index d96dd455..93b67407 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -593,9 +593,11 @@ paths: enum: [ "open", + "placed", "selected", - "shortlist", - "rejected", + "client rejected - screening", + "client rejected - interview", + "rejected - other", "cancelled", "interview", "topcoder-rejected", @@ -1305,7 +1307,7 @@ paths: required: false schema: type: string - enum: ["assigned", "in-progress", "completed"] + enum: ["placed", "in-progress", "completed"] description: The status. - in: query name: startDate @@ -3283,9 +3285,11 @@ components: enum: [ "open", + "placed", "selected", - "shortlist", - "rejected", + "client rejected - screening", + "client rejected - interview", + "rejected - other", "cancelled", "interview", "topcoder-rejected", @@ -3392,7 +3396,7 @@ components: description: "The user id." status: type: string - enum: ["open", "selected", "shortlist", "rejected", "cancelled"] + enum: ["open", "placed", "selected", "client rejected - screening", "client rejected - interview", "rejected - other", "cancelled", "interview", "topcoder-rejected"] description: "The job candidate status." default: open externalId: @@ -3410,9 +3414,11 @@ components: enum: [ "open", + "placed", "selected", - "shortlist", - "rejected", + "client rejected - screening", + "client rejected - interview", + "rejected - other", "cancelled", "interview", "topcoder-rejected", @@ -3449,8 +3455,8 @@ components: description: "The google calendar id." xaiTemplate: type: string - example: "30-min-interview" - enum: ["30-min-interview", "60-min-interview"] + example: "30-minutes" + enum: ["30-minutes", "60-minutes"] description: "The x.ai template name" customMessage: type: string @@ -3504,8 +3510,8 @@ components: description: "The custom message." xaiTemplate: type: string - enum: ["30-min-interview", "60-min-interview"] - example: "30-min-interview" + enum: ["30-minutes", "60-minutes"] + example: "30-minutes" description: "The x.ai template name" attendeesList: type: array @@ -3529,8 +3535,8 @@ components: description: "The custom message." xaiTemplate: type: string - enum: ["30-min-interview", "60-min-interview"] - example: "30-min-interview" + enum: ["30-minutes", "60-minutes"] + example: "30-minutes" description: "The x.ai template name" attendeesList: type: array @@ -3617,7 +3623,7 @@ components: description: "The external id." status: type: string - enum: ["assigned", "closed", "cancelled"] + enum: ["placed", "closed", "cancelled"] description: "The job status." startDate: type: string @@ -3684,7 +3690,7 @@ components: description: "The job id." status: type: string - enum: ["assigned", "closed", "cancelled"] + enum: ["placed", "closed", "cancelled"] description: "The job status." default: sourcing startDate: @@ -3719,7 +3725,7 @@ components: properties: status: type: string - enum: ["assigned", "closed", "cancelled"] + enum: ["placed", "closed", "cancelled"] startDate: type: string format: date @@ -4338,14 +4344,20 @@ components: type: string format: url description: "The link for the resume that can be downloaded" + interviews: + type: array + items: + $ref: "#/components/schemas/Interview" status: type: string enum: [ "open", + "placed", "selected", - "shortlist", - "rejected", + "client rejected - screening", + "client rejected - interview", + "rejected - other", "cancelled", "interview", "topcoder-rejected", diff --git a/migrations/2021-04-27-172352-resource-booking-placed-status-migration.js b/migrations/2021-04-27-172352-resource-booking-placed-status-migration.js new file mode 100644 index 00000000..70ae3c6c --- /dev/null +++ b/migrations/2021-04-27-172352-resource-booking-placed-status-migration.js @@ -0,0 +1,18 @@ +'use strict'; + +const config = require('config') + +/** + * Migrate ResourceBooking status - from assigned to placed. + */ +module.exports = { + up: async (queryInterface, Sequelize) => { + const tableName = `${config.DB_SCHEMA_NAME}.resource_bookings` + await queryInterface.sequelize.query(`UPDATE ${tableName} SET status = 'placed' WHERE status = 'assigned'`) + }, + + down: async (queryInterface, Sequelize) => { + const tableName = `${config.DB_SCHEMA_NAME}.resource_bookings` + await queryInterface.sequelize.query(`UPDATE ${tableName} SET status = 'assigned' WHERE status = 'placed'`) + } +}; diff --git a/migrations/2021-04-27-172407-job-candidate-placed-status-migration.js b/migrations/2021-04-27-172407-job-candidate-placed-status-migration.js new file mode 100644 index 00000000..611184ee --- /dev/null +++ b/migrations/2021-04-27-172407-job-candidate-placed-status-migration.js @@ -0,0 +1,18 @@ +'use strict'; + +const config = require('config') + +/** + * Migrate JobCandidate status - from selected to placed. + */ +module.exports = { + up: async (queryInterface, Sequelize) => { + const tableName = `${config.DB_SCHEMA_NAME}.job_candidates` + await queryInterface.sequelize.query(`UPDATE ${tableName} SET status = 'placed' WHERE status = 'selected'`) + }, + + down: async (queryInterface, Sequelize) => { + const tableName = `${config.DB_SCHEMA_NAME}.job_candidates` + await queryInterface.sequelize.query(`UPDATE ${tableName} SET status = 'selected' WHERE status = 'placed'`) + } +}; diff --git a/migrations/2021-04-27-172422-job-candidate-selected-status-migration.js b/migrations/2021-04-27-172422-job-candidate-selected-status-migration.js new file mode 100644 index 00000000..3ba8ec06 --- /dev/null +++ b/migrations/2021-04-27-172422-job-candidate-selected-status-migration.js @@ -0,0 +1,18 @@ +'use strict'; + +const config = require('config') + +/** + * Migrate JobCandidate status - from shortlist to selected. + */ +module.exports = { + up: async (queryInterface, Sequelize) => { + const tableName = `${config.DB_SCHEMA_NAME}.job_candidates` + await queryInterface.sequelize.query(`UPDATE ${tableName} SET status = 'selected' WHERE status = 'shortlist'`) + }, + + down: async (queryInterface, Sequelize) => { + const tableName = `${config.DB_SCHEMA_NAME}.job_candidates` + await queryInterface.sequelize.query(`UPDATE ${tableName} SET status = 'shortlist' WHERE status = 'selected'`) + } +}; diff --git a/migrations/2021-04-27-172437-job-candidate-rejected-other-status-migration.js b/migrations/2021-04-27-172437-job-candidate-rejected-other-status-migration.js new file mode 100644 index 00000000..9e8a2480 --- /dev/null +++ b/migrations/2021-04-27-172437-job-candidate-rejected-other-status-migration.js @@ -0,0 +1,22 @@ +'use strict'; + +const config = require('config') + +/** + * Migrate JobCandidate status - from rejected to rejected - other. + */ +module.exports = { + up: async (queryInterface, Sequelize) => { + const tableName = `${config.DB_SCHEMA_NAME}.job_candidates` + await queryInterface.sequelize.query( + `UPDATE ${tableName} SET status = 'rejected - other' WHERE status = 'rejected'` + ) + }, + + down: async (queryInterface, Sequelize) => { + const tableName = `${config.DB_SCHEMA_NAME}.job_candidates` + await queryInterface.sequelize.query( + `UPDATE ${tableName} SET status = 'rejected' WHERE status = 'rejected - other'` + ) + } +}; diff --git a/scripts/recruit-crm-job-import/index.js b/scripts/recruit-crm-job-import/index.js index c82254ab..596ab680 100644 --- a/scripts/recruit-crm-job-import/index.js +++ b/scripts/recruit-crm-job-import/index.js @@ -89,7 +89,7 @@ async function processJob (job, info = []) { data.resourceBookingId = result.id } // update the resourceBooking based on startDate and endDate - const resourceBookingStatus = dateFNS.isBefore(data.endDate, dateFNS.startOfToday()) ? 'closed' : 'assigned' + const resourceBookingStatus = dateFNS.isBefore(data.endDate, dateFNS.startOfToday()) ? 'closed' : 'placed' logger.debug(`resourceBookingId: ${data.resourceBookingId} status: ${resourceBookingStatus}`) await helper.updateResourceBookingStatus(data.resourceBookingId, resourceBookingStatus) info.push({ text: `id: ${data.resourceBookingId} status: ${resourceBookingStatus} resource booking updated`, tag: 'resource_booking_status_updated' }) diff --git a/src/bootstrap.js b/src/bootstrap.js index 19e93973..6a364e8a 100644 --- a/src/bootstrap.js +++ b/src/bootstrap.js @@ -8,15 +8,15 @@ const constants = require('../app-constants') const config = require('config') const allowedInterviewStatuses = _.values(Interviews.Status) -const allowedXAITemplate = _.values(Interviews.XaiTemplate) +const allowedXAITemplate = _.keys(Interviews.XaiTemplate) Joi.page = () => Joi.number().integer().min(1).default(1) Joi.perPage = () => Joi.number().integer().min(1).default(20) Joi.rateType = () => Joi.string().valid('hourly', 'daily', 'weekly', 'monthly') Joi.jobStatus = () => Joi.string().valid('sourcing', 'in-review', 'assigned', 'closed', 'cancelled') -Joi.resourceBookingStatus = () => Joi.string().valid('assigned', 'closed', 'cancelled') +Joi.resourceBookingStatus = () => Joi.string().valid('placed', 'closed', 'cancelled') Joi.workload = () => Joi.string().valid('full-time', 'fractional') -Joi.jobCandidateStatus = () => Joi.string().valid('open', 'selected', 'shortlist', 'rejected', 'cancelled', 'interview', 'topcoder-rejected') +Joi.jobCandidateStatus = () => Joi.string().valid('open', 'placed', 'selected', 'client rejected - screening', 'client rejected - interview', 'rejected - other', 'cancelled', 'interview', 'topcoder-rejected') Joi.title = () => Joi.string().max(128) Joi.paymentStatus = () => Joi.string().valid('pending', 'partially-completed', 'completed', 'cancelled') Joi.xaiTemplate = () => Joi.string().valid(...allowedXAITemplate) diff --git a/src/common/helper.js b/src/common/helper.js index b65f6ba7..ec55e2d8 100644 --- a/src/common/helper.js +++ b/src/common/helper.js @@ -679,6 +679,11 @@ function encodeQueryString (queryObj, nesting = '') { * @returns {Array} the users found */ async function listUsersByExternalId (externalId) { + // return empty list if externalId is null or undefined + if (!!externalId !== true) { + return [] + } + const token = await getM2MUbahnToken() const q = { enrich: true, diff --git a/src/eventHandlers/InterviewEventHandler.js b/src/eventHandlers/InterviewEventHandler.js index ee503ee5..af7ce400 100644 --- a/src/eventHandlers/InterviewEventHandler.js +++ b/src/eventHandlers/InterviewEventHandler.js @@ -3,8 +3,9 @@ */ const models = require('../models') -const logger = require('../common/logger') +// const logger = require('../common/logger') const helper = require('../common/helper') +const { Interviews } = require('../../app-constants') const teamService = require('../services/TeamService') /** @@ -15,27 +16,45 @@ const teamService = require('../services/TeamService') */ async function sendInvitationEmail (payload) { const interview = payload.value + // get job candidate user details const jobCandidate = await models.JobCandidate.findById(interview.jobCandidateId) const jobCandidateUser = await helper.getUserById(jobCandidate.userId, true) - const jobCandidateUserEmail = helper.getUserAttributeValue(jobCandidateUser, 'email') + // const jobCandidateUserEmail = helper.getUserAttributeValue(jobCandidateUser, 'email') // get customer details const job = await jobCandidate.getJob() - const customerUser = await helper.getUserByExternalId(job.externalId, true) - const customerUserEmail = helper.getUserAttributeValue(customerUser, 'email') - if (jobCandidateUserEmail && customerUserEmail) { - teamService.sendEmail({}, { - template: 'interview-invitation', - recipients: [jobCandidateUserEmail, customerUserEmail], - cc: interview.attendeesList, - data: { - interviewType: interview.xaiTemplate, - jobName: job.title, - candidateName: `${jobCandidateUser.firstName} ${jobCandidateUser.lastName}`, - customMessage: interview.customMessage - } - }) - } else { + // const customerUser = await helper.getUserByExternalId(job.externalId, true) + // const customerUserEmail = helper.getUserAttributeValue(customerUser, 'email') + + // TODO: remove mock addresses & switch back to the old implementation once API gets fixed + // Both emails will be undefined since TC API doesn't return attributes, + // this is a workaround to skip check/condition & log the payload + // it will post the event nevertheless (with mocked candidate&customer address), so you can see on the logs as kafka event + // and verify the payload content + const customerMockEmail = 'testcustomer@yopmail.com' + const candidateMockEmail = 'testuserforemail@yopmail.com' + + // if (jobCandidateUserEmail && customerUserEmail) { + const interviewerList = interview.attendeesList + // ? [customerUserEmail, ...interview.attendeesList].join(', ') // "customer@mail.com, first@attendee.com, second@attendee.com..." + // : customerUserEmail + ? [customerMockEmail, ...interview.attendeesList].join(', ') // "customer@mail.com, first@attendee.com, second@attendee.com..." + : customerMockEmail + teamService.sendEmail({}, { + template: 'interview-invitation', + recipients: [candidateMockEmail, customerMockEmail], + cc: interview.attendeesList, + data: { + interviewType: interview.xaiTemplate, + interviewRound: interview.round, + interviewDuration: Interviews.XaiTemplate[interview.xaiTemplate], + interviewerList, + jobName: job.title, + candidateName: `${jobCandidateUser.firstName} ${jobCandidateUser.lastName}`, + candidateId: interview.jobCandidateId + } + }) + /* } else { // one (or both) of the emails are missing due to some reason // for e.g. some users' externalIds may be set to null or similar // log error @@ -44,7 +63,7 @@ async function sendInvitationEmail (payload) { context: 'sendInvitationEmail', message: 'Couldn\'t sent invitation emails. Insufficient details.' }) - } + } */ } /** diff --git a/src/eventHandlers/ResourceBookingEventHandler.js b/src/eventHandlers/ResourceBookingEventHandler.js index 95947436..7bf821df 100644 --- a/src/eventHandlers/ResourceBookingEventHandler.js +++ b/src/eventHandlers/ResourceBookingEventHandler.js @@ -13,26 +13,26 @@ const WorkPeriodService = require('../services/WorkPeriodService') const WorkPeriod = models.WorkPeriod /** - * When ResourceBooking's status is changed to `assigned` + * When ResourceBooking's status is changed to `placed` * the corresponding JobCandidate record (with the same userId and jobId) - * should be updated with status `selected` + * should be updated with status `placed` * * @param {Object} payload the event payload * @returns {undefined} */ -async function selectJobCandidate (payload) { +async function placeJobCandidate (payload) { if (_.get(payload, 'options.oldValue') && payload.value.status === payload.options.oldValue.status) { logger.debug({ component: 'ResourceBookingEventHandler', - context: 'selectJobCandidate', + context: 'placeJobCandidate', message: 'status not changed' }) return } - if (payload.value.status !== 'assigned') { + if (payload.value.status !== 'placed') { logger.debug({ component: 'ResourceBookingEventHandler', - context: 'selectJobCandidate', + context: 'placeJobCandidate', message: `not interested resource booking - status: ${payload.value.status}` }) return @@ -41,7 +41,7 @@ async function selectJobCandidate (payload) { if (!resourceBooking.jobId) { logger.debug({ component: 'ResourceBookingEventHandler', - context: 'selectJobCandidate', + context: 'placeJobCandidate', message: `id: ${resourceBooking.id} resource booking without jobId - ignored` }) return @@ -51,42 +51,42 @@ async function selectJobCandidate (payload) { jobId: resourceBooking.jobId, userId: resourceBooking.userId, status: { - [Op.not]: 'selected' + [Op.not]: 'placed' } } }) await Promise.all(candidates.map(candidate => JobCandidateService.partiallyUpdateJobCandidate( helper.getAuditM2Muser(), candidate.id, - { status: 'selected' } + { status: 'placed' } ).then(result => { logger.info({ component: 'ResourceBookingEventHandler', - context: 'selectJobCandidate', + context: 'placeJobCandidate', message: `id: ${result.id} candidate got selected.` }) }))) } /** - * Update the status of the Job to assigned when it positions requirement is fullfilled. + * Update the status of the Job to placed when it positions requirement is fullfilled. * * @param {Object} payload the event payload * @returns {undefined} */ -async function assignJob (payload) { +async function placeJob (payload) { if (_.get(payload, 'options.oldValue') && payload.value.status === payload.options.oldValue.status) { logger.debug({ component: 'ResourceBookingEventHandler', - context: 'assignJob', + context: 'placeJob', message: 'status not changed' }) return } - if (payload.value.status !== 'assigned') { + if (payload.value.status !== 'placed') { logger.debug({ component: 'ResourceBookingEventHandler', - context: 'assignJob', + context: 'placeJob', message: `not interested resource booking - status: ${payload.value.status}` }) return @@ -95,34 +95,34 @@ async function assignJob (payload) { if (!resourceBooking.jobId) { logger.debug({ component: 'ResourceBookingEventHandler', - context: 'assignJob', + context: 'placeJob', message: `id: ${resourceBooking.id} resource booking without jobId - ignored` }) return } const job = await models.Job.findById(resourceBooking.jobId) - if (job.status === 'assigned') { + if (job.status === 'placed') { logger.debug({ component: 'ResourceBookingEventHandler', - context: 'assignJob', - message: `job with projectId ${job.projectId} is already assigned` + context: 'placeJob', + message: `job with projectId ${job.projectId} is already placed` }) return } const resourceBookings = await models.ResourceBooking.findAll({ where: { jobId: job.id, - status: 'assigned' + status: 'placed' } }) logger.debug({ component: 'ResourceBookingEventHandler', - context: 'assignJob', - message: `the number of assigned resource bookings is ${resourceBookings.length} - the numPositions of the job is ${job.numPositions}` + context: 'placeJob', + message: `the number of placed resource bookings is ${resourceBookings.length} - the numPositions of the job is ${job.numPositions}` }) if (job.numPositions === resourceBookings.length) { - await JobService.partiallyUpdateJob(helper.getAuditM2Muser(), job.id, { status: 'assigned' }) - logger.info({ component: 'ResourceBookingEventHandler', context: 'assignJob', message: `job ${job.id} is assigned` }) + await JobService.partiallyUpdateJob(helper.getAuditM2Muser(), job.id, { status: 'placed' }) + logger.info({ component: 'ResourceBookingEventHandler', context: 'placeJob', message: `job ${job.id} is placed` }) } } @@ -294,8 +294,8 @@ async function _deleteWorkPeriods (workPeriods) { * @returns {undefined} */ async function processCreate (payload) { - await selectJobCandidate(payload) - await assignJob(payload) + await placeJobCandidate(payload) + await placeJob(payload) await createWorkPeriods(payload) } @@ -306,8 +306,8 @@ async function processCreate (payload) { * @returns {undefined} */ async function processUpdate (payload) { - await selectJobCandidate(payload) - await assignJob(payload) + await placeJobCandidate(payload) + await placeJob(payload) await updateWorkPeriods(payload) } diff --git a/src/services/InterviewService.js b/src/services/InterviewService.js index 2afad72e..d4f67576 100644 --- a/src/services/InterviewService.js +++ b/src/services/InterviewService.js @@ -125,10 +125,18 @@ async function requestInterview (currentUser, jobCandidateId, interview) { }) interview.round = round + 1 - // create try { + // create the interview const created = await Interview.create(interview) await helper.postEvent(config.TAAS_INTERVIEW_REQUEST_TOPIC, created.toJSON()) + // update jobCandidate.status to Interview + const [, affectedRows] = await models.JobCandidate.update( + { status: 'interview' }, + { where: { id: created.jobCandidateId }, returning: true } + ) + const updatedJobCandidate = _.omit(_.get(affectedRows, '0.dataValues'), 'deletedAt') + await helper.postEvent(config.TAAS_JOB_CANDIDATE_UPDATE_TOPIC, updatedJobCandidate) + // return created interview return created.dataValues } catch (err) { // gracefully handle if one of the common sequelize errors diff --git a/src/services/PaymentService.js b/src/services/PaymentService.js index 15c6ee7c..7d714f75 100644 --- a/src/services/PaymentService.js +++ b/src/services/PaymentService.js @@ -79,13 +79,13 @@ async function createChallenge (challenge, token) { pureV5Task: true }, tags: ['Other'], - startDate: new Date(), + startDate: new Date() } if (challenge.billingAccountId) { body.billing = { billingAccountId: challenge.billingAccountId, - markup: 0, // for TaaS payments we always use 0 markup + markup: 0 // for TaaS payments we always use 0 markup } } try { diff --git a/src/services/ResourceBookingService.js b/src/services/ResourceBookingService.js index 4fef4e46..3693f22c 100644 --- a/src/services/ResourceBookingService.js +++ b/src/services/ResourceBookingService.js @@ -159,7 +159,7 @@ async function createResourceBooking (currentUser, resourceBooking) { createResourceBooking.schema = Joi.object().keys({ currentUser: Joi.object().required(), resourceBooking: Joi.object().keys({ - status: Joi.resourceBookingStatus().default('assigned'), + status: Joi.resourceBookingStatus().default('placed'), projectId: Joi.number().integer().required(), userId: Joi.string().uuid().required(), jobId: Joi.string().uuid().allow(null), diff --git a/src/services/TeamService.js b/src/services/TeamService.js index 459e6228..8eb6714c 100644 --- a/src/services/TeamService.js +++ b/src/services/TeamService.js @@ -23,13 +23,13 @@ const emailTemplates = _.mapValues(emailTemplateConfig, (template) => { }) /** - * Function to get assigned resource bookings with specific projectIds + * Function to get placed resource bookings with specific projectIds * @param {Object} currentUser the user who perform this operation. * @param {Array} projectIds project ids * @returns the request result */ -async function _getAssignedResourceBookingsByProjectIds (currentUser, projectIds) { - const criteria = { status: 'assigned', projectIds } +async function _getPlacedResourceBookingsByProjectIds (currentUser, projectIds) { + const criteria = { status: 'placed', projectIds } const { result } = await ResourceBookingService.searchResourceBookings(currentUser, criteria, { returnAll: true }) return result } @@ -95,8 +95,8 @@ searchTeams.schema = Joi.object().keys({ */ async function getTeamDetail (currentUser, projects, isSearch = true) { const projectIds = _.map(projects, 'id') - // Get all assigned resourceBookings filtered by projectIds - const resourceBookings = await _getAssignedResourceBookingsByProjectIds(currentUser, projectIds) + // Get all placed resourceBookings filtered by projectIds + const resourceBookings = await _getPlacedResourceBookingsByProjectIds(currentUser, projectIds) // Get all jobs filtered by projectIds const jobs = await _getJobsByProjectIds(currentUser, projectIds) @@ -285,7 +285,7 @@ async function getTeamJob (currentUser, id, jobId) { const photoURLMap = _.groupBy(members, 'handleLower') result.candidates = _.map(job.candidates, candidate => { - const candidateData = _.pick(candidate, ['status', 'resume', 'userId', 'id']) + const candidateData = _.pick(candidate, ['status', 'resume', 'userId', 'interviews', 'id']) const userData = userMap[candidate.userId][0] // attach user data to the candidate Object.assign(candidateData, _.pick(userData, ['handle', 'firstName', 'lastName', 'skills'])) From de3b4d33d6dce9a621f54f844198a818b99f8e2e Mon Sep 17 00:00:00 2001 From: Maksym Mykhailenko Date: Wed, 28 Apr 2021 10:20:29 +0300 Subject: [PATCH 03/20] fix: migration JC status --- ...21-04-27-172422-job-candidate-selected-status-migration.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/migrations/2021-04-27-172422-job-candidate-selected-status-migration.js b/migrations/2021-04-27-172422-job-candidate-selected-status-migration.js index 3ba8ec06..2959e798 100644 --- a/migrations/2021-04-27-172422-job-candidate-selected-status-migration.js +++ b/migrations/2021-04-27-172422-job-candidate-selected-status-migration.js @@ -8,11 +8,11 @@ const config = require('config') module.exports = { up: async (queryInterface, Sequelize) => { const tableName = `${config.DB_SCHEMA_NAME}.job_candidates` - await queryInterface.sequelize.query(`UPDATE ${tableName} SET status = 'selected' WHERE status = 'shortlist'`) + await queryInterface.sequelize.query(`UPDATE ${tableName} SET status = 'interview' WHERE status = 'shortlist'`) }, down: async (queryInterface, Sequelize) => { const tableName = `${config.DB_SCHEMA_NAME}.job_candidates` - await queryInterface.sequelize.query(`UPDATE ${tableName} SET status = 'shortlist' WHERE status = 'selected'`) + await queryInterface.sequelize.query(`UPDATE ${tableName} SET status = 'shortlist' WHERE status = 'interview'`) } }; From 3992a6c1245e7be91e2498eba4e68affad7312b3 Mon Sep 17 00:00:00 2001 From: urwithat Date: Wed, 28 Apr 2021 16:06:52 +0530 Subject: [PATCH 04/20] Interview changes from, recipients, & cc --- config/default.js | 8 +++--- config/email_template.config.js | 1 + src/eventHandlers/InterviewEventHandler.js | 29 +--------------------- 3 files changed, 7 insertions(+), 31 deletions(-) diff --git a/config/default.js b/config/default.js index 56ad8263..f7eddb93 100644 --- a/config/default.js +++ b/config/default.js @@ -144,8 +144,10 @@ module.exports = { REQUEST_EXTENSION_EMAILS: (process.env.REQUEST_EXTENSION_EMAILS || '').split(','), // the emails address for interview invitation // INTERVIEW_INVITATION_CC_LIST may contain comma-separated list of email which is converted to array - // scheduler@x.ai should be in the CC list - INTERVIEW_INVITATION_CC_LIST: (process.env.INTERVIEW_INVITATION_CC_LIST || 'scheduler@x.ai').split(','), + INTERVIEW_INVITATION_CC_LIST: (process.env.INTERVIEW_INVITATION_CC_LIST || '').split(','), + // INTERVIEW_INVITATION_RECIPIENTS_LIST may contain comma-separated list of email which is converted to array + // scheduler@x.ai should be in the RECIPIENTS list + INTERVIEW_INVITATION_RECIPIENTS_LIST: (process.env.INTERVIEW_INVITATION_RECIPIENTS_LIST || 'scheduler@topcoder.com').split(','), // SendGrid email template ID for reporting issue REPORT_ISSUE_SENDGRID_TEMPLATE_ID: process.env.REPORT_ISSUE_SENDGRID_TEMPLATE_ID, // SendGrid email template ID for requesting extension @@ -153,7 +155,7 @@ module.exports = { // SendGrid email template ID for interview invitation INTERVIEW_INVITATION_SENDGRID_TEMPLATE_ID: process.env.INTERVIEW_INVITATION_SENDGRID_TEMPLATE_ID, // The sender (aka `from`) email for invitation. - INTERVIEW_INVITATION_SENDER_EMAIL: process.env.INTERVIEW_INVITATION_SENDER_EMAIL || 'scheduler@topcoder.com', + INTERVIEW_INVITATION_SENDER_EMAIL: process.env.INTERVIEW_INVITATION_SENDER_EMAIL || 'talent@topcoder.com', // the URL where TaaS App is hosted TAAS_APP_URL: process.env.TAAS_APP_URL || 'https://platform.topcoder-dev.com/taas/myteams', // environment variables for Payment Service diff --git a/config/email_template.config.js b/config/email_template.config.js index 01775ad8..eac17e4f 100644 --- a/config/email_template.config.js +++ b/config/email_template.config.js @@ -96,6 +96,7 @@ module.exports = { 'interview-invitation': { from: config.INTERVIEW_INVITATION_SENDER_EMAIL, cc: config.INTERVIEW_INVITATION_CC_LIST, + recipients: config.INTERVIEW_INVITATION_RECIPIENTS_LIST, sendgridTemplateId: config.INTERVIEW_INVITATION_SENDGRID_TEMPLATE_ID } } diff --git a/src/eventHandlers/InterviewEventHandler.js b/src/eventHandlers/InterviewEventHandler.js index af7ce400..dc11c07e 100644 --- a/src/eventHandlers/InterviewEventHandler.js +++ b/src/eventHandlers/InterviewEventHandler.js @@ -20,29 +20,12 @@ async function sendInvitationEmail (payload) { // get job candidate user details const jobCandidate = await models.JobCandidate.findById(interview.jobCandidateId) const jobCandidateUser = await helper.getUserById(jobCandidate.userId, true) - // const jobCandidateUserEmail = helper.getUserAttributeValue(jobCandidateUser, 'email') // get customer details const job = await jobCandidate.getJob() - // const customerUser = await helper.getUserByExternalId(job.externalId, true) - // const customerUserEmail = helper.getUserAttributeValue(customerUser, 'email') - - // TODO: remove mock addresses & switch back to the old implementation once API gets fixed - // Both emails will be undefined since TC API doesn't return attributes, - // this is a workaround to skip check/condition & log the payload - // it will post the event nevertheless (with mocked candidate&customer address), so you can see on the logs as kafka event - // and verify the payload content - const customerMockEmail = 'testcustomer@yopmail.com' - const candidateMockEmail = 'testuserforemail@yopmail.com' - - // if (jobCandidateUserEmail && customerUserEmail) { const interviewerList = interview.attendeesList - // ? [customerUserEmail, ...interview.attendeesList].join(', ') // "customer@mail.com, first@attendee.com, second@attendee.com..." - // : customerUserEmail - ? [customerMockEmail, ...interview.attendeesList].join(', ') // "customer@mail.com, first@attendee.com, second@attendee.com..." - : customerMockEmail + teamService.sendEmail({}, { template: 'interview-invitation', - recipients: [candidateMockEmail, customerMockEmail], cc: interview.attendeesList, data: { interviewType: interview.xaiTemplate, @@ -54,16 +37,6 @@ async function sendInvitationEmail (payload) { candidateId: interview.jobCandidateId } }) - /* } else { - // one (or both) of the emails are missing due to some reason - // for e.g. some users' externalIds may be set to null or similar - // log error - logger.error({ - component: 'InterviewEventHandler', - context: 'sendInvitationEmail', - message: 'Couldn\'t sent invitation emails. Insufficient details.' - }) - } */ } /** From 48225d86f6a5b240527054de2f5339713d1d623d Mon Sep 17 00:00:00 2001 From: urwithat Date: Wed, 28 Apr 2021 21:54:07 +0530 Subject: [PATCH 05/20] Passing new SendEmail properties --- src/eventHandlers/InterviewEventHandler.js | 1 - src/services/TeamService.js | 15 ++++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/eventHandlers/InterviewEventHandler.js b/src/eventHandlers/InterviewEventHandler.js index dc11c07e..ccbbd10e 100644 --- a/src/eventHandlers/InterviewEventHandler.js +++ b/src/eventHandlers/InterviewEventHandler.js @@ -31,7 +31,6 @@ async function sendInvitationEmail (payload) { interviewType: interview.xaiTemplate, interviewRound: interview.round, interviewDuration: Interviews.XaiTemplate[interview.xaiTemplate], - interviewerList, jobName: job.title, candidateName: `${jobCandidateUser.firstName} ${jobCandidateUser.lastName}`, candidateId: interview.jobCandidateId diff --git a/src/services/TeamService.js b/src/services/TeamService.js index 8eb6714c..03f5ec28 100644 --- a/src/services/TeamService.js +++ b/src/services/TeamService.js @@ -315,22 +315,23 @@ getTeamJob.schema = Joi.object().keys({ */ async function sendEmail (currentUser, data) { const template = emailTemplates[data.template] - const dataCC = data.cc || [] const templateCC = template.cc || [] const dataRecipients = data.recipients || [] const templateRecipients = template.recipients || [] - - await helper.postEvent(config.EMAIL_TOPIC, { - data: data.data, // substitutions - sendgrid_template_id: template.sendgridTemplateId, - version: 'v3', + let emailProps = { // override template if coming data already have the 'from' address from: data.from || template.from, // create a set of uniq. recipients & CCs, from both coming data & template recipients: _.uniq([...dataRecipients, ...templateRecipients]), cc: _.uniq([...dataCC, ...templateCC]) - }) + }; + let emailData = { + data: { ...data.data, ...emailProps }, + sendgrid_template_id: template.sendgridTemplateId, + version: 'v3' + } + await helper.postEvent(config.EMAIL_TOPIC, { ...emailData, ...emailProps }) } sendEmail.schema = Joi.object().keys({ From 03f5bf5f047812488549feb5d354ea4b660caa24 Mon Sep 17 00:00:00 2001 From: urwithat Date: Wed, 28 Apr 2021 22:16:09 +0530 Subject: [PATCH 06/20] Send Email Template Fix's --- app-constants.js | 4 +- config/email_template.config.js | 2 +- ...coder-bookings-api.postman_collection.json | 60 +++++++++---------- docs/swagger.yaml | 13 ++-- src/services/TeamService.js | 7 ++- 5 files changed, 46 insertions(+), 40 deletions(-) diff --git a/app-constants.js b/app-constants.js index 37217f99..2721ddd0 100644 --- a/app-constants.js +++ b/app-constants.js @@ -64,8 +64,8 @@ const Interviews = { }, // key: template name in x.ai, value: duration XaiTemplate: { - '30-minutes': 30, - '60-minutes': 60 + 'interview-30': 30, + 'interview-60': 60 } } diff --git a/config/email_template.config.js b/config/email_template.config.js index eac17e4f..b7570a73 100644 --- a/config/email_template.config.js +++ b/config/email_template.config.js @@ -63,7 +63,7 @@ module.exports = { /* Request interview for a job candidate * - * - interviewType: the x.ai interview type. Example: "30-minutes" + * - interviewType: the x.ai interview type. Example: "interview-30" * - interviewRound: the round of the interview. Example: 2 * - interviewDuration: duration of the interview, in minutes. Example: 30 * - interviewerList: The list of interviewer email addresses. Example: "first@attendee.com, second@attendee.com" diff --git a/docs/Topcoder-bookings-api.postman_collection.json b/docs/Topcoder-bookings-api.postman_collection.json index 704ad61d..52000d57 100644 --- a/docs/Topcoder-bookings-api.postman_collection.json +++ b/docs/Topcoder-bookings-api.postman_collection.json @@ -3217,7 +3217,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-minutes\",\r\n \"status\": \"Completed\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"interview-30\",\r\n \"status\": \"Completed\"\r\n}", "options": { "raw": { "language": "json" @@ -3270,7 +3270,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-minutes\",\r\n \"googleCalendarId\": \"dummyId\",\r\n \"customMessage\": \"This is a custom message\",\r\n \"attendeesList\": [\"attendee1@yopmail.com\", \"attendee2@yopmail.com\"],\r\n \"status\": \"Scheduling\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"interview-30\",\r\n \"googleCalendarId\": \"dummyId\",\r\n \"customMessage\": \"This is a custom message\",\r\n \"attendeesList\": [\"attendee1@yopmail.com\", \"attendee2@yopmail.com\"],\r\n \"status\": \"Scheduling\"\r\n}", "options": { "raw": { "language": "json" @@ -3321,7 +3321,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-minutes\",\r\n \"googleCalendarId\": \"dummyId\",\r\n \"customMessage\": \"This is a custom message\",\r\n \"status\": \"Scheduling\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"interview-30\",\r\n \"googleCalendarId\": \"dummyId\",\r\n \"customMessage\": \"This is a custom message\",\r\n \"status\": \"Scheduling\"\r\n}", "options": { "raw": { "language": "json" @@ -3373,7 +3373,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-minutes\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"interview-30\"\r\n}", "options": { "raw": { "language": "json" @@ -3422,7 +3422,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-minutes\",\r\n \"status\": \"xxxx\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"interview-30\",\r\n \"status\": \"xxxx\"\r\n}", "options": { "raw": { "language": "json" @@ -3472,7 +3472,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-minutes\",\r\n \"attendeesList\": [\"attendee1@yopmail.com\", \"attendee2@yopmail.com\"]\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"interview-30\",\r\n \"attendeesList\": [\"attendee1@yopmail.com\", \"attendee2@yopmail.com\"]\r\n}", "options": { "raw": { "language": "json" @@ -3521,7 +3521,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-minutes\",\r\n \"attendeesList\": \"asddd\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"interview-30\",\r\n \"attendeesList\": \"asddd\"\r\n}", "options": { "raw": { "language": "json" @@ -3570,7 +3570,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-minutes\",\r\n \"attendeesList\": [\"asdas\"]\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"interview-30\",\r\n \"attendeesList\": [\"asdas\"]\r\n}", "options": { "raw": { "language": "json" @@ -3619,7 +3619,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-minutes\",\r\n \"round\": 1\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"interview-30\",\r\n \"round\": 1\r\n}", "options": { "raw": { "language": "json" @@ -3668,7 +3668,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-minutes\",\r\n \"startTimestamp\": \"2021-04-17\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"interview-30\",\r\n \"startTimestamp\": \"2021-04-17\"\r\n}", "options": { "raw": { "language": "json" @@ -3748,7 +3748,7 @@ "pm.test('Status code is 400', function () {\r", " pm.response.to.have.status(400);\r", " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"\\\"interview.xaiTemplate\\\" must be one of [30-minutes, 60-minutes]\")\r", + " pm.expect(response.message).to.eq(\"\\\"interview.xaiTemplate\\\" must be one of [interview-30, interview-60]\")\r", "});" ], "type": "text/javascript" @@ -3815,7 +3815,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-minutes\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"interview-30\"\r\n}", "options": { "raw": { "language": "json" @@ -3864,7 +3864,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-minutes\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"interview-30\"\r\n}", "options": { "raw": { "language": "json" @@ -3911,7 +3911,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-minutes\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"interview-30\"\r\n}", "options": { "raw": { "language": "json" @@ -3958,7 +3958,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-minutes\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"interview-30\"\r\n}", "options": { "raw": { "language": "json" @@ -4005,7 +4005,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-minutes\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"interview-30\"\r\n}", "options": { "raw": { "language": "json" @@ -4052,7 +4052,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-minutes\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"interview-30\"\r\n}", "options": { "raw": { "language": "json" @@ -4101,7 +4101,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-minutes\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"interview-30\"\r\n}", "options": { "raw": { "language": "json" @@ -4150,7 +4150,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-minutes\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"interview-30\"\r\n}", "options": { "raw": { "language": "json" @@ -4199,7 +4199,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-minutes\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"interview-30\"\r\n}", "options": { "raw": { "language": "json" @@ -4248,7 +4248,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-minutes\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"interview-30\"\r\n}", "options": { "raw": { "language": "json" @@ -4297,7 +4297,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-minutes\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"interview-30\"\r\n}", "options": { "raw": { "language": "json" @@ -4340,7 +4340,7 @@ "header": [], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-minutes\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"interview-30\"\r\n}", "options": { "raw": { "language": "json" @@ -4389,7 +4389,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-minutes\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"interview-30\"\r\n}", "options": { "raw": { "language": "json" @@ -5312,7 +5312,7 @@ "pm.test('Status code is 400', function () {\r", " pm.response.to.have.status(400);\r", " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"\\\"data.xaiTemplate\\\" must be one of [30-minutes, 60-minutes]\")\r", + " pm.expect(response.message).to.eq(\"\\\"data.xaiTemplate\\\" must be one of [interview-30, interview-60]\")\r", "});" ], "type": "text/javascript" @@ -19449,7 +19449,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-minutes\",\r\n \"googleCalendarId\": \"dummyId\",\r\n \"customMessage\": \"This is a custom message\",\r\n \"status\": \"Scheduling\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"interview-30\",\r\n \"googleCalendarId\": \"dummyId\",\r\n \"customMessage\": \"This is a custom message\",\r\n \"status\": \"Scheduling\"\r\n}", "options": { "raw": { "language": "json" @@ -21389,7 +21389,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-minutes\",\r\n \"googleCalendarId\": \"dummyId\",\r\n \"customMessage\": \"This is a custom message\",\r\n \"status\": \"Scheduling\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"interview-30\",\r\n \"googleCalendarId\": \"dummyId\",\r\n \"customMessage\": \"This is a custom message\",\r\n \"status\": \"Scheduling\"\r\n}", "options": { "raw": { "language": "json" @@ -21440,7 +21440,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-minutes\",\r\n \"googleCalendarId\": \"dummyId\",\r\n \"customMessage\": \"This is a custom message\",\r\n \"status\": \"Scheduling\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"interview-30\",\r\n \"googleCalendarId\": \"dummyId\",\r\n \"customMessage\": \"This is a custom message\",\r\n \"status\": \"Scheduling\"\r\n}", "options": { "raw": { "language": "json" @@ -23544,7 +23544,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-minutes\",\r\n \"googleCalendarId\": \"dummyId\",\r\n \"customMessage\": \"This is a custom message\",\r\n \"status\": \"Scheduling\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"interview-30\",\r\n \"googleCalendarId\": \"dummyId\",\r\n \"customMessage\": \"This is a custom message\",\r\n \"status\": \"Scheduling\"\r\n}", "options": { "raw": { "language": "json" @@ -23595,7 +23595,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiTemplate\": \"30-minutes\",\r\n \"googleCalendarId\": \"dummyId\",\r\n \"customMessage\": \"This is a custom message\",\r\n \"status\": \"Scheduling\"\r\n}", + "raw": "{\r\n \"xaiTemplate\": \"interview-30\",\r\n \"googleCalendarId\": \"dummyId\",\r\n \"customMessage\": \"This is a custom message\",\r\n \"status\": \"Scheduling\"\r\n}", "options": { "raw": { "language": "json" diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 93b67407..00dab590 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -5,6 +5,7 @@ info: version: 1.0.0 servers: - url: /api/{apiVersion}/ + - url: https://api.topcoder-dev.com/{apiVersion}/ variables: apiVersion: default: "v5" @@ -3455,8 +3456,8 @@ components: description: "The google calendar id." xaiTemplate: type: string - example: "30-minutes" - enum: ["30-minutes", "60-minutes"] + example: "interview-30" + enum: ["interview-30", "interview-60"] description: "The x.ai template name" customMessage: type: string @@ -3510,8 +3511,8 @@ components: description: "The custom message." xaiTemplate: type: string - enum: ["30-minutes", "60-minutes"] - example: "30-minutes" + enum: ["interview-30", "interview-60"] + example: "interview-30" description: "The x.ai template name" attendeesList: type: array @@ -3535,8 +3536,8 @@ components: description: "The custom message." xaiTemplate: type: string - enum: ["30-minutes", "60-minutes"] - example: "30-minutes" + enum: ["interview-30", "interview-60"] + example: "interview-30" description: "The x.ai template name" attendeesList: type: array diff --git a/src/services/TeamService.js b/src/services/TeamService.js index 03f5ec28..c80a2eb5 100644 --- a/src/services/TeamService.js +++ b/src/services/TeamService.js @@ -326,8 +326,13 @@ async function sendEmail (currentUser, data) { recipients: _.uniq([...dataRecipients, ...templateRecipients]), cc: _.uniq([...dataCC, ...templateCC]) }; + let emailStringProps = { + from: emailProps.from.join(','), + recipients: emailProps.recipients.join(','), + cc: emailProps.cc.join(',') + }; let emailData = { - data: { ...data.data, ...emailProps }, + data: { ...data.data, ...emailStringProps }, sendgrid_template_id: template.sendgridTemplateId, version: 'v3' } From f86289ec71fffb010f2a5456973bbb0c7c83eb93 Mon Sep 17 00:00:00 2001 From: urwithat Date: Wed, 28 Apr 2021 23:09:04 +0530 Subject: [PATCH 07/20] fix --- src/services/TeamService.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/services/TeamService.js b/src/services/TeamService.js index c80a2eb5..0648db99 100644 --- a/src/services/TeamService.js +++ b/src/services/TeamService.js @@ -327,9 +327,9 @@ async function sendEmail (currentUser, data) { cc: _.uniq([...dataCC, ...templateCC]) }; let emailStringProps = { - from: emailProps.from.join(','), - recipients: emailProps.recipients.join(','), - cc: emailProps.cc.join(',') + from: (emailProps.from).join(','), + recipients: (emailProps.recipients).join(','), + cc: (emailProps.cc).join(',') }; let emailData = { data: { ...data.data, ...emailStringProps }, From 14715c6584ba6316d896e8a06e3632303e5badfc Mon Sep 17 00:00:00 2001 From: urwithat Date: Wed, 28 Apr 2021 23:30:24 +0530 Subject: [PATCH 08/20] Fix from not an array --- src/services/TeamService.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/TeamService.js b/src/services/TeamService.js index 0648db99..56a22e00 100644 --- a/src/services/TeamService.js +++ b/src/services/TeamService.js @@ -327,7 +327,7 @@ async function sendEmail (currentUser, data) { cc: _.uniq([...dataCC, ...templateCC]) }; let emailStringProps = { - from: (emailProps.from).join(','), + from: emailProps.from, recipients: (emailProps.recipients).join(','), cc: (emailProps.cc).join(',') }; From 2a079f5ea4bbbbf180d822ad2e844eaeae0b06c2 Mon Sep 17 00:00:00 2001 From: Cagdas U Date: Thu, 29 Apr 2021 23:48:51 +0300 Subject: [PATCH 09/20] fix(interview-scheduler): fix interview permissions & mail feature 1. Fixes the interview permissions as per [1]. 2. Updates email sending feature to get candidate's email automatically. [2] References: [1]: https://github.com/topcoder-platform/taas-app/issues/173 [2]: https://github.com/topcoder-platform/taas-app/issues/165 --- src/common/helper.js | 21 ++++++++++++++++++++- src/eventHandlers/InterviewEventHandler.js | 7 ++++--- src/services/InterviewService.js | 18 ++++++++++-------- 3 files changed, 34 insertions(+), 12 deletions(-) diff --git a/src/common/helper.js b/src/common/helper.js index 8c51a750..42f96ca5 100644 --- a/src/common/helper.js +++ b/src/common/helper.js @@ -1350,6 +1350,24 @@ function extractWorkPeriods (start, end) { return periods } +/** + * Returns the email address of specified (via handle) user. + * + * @param {String} userHandle user handle + * @returns {String} email address of the user + */ +async function getUserEmailByHandle (userHandle) { + const token = await getM2MToken() + const url = `${config.TC_API}/members/${userHandle}` + const res = await request + .get(url) + .set('Authorization', `Bearer ${token}`) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json') + localLogger.debug({ context: 'getUserEmailByHandle', message: `response body: ${JSON.stringify(res.body)}` }) + return _.get(res, 'body.email') +} + module.exports = { getParamFromCliArgs, promptUser, @@ -1398,5 +1416,6 @@ module.exports = { createChallenge, updateChallenge, createChallengeResource, - extractWorkPeriods + extractWorkPeriods, + getUserEmailByHandle } diff --git a/src/eventHandlers/InterviewEventHandler.js b/src/eventHandlers/InterviewEventHandler.js index ccbbd10e..1a4daaba 100644 --- a/src/eventHandlers/InterviewEventHandler.js +++ b/src/eventHandlers/InterviewEventHandler.js @@ -19,18 +19,19 @@ async function sendInvitationEmail (payload) { // get job candidate user details const jobCandidate = await models.JobCandidate.findById(interview.jobCandidateId) - const jobCandidateUser = await helper.getUserById(jobCandidate.userId, true) + const jobCandidateUser = await helper.getUserById(jobCandidate.userId) + const jobCandidateUserEmail = await helper.getUserEmailByHandle(jobCandidateUser.handle) // get customer details const job = await jobCandidate.getJob() - const interviewerList = interview.attendeesList teamService.sendEmail({}, { template: 'interview-invitation', - cc: interview.attendeesList, + cc: [jobCandidateUserEmail, ...interview.attendeesList], data: { interviewType: interview.xaiTemplate, interviewRound: interview.round, interviewDuration: Interviews.XaiTemplate[interview.xaiTemplate], + interviewerList: interview.attendeesList, jobName: job.title, candidateName: `${jobCandidateUser.firstName} ${jobCandidateUser.lastName}`, candidateId: interview.jobCandidateId diff --git a/src/services/InterviewService.js b/src/services/InterviewService.js index d4f67576..e1c57e7e 100644 --- a/src/services/InterviewService.js +++ b/src/services/InterviewService.js @@ -20,12 +20,14 @@ const esClient = helper.getESClient() * Ensures user is permitted for the operation. * * @param {Object} currentUser the user who perform this operation. + * @param {String} jobCandidateId the job candidate id * @throws {errors.ForbiddenError} */ -function ensureUserIsPermitted (currentUser) { - const isUserPermitted = currentUser.hasManagePermission || currentUser.isMachine - if (isUserPermitted !== true) { - throw new errors.ForbiddenError('You are not allowed to perform this action!') +async function ensureUserIsPermitted (currentUser, jobCandidateId) { + if (!currentUser.hasManagePermission && !currentUser.isMachine) { + const jobCandidate = await models.JobCandidate.findById(jobCandidateId) + const job = jobCandidate.getJob() + await helper.checkIsMemberOfProject(currentUser.userId, job.projectId) } } @@ -58,7 +60,7 @@ function handleSequelizeError (err, jobCandidateId) { */ async function getInterviewByRound (currentUser, jobCandidateId, round, fromDb = false) { // check permission - ensureUserIsPermitted(currentUser) + await ensureUserIsPermitted(currentUser, jobCandidateId) if (!fromDb) { try { // get job candidate from ES @@ -113,7 +115,7 @@ getInterviewByRound.schema = Joi.object().keys({ */ async function requestInterview (currentUser, jobCandidateId, interview) { // check permission - ensureUserIsPermitted(currentUser) + await ensureUserIsPermitted(currentUser, jobCandidateId) interview.id = uuid() interview.jobCandidateId = jobCandidateId @@ -168,7 +170,7 @@ requestInterview.schema = Joi.object().keys({ */ async function partiallyUpdateInterview (currentUser, jobCandidateId, round, data) { // check permission - ensureUserIsPermitted(currentUser) + await ensureUserIsPermitted(currentUser, jobCandidateId) const interview = await Interview.findOne({ where: { @@ -234,7 +236,7 @@ partiallyUpdateInterview.schema = Joi.object().keys({ */ async function searchInterviews (currentUser, jobCandidateId, criteria) { // check permission - ensureUserIsPermitted(currentUser) + await ensureUserIsPermitted(currentUser, jobCandidateId) const { page, perPage } = criteria From c6961f826d99940f358ea4a44052ac6c1da5671f Mon Sep 17 00:00:00 2001 From: urwithat Date: Fri, 30 Apr 2021 14:34:02 +0530 Subject: [PATCH 10/20] Changes for new sendgrid template --- src/common/helper.js | 8 ++++---- src/eventHandlers/InterviewEventHandler.js | 20 +++++++++++--------- src/services/TeamService.js | 15 ++++----------- 3 files changed, 19 insertions(+), 24 deletions(-) diff --git a/src/common/helper.js b/src/common/helper.js index 42f96ca5..fb51186b 100644 --- a/src/common/helper.js +++ b/src/common/helper.js @@ -1356,7 +1356,7 @@ function extractWorkPeriods (start, end) { * @param {String} userHandle user handle * @returns {String} email address of the user */ -async function getUserEmailByHandle (userHandle) { +async function getUserByHandle (userHandle) { const token = await getM2MToken() const url = `${config.TC_API}/members/${userHandle}` const res = await request @@ -1364,8 +1364,8 @@ async function getUserEmailByHandle (userHandle) { .set('Authorization', `Bearer ${token}`) .set('Content-Type', 'application/json') .set('Accept', 'application/json') - localLogger.debug({ context: 'getUserEmailByHandle', message: `response body: ${JSON.stringify(res.body)}` }) - return _.get(res, 'body.email') + localLogger.debug({ context: 'getUserByHandle', message: `response body: ${JSON.stringify(res.body)}` }) + return _.get(res, 'body') } module.exports = { @@ -1417,5 +1417,5 @@ module.exports = { updateChallenge, createChallengeResource, extractWorkPeriods, - getUserEmailByHandle + getUserByHandle } diff --git a/src/eventHandlers/InterviewEventHandler.js b/src/eventHandlers/InterviewEventHandler.js index 1a4daaba..7825746d 100644 --- a/src/eventHandlers/InterviewEventHandler.js +++ b/src/eventHandlers/InterviewEventHandler.js @@ -20,21 +20,23 @@ async function sendInvitationEmail (payload) { // get job candidate user details const jobCandidate = await models.JobCandidate.findById(interview.jobCandidateId) const jobCandidateUser = await helper.getUserById(jobCandidate.userId) - const jobCandidateUserEmail = await helper.getUserEmailByHandle(jobCandidateUser.handle) + const jobCandidateUserEmail = await helper.getUserByHandle(jobCandidateUser.handle) // get customer details const job = await jobCandidate.getJob() teamService.sendEmail({}, { template: 'interview-invitation', - cc: [jobCandidateUserEmail, ...interview.attendeesList], + cc: [jobCandidateUserEmail.email, ...interview.attendeesList], data: { - interviewType: interview.xaiTemplate, - interviewRound: interview.round, - interviewDuration: Interviews.XaiTemplate[interview.xaiTemplate], - interviewerList: interview.attendeesList, - jobName: job.title, - candidateName: `${jobCandidateUser.firstName} ${jobCandidateUser.lastName}`, - candidateId: interview.jobCandidateId + job_candidate_id: interview.jobCandidateId, + interview_round: interview.round, + interviewee_name: `${jobCandidateUser.firstName} ${jobCandidateUser.lastName}`, + interviewer_name: `${jobCandidateUserEmail.firstName} ${jobCandidateUserEmail.lastName}`, + xai_template: interview.xaiTemplate, + additional_interviewers: interview.attendeesList, + interview_length: Interviews.XaiTemplate[interview.xaiTemplate], + job_name: job.title, + interviewee_handle: jobCandidateUserEmail.handle } }) } diff --git a/src/services/TeamService.js b/src/services/TeamService.js index 56a22e00..d203e5dd 100644 --- a/src/services/TeamService.js +++ b/src/services/TeamService.js @@ -319,24 +319,17 @@ async function sendEmail (currentUser, data) { const templateCC = template.cc || [] const dataRecipients = data.recipients || [] const templateRecipients = template.recipients || [] - let emailProps = { + let emailData = { // override template if coming data already have the 'from' address from: data.from || template.from, // create a set of uniq. recipients & CCs, from both coming data & template recipients: _.uniq([...dataRecipients, ...templateRecipients]), - cc: _.uniq([...dataCC, ...templateCC]) - }; - let emailStringProps = { - from: emailProps.from, - recipients: (emailProps.recipients).join(','), - cc: (emailProps.cc).join(',') - }; - let emailData = { - data: { ...data.data, ...emailStringProps }, + cc: _.uniq([...dataCC, ...templateCC]), + data: data.data, sendgrid_template_id: template.sendgridTemplateId, version: 'v3' } - await helper.postEvent(config.EMAIL_TOPIC, { ...emailData, ...emailProps }) + await helper.postEvent(config.EMAIL_TOPIC, emailData) } sendEmail.schema = Joi.object().keys({ From 898ba715e57fc78afb126a9cd9358a8b100c650a Mon Sep 17 00:00:00 2001 From: urwithat Date: Fri, 30 Apr 2021 15:37:49 +0530 Subject: [PATCH 11/20] Fix for new sendgrid template --- src/common/helper.js | 2 +- src/eventHandlers/InterviewEventHandler.js | 16 +++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/common/helper.js b/src/common/helper.js index fb51186b..4e4e0808 100644 --- a/src/common/helper.js +++ b/src/common/helper.js @@ -1109,7 +1109,7 @@ async function _getMemberDetailsByEmail (token, email) { .get(config.TOPCODER_USERS_API) .query({ filter: `email=${email}`, - fields: 'handle,id,email' + fields: 'handle,id,email,firstName,lastName' }) .set('Authorization', `Bearer ${token}`) .set('Accept', 'application/json') diff --git a/src/eventHandlers/InterviewEventHandler.js b/src/eventHandlers/InterviewEventHandler.js index 7825746d..90a5ac78 100644 --- a/src/eventHandlers/InterviewEventHandler.js +++ b/src/eventHandlers/InterviewEventHandler.js @@ -16,27 +16,29 @@ const teamService = require('../services/TeamService') */ async function sendInvitationEmail (payload) { const interview = payload.value - + // get the Interviewer + const interviewerUser = await helper.getMemberDetailsByEmails(interview.attendeesList[0]) + .then((members) => _.map(members, (member) => ({ ...member, emailLowerCase: member.email.toLowerCase() }))) // get job candidate user details const jobCandidate = await models.JobCandidate.findById(interview.jobCandidateId) const jobCandidateUser = await helper.getUserById(jobCandidate.userId) - const jobCandidateUserEmail = await helper.getUserByHandle(jobCandidateUser.handle) + const jobCandidateMember = await helper.getUserByHandle(jobCandidateUser.handle) // get customer details const job = await jobCandidate.getJob() teamService.sendEmail({}, { template: 'interview-invitation', - cc: [jobCandidateUserEmail.email, ...interview.attendeesList], + cc: [jobCandidateMember.email, ...interview.attendeesList], data: { job_candidate_id: interview.jobCandidateId, interview_round: interview.round, - interviewee_name: `${jobCandidateUser.firstName} ${jobCandidateUser.lastName}`, - interviewer_name: `${jobCandidateUserEmail.firstName} ${jobCandidateUserEmail.lastName}`, - xai_template: interview.xaiTemplate, + interviewee_name: `${jobCandidateMember.firstName} ${jobCandidateMember.lastName}`, + interviewer_name: `${interviewerUser.firstName} ${interviewerUser.lastName}`, + xai_template: '/' + interview.xaiTemplate, additional_interviewers: interview.attendeesList, interview_length: Interviews.XaiTemplate[interview.xaiTemplate], job_name: job.title, - interviewee_handle: jobCandidateUserEmail.handle + interviewee_handle: jobCandidateMember.handle } }) } From 2d08648de01c0eca079df52633a610983c0ab5e2 Mon Sep 17 00:00:00 2001 From: urwithat Date: Fri, 30 Apr 2021 15:51:57 +0530 Subject: [PATCH 12/20] Fix for new sendgrid template --- src/eventHandlers/InterviewEventHandler.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/eventHandlers/InterviewEventHandler.js b/src/eventHandlers/InterviewEventHandler.js index 90a5ac78..f1adfbbc 100644 --- a/src/eventHandlers/InterviewEventHandler.js +++ b/src/eventHandlers/InterviewEventHandler.js @@ -17,7 +17,7 @@ const teamService = require('../services/TeamService') async function sendInvitationEmail (payload) { const interview = payload.value // get the Interviewer - const interviewerUser = await helper.getMemberDetailsByEmails(interview.attendeesList[0]) + const interviewerUsers = await helper.getMemberDetailsByEmails(interview.attendeesList) .then((members) => _.map(members, (member) => ({ ...member, emailLowerCase: member.email.toLowerCase() }))) // get job candidate user details const jobCandidate = await models.JobCandidate.findById(interview.jobCandidateId) @@ -33,9 +33,9 @@ async function sendInvitationEmail (payload) { job_candidate_id: interview.jobCandidateId, interview_round: interview.round, interviewee_name: `${jobCandidateMember.firstName} ${jobCandidateMember.lastName}`, - interviewer_name: `${interviewerUser.firstName} ${interviewerUser.lastName}`, + interviewer_name: `${interviewerUsers[0].firstName} ${interviewerUsers[0].lastName}`, xai_template: '/' + interview.xaiTemplate, - additional_interviewers: interview.attendeesList, + additional_interviewers: (interview.attendeesList).join(','), interview_length: Interviews.XaiTemplate[interview.xaiTemplate], job_name: job.title, interviewee_handle: jobCandidateMember.handle From 0b57894a418bbdac836c181a08cf541771f65d76 Mon Sep 17 00:00:00 2001 From: urwithat Date: Fri, 30 Apr 2021 15:59:00 +0530 Subject: [PATCH 13/20] Import lodash --- src/eventHandlers/InterviewEventHandler.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/eventHandlers/InterviewEventHandler.js b/src/eventHandlers/InterviewEventHandler.js index f1adfbbc..11d118b4 100644 --- a/src/eventHandlers/InterviewEventHandler.js +++ b/src/eventHandlers/InterviewEventHandler.js @@ -7,6 +7,7 @@ const models = require('../models') const helper = require('../common/helper') const { Interviews } = require('../../app-constants') const teamService = require('../services/TeamService') +const _ = require('lodash') /** * Once we request Interview for a JobCandidate, the invitation emails to be sent out. From 0611e65d63225ba7b171ab2a2aca5f86c4f1dd0e Mon Sep 17 00:00:00 2001 From: Cagdas U Date: Fri, 30 Apr 2021 19:24:52 +0300 Subject: [PATCH 14/20] fix(interview-scheduler): await getJob promise Fix an issue, which was causing getting `undefined` as jobProjectId. This was causing unexpected behaviors when checking the project-based user access level. Addresses https://github.com/topcoder-platform/taas-app/issues/173#issuecomment-829851397 --- src/services/InterviewService.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/InterviewService.js b/src/services/InterviewService.js index e1c57e7e..ee7ce357 100644 --- a/src/services/InterviewService.js +++ b/src/services/InterviewService.js @@ -26,7 +26,7 @@ const esClient = helper.getESClient() async function ensureUserIsPermitted (currentUser, jobCandidateId) { if (!currentUser.hasManagePermission && !currentUser.isMachine) { const jobCandidate = await models.JobCandidate.findById(jobCandidateId) - const job = jobCandidate.getJob() + const job = await jobCandidate.getJob() await helper.checkIsMemberOfProject(currentUser.userId, job.projectId) } } From 5b7212f2b36d66b24d8caca4c6b638b74f056237 Mon Sep 17 00:00:00 2001 From: Cagdas U Date: Sat, 1 May 2021 04:48:10 +0300 Subject: [PATCH 15/20] feat(interview-scheduler): add a limit on max. allowed rounds Add a limit on maximum allowed number of interview rounds. --- app-constants.js | 3 ++- src/services/InterviewService.js | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/app-constants.js b/app-constants.js index 2721ddd0..534e46de 100644 --- a/app-constants.js +++ b/app-constants.js @@ -66,7 +66,8 @@ const Interviews = { XaiTemplate: { 'interview-30': 30, 'interview-60': 60 - } + }, + MaxAllowedCount: 3 } const ChallengeStatus = { diff --git a/src/services/InterviewService.js b/src/services/InterviewService.js index e1c57e7e..8dbf17af 100644 --- a/src/services/InterviewService.js +++ b/src/services/InterviewService.js @@ -125,6 +125,11 @@ async function requestInterview (currentUser, jobCandidateId, interview) { const round = await Interview.count({ where: { jobCandidateId } }) + + // throw error if candidate has already had MaxAllowedCount interviews + if (round >= InterviewConstants.MaxAllowedCount) { + throw new errors.ConflictError(`You've reached the maximum allowed number (${InterviewConstants.MaxAllowedCount}) of interviews for this candidate.`) + } interview.round = round + 1 try { From 6f139acc2dc5225596183901f50b1f577d9ebf3b Mon Sep 17 00:00:00 2001 From: Maksym Mykhailenko Date: Sat, 1 May 2021 13:13:29 +0300 Subject: [PATCH 16/20] fix: Job assigned auto-logic --- .../ResourceBookingEventHandler.js | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/eventHandlers/ResourceBookingEventHandler.js b/src/eventHandlers/ResourceBookingEventHandler.js index f2471591..7a4a7c0a 100644 --- a/src/eventHandlers/ResourceBookingEventHandler.js +++ b/src/eventHandlers/ResourceBookingEventHandler.js @@ -69,16 +69,16 @@ async function placeJobCandidate (payload) { } /** - * Update the status of the Job to placed when it positions requirement is fullfilled. + * Update the status of the Job to assigned when it positions requirement is fulfilled. * * @param {Object} payload the event payload * @returns {undefined} */ -async function placeJob (payload) { +async function assignJob (payload) { if (_.get(payload, 'options.oldValue') && payload.value.status === payload.options.oldValue.status) { logger.debug({ component: 'ResourceBookingEventHandler', - context: 'placeJob', + context: 'assignJob', message: 'status not changed' }) return @@ -86,7 +86,7 @@ async function placeJob (payload) { if (payload.value.status !== 'placed') { logger.debug({ component: 'ResourceBookingEventHandler', - context: 'placeJob', + context: 'assignJob', message: `not interested resource booking - status: ${payload.value.status}` }) return @@ -95,7 +95,7 @@ async function placeJob (payload) { if (!resourceBooking.jobId) { logger.debug({ component: 'ResourceBookingEventHandler', - context: 'placeJob', + context: 'assignJob', message: `id: ${resourceBooking.id} resource booking without jobId - ignored` }) return @@ -104,7 +104,7 @@ async function placeJob (payload) { if (job.status === 'placed') { logger.debug({ component: 'ResourceBookingEventHandler', - context: 'placeJob', + context: 'assignJob', message: `job with projectId ${job.projectId} is already placed` }) return @@ -117,12 +117,12 @@ async function placeJob (payload) { }) logger.debug({ component: 'ResourceBookingEventHandler', - context: 'placeJob', + context: 'assignJob', message: `the number of placed resource bookings is ${resourceBookings.length} - the numPositions of the job is ${job.numPositions}` }) if (job.numPositions === resourceBookings.length) { - await JobService.partiallyUpdateJob(helper.getAuditM2Muser(), job.id, { status: 'placed' }) - logger.info({ component: 'ResourceBookingEventHandler', context: 'placeJob', message: `job ${job.id} is placed` }) + await JobService.partiallyUpdateJob(helper.getAuditM2Muser(), job.id, { status: 'assigned' }) + logger.info({ component: 'ResourceBookingEventHandler', context: 'assignJob', message: `job ${job.id} is assigned` }) } } @@ -295,7 +295,7 @@ async function _deleteWorkPeriods (workPeriods) { */ async function processCreate (payload) { await placeJobCandidate(payload) - await placeJob(payload) + await assignJob(payload) await createWorkPeriods(payload) } @@ -307,7 +307,7 @@ async function processCreate (payload) { */ async function processUpdate (payload) { await placeJobCandidate(payload) - await placeJob(payload) + await assignJob(payload) await updateWorkPeriods(payload) } From 969b1375a66f312ed0363e92e514c211cdf7b547 Mon Sep 17 00:00:00 2001 From: Maksym Mykhailenko Date: Sat, 1 May 2021 13:13:37 +0300 Subject: [PATCH 17/20] fix: lint --- src/services/TeamService.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/TeamService.js b/src/services/TeamService.js index d203e5dd..bbb34485 100644 --- a/src/services/TeamService.js +++ b/src/services/TeamService.js @@ -319,7 +319,7 @@ async function sendEmail (currentUser, data) { const templateCC = template.cc || [] const dataRecipients = data.recipients || [] const templateRecipients = template.recipients || [] - let emailData = { + const emailData = { // override template if coming data already have the 'from' address from: data.from || template.from, // create a set of uniq. recipients & CCs, from both coming data & template From bccba30252092904e66d1f1f41fde929f8ab45a3 Mon Sep 17 00:00:00 2001 From: urwithat Date: Mon, 3 May 2021 11:34:52 +0530 Subject: [PATCH 18/20] Missing subject and body in template & send email --- src/services/TeamService.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/services/TeamService.js b/src/services/TeamService.js index bbb34485..fd5333ae 100644 --- a/src/services/TeamService.js +++ b/src/services/TeamService.js @@ -15,6 +15,8 @@ const ResourceBookingService = require('./ResourceBookingService') const emailTemplates = _.mapValues(emailTemplateConfig, (template) => { return { + subject: template.subject, + body: template.body, from: template.from, recipients: template.recipients, cc: template.cc, @@ -320,6 +322,8 @@ async function sendEmail (currentUser, data) { const dataRecipients = data.recipients || [] const templateRecipients = template.recipients || [] const emailData = { + subject: data.subject || template.subject, + body: data.body || template.body, // override template if coming data already have the 'from' address from: data.from || template.from, // create a set of uniq. recipients & CCs, from both coming data & template From ac8471ec415e5de5ff2debc5d00540b593b435f0 Mon Sep 17 00:00:00 2001 From: urwithat Date: Mon, 3 May 2021 12:05:03 +0530 Subject: [PATCH 19/20] Moving Subject and Body inside data attribute --- src/services/TeamService.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/services/TeamService.js b/src/services/TeamService.js index fd5333ae..08a19fa3 100644 --- a/src/services/TeamService.js +++ b/src/services/TeamService.js @@ -321,15 +321,17 @@ async function sendEmail (currentUser, data) { const templateCC = template.cc || [] const dataRecipients = data.recipients || [] const templateRecipients = template.recipients || [] - const emailData = { + const subjectBody = { subject: data.subject || template.subject, - body: data.body || template.body, + body: data.body || template.body + } + const emailData = { // override template if coming data already have the 'from' address from: data.from || template.from, // create a set of uniq. recipients & CCs, from both coming data & template recipients: _.uniq([...dataRecipients, ...templateRecipients]), cc: _.uniq([...dataCC, ...templateCC]), - data: data.data, + data: { ...data.data, ...subjectBody }, sendgrid_template_id: template.sendgridTemplateId, version: 'v3' } From 813935b4f8aa1de9a84db5175d2a9f65dac6b7f1 Mon Sep 17 00:00:00 2001 From: urwithat Date: Mon, 3 May 2021 13:04:38 +0530 Subject: [PATCH 20/20] Substitute the Subject and Body with values --- src/common/helper.js | 19 ++++++++++++++++++- src/services/TeamService.js | 3 +++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/common/helper.js b/src/common/helper.js index 4e4e0808..26caf51b 100644 --- a/src/common/helper.js +++ b/src/common/helper.js @@ -1368,6 +1368,22 @@ async function getUserByHandle (userHandle) { return _.get(res, 'body') } +/** + * + * @param {String} string that will be modifed + * @param {*} object of json that would be replaced in string + * @returns + */ +async function substituteStringByObject (string, object) { + for (var key in object) { + if (!object.hasOwnProperty(key)) { + continue; + } + string = string.replace(new RegExp("{{" + key + "}}", "g"), object[key]); + } + return string +} + module.exports = { getParamFromCliArgs, promptUser, @@ -1417,5 +1433,6 @@ module.exports = { updateChallenge, createChallengeResource, extractWorkPeriods, - getUserByHandle + getUserByHandle, + substituteStringByObject } diff --git a/src/services/TeamService.js b/src/services/TeamService.js index 08a19fa3..2f9b32c5 100644 --- a/src/services/TeamService.js +++ b/src/services/TeamService.js @@ -325,6 +325,9 @@ async function sendEmail (currentUser, data) { subject: data.subject || template.subject, body: data.body || template.body } + for(var key in subjectBody) { + subjectBody[key] = await helper.substituteStringByObject(subjectBody[key], data.data) + } const emailData = { // override template if coming data already have the 'from' address from: data.from || template.from,