diff --git a/.circleci/config.yml b/.circleci/config.yml index e6268124..d634f7e6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -68,6 +68,7 @@ workflows: branches: only: - dev + - change-validatations-in-job-jc # Production builds are exectuted only on tagged commits to the # master branch. diff --git a/README.md b/README.md index d9481f21..287bf7cb 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,9 @@ tc-taas-es-processor | [2021-04-09T21:20:19.035Z] app INFO : Starting kafka consumer tc-taas-es-processor | 2021-04-09T21:20:21.292Z INFO no-kafka-client Joined group taas-es-processor generationId 1 as no-kafka-client-076538fc-60dd-4ca4-a2b9-520bdf73bc9e tc-taas-es-processor | 2021-04-09T21:20:21.293Z INFO no-kafka-client Elected as group leader + tc-taas-es-processor | 2021-04-09T21:20:21.449Z DEBUG no-kafka-client Subscribed to taas.role.update:0 offset 0 leader kafka:9093 + tc-taas-es-processor | 2021-04-09T21:20:21.450Z DEBUG no-kafka-client Subscribed to taas.role.delete:0 offset 0 leader kafka:9093 + tc-taas-es-processor | 2021-04-09T21:20:21.451Z DEBUG no-kafka-client Subscribed to taas.role.requested:0 offset 0 leader kafka:9093 tc-taas-es-processor | 2021-04-09T21:20:21.452Z DEBUG no-kafka-client Subscribed to taas.jobcandidate.create:0 offset 0 leader kafka:9093 tc-taas-es-processor | 2021-04-09T21:20:21.455Z DEBUG no-kafka-client Subscribed to taas.job.create:0 offset 0 leader kafka:9093 tc-taas-es-processor | 2021-04-09T21:20:21.456Z DEBUG no-kafka-client Subscribed to taas.resourcebooking.delete:0 offset 0 leader kafka:9093 @@ -100,10 +103,11 @@ tc-taas-es-processor | 2021-04-09T21:20:21.469Z DEBUG no-kafka-client Subscribed to taas.workperiodpayment.update:0 offset 0 leader kafka:9093 tc-taas-es-processor | 2021-04-09T21:20:21.470Z DEBUG no-kafka-client Subscribed to taas.workperiodpayment.delete:0 offset 0 leader kafka:9093 tc-taas-es-processor | 2021-04-09T21:20:21.471Z DEBUG no-kafka-client Subscribed to taas.workperiodpayment.create:0 offset 0 leader kafka:9093 + tc-taas-es-processor | 2021-04-09T21:20:21.472Z DEBUG no-kafka-client Subscribed to taas.action.retry:0 offset 0 leader kafka:9093 tc-taas-es-processor | 2021-04-09T21:20:21.473Z DEBUG no-kafka-client Subscribed to taas.job.update:0 offset 0 leader kafka:9093 tc-taas-es-processor | 2021-04-09T21:20:21.474Z DEBUG no-kafka-client Subscribed to taas.resourcebooking.update:0 offset 0 leader kafka:9093 tc-taas-es-processor | [2021-04-09T21:20:21.475Z] app INFO : Initialized....... - tc-taas-es-processor | [2021-04-09T21:20:21.479Z] app INFO : taas.job.create,taas.job.update,taas.job.delete,taas.jobcandidate.create,taas.jobcandidate.update,taas.jobcandidate.delete,taas.resourcebooking.create,taas.resourcebooking.update,taas.resourcebooking.delete,taas.workperiod.create,taas.workperiod.update,taas.workperiod.delete,taas.workperiodpayment.create,taas.workperiodpayment.update,taas.workperiodpayment.delete + tc-taas-es-processor | [2021-04-09T21:20:21.479Z] app INFO : common.error.reporting,taas.job.create,taas.job.update,taas.job.delete,taas.jobcandidate.create,taas.jobcandidate.update,taas.jobcandidate.delete,taas.resourcebooking.create,taas.resourcebooking.update,taas.resourcebooking.delete,taas.workperiod.create,taas.workperiod.update,taas.workperiod.delete,taas.workperiodpayment.create,taas.workperiodpayment.update,taas.interview.requested,taas.interview.update,taas.interview.bulkUpdate,taas.role.requested,taas.role.update,taas.role.delete,taas.action.retry tc-taas-es-processor | [2021-04-09T21:20:21.480Z] app INFO : Kick Start....... tc-taas-es-processor | ********** Topcoder Health Check DropIn listening on port 3001 tc-taas-es-processor | Topcoder Health Check DropIn started and ready to roll @@ -173,6 +177,19 @@ To be able to change and test `taas-es-processor` locally you can follow the nex 2. Run `taas-es-processor` separately from the source code. As `npm run services:up` already run all the dependencies for both `taas-apis` and for `taas-es-processor`. The only thing you need to do for running `taas-es-processor` locally is clone the [taas-es-processor](https://github.com/topcoder-platform/taas-es-processor) repository and inside `taas-es-processor` folder run: - `nvm use` - to use correct Node version - `npm run install` + - Create `.env` file with the next environment variables. Values for **Auth0 config** should be shared with you on the forum.
+ + ```bash + # Auth0 config + AUTH0_URL= + AUTH0_AUDIENCE= + AUTH0_CLIENT_ID= + AUTH0_CLIENT_SECRET= + ``` + + - Values from this file would be automatically used by many `npm` commands. + - ⚠️ Never commit this file or its copy to the repository! + - `npm run start` ## NPM Commands @@ -194,7 +211,7 @@ To be able to change and test `taas-es-processor` locally you can follow the nex | `npm run index:jobs ` | Indexes job data from db into ES, if jobId is not given all data is indexed. Use `-- --force` flag to skip confirmation | | `npm run index:job-candidates ` | Indexes job candidate data from db into ES, if jobCandidateId is not given all data is indexed. Use `-- --force` flag to skip confirmation | | `npm run index:resource-bookings ` | Indexes resource bookings data from db into ES, if resourceBookingsId is not given all data is indexed. Use `-- --force` flag to skip confirmation | -| `npm run index:work-periods ` | Indexes work periods data from db into ES, if workPeriodId is not given all data is indexed. Use `-- --force` flag to skip confirmation | +| `npm run index:roles ` | Indexes roles data from db into ES, if roleId is not given all data is indexed. Use `-- --force` flag to skip confirmation | | `npm run services:up` | Start services via docker-compose for local development. | | `npm run services:down` | Stop services via docker-compose for local development. | | `npm run services:logs -- -f ` | View logs of some service inside docker-compose. | @@ -203,6 +220,7 @@ To be able to change and test `taas-es-processor` locally you can follow the nex | `npm run cov` | Code Coverage Report. | | `npm run migrate` | Run any migration files which haven't run yet. | | `npm run migrate:undo` | Revert most recent migration. | +| `npm run demo-payment-scheduler` | Create 1000 Work Periods Payment records in with status "scheduled" and various "amount" | ## Import and Export data diff --git a/app-constants.js b/app-constants.js index 534e46de..83dcbdb2 100644 --- a/app-constants.js +++ b/app-constants.js @@ -34,6 +34,8 @@ const Scopes = { ALL_RESOURCE_BOOKING: 'all:taas-resourceBookings', // taas-team READ_TAAS_TEAM: 'read:taas-teams', + CREATE_ROLE_SEARCH_REQUEST: 'create:taas-roleSearchRequests', + CREATE_TAAS_TEAM: 'create:taas-teams', // work period READ_WORK_PERIOD: 'read:taas-workPeriods', CREATE_WORK_PERIOD: 'create:taas-workPeriods', @@ -49,7 +51,13 @@ const Scopes = { READ_INTERVIEW: 'read:taas-interviews', CREATE_INTERVIEW: 'create:taas-interviews', UPDATE_INTERVIEW: 'update:taas-interviews', - ALL_INTERVIEW: 'all:taas-interviews' + ALL_INTERVIEW: 'all:taas-interviews', + // role + READ_ROLE: 'read:taas-roles', + CREATE_ROLE: 'create:taas-roles', + UPDATE_ROLE: 'update:taas-roles', + DELETE_ROLE: 'delete:taas-roles', + ALL_ROLE: 'all:taas-roles' } // Interview related constants @@ -76,16 +84,85 @@ const ChallengeStatus = { COMPLETED: 'Completed' } +/** + * Aggregate payment status for Work Period which is determined + * based on the payments the Work Period has using `PaymentStatusRules` + */ +const AggregatePaymentStatus = { + PENDING: 'pending', + IN_PROGRESS: 'in-progress', + PARTIALLY_COMPLETED: 'partially-completed', + COMPLETED: 'completed', + NO_DAYS: 'no-days' +} + +/** + * `WorkPeriodPayment.status` - possible values + */ +const WorkPeriodPaymentStatus = { + COMPLETED: 'completed', + SCHEDULED: 'scheduled', + IN_PROGRESS: 'in-progress', + FAILED: 'failed', + CANCELLED: 'cancelled' +} + +/** + * The rules how to determine WorkPeriod.paymentStatus based on the payments + * + * The top rule has priority over the bottom rules. + */ +const PaymentStatusRules = [ + { paymentStatus: AggregatePaymentStatus.NO_DAYS, condition: { daysWorked: 0 } }, + { paymentStatus: AggregatePaymentStatus.IN_PROGRESS, condition: { hasWorkPeriodPaymentStatus: [WorkPeriodPaymentStatus.SCHEDULED, WorkPeriodPaymentStatus.IN_PROGRESS] } }, + { paymentStatus: AggregatePaymentStatus.COMPLETED, condition: { hasWorkPeriodPaymentStatus: [WorkPeriodPaymentStatus.COMPLETED], hasDueDays: false } }, + { paymentStatus: AggregatePaymentStatus.PARTIALLY_COMPLETED, condition: { hasWorkPeriodPaymentStatus: [WorkPeriodPaymentStatus.COMPLETED], hasDueDays: true } }, + { paymentStatus: AggregatePaymentStatus.PENDING, condition: { hasDueDays: true } } +] + +/** + * The WorkPeriodPayment.status values which we take into account when calculate + * aggregate values inside WorkPeriod: + * - daysPaid + * - paymentTotal + * - paymentStatus + */ +const ActiveWorkPeriodPaymentStatuses = [ + WorkPeriodPaymentStatus.SCHEDULED, + WorkPeriodPaymentStatus.IN_PROGRESS, + WorkPeriodPaymentStatus.COMPLETED +] + +const WorkPeriodPaymentUpdateStatus = { + SCHEDULED: 'scheduled', + CANCELLED: 'cancelled' +} + const PaymentProcessingSwitch = { ON: 'ON', OFF: 'OFF' } +const PaymentSchedulerStatus = { + START_PROCESS: 'start-process', + CREATE_CHALLENGE: 'create-challenge', + ASSIGN_MEMBER: 'assign-member', + ACTIVATE_CHALLENGE: 'activate-challenge', + GET_USER_ID: 'get-userId', + CLOSE_CHALLENGE: 'close-challenge' +} + module.exports = { UserRoles, FullManagePermissionRoles, Scopes, Interviews, ChallengeStatus, - PaymentProcessingSwitch + AggregatePaymentStatus, + WorkPeriodPaymentStatus, + WorkPeriodPaymentUpdateStatus, + PaymentSchedulerStatus, + PaymentProcessingSwitch, + PaymentStatusRules, + ActiveWorkPeriodPaymentStatuses } diff --git a/app.js b/app.js index 7f3d7d85..e6d79c69 100644 --- a/app.js +++ b/app.js @@ -13,6 +13,7 @@ const schedule = require('node-schedule') const logger = require('./src/common/logger') const eventHandlers = require('./src/eventHandlers') const interviewService = require('./src/services/InterviewService') +const { processScheduler } = require('./src/services/PaymentSchedulerService') // setup express app const app = express() @@ -97,6 +98,9 @@ const server = app.listen(app.get('port'), () => { eventHandlers.init() // schedule updateCompletedInterviews to run every hour schedule.scheduleJob('0 0 * * * *', interviewService.updateCompletedInterviews) + + // schedule payment processing + schedule.scheduleJob(config.PAYMENT_PROCESSING.CRON, processScheduler) }) if (process.env.NODE_ENV === 'test') { diff --git a/config/default.js b/config/default.js index f7eddb93..726c40fa 100644 --- a/config/default.js +++ b/config/default.js @@ -40,7 +40,7 @@ module.exports = { TOPCODER_USERS_API: process.env.TOPCODER_USERS_API || 'https://api.topcoder-dev.com/v3/users', // the api to find topcoder members - TOPCODER_MEMBERS_API: process.env.TOPCODER_MEMBERS_API || 'https://api.topcoder-dev.com/v3/members', + TOPCODER_MEMBERS_API: process.env.TOPCODER_MEMBERS_API || 'https://api.topcoder-dev.com/v5/members', // rate limit of requests to user api MAX_PARALLEL_REQUEST_TOPCODER_USERS_API: process.env.MAX_PARALLEL_REQUEST_TOPCODER_USERS_API || 100, @@ -76,8 +76,8 @@ module.exports = { ES_INDEX_JOB_CANDIDATE: process.env.ES_INDEX_JOB_CANDIDATE || 'job_candidate', // the resource booking index ES_INDEX_RESOURCE_BOOKING: process.env.ES_INDEX_RESOURCE_BOOKING || 'resource_booking', - // the work period index - ES_INDEX_WORK_PERIOD: process.env.ES_INDEX_WORK_PERIOD || 'work_period', + // the role index + ES_INDEX_ROLE: process.env.ES_INDEX_ROLE || 'role', // the max bulk size in MB for ES indexing MAX_BULK_REQUEST_SIZE_MB: process.env.MAX_BULK_REQUEST_SIZE_MB || 20, @@ -133,6 +133,15 @@ module.exports = { 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', + // topics for role service + // the create role entity Kafka message topic + TAAS_ROLE_CREATE_TOPIC: process.env.TAAS_ROLE_CREATE_TOPIC || 'taas.role.requested', + // the update role entity Kafka message topic + TAAS_ROLE_UPDATE_TOPIC: process.env.TAAS_ROLE_UPDATE_TOPIC || 'taas.role.update', + // the delete role entity Kafka message topic + TAAS_ROLE_DELETE_TOPIC: process.env.TAAS_ROLE_DELETE_TOPIC || 'taas.role.delete', + // special kafka topics + TAAS_ACTION_RETRY_TOPIC: process.env.TAAS_ACTION_RETRY_TOPIC || 'taas.action.retry', // the Kafka message topic for sending email EMAIL_TOPIC: process.env.EMAIL_TOPIC || 'external.action.email', @@ -163,6 +172,45 @@ module.exports = { TYPE_ID_TASK: process.env.TYPE_ID_TASK || 'ecd58c69-238f-43a4-a4bb-d172719b9f31', DEFAULT_TIMELINE_TEMPLATE_ID: process.env.DEFAULT_TIMELINE_TEMPLATE_ID || '53a307ce-b4b3-4d6f-b9a1-3741a58f77e6', DEFAULT_TRACK_ID: process.env.DEFAULT_TRACK_ID || '9b6fc876-f4d9-4ccb-9dfd-419247628825', - - PAYMENT_PROCESSING_SWITCH: process.env.PAYMENT_PROCESSING_SWITCH || 'OFF' + // the minimum matching rate when searching roles by skills + ROLE_MATCHING_RATE: process.env.ROLE_MATCHING_RATE || 0.70, + // member groups representing Wipro or TopCoder employee + INTERNAL_MEMBER_GROUPS: process.env.INTERNAL_MEMBER_GROUPS || ['20000000', '20000001', '20000003', '20000010', '20000015'], + // Topcoder skills cache time in minutes + TOPCODER_SKILLS_CACHE_TIME: process.env.TOPCODER_SKILLS_CACHE_TIME || 60, + // payment scheduler config + PAYMENT_PROCESSING: { + // switch off actual API calls in Payment Scheduler + SWITCH: process.env.PAYMENT_PROCESSING_SWITCH || 'OFF', + // the payment scheduler cron config + CRON: process.env.PAYMENT_PROCESSING_CRON || '0 */5 * * * *', + // the number of records processed by one time + BATCH_SIZE: parseInt(process.env.PAYMENT_PROCESSING_BATCH_SIZE || 50), + // in-progress expired to determine whether a record has been processed abnormally, moment duration format + IN_PROGRESS_EXPIRED: process.env.IN_PROGRESS_EXPIRED || 'PT1H', + // the number of max retry config + MAX_RETRY_COUNT: parseInt(process.env.PAYMENT_PROCESSING_MAX_RETRY_COUNT || 10), + // the time of retry base delay, unit: ms + RETRY_BASE_DELAY: parseInt(process.env.PAYMENT_PROCESSING_RETRY_BASE_DELAY || 100), + // the time of retry max delay, unit: ms + RETRY_MAX_DELAY: parseInt(process.env.PAYMENT_PROCESSING_RETRY_MAX_DELAY || 10000), + // the max time of one request, unit: ms + PER_REQUEST_MAX_TIME: parseInt(process.env.PAYMENT_PROCESSING_PER_REQUEST_MAX_TIME || 30000), + // the max time of one payment record, unit: ms + PER_PAYMENT_MAX_TIME: parseInt(process.env.PAYMENT_PROCESSING_PER_PAYMENT_MAX_TIME || 60000), + // the max records of payment of a minute + PER_MINUTE_PAYMENT_MAX_COUNT: parseInt(process.env.PAYMENT_PROCESSING_PER_MINUTE_PAYMENT_MAX_COUNT || 12), + // the max requests of challenge of a minute + PER_MINUTE_CHALLENGE_REQUEST_MAX_COUNT: parseInt(process.env.PAYMENT_PROCESSING_PER_MINUTE_CHALLENGE_REQUEST_MAX_COUNT || 60), + // the max requests of resource of a minute + PER_MINUTE_RESOURCE_REQUEST_MAX_COUNT: parseInt(process.env.PAYMENT_PROCESSING_PER_MINUTE_CHALLENGE_REQUEST_MAX_COUNT || 20), + // the default step fix delay, unit: ms + FIX_DELAY_STEP: parseInt(process.env.PAYMENT_PROCESSING_FIX_DELAY_STEP || 500), + // the fix delay after step of create challenge, unit: ms + FIX_DELAY_STEP_CREATE_CHALLENGE: parseInt(process.env.PAYMENT_PROCESSING_FIX_DELAY_STEP_CREATE_CHALLENGE || process.env.PAYMENT_PROCESSING_FIX_DELAY_STEP || 500), + // the fix delay after step of assign member, unit: ms + FIX_DELAY_STEP_ASSIGN_MEMBER: parseInt(process.env.PAYMENT_PROCESSING_FIX_DELAY_STEP_ASSIGN_MEMBER || process.env.PAYMENT_PROCESSING_FIX_DELAY_STEP || 500), + // the fix delay after step of activate challenge, unit: ms + FIX_DELAY_STEP_ACTIVATE_CHALLENGE: parseInt(process.env.PAYMENT_PROCESSING_FIX_DELAY_STEP_ACTIVATE_CHALLENGE || process.env.PAYMENT_PROCESSING_FIX_DELAY_STEP || 500) + } } diff --git a/data/demo-data.json b/data/demo-data.json index 2c7a94a7..ce9f2456 100644 --- a/data/demo-data.json +++ b/data/demo-data.json @@ -1,2394 +1,7745 @@ { - "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": "selected", - "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 - other", - "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": "placed", - "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": "placed", - "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": "placed", - "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": "placed", - "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": "placed", - "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": "placed", - "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": "interview", - "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", - "calendarEventId": "dummyId", - "templateUrl": "interview-30", - "round": 1, - "duration": 30, - "hostName": "John Doe", - "hostEmail": "testuserforemail@yopmail.com", - "guestNames": ["Customer Test"], - "guestEmails": ["testcustomer@yopmail.com"], - "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", - "calendarEventId": "dummyId", - "templateUrl": "interview-30", - "round": 2, - "duration": 30, - "hostName": "John Doe", - "hostEmail": "testuserforemail@yopmail.com", - "guestNames": ["Customer Test"], - "guestEmails": ["testcustomer@yopmail.com"], - "status": "Scheduling", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T08:50:15.109Z", - "updatedAt": "2021-04-14T08:50:15.109Z" + "Job": [ + { + "id": "36dad9f2-98ed-4d3a-9ea7-2cd3d0f8a51a", + "projectId": 111, + "externalId": "88774632", + "description": "Dummy Description", + "title": "Dummy title - at most 64 characters", + "startDate": "2020-09-27T00:00:00.000Z", + "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, + "minSalary": 100, + "maxSalary": 200, + "hoursPerWeek": 20, + "jobLocation": "Any location", + "jobTimezone": "GMT", + "currency": "USD", + "roleIds": null, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-09T21:21:10.394Z", + "updatedAt": "2021-05-09T21:21:14.010Z" + }, + { + "id": "728ff056-63f6-4730-8a9f-3074acad8479", + "projectId": 111, + "externalId": "1212", + "description": "Dummy Description", + "title": "Dummy title - at most 64 characters", + "startDate": "2020-09-27T04:17:23.131Z", + "duration": 1, + "numPositions": 10, + "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, + "minSalary": 100, + "maxSalary": 200, + "hoursPerWeek": 20, + "jobLocation": "Any location", + "jobTimezone": "GMT", + "currency": "USD", + "roleIds": null, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-09T21:11:26.934Z", + "updatedAt": "2021-05-09T21:14:05.495Z" + }, + { + "id": "a8adb1f8-a6ee-48b1-8661-33bd851b726e", + "projectId": 111, + "externalId": "1212", + "description": "Dummy Description", + "title": "Dummy title - at most 64 characters", + "startDate": "2020-09-27T04:17:23.131Z", + "duration": 1, + "numPositions": 7, + "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, + "minSalary": 100, + "maxSalary": 200, + "hoursPerWeek": 20, + "jobLocation": "Any location", + "jobTimezone": "GMT", + "currency": "USD", + "roleIds": null, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-09T21:23:18.595Z", + "updatedAt": "2021-05-09T21:23:23.474Z" + }, + { + "id": "b28f4e67-324f-4ada-a23a-c27499053ed4", + "projectId": 111, + "externalId": "1212", + "description": "Dummy Description", + "title": "Dummy title - at most 64 characters", + "startDate": "2020-09-27T04:17:23.131Z", + "duration": 1, + "numPositions": 5, + "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, + "minSalary": 100, + "maxSalary": 200, + "hoursPerWeek": 20, + "jobLocation": "Any location", + "jobTimezone": "GMT", + "currency": "USD", + "roleIds": null, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-09T21:12:09.293Z", + "updatedAt": "2021-05-09T21:14:59.157Z" + }, + { + "id": "ff76b81d-f49b-4019-b50e-c7932a818f19", + "projectId": 17232, + "externalId": "51974177", + "description": "Welcome to the “Design Practice Challenge - Design a User Profile Screen”!\nThis challenge is created specifically for you, our new member, to learn/practice and get started with Design Competitions at Topcoder by participating and submitting to this very simple challenge where we are asking you to create a single design screen that shows a user’s profile information. You are free to create the design using design tools like Adobe XD, Figma, Sketch, or Photoshop!\nMake sure you register for the challenge and then read more details below and let us know if you have any doubts or questions in The Challenge Forum! Topcoder Design competitions provide coverage for a full range of design needs, from responsive and mobile application user experience to marketing collateral creation and support. To be specific, there are seven types of design challenges that we offer in the Design track: Application Front End Design Web Design Widget or Mobile Screen Design Wireframes Print/Presentation Design First2Finish Idea Generation\nYou must ensure your design submission addresses all the requirements mentioned in the challenge specification, and ensure your design follows the best practice for the specific interface or devices.\nTopcoder design challenges usually offer cash prizes for the three top winners and five checkpoint winners, and sometimes beyond that for special challenges like RUX (five top winners and eight rolling checkpoint winners) or LUX (eight top winners and eight rolling checkpoint winners).\nIn this practice challenge, we bring a basic Design Challenge for you so that you can adapt and get accustomed to the challenge phases.\nEach design challenge goes through the following time period phases: Registration - Duration in which you can register for the challenge 1st Round/Checkpoint Submission - Duration in which you can submit according to round one requirements Checkpoint Screening - Duration in which a Topcoder Screener will check your checkpoint design submission Checkpoint Review - Duration in which DRB and client will review submissions from round one and provide feedback 2nd Round/Final Submission - Duration in which all first-round submitters can submit design work after applying the checkpoint feedback received from DRB and Client\nAfter your final submission, the following phases take place: Final Screening, Final Review, Final Fixes, and Approval.\nThe majority of design challenges at Topcoder usually use the two-round format unless it is a one-round type challenge such as a Design First2Finish, Rapid User Experience (RUX), or Live User Experience (LUX)\nFor more help, we have a Detailed Guide about how to compete in a Design Challenge or check out This Video.\nMake sure you register for the challenge and then read more details below and let us know if you have any doubts or questions in The Challenge Forum!\nOVERVIEW Create a single UI Design Screen for any web device for a user’s profile.\nCHALLENGE REQUIREMENTS Please make sure to create and include the following requests in the User Profile screen: Name and Profile Picture such that the audience can easily recognize the user. About to give some brief information about the user. Skills and Specialization to emphasize a user’s strength. Profile links linking to user’s other important and relevant websites (Facebook, Twitter, Dribbble, Github, etc) You can check a sample of Topcoder existing user profiles to get an idea Here Feel free to use and copy content from Topcoder’s Profile Page and create your own version for the user profile screen Quotes? Hobbies? Interest? Etc? Feel free to add as many details as you want to make your design better!\nTARGET AUDIENCE Topcoder members that want to know about you and your history at Topcoder Potential clients that want to know about your skills and achievement at Topcoder before they hire you\nJUDGING CRITERIA SCORE Creativity: 8 1: barely new ideas Aesthetics: 10 1: low-fidelity design, wireframe or plain sketch Exploration: 7 1: strictly follow an existing reference or production guideline Branding: 10 1: don’t care at all about the branding just functionality\nBRANDING GUIDELINES Open to Designers (Font, Colors, Style, etc)\nTARGET DEVICES Web App: Minimum 1440px width with height adjusted accordingly\nFINAL SUBMISSION GUIDELINES All original source files created in Adobe XD, Adobe Photoshop, Figma, or Sketch Marvel Prototype: Upload your screens to Marvel App Ask for Marvel Prototype access in the challenge forum Include your Marvel App URL as a text file in your final submission. Label the file as “MarvelApp URL”", + "title": "Job Taas", + "startDate": "2021-03-08T15:00:00.000Z", + "duration": 4, + "numPositions": 2, + "resourceType": "software-developer", + "rateType": "hourly", + "workload": "full-time", + "skills": [ + "4cb4c2c3-f8af-49e4-8b67-6318d5d1d329", + "ad43a3f3-413f-4bfe-9703-28afad49b116", + "d67a5932-3f8d-4a5a-88cf-d7b706aae2d5", + "b4e1d1d2-794f-486d-8629-b9d7f26af5c6", + "0b104b7c-0792-4118-8bc7-a274e9ee19e3" + ], + "status": "closed", + "isApplicationPageActive": false, + "minSalary": null, + "maxSalary": null, + "hoursPerWeek": null, + "jobLocation": null, + "jobTimezone": null, + "currency": null, + "roleIds": null, + "createdBy": "fe38eed1-af73-41fd-85a2-ac4da1ff09a3", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-03-19T08:11:26.966Z", + "updatedAt": "2021-03-23T04:35:03.686Z" + }, + { + "id": "ff753824-919c-4712-9197-49d7edaa4db7", + "projectId": 17430, + "externalId": "54439701", + "description": null, + "title": "job-Thu May 27 2021 11:58:55 GMT+0530 (India Standard Time)", + "startDate": null, + "duration": null, + "numPositions": 1, + "resourceType": null, + "rateType": null, + "workload": null, + "skills": [ + "5843b329-433c-4a17-a5b2-570caaa34baf" + ], + "status": "sourcing", + "isApplicationPageActive": false, + "minSalary": null, + "maxSalary": null, + "hoursPerWeek": null, + "jobLocation": null, + "jobTimezone": null, + "currency": null, + "roleIds": null, + "createdBy": "71c5e6a8-51d9-4fb5-91ce-d974642531af", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-27T06:28:58.039Z", + "updatedAt": "2021-05-27T06:29:06.204Z" + }, + { + "id": "ff3feeae-d4f7-457c-bff7-215be5efe2b8", + "projectId": 16781, + "externalId": "0", + "description": "Designer", + "title": "Designer", + "startDate": "2020-12-14T12:41:13.019Z", + "duration": null, + "numPositions": 5, + "resourceType": "desiger", + "rateType": "hourly", + "workload": "full-time", + "skills": [], + "status": "assigned", + "isApplicationPageActive": false, + "minSalary": null, + "maxSalary": null, + "hoursPerWeek": null, + "jobLocation": null, + "jobTimezone": null, + "currency": null, + "roleIds": null, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2020-12-14T12:41:14.323Z", + "updatedAt": "2021-02-01T07:14:33.994Z" + }, + { + "id": "fefd2618-9b66-4431-9874-1d02d7a37d90", + "projectId": 17324, + "externalId": "53432162", + "description": "

Python Data Science

", + "title": "Data Scientist", + "startDate": "2021-07-06T18:30:00.000Z", + "duration": 9, + "numPositions": 2, + "resourceType": "data-scientist", + "rateType": "weekly", + "workload": "full-time", + "skills": [ + "2752d41b-1082-478b-9fd4-6396f510a130", + "bfc796ee-0c25-4838-ab23-5b007dee7672" + ], + "status": "sourcing", + "isApplicationPageActive": false, + "minSalary": null, + "maxSalary": null, + "hoursPerWeek": null, + "jobLocation": null, + "jobTimezone": null, + "currency": null, + "roleIds": null, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-13T08:51:26.517Z", + "updatedAt": "2021-05-13T08:52:02.354Z" + }, + { + "id": "feef8b66-989d-4ec7-bdb0-59ca05c95003", + "projectId": 17103, + "externalId": null, + "description": "# Heading\n\n**bold**\n*italic*\n~~crossed~~\n\n- - -\n\n> test\n\n* 1\n * 2\n\n1. 2\n 1. 3\n\n* [ ] asdfsdf\n\n
\n| 1 | 1 |\n| --- | --- |\n| 2 | 2 |\n\n![test](https://user-images.githubusercontent.com/146016/108334984-235ce880-71db-11eb-8643-263675197b2c.png)\n[https://user-images.githubusercontent.com/146016/108334984-235ce880-71db-11eb-8643-263675197b2c.png](https://user-images.githubusercontent.com/146016/108334984-235ce880-71db-11eb-8643-263675197b2c.png)\n`asdfsadfasdf`\n\n
\n```\nasdsdf\n```", + "title": "1", + "startDate": null, + "duration": 1, + "numPositions": 10, + "resourceType": "software-developer", + "rateType": "weekly", + "workload": "full-time", + "skills": [ + "24ba39a5-0b75-41f3-9a33-4f8063fcd828" + ], + "status": "sourcing", + "isApplicationPageActive": false, + "minSalary": null, + "maxSalary": null, + "hoursPerWeek": null, + "jobLocation": null, + "jobTimezone": null, + "currency": null, + "roleIds": null, + "createdBy": "077fd578-7463-457f-b6ef-22c02178d7f5", + "updatedBy": null, + "createdAt": "2021-02-21T09:26:04.620Z", + "updatedAt": "2021-02-21T09:26:04.620Z" + }, + { + "id": "fed687e1-4257-48bb-806c-38712f9bf14f", + "projectId": 16870, + "externalId": "1212", + "description": "Dummy Description", + "title": "Dummy title - at most 64 characters", + "startDate": "2020-09-27T04:17:23.131Z", + "duration": 2, + "numPositions": 13, + "resourceType": "Dummy Resource Type", + "rateType": "monthly", + "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": "sourcing", + "isApplicationPageActive": false, + "minSalary": null, + "maxSalary": null, + "hoursPerWeek": null, + "jobLocation": null, + "jobTimezone": null, + "currency": null, + "roleIds": null, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": "077fd578-7463-457f-b6ef-22c02178d7f5", + "createdAt": "2021-02-04T10:25:20.358Z", + "updatedAt": "2021-02-18T13:48:13.326Z" + }, + { + "id": "fed14737-9ea2-4d90-b26c-781ad689b4ae", + "projectId": 16949, + "externalId": null, + "description": null, + "title": "Test", + "startDate": null, + "duration": null, + "numPositions": 1, + "resourceType": null, + "rateType": "weekly", + "workload": "full-time", + "skills": [], + "status": "sourcing", + "isApplicationPageActive": false, + "minSalary": null, + "maxSalary": null, + "hoursPerWeek": null, + "jobLocation": null, + "jobTimezone": null, + "currency": null, + "roleIds": null, + "createdBy": "0bcb0d86-09bb-410a-b2b1-fba90d1a7699", + "updatedBy": "0bcb0d86-09bb-410a-b2b1-fba90d1a7699", + "createdAt": "2021-01-31T20:29:34.581Z", + "updatedAt": "2021-01-31T22:00:51.803Z" + }, + { + "id": "fe8da845-5313-496f-b859-9824bd06a0db", + "projectId": 16870, + "externalId": "1212", + "description": null, + "title": "Max Dummy title - at most 64 characters", + "startDate": null, + "duration": 3, + "numPositions": 13, + "resourceType": null, + "rateType": null, + "workload": null, + "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, + "minSalary": null, + "maxSalary": null, + "hoursPerWeek": null, + "jobLocation": null, + "jobTimezone": null, + "currency": null, + "roleIds": null, + "createdBy": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "updatedBy": "077fd578-7463-457f-b6ef-22c02178d7f5", + "createdAt": "2021-01-11T08:29:29.153Z", + "updatedAt": "2021-02-18T13:48:30.718Z" + }, + { + "id": "fe600350-0a6d-4dac-922f-a6a7d285daa1", + "projectId": 17290, + "externalId": "52700649", + "description": "test", + "title": "PICACHUI APR 30 JOB 5", + "startDate": "2021-04-30T18:30:00.000Z", + "duration": 5, + "numPositions": 5, + "resourceType": "software-developer", + "rateType": "weekly", + "workload": "full-time", + "skills": [ + "ad43a3f3-413f-4bfe-9703-28afad49b116" + ], + "status": "in-review", + "isApplicationPageActive": false, + "minSalary": null, + "maxSalary": null, + "hoursPerWeek": null, + "jobLocation": null, + "jobTimezone": null, + "currency": null, + "roleIds": null, + "createdBy": "3f64739e-10bf-42ca-8314-8aea0245cd0f", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-04-30T07:56:22.940Z", + "updatedAt": "2021-04-30T08:06:25.212Z" + }, + { + "id": "fe539bef-9119-4a8c-b7b0-915e7e3a3ba3", + "projectId": 16870, + "externalId": "1212", + "description": "Dummy Description", + "title": "Dummy title - at most 64 characters", + "startDate": "2020-09-27T04:17:23.131Z", + "duration": null, + "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": "sourcing", + "isApplicationPageActive": false, + "minSalary": null, + "maxSalary": null, + "hoursPerWeek": null, + "jobLocation": null, + "jobTimezone": null, + "currency": null, + "roleIds": null, + "createdBy": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "updatedBy": null, + "createdAt": "2021-01-07T19:42:10.255Z", + "updatedAt": "2021-05-30T11:14:08.434Z" + }, + { + "id": "fe481d1c-cf87-49c1-9370-695f9f754041", + "projectId": 16762, + "externalId": "0", + "description": "Designer #1", + "title": "Designer #1", + "startDate": "2020-09-27T04:17:23.131Z", + "duration": null, + "numPositions": 13, + "resourceType": "Dummy Resource Type", + "rateType": "hourly", + "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, + "minSalary": null, + "maxSalary": null, + "hoursPerWeek": null, + "jobLocation": null, + "jobTimezone": null, + "currency": null, + "roleIds": null, + "createdBy": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "updatedBy": null, + "createdAt": "2020-12-08T15:56:18.707Z", + "updatedAt": "2021-05-30T11:14:08.434Z" + }, + { + "id": "fe270791-bc24-4f6a-8c1b-b897f5d97d2f", + "projectId": 16899, + "externalId": null, + "description": "Software Developer Full time", + "title": "Software Developer", + "startDate": null, + "duration": null, + "numPositions": 1, + "resourceType": "software-developer", + "rateType": "weekly", + "workload": "full-time", + "skills": [ + "e2b8acc2-881f-45a6-8321-489976b1db21", + "4fce6ced-3610-443c-92eb-3f6d76b34f5c", + "5c6c79ee-a8fe-4ec2-b9df-813bd67df413", + "24ba39a5-0b75-41f3-9a33-4f8063fcd828", + "4cb4c2c3-f8af-49e4-8b67-6318d5d1d329", + "1fd02aad-e08a-4669-9ffd-181468fea694" + ], + "status": "sourcing", + "isApplicationPageActive": false, + "minSalary": null, + "maxSalary": null, + "hoursPerWeek": null, + "jobLocation": null, + "jobTimezone": null, + "currency": null, + "roleIds": null, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": null, + "createdAt": "2021-01-12T08:57:01.987Z", + "updatedAt": "2021-05-30T11:14:08.434Z" + }, + { + "id": "fd48d96e-b0f2-43b7-8a48-f4fa194d6bc8", + "projectId": 17363, + "externalId": "54085472", + "description": "Test", + "title": "Test Job May 25", + "startDate": null, + "duration": 2, + "numPositions": 5, + "resourceType": "designer", + "rateType": "weekly", + "workload": "full-time", + "skills": [ + "24ba39a5-0b75-41f3-9a33-4f8063fcd828" + ], + "status": "in-review", + "isApplicationPageActive": false, + "minSalary": null, + "maxSalary": null, + "hoursPerWeek": null, + "jobLocation": null, + "jobTimezone": null, + "currency": null, + "roleIds": null, + "createdBy": "fe38eed1-af73-41fd-85a2-ac4da1ff09a3", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-25T11:03:00.164Z", + "updatedAt": "2021-05-27T04:48:06.194Z" + }, + { + "id": "fd13ad99-f16a-4362-9274-80f5f38895c3", + "projectId": 17300, + "externalId": "52885626", + "description": "Description", + "title": "Test Job RB 3", + "startDate": null, + "duration": 1, + "numPositions": 3, + "resourceType": "designer", + "rateType": "weekly", + "workload": "full-time", + "skills": [ + "4fce6ced-3610-443c-92eb-3f6d76b34f5c" + ], + "status": "in-review", + "isApplicationPageActive": false, + "minSalary": null, + "maxSalary": null, + "hoursPerWeek": null, + "jobLocation": null, + "jobTimezone": null, + "currency": null, + "roleIds": null, + "createdBy": "3f64739e-10bf-42ca-8314-8aea0245cd0f", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-01T09:43:13.357Z", + "updatedAt": "2021-05-01T09:44:53.411Z" + }, + { + "id": "fc5ba131-566f-46fe-8501-79c593241896", + "projectId": 16739, + "externalId": "0", + "description": "Designer", + "title": "Designer", + "startDate": "2020-12-07T09:30:37.304Z", + "duration": null, + "numPositions": 12, + "resourceType": "desiger", + "rateType": "hourly", + "workload": "full-time", + "skills": [ + "ee4c50c1-c8c3-475e-b6b6-edbd136a19d6", + "89139c80-d0a2-47c2-aa16-14589d5afd10", + "c854ab55-5922-4be1-8ecc-b3bc1f8629af", + "38471151-8513-4e04-b0fe-80331556abd9", + "8456002e-fa2d-44f0-b0e7-86b1c02b6e4c", + "9515e7ee-83b6-49d1-ba5c-6c59c5a8ef1b", + "b37a48db-f775-4e4e-b403-8ad1d234cdea", + "9f2d9127-6a2e-4506-ad76-c4ab63577b09", + "213408aa-f16f-46c8-bc57-9e569cee3f11", + "114b4ec8-805e-4c60-b351-14a955a991a9", + "afc39636-f7d7-4349-aef5-f9a76cc9e155", + "c2ac5154-6a0d-425d-9c90-9fd0af5d88a5", + "bfc796ee-0c25-4838-ab23-5b007dee7672", + "fbf792fc-0920-4b54-866a-f48c386994a0", + "63189fe0-94a9-4e2e-90f3-ef764e6a005b", + "87a8dd0f-12ea-47cd-a80d-20f47f0b7b9a", + "7a359e66-82bd-429c-8f95-8913bf00e67b" + ], + "status": "sourcing", + "isApplicationPageActive": false, + "minSalary": null, + "maxSalary": null, + "hoursPerWeek": null, + "jobLocation": null, + "jobTimezone": null, + "currency": null, + "roleIds": null, + "createdBy": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "updatedBy": null, + "createdAt": "2020-12-07T09:30:37.470Z", + "updatedAt": "2021-05-30T11:14:08.434Z" + }, + { + "id": "fc58382a-31d7-44b7-bfe5-2d671300f8d9", + "projectId": 16805, + "externalId": "1212", + "description": "QA Demo Description", + "title": "QA Demo Description", + "startDate": "2020-09-27T04:17:23.131Z", + "duration": null, + "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": "cancelled", + "isApplicationPageActive": false, + "minSalary": null, + "maxSalary": null, + "hoursPerWeek": null, + "jobLocation": null, + "jobTimezone": null, + "currency": null, + "roleIds": null, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2020-12-24T06:48:56.943Z", + "updatedAt": "2020-12-24T06:49:28.997Z" + }, + { + "id": "fc2b006d-997b-49c3-a414-59ee54a48f9f", + "projectId": 16706, + "externalId": "10003", + "description": "Dummy10003 Description", + "title": "Dummy10003 Description", + "startDate": "2020-11-28T04:17:23.131Z", + "duration": null, + "numPositions": 9, + "resourceType": "Dummy Resource Type", + "rateType": "weekly", + "workload": "full-time", + "skills": [ + "cb01fd31-e8d2-4e34-8bf3-b149705de3e1" + ], + "status": "sourcing", + "isApplicationPageActive": false, + "minSalary": null, + "maxSalary": null, + "hoursPerWeek": null, + "jobLocation": null, + "jobTimezone": null, + "currency": null, + "roleIds": null, + "createdBy": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "updatedBy": null, + "createdAt": "2020-11-20T05:30:03.014Z", + "updatedAt": "2021-05-30T11:14:08.434Z" + }, + { + "id": "fc0240f0-8c8f-40ce-a551-e83b45673098", + "projectId": 16714, + "externalId": "2227", + "description": "zapier2227 Description", + "title": "zapier2227 Description", + "startDate": "2021-01-04T04:17:23.131Z", + "duration": null, + "numPositions": 8, + "resourceType": "Dummy2227 Resource Type", + "rateType": "weekly", + "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": "sourcing", + "isApplicationPageActive": false, + "minSalary": null, + "maxSalary": null, + "hoursPerWeek": null, + "jobLocation": null, + "jobTimezone": null, + "currency": null, + "roleIds": null, + "createdBy": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "updatedBy": null, + "createdAt": "2020-12-08T13:50:26.805Z", + "updatedAt": "2021-05-30T11:14:08.434Z" + }, + { + "id": "fb8b92f6-4ffb-4ba6-8c38-c2d4a151f76b", + "projectId": 17091, + "externalId": "12312", + "description": "second Job created from api", + "title": "second Job from api", + "startDate": "2021-02-27T04:17:23.131Z", + "duration": null, + "numPositions": 12, + "resourceType": "software Developer", + "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": "sourcing", + "isApplicationPageActive": false, + "minSalary": null, + "maxSalary": null, + "hoursPerWeek": null, + "jobLocation": null, + "jobTimezone": null, + "currency": null, + "roleIds": null, + "createdBy": "71c5e6a8-51d9-4fb5-91ce-d974642531af", + "updatedBy": null, + "createdAt": "2021-02-18T09:43:11.985Z", + "updatedAt": "2021-02-18T09:43:11.985Z" + }, + { + "id": "fb2f5f9b-5874-4dcd-af94-727fc0409760", + "projectId": 16718, + "externalId": "12131", + "description": "# Awesome Editor!\n\nIt has been *released as opensource in 2018* and has\n~~continually~~\n evolved to **receive 10k GitHub ⭐️ Stars**.\n\n## Create Instance\n\nYou can create an instance with the following code and use `getHtml()` and `getMarkdown()` of the [Editor](https://github.com/nhn/tui.editor).\n
\n``` js\nconst editor = new Editor(options);\n```\n\n> See the table below for default options\n> \n> \n> \n> > More API information can be found in the document\n\n| name | type | description |\n| ---- | ---- | ----------- |\n| el | `HTMLElement` | container element |\n\n## Features\n\n* CommonMark + GFM Specifications\n * Live Preview\n * Scroll Sync\n * Auto Indent\n * Syntax Highlight\n 1. Markdown\n 2. Preview\n\n## Support Wrappers\n\n> * Wrappers\n> \n> 1. [x] React\n> 2. [x] Vue\n> 3. [ ] Ember", + "title": "aaaaa", + "startDate": "2021-02-27T04:17:23.131Z", + "duration": null, + "numPositions": 3, + "resourceType": "Dummy Resource Type", + "rateType": "hourly", + "workload": "full-time", + "skills": [], + "status": "sourcing", + "isApplicationPageActive": false, + "minSalary": null, + "maxSalary": null, + "hoursPerWeek": null, + "jobLocation": null, + "jobTimezone": null, + "currency": null, + "roleIds": null, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": "077fd578-7463-457f-b6ef-22c02178d7f5", + "createdAt": "2021-01-25T10:07:56.847Z", + "updatedAt": "2021-02-23T13:02:59.708Z" + } + ], + "JobCandidate": [ + { + "id": "b0fc417b-3f41-4c06-9f2b-8e680c3a03c6", + "jobId": "728ff056-63f6-4730-8a9f-3074acad8479", + "userId": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "status": "open", + "externalId": "300234321", + "resume": "http://example.com", + "remark": "excellent", + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:14:05.412Z", + "updatedAt": "2021-05-09T21:14:05.412Z", + "interviews": [] + }, + { + "id": "c637ecf3-8df5-42e7-80d6-daba422e371a", + "jobId": "728ff056-63f6-4730-8a9f-3074acad8479", + "userId": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "status": "open", + "externalId": "300234321", + "resume": "http://example.com", + "remark": "excellent", + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:14:41.500Z", + "updatedAt": "2021-05-09T21:14:41.500Z", + "interviews": [] + }, + { + "id": "02a622f4-7894-4ac0-a823-a952ffa1b3f3", + "jobId": "728ff056-63f6-4730-8a9f-3074acad8479", + "userId": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "status": "open", + "externalId": "300234321", + "resume": "http://example.com", + "remark": "excellent", + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:14:43.985Z", + "updatedAt": "2021-05-09T21:14:43.985Z", + "interviews": [] + }, + { + "id": "b32b4819-7bfa-49a8-851e-69cdddff8149", + "jobId": "728ff056-63f6-4730-8a9f-3074acad8479", + "userId": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "status": "open", + "externalId": "300234321", + "resume": "http://example.com", + "remark": "excellent", + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:14:46.310Z", + "updatedAt": "2021-05-09T21:14:46.310Z", + "interviews": [] + }, + { + "id": "08a67e4d-6857-492c-a3fa-cd7c64e76a69", + "jobId": "728ff056-63f6-4730-8a9f-3074acad8479", + "userId": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "status": "open", + "externalId": "300234321", + "resume": "http://example.com", + "remark": "excellent", + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:14:48.449Z", + "updatedAt": "2021-05-09T21:14:48.449Z", + "interviews": [] + }, + { + "id": "881a19de-2b0c-4bb9-b36a-4cb5e223bdb5", + "jobId": "728ff056-63f6-4730-8a9f-3074acad8479", + "userId": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "status": "open", + "externalId": "300234321", + "resume": "http://example.com", + "remark": "excellent", + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:14:50.595Z", + "updatedAt": "2021-05-09T21:14:50.595Z", + "interviews": [ + { + "id": "077aa2ca-5b60-4ad9-a965-1b37e08a5046", + "xaiId": null, + "jobCandidateId": "881a19de-2b0c-4bb9-b36a-4cb5e223bdb5", + "calendarEventId": null, + "templateUrl": "interview-30", + "templateId": null, + "templateType": null, + "title": null, + "locationDetails": null, + "duration": null, + "round": 1, + "startTimestamp": null, + "endTimestamp": null, + "hostName": null, + "hostEmail": null, + "guestNames": null, + "guestEmails": null, + "status": "Completed", + "rescheduleUrl": null, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:16:10.887Z", + "updatedAt": "2021-05-09T21:16:10.887Z", + "deletedAt": null + } + ] + }, + { + "id": "827ee401-df04-42e1-abbe-7b97ce7937ff", + "jobId": "728ff056-63f6-4730-8a9f-3074acad8479", + "userId": "95e7970f-12b4-43b7-ab35-38c34bf033c7", + "status": "open", + "externalId": "88774631", + "resume": "http://example.com", + "remark": "excellent", + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:16:34.914Z", + "updatedAt": "2021-05-09T21:16:34.914Z", + "interviews": [ + { + "id": "b1f7ba76-640f-47e2-9463-59e51b51ec60", + "xaiId": null, + "jobCandidateId": "827ee401-df04-42e1-abbe-7b97ce7937ff", + "calendarEventId": null, + "templateUrl": "interview-30", + "templateId": null, + "templateType": null, + "title": null, + "locationDetails": null, + "duration": null, + "round": 2, + "startTimestamp": null, + "endTimestamp": null, + "hostName": null, + "hostEmail": null, + "guestNames": null, + "guestEmails": null, + "status": "Scheduling", + "rescheduleUrl": null, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:17:23.517Z", + "updatedAt": "2021-05-09T21:17:23.517Z", + "deletedAt": null + }, + { + "id": "3144fa65-ea1a-4bec-81b0-7cb1c8845826", + "xaiId": null, + "jobCandidateId": "827ee401-df04-42e1-abbe-7b97ce7937ff", + "calendarEventId": null, + "templateUrl": "interview-30", + "templateId": null, + "templateType": null, + "title": null, + "locationDetails": null, + "duration": null, + "round": 1, + "startTimestamp": null, + "endTimestamp": null, + "hostName": null, + "hostEmail": null, + "guestNames": null, + "guestEmails": null, + "status": "Completed", + "rescheduleUrl": null, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:16:39.019Z", + "updatedAt": "2021-05-09T21:16:39.019Z", + "deletedAt": null + } + ] + }, + { + "id": "a4ea7bcf-5b99-4381-b99c-a9bd05d83a36", + "jobId": "36dad9f2-98ed-4d3a-9ea7-2cd3d0f8a51a", + "userId": "95e7970f-12b4-43b7-ab35-38c34bf033c7", + "status": "open", + "externalId": "88774631", + "resume": "http://example.com", + "remark": "excellent", + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:21:13.939Z", + "updatedAt": "2021-05-09T21:21:13.939Z", + "interviews": [ + { + "id": "976d23a9-5710-453f-99d9-f57a588bb610", + "xaiId": null, + "jobCandidateId": "a4ea7bcf-5b99-4381-b99c-a9bd05d83a36", + "calendarEventId": null, + "templateUrl": "interview-30", + "templateId": null, + "templateType": null, + "title": null, + "locationDetails": null, + "duration": null, + "round": 3, + "startTimestamp": null, + "endTimestamp": null, + "hostName": null, + "hostEmail": null, + "guestNames": null, + "guestEmails": null, + "status": "Scheduling", + "rescheduleUrl": null, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:21:28.713Z", + "updatedAt": "2021-05-09T21:21:28.713Z", + "deletedAt": null + }, + { + "id": "a23e1bf2-1084-4cfe-a0d8-d83bc6fec655", + "xaiId": null, + "jobCandidateId": "a4ea7bcf-5b99-4381-b99c-a9bd05d83a36", + "calendarEventId": null, + "templateUrl": "interview-30", + "templateId": null, + "templateType": null, + "title": null, + "locationDetails": null, + "duration": null, + "round": 2, + "startTimestamp": null, + "endTimestamp": null, + "hostName": null, + "hostEmail": null, + "guestNames": null, + "guestEmails": null, + "status": "Scheduling", + "rescheduleUrl": null, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:21:22.428Z", + "updatedAt": "2021-05-09T21:21:22.428Z", + "deletedAt": null + }, + { + "id": "9efd72c3-1dc7-4ce2-9869-8cca81d0adeb", + "xaiId": null, + "jobCandidateId": "a4ea7bcf-5b99-4381-b99c-a9bd05d83a36", + "calendarEventId": null, + "templateUrl": "interview-30", + "templateId": null, + "templateType": null, + "title": null, + "locationDetails": null, + "duration": null, + "round": 1, + "startTimestamp": null, + "endTimestamp": null, + "hostName": null, + "hostEmail": null, + "guestNames": null, + "guestEmails": null, + "status": "Completed", + "rescheduleUrl": null, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:21:17.346Z", + "updatedAt": "2021-05-09T21:21:17.346Z", + "deletedAt": null + } + ] + }, + { + "id": "a65b7ff1-8d79-4d6e-b29b-360473131273", + "jobId": "a8adb1f8-a6ee-48b1-8661-33bd851b726e", + "userId": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "status": "placed", + "externalId": "300234321", + "resume": "http://example.com", + "remark": "excellent", + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-09T21:23:23.420Z", + "updatedAt": "2021-05-09T21:25:46.850Z", + "interviews": [] + }, + { + "id": "0967d234-a11e-4af9-8f6c-b88d21277e15", + "jobId": "a8adb1f8-a6ee-48b1-8661-33bd851b726e", + "userId": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "status": "placed", + "externalId": "300234321", + "resume": "http://example.com", + "remark": "excellent", + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-09T21:23:41.691Z", + "updatedAt": "2021-05-09T21:25:46.861Z", + "interviews": [] + }, + { + "id": "9674672a-4bc8-454d-a0e8-cb4f1ce1411c", + "jobId": "a8adb1f8-a6ee-48b1-8661-33bd851b726e", + "userId": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "status": "placed", + "externalId": "300234321", + "resume": "http://example.com", + "remark": "excellent", + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-09T21:23:35.819Z", + "updatedAt": "2021-05-09T21:25:46.853Z", + "interviews": [] + }, + { + "id": "bab422c9-cf0f-485b-a734-dbb4e8bea4f0", + "jobId": "a8adb1f8-a6ee-48b1-8661-33bd851b726e", + "userId": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "status": "placed", + "externalId": "300234321", + "resume": "http://example.com", + "remark": "excellent", + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-09T21:23:39.914Z", + "updatedAt": "2021-05-09T21:25:46.858Z", + "interviews": [] + }, + { + "id": "292a25c4-a895-4983-a66d-fed44e57244e", + "jobId": "a8adb1f8-a6ee-48b1-8661-33bd851b726e", + "userId": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "status": "placed", + "externalId": "300234321", + "resume": "http://example.com", + "remark": "excellent", + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-09T21:23:37.962Z", + "updatedAt": "2021-05-09T21:25:46.855Z", + "interviews": [] + }, + { + "id": "68547eee-c130-42a4-bbec-dad62d7c6852", + "jobId": "a8adb1f8-a6ee-48b1-8661-33bd851b726e", + "userId": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "status": "placed", + "externalId": "300234321", + "resume": "http://example.com", + "remark": "excellent", + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-09T21:23:43.611Z", + "updatedAt": "2021-05-09T21:25:46.862Z", + "interviews": [] + }, + { + "id": "0e9996f1-2629-4115-9e23-dc57e23811b2", + "jobId": "a8adb1f8-a6ee-48b1-8661-33bd851b726e", + "userId": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "status": "placed", + "externalId": "300234321", + "resume": "http://example.com", + "remark": "excellent", + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-09T21:23:47.468Z", + "updatedAt": "2021-05-09T21:25:46.863Z", + "interviews": [] + }, + { + "id": "2cff52f7-4a2f-48b7-9fad-177745cc759b", + "jobId": "a8adb1f8-a6ee-48b1-8661-33bd851b726e", + "userId": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "status": "placed", + "externalId": "300234321", + "resume": "http://example.com", + "remark": "excellent", + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-09T21:23:45.506Z", + "updatedAt": "2021-05-09T21:25:46.864Z", + "interviews": [] + }, + { + "id": "74ed50a4-4082-48af-a2e5-33c3cc2e7f10", + "jobId": "a8adb1f8-a6ee-48b1-8661-33bd851b726e", + "userId": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "status": "placed", + "externalId": "300234321", + "resume": "http://example.com", + "remark": "excellent", + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-09T21:23:57.355Z", + "updatedAt": "2021-05-09T21:25:46.866Z", + "interviews": [] + }, + { + "id": "113b3e4d-3aed-4602-b952-3fb28e4bc908", + "jobId": "a8adb1f8-a6ee-48b1-8661-33bd851b726e", + "userId": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "status": "placed", + "externalId": "300234321", + "resume": "http://example.com", + "remark": "excellent", + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-09T21:23:49.415Z", + "updatedAt": "2021-05-09T21:25:46.867Z", + "interviews": [] + }, + { + "id": "c3f2bddb-39d1-4558-8052-c556b1436d3a", + "jobId": "a8adb1f8-a6ee-48b1-8661-33bd851b726e", + "userId": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "status": "placed", + "externalId": "300234321", + "resume": "http://example.com", + "remark": "excellent", + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-09T21:23:51.500Z", + "updatedAt": "2021-05-09T21:25:46.868Z", + "interviews": [] + }, + { + "id": "26fea152-9f15-437f-876a-a3ef211d60b9", + "jobId": "a8adb1f8-a6ee-48b1-8661-33bd851b726e", + "userId": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "status": "placed", + "externalId": "300234321", + "resume": "http://example.com", + "remark": "excellent", + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-09T21:23:53.297Z", + "updatedAt": "2021-05-09T21:25:46.869Z", + "interviews": [] + }, + { + "id": "fa137ab6-daee-4201-8cec-9e70086f9c4a", + "jobId": "a8adb1f8-a6ee-48b1-8661-33bd851b726e", + "userId": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "status": "placed", + "externalId": "300234321", + "resume": "http://example.com", + "remark": "excellent", + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-09T21:23:55.300Z", + "updatedAt": "2021-05-09T21:25:46.870Z", + "interviews": [] + }, + { + "id": "a591149a-d16a-4287-a520-d021a5c767b1", + "jobId": "a8adb1f8-a6ee-48b1-8661-33bd851b726e", + "userId": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "status": "placed", + "externalId": "300234321", + "resume": "http://example.com", + "remark": "excellent", + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-09T21:23:59.282Z", + "updatedAt": "2021-05-09T21:25:46.872Z", + "interviews": [] + }, + { + "id": "7ccb9a34-553e-427d-9f03-3b7caf0216e9", + "jobId": "a8adb1f8-a6ee-48b1-8661-33bd851b726e", + "userId": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "status": "placed", + "externalId": "300234321", + "resume": "http://example.com", + "remark": "excellent", + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-09T21:24:01.429Z", + "updatedAt": "2021-05-09T21:25:46.873Z", + "interviews": [] + }, + { + "id": "8845ae56-5291-4ce0-8cf6-9e684b152d03", + "jobId": "a8adb1f8-a6ee-48b1-8661-33bd851b726e", + "userId": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "status": "placed", + "externalId": "300234321", + "resume": "http://example.com", + "remark": "excellent", + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-09T21:24:03.511Z", + "updatedAt": "2021-05-09T21:25:46.874Z", + "interviews": [] + }, + { + "id": "85dddeda-a4cc-48dc-9a1d-8d96bf52bc5d", + "jobId": "a8adb1f8-a6ee-48b1-8661-33bd851b726e", + "userId": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "status": "placed", + "externalId": "300234321", + "resume": "http://example.com", + "remark": "excellent", + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-09T21:24:05.605Z", + "updatedAt": "2021-05-09T21:25:46.877Z", + "interviews": [] + }, + { + "id": "06450cf6-aafa-436f-8078-b0ced9f99432", + "jobId": "b28f4e67-324f-4ada-a23a-c27499053ed4", + "userId": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "status": "placed", + "externalId": "300234321", + "resume": "http://example.com", + "remark": "excellent", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-09T21:15:05.339Z", + "updatedAt": "2021-05-09T21:25:50.517Z", + "interviews": [] + }, + { + "id": "d4b2fe37-e0ed-41db-9c31-561ea2a5fb63", + "jobId": "b28f4e67-324f-4ada-a23a-c27499053ed4", + "userId": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "status": "placed", + "externalId": "300234321", + "resume": "http://example.com", + "remark": "excellent", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-09T21:15:03.606Z", + "updatedAt": "2021-05-09T21:25:50.519Z", + "interviews": [] + }, + { + "id": "aa72b3df-7c94-4a4a-a6cb-bd14d92aadfc", + "jobId": "b28f4e67-324f-4ada-a23a-c27499053ed4", + "userId": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "status": "placed", + "externalId": "300234321", + "resume": "http://example.com", + "remark": "excellent", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-09T21:14:59.106Z", + "updatedAt": "2021-05-09T21:25:50.520Z", + "interviews": [] + }, + { + "id": "da1be4fc-21d3-4544-abeb-c3434c172cdf", + "jobId": "b28f4e67-324f-4ada-a23a-c27499053ed4", + "userId": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "status": "placed", + "externalId": "300234321", + "resume": "http://example.com", + "remark": "excellent", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-09T21:15:02.183Z", + "updatedAt": "2021-05-09T21:25:50.521Z", + "interviews": [] + }, + { + "id": "e07848de-ecee-4eec-8163-4f17e40e756b", + "jobId": "b28f4e67-324f-4ada-a23a-c27499053ed4", + "userId": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "status": "placed", + "externalId": "300234321", + "resume": "http://example.com", + "remark": "excellent", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-09T21:15:00.676Z", + "updatedAt": "2021-05-09T21:25:50.523Z", + "interviews": [] + }, + { + "id": "458de082-d5ea-495a-8939-e8da3bb00e90", + "jobId": "b28f4e67-324f-4ada-a23a-c27499053ed4", + "userId": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "status": "placed", + "externalId": "300234321", + "resume": "http://example.com", + "remark": "excellent", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-09T21:15:06.739Z", + "updatedAt": "2021-05-09T21:25:50.525Z", + "interviews": [] + } + ], + "ResourceBooking": [ + { + "id": "d6103727-6615-4168-8169-0485577bfb3f", + "projectId": 111, + "userId": "bef43122-426b-4b2b-acdd-9b5b3bd1c0bf", + "jobId": "a8adb1f8-a6ee-48b1-8661-33bd851b726e", + "status": "placed", + "startDate": "2021-03-27", + "endDate": "2021-04-27", + "memberRate": 13.23, + "customerRate": 13, + "rateType": "hourly", + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:27:11.914Z", + "updatedAt": "2021-05-09T21:27:11.914Z", + "workPeriods": [ + { + "id": "5904b1d9-cb50-4b5d-8103-6741fec2f86b", + "resourceBookingId": "d6103727-6615-4168-8169-0485577bfb3f", + "userHandle": "testcat", + "projectId": 111, + "startDate": "2021-04-18", + "endDate": "2021-04-24", + "daysWorked": 2, + "daysPaid": 2, + "paymentTotal": 9.13, + "paymentStatus": "completed", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-09T21:27:12.746Z", + "updatedAt": "2021-05-09T21:47:44.291Z", + "payments": [ + { + "id": "dfc9bed6-78f2-407e-a7e4-abea9a3d3b46", + "workPeriodId": "5904b1d9-cb50-4b5d-8103-6741fec2f86b", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 22.82, + "customerRate": 4.07, + "days": 2, + "amount": 9.13, + "status": "cancelled", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:32:27.398Z", + "updatedAt": "2021-05-09T21:32:27.398Z" + }, + { + "id": "be4d5099-8b8e-45e2-b6cd-ab1997f57e26", + "workPeriodId": "5904b1d9-cb50-4b5d-8103-6741fec2f86b", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 22.82, + "customerRate": 4.07, + "days": 2, + "amount": 9.13, + "status": "completed", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:32:26.174Z", + "updatedAt": "2021-05-09T21:32:26.174Z" + } + ] + }, + { + "id": "d111a56f-593d-452e-9787-551bea504c92", + "resourceBookingId": "d6103727-6615-4168-8169-0485577bfb3f", + "userHandle": "testcat", + "projectId": 111, + "startDate": "2021-04-04", + "endDate": "2021-04-10", + "daysWorked": 4, + "daysPaid": 3, + "paymentTotal": 13.92, + "paymentStatus": "partially-completed", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-09T21:27:12.731Z", + "updatedAt": "2021-05-09T21:48:08.381Z", + "payments": [ + { + "id": "abb79afc-a370-4625-a067-a3b57c9b4700", + "workPeriodId": "d111a56f-593d-452e-9787-551bea504c92", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 23.2, + "customerRate": 30.71, + "days": 2, + "amount": 9.28, + "status": "completed", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:34:10.371Z", + "updatedAt": "2021-05-09T21:34:10.371Z" + }, + { + "id": "fa9bd31c-6c83-4ee4-9d45-a833cfe821f5", + "workPeriodId": "d111a56f-593d-452e-9787-551bea504c92", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 23.2, + "customerRate": 30.71, + "days": 1, + "amount": 4.64, + "status": "completed", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:34:11.662Z", + "updatedAt": "2021-05-09T21:34:11.662Z" + } + ] + }, + { + "id": "061f31fb-4f8c-462f-92c2-e5d275c45fde", + "resourceBookingId": "d6103727-6615-4168-8169-0485577bfb3f", + "userHandle": "testcat", + "projectId": 111, + "startDate": "2021-03-28", + "endDate": "2021-04-03", + "daysWorked": 2, + "daysPaid": 2, + "paymentTotal": 3.24, + "paymentStatus": "completed", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-09T21:27:12.733Z", + "updatedAt": "2021-05-09T21:47:38.022Z", + "payments": [ + { + "id": "3770680c-8045-43d4-8baf-cb7b3b714d39", + "workPeriodId": "061f31fb-4f8c-462f-92c2-e5d275c45fde", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 8.09, + "customerRate": 22.15, + "days": 2, + "amount": 3.24, + "status": "cancelled", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:30:42.711Z", + "updatedAt": "2021-05-09T21:30:42.711Z" + }, + { + "id": "c658d66e-86e1-49c7-8051-2b9a017935ad", + "workPeriodId": "061f31fb-4f8c-462f-92c2-e5d275c45fde", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 8.09, + "customerRate": 22.15, + "days": 2, + "amount": 3.24, + "status": "completed", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:30:41.304Z", + "updatedAt": "2021-05-09T21:30:41.304Z" + } + ] + }, + { + "id": "6adbf80c-43aa-41ad-b7db-544dc76f9b1c", + "resourceBookingId": "d6103727-6615-4168-8169-0485577bfb3f", + "userHandle": "testcat", + "projectId": 111, + "startDate": "2021-04-25", + "endDate": "2021-05-01", + "daysWorked": 0, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "no-days", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-09T21:27:12.794Z", + "updatedAt": "2021-05-09T21:47:51.348Z", + "payments": [] + }, + { + "id": "6ed56eb5-cadc-45f8-bbdf-3f408948c274", + "resourceBookingId": "d6103727-6615-4168-8169-0485577bfb3f", + "userHandle": "testcat", + "projectId": 111, + "startDate": "2021-03-21", + "endDate": "2021-03-27", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-09T21:27:12.737Z", + "updatedAt": "2021-05-09T21:47:58.216Z", + "payments": [ + { + "id": "ea3bdc7a-7c14-4ac1-955d-2540589fcfa6", + "workPeriodId": "6ed56eb5-cadc-45f8-bbdf-3f408948c274", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 22.85, + "customerRate": 29.89, + "days": 2, + "amount": 9.14, + "status": "cancelled", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:33:00.899Z", + "updatedAt": "2021-05-09T21:33:00.899Z" + }, + { + "id": "3bf29da2-581c-4f9c-8b0f-ff3c876848a0", + "workPeriodId": "6ed56eb5-cadc-45f8-bbdf-3f408948c274", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 22.85, + "customerRate": 29.89, + "days": 1, + "amount": 4.57, + "status": "cancelled", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:32:59.500Z", + "updatedAt": "2021-05-09T21:32:59.500Z" + } + ] + }, + { + "id": "0c825dec-6e7b-4dde-943a-f3f8354219cc", + "resourceBookingId": "d6103727-6615-4168-8169-0485577bfb3f", + "userHandle": "testcat", + "projectId": 111, + "startDate": "2021-04-11", + "endDate": "2021-04-17", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-09T21:27:12.783Z", + "updatedAt": "2021-05-09T21:48:03.740Z", + "payments": [ + { + "id": "78641310-ad51-40a3-a0fd-fdd8d15455b9", + "workPeriodId": "0c825dec-6e7b-4dde-943a-f3f8354219cc", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 5.59, + "customerRate": 30.54, + "days": 3, + "amount": 3.35, + "status": "cancelled", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:30:50.460Z", + "updatedAt": "2021-05-09T21:30:50.460Z" + }, + { + "id": "5bdd5c22-d9b7-428c-b084-d0950a18bc37", + "workPeriodId": "0c825dec-6e7b-4dde-943a-f3f8354219cc", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 5.59, + "customerRate": 30.54, + "days": 4, + "amount": 4.47, + "status": "cancelled", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:30:49.123Z", + "updatedAt": "2021-05-09T21:30:49.123Z" + } + ] + } + ] + }, + { + "id": "c0a12936-77ef-46fa-8c75-6996339e79f6", + "projectId": 111, + "userId": "05e988b7-7d54-4c10-ada1-1a04870a88a8", + "jobId": "a8adb1f8-a6ee-48b1-8661-33bd851b726e", + "status": "placed", + "startDate": "2020-09-27", + "endDate": "2020-10-27", + "memberRate": 13.23, + "customerRate": 13, + "rateType": "hourly", + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:25:46.728Z", + "updatedAt": "2021-05-09T21:25:46.728Z", + "workPeriods": [ + { + "id": "1cdd1505-f6f4-40f6-acce-da7a4578dab5", + "resourceBookingId": "c0a12936-77ef-46fa-8c75-6996339e79f6", + "userHandle": "sachin-wipro", + "projectId": 111, + "startDate": "2020-09-27", + "endDate": "2020-10-03", + "daysWorked": 4, + "daysPaid": 3, + "paymentTotal": 16.24, + "paymentStatus": "partially-completed", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-09T21:25:47.813Z", + "updatedAt": "2021-05-09T21:45:32.659Z", + "payments": [ + { + "id": "1c682ea9-ba63-4fcc-b00c-049d2458d3ac", + "workPeriodId": "1cdd1505-f6f4-40f6-acce-da7a4578dab5", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 27.06, + "customerRate": 13.13, + "days": 3, + "amount": 16.24, + "status": "completed", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:31:35.726Z", + "updatedAt": "2021-05-09T21:31:35.726Z" + }, + { + "id": "14b266c6-e76a-4042-b439-74fe3e42c90f", + "workPeriodId": "1cdd1505-f6f4-40f6-acce-da7a4578dab5", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 27.06, + "customerRate": 13.13, + "days": 4, + "amount": 21.65, + "status": "cancelled", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:31:38.183Z", + "updatedAt": "2021-05-09T21:31:38.183Z" + }, + { + "id": "03a0163c-472e-4ea6-b8ad-3dc86d418ecf", + "workPeriodId": "1cdd1505-f6f4-40f6-acce-da7a4578dab5", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 27.06, + "customerRate": 13.13, + "days": 4, + "amount": 21.65, + "status": "cancelled", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:31:36.932Z", + "updatedAt": "2021-05-09T21:31:36.932Z" + } + ] + }, + { + "id": "61c1e7e3-5e0a-4892-9099-872bc4c11a22", + "resourceBookingId": "c0a12936-77ef-46fa-8c75-6996339e79f6", + "userHandle": "sachin-wipro", + "projectId": 111, + "startDate": "2020-10-04", + "endDate": "2020-10-10", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-09T21:25:47.841Z", + "updatedAt": "2021-05-09T21:45:27.504Z", + "payments": [ + { + "id": "40e862a0-8772-4587-88b4-23acff8eb2e0", + "workPeriodId": "61c1e7e3-5e0a-4892-9099-872bc4c11a22", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 16.71, + "customerRate": 24.11, + "days": 4, + "amount": 13.37, + "status": "cancelled", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:32:40.091Z", + "updatedAt": "2021-05-09T21:32:40.091Z" + }, + { + "id": "fcd10a26-3548-4f9b-9e2b-20397d057800", + "workPeriodId": "61c1e7e3-5e0a-4892-9099-872bc4c11a22", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 16.71, + "customerRate": 24.11, + "days": 2, + "amount": 6.68, + "status": "cancelled", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:32:41.381Z", + "updatedAt": "2021-05-09T21:32:41.381Z" + } + ] + }, + { + "id": "e8346d7b-4ada-428d-a768-c2989306f63a", + "resourceBookingId": "c0a12936-77ef-46fa-8c75-6996339e79f6", + "userHandle": "sachin-wipro", + "projectId": 111, + "startDate": "2020-10-18", + "endDate": "2020-10-24", + "daysWorked": 4, + "daysPaid": 4, + "paymentTotal": 3.26, + "paymentStatus": "completed", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-09T21:25:47.834Z", + "updatedAt": "2021-05-09T21:45:37.647Z", + "payments": [ + { + "id": "cc235aee-0911-4869-bb49-911507bb31e7", + "workPeriodId": "e8346d7b-4ada-428d-a768-c2989306f63a", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 4.08, + "customerRate": 3.89, + "days": 4, + "amount": 3.26, + "status": "cancelled", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:34:26.807Z", + "updatedAt": "2021-05-09T21:34:26.807Z" + }, + { + "id": "e8f3d379-f5a0-47f6-b37b-cae24f5909e9", + "workPeriodId": "e8346d7b-4ada-428d-a768-c2989306f63a", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 4.08, + "customerRate": 3.89, + "days": 4, + "amount": 3.26, + "status": "completed", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:34:22.403Z", + "updatedAt": "2021-05-09T21:34:22.403Z" + } + ] + }, + { + "id": "a3bbd01d-535d-4f02-8524-0d61395b84e9", + "resourceBookingId": "c0a12936-77ef-46fa-8c75-6996339e79f6", + "userHandle": "sachin-wipro", + "projectId": 111, + "startDate": "2020-10-25", + "endDate": "2020-10-31", + "daysWorked": 3, + "daysPaid": 3, + "paymentTotal": 9.37, + "paymentStatus": "completed", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-09T21:25:47.824Z", + "updatedAt": "2021-05-09T21:45:48.727Z", + "payments": [ + { + "id": "7c27346e-a23f-46f3-b4d5-88a323fd437d", + "workPeriodId": "a3bbd01d-535d-4f02-8524-0d61395b84e9", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 15.61, + "customerRate": 9.76, + "days": 3, + "amount": 9.37, + "status": "completed", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:33:46.507Z", + "updatedAt": "2021-05-09T21:33:46.507Z" + } + ] + }, + { + "id": "fa030947-2f2f-4976-82ea-0a22ee96635a", + "resourceBookingId": "c0a12936-77ef-46fa-8c75-6996339e79f6", + "userHandle": "sachin-wipro", + "projectId": 111, + "startDate": "2020-10-11", + "endDate": "2020-10-17", + "daysWorked": 4, + "daysPaid": 3, + "paymentTotal": 6.49, + "paymentStatus": "partially-completed", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-09T21:25:47.815Z", + "updatedAt": "2021-05-09T21:45:41.810Z", + "payments": [ + { + "id": "2a4d1488-d27b-4bc8-af68-1a2b893774de", + "workPeriodId": "fa030947-2f2f-4976-82ea-0a22ee96635a", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 10.82, + "customerRate": 30.71, + "days": 3, + "amount": 6.49, + "status": "completed", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:34:31.474Z", + "updatedAt": "2021-05-09T21:34:31.474Z" + } + ] + } + ] + }, + { + "id": "314084fc-e854-4b62-8901-03ea9bbf2ffa", + "projectId": 111, + "userId": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "jobId": "b28f4e67-324f-4ada-a23a-c27499053ed4", + "status": "cancelled", + "startDate": "2020-12-27", + "endDate": "2021-01-27", + "memberRate": 13.23, + "customerRate": 13, + "rateType": "hourly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": null, + "createdAt": "2021-05-09T21:25:50.450Z", + "updatedAt": "2021-05-09T21:25:50.450Z", + "workPeriods": [ + { + "id": "32b977c9-386a-4159-a1c3-08169ee12f6e", + "resourceBookingId": "314084fc-e854-4b62-8901-03ea9bbf2ffa", + "userHandle": "pshah_manager", + "projectId": 111, + "startDate": "2021-01-10", + "endDate": "2021-01-16", + "daysWorked": 3, + "daysPaid": 2, + "paymentTotal": 5.5, + "paymentStatus": "partially-completed", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-09T21:25:51.435Z", + "updatedAt": "2021-05-09T21:45:08.968Z", + "payments": [ + { + "id": "99e4bffb-90f8-411e-9a49-fc7779bd2c07", + "workPeriodId": "32b977c9-386a-4159-a1c3-08169ee12f6e", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 13.74, + "customerRate": 22.37, + "days": 2, + "amount": 5.5, + "status": "completed", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:31:57.470Z", + "updatedAt": "2021-05-09T21:31:57.470Z" + }, + { + "id": "fa4c7e24-470f-4aef-a269-59b7e0b2bc05", + "workPeriodId": "32b977c9-386a-4159-a1c3-08169ee12f6e", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 13.74, + "customerRate": 22.37, + "days": 3, + "amount": 8.24, + "status": "cancelled", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:31:56.152Z", + "updatedAt": "2021-05-09T21:31:56.152Z" + } + ] + }, + { + "id": "13f22f72-9240-43bb-ba0c-618d0b24ad8c", + "resourceBookingId": "314084fc-e854-4b62-8901-03ea9bbf2ffa", + "userHandle": "pshah_manager", + "projectId": 111, + "startDate": "2021-01-17", + "endDate": "2021-01-23", + "daysWorked": 5, + "daysPaid": 5, + "paymentTotal": 24.35, + "paymentStatus": "completed", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-09T21:25:51.398Z", + "updatedAt": "2021-05-09T21:45:01.792Z", + "payments": [ + { + "id": "1d2b92e8-194f-477a-97f8-e104056e6b10", + "workPeriodId": "13f22f72-9240-43bb-ba0c-618d0b24ad8c", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 24.35, + "customerRate": 4.79, + "days": 2, + "amount": 9.74, + "status": "completed", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:31:09.459Z", + "updatedAt": "2021-05-09T21:31:09.459Z" + }, + { + "id": "381af41e-6b0a-49fe-987f-1bcb03fda571", + "workPeriodId": "13f22f72-9240-43bb-ba0c-618d0b24ad8c", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 24.35, + "customerRate": 4.79, + "days": 3, + "amount": 14.61, + "status": "completed", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:31:08.119Z", + "updatedAt": "2021-05-09T21:31:08.119Z" + } + ] + }, + { + "id": "0cf74043-b432-41a5-99d9-83420a6ad8ef", + "resourceBookingId": "314084fc-e854-4b62-8901-03ea9bbf2ffa", + "userHandle": "pshah_manager", + "projectId": 111, + "startDate": "2021-01-03", + "endDate": "2021-01-09", + "daysWorked": 2, + "daysPaid": 2, + "paymentTotal": 5.5, + "paymentStatus": "completed", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-09T21:25:51.419Z", + "updatedAt": "2021-05-09T21:44:51.852Z", + "payments": [ + { + "id": "f0f85e56-6bf4-4e1f-a1ef-c31529efe4cd", + "workPeriodId": "0cf74043-b432-41a5-99d9-83420a6ad8ef", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 13.74, + "customerRate": 21.1, + "days": 1, + "amount": 2.75, + "status": "cancelled", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:30:58.017Z", + "updatedAt": "2021-05-09T21:30:58.017Z" + }, + { + "id": "ef951baa-a007-48db-a658-495c6eeda9bc", + "workPeriodId": "0cf74043-b432-41a5-99d9-83420a6ad8ef", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 13.74, + "customerRate": 21.1, + "days": 2, + "amount": 5.5, + "status": "completed", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:30:59.323Z", + "updatedAt": "2021-05-09T21:30:59.323Z" + } + ] + }, + { + "id": "e71f17b2-acb4-4c14-a492-8cab071fe2b5", + "resourceBookingId": "314084fc-e854-4b62-8901-03ea9bbf2ffa", + "userHandle": "pshah_manager", + "projectId": 111, + "startDate": "2020-12-27", + "endDate": "2021-01-02", + "daysWorked": 4, + "daysPaid": 4, + "paymentTotal": 12.49, + "paymentStatus": "completed", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-09T21:25:51.383Z", + "updatedAt": "2021-05-09T21:45:22.801Z", + "payments": [ + { + "id": "a376dfdc-3330-417b-916d-3a7d4f9ab384", + "workPeriodId": "e71f17b2-acb4-4c14-a492-8cab071fe2b5", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 15.61, + "customerRate": 2.54, + "days": 4, + "amount": 12.49, + "status": "completed", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:34:17.363Z", + "updatedAt": "2021-05-09T21:34:17.363Z" + } + ] + }, + { + "id": "028287bf-6999-4fef-bdfa-1229b4e23ac1", + "resourceBookingId": "314084fc-e854-4b62-8901-03ea9bbf2ffa", + "userHandle": "pshah_manager", + "projectId": 111, + "startDate": "2021-01-24", + "endDate": "2021-01-30", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-09T21:25:51.432Z", + "updatedAt": "2021-05-09T21:45:16.298Z", + "payments": [ + { + "id": "1cb5129e-8d92-4280-a946-8cb0f5757abc", + "workPeriodId": "028287bf-6999-4fef-bdfa-1229b4e23ac1", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 27.06, + "customerRate": 2.54, + "days": 2, + "amount": 10.82, + "status": "cancelled", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:30:33.549Z", + "updatedAt": "2021-05-09T21:30:33.549Z" + }, + { + "id": "b576f845-7dea-4b56-b0de-6ce15fd2c245", + "workPeriodId": "028287bf-6999-4fef-bdfa-1229b4e23ac1", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 27.06, + "customerRate": 2.54, + "days": 2, + "amount": 10.82, + "status": "cancelled", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:30:25.688Z", + "updatedAt": "2021-05-09T21:30:25.688Z" + } + ] + } + ] + }, + { + "id": "d4134cc8-d306-45e2-bb76-cf3707b6df3e", + "projectId": 111, + "userId": "dd5adacb-444d-4992-8b7b-0c349be598db", + "jobId": "b28f4e67-324f-4ada-a23a-c27499053ed4", + "status": "placed", + "startDate": "2021-05-10", + "endDate": "2021-06-15", + "memberRate": 13.23, + "customerRate": 13, + "rateType": "hourly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": null, + "createdAt": "2021-05-09T21:26:30.065Z", + "updatedAt": "2021-05-09T21:26:30.065Z", + "workPeriods": [ + { + "id": "28bd80ec-ef91-4516-90d6-6979e6cc341c", + "resourceBookingId": "d4134cc8-d306-45e2-bb76-cf3707b6df3e", + "userHandle": "amy_admin", + "projectId": 111, + "startDate": "2021-05-23", + "endDate": "2021-05-29", + "daysWorked": 5, + "daysPaid": 4, + "paymentTotal": 22.72, + "paymentStatus": "partially-completed", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-09T21:26:30.824Z", + "updatedAt": "2021-05-09T21:46:34.331Z", + "payments": [ + { + "id": "4892cd43-a132-4ca9-a511-8d10cdc22f5d", + "workPeriodId": "28bd80ec-ef91-4516-90d6-6979e6cc341c", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 28.4, + "customerRate": 12.25, + "days": 4, + "amount": 22.72, + "status": "completed", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:31:43.808Z", + "updatedAt": "2021-05-09T21:31:43.808Z" + } + ] + }, + { + "id": "355c7114-753a-4f99-b026-1d1430bf5530", + "resourceBookingId": "d4134cc8-d306-45e2-bb76-cf3707b6df3e", + "userHandle": "amy_admin", + "projectId": 111, + "startDate": "2021-05-16", + "endDate": "2021-05-22", + "daysWorked": 5, + "daysPaid": 4, + "paymentTotal": 7.4, + "paymentStatus": "partially-completed", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-09T21:26:30.865Z", + "updatedAt": "2021-05-09T21:46:39.040Z", + "payments": [ + { + "id": "71b3b7d4-129c-4348-9ead-6f22eafa6db8", + "workPeriodId": "355c7114-753a-4f99-b026-1d1430bf5530", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 9.26, + "customerRate": 16.44, + "days": 2, + "amount": 3.7, + "status": "completed", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:32:05.827Z", + "updatedAt": "2021-05-09T21:32:05.827Z" + }, + { + "id": "d0ebcc96-70f2-4716-92d4-74e40af04387", + "workPeriodId": "355c7114-753a-4f99-b026-1d1430bf5530", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 9.26, + "customerRate": 16.44, + "days": 2, + "amount": 3.7, + "status": "completed", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:32:04.463Z", + "updatedAt": "2021-05-09T21:32:04.463Z" + } + ] + }, + { + "id": "9c024b6a-229a-4b8d-ac03-a53e4e412a73", + "resourceBookingId": "d4134cc8-d306-45e2-bb76-cf3707b6df3e", + "userHandle": "amy_admin", + "projectId": 111, + "startDate": "2021-05-09", + "endDate": "2021-05-15", + "daysWorked": 5, + "daysPaid": 5, + "paymentTotal": 5.59, + "paymentStatus": "completed", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-09T21:26:30.813Z", + "updatedAt": "2021-05-09T21:46:53.821Z", + "payments": [ + { + "id": "28f285ec-0965-4904-901d-7ae5c5d8e220", + "workPeriodId": "9c024b6a-229a-4b8d-ac03-a53e4e412a73", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 5.59, + "customerRate": 18.55, + "days": 5, + "amount": 5.59, + "status": "completed", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:33:35.441Z", + "updatedAt": "2021-05-09T21:33:35.441Z" + } + ] + }, + { + "id": "48c4b614-6588-46c9-8b4f-54d3175ae47d", + "resourceBookingId": "d4134cc8-d306-45e2-bb76-cf3707b6df3e", + "userHandle": "amy_admin", + "projectId": 111, + "startDate": "2021-06-06", + "endDate": "2021-06-12", + "daysWorked": 5, + "daysPaid": 5, + "paymentTotal": 16.02, + "paymentStatus": "completed", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-09T21:26:30.878Z", + "updatedAt": "2021-05-09T21:46:27.840Z", + "payments": [ + { + "id": "e1f9634a-4c3b-4dcd-ad81-3703c807a820", + "workPeriodId": "48c4b614-6588-46c9-8b4f-54d3175ae47d", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 16.02, + "customerRate": 30.71, + "days": 5, + "amount": 16.02, + "status": "completed", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:32:12.499Z", + "updatedAt": "2021-05-09T21:32:12.499Z" + } + ] + }, + { + "id": "91fcf91f-b2cf-4909-8f03-b5efc0732b28", + "resourceBookingId": "d4134cc8-d306-45e2-bb76-cf3707b6df3e", + "userHandle": "amy_admin", + "projectId": 111, + "startDate": "2021-06-13", + "endDate": "2021-06-19", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-09T21:26:30.893Z", + "updatedAt": "2021-05-09T21:46:44.896Z", + "payments": [ + { + "id": "d36afd1d-1f76-4f2d-b630-69bf85796496", + "workPeriodId": "91fcf91f-b2cf-4909-8f03-b5efc0732b28", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 1.53, + "customerRate": 2.1, + "days": 5, + "amount": 1.53, + "status": "cancelled", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:33:12.838Z", + "updatedAt": "2021-05-09T21:33:12.838Z" + }, + { + "id": "71750282-0ffe-46ed-b8c2-37e36c148833", + "workPeriodId": "91fcf91f-b2cf-4909-8f03-b5efc0732b28", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 1.53, + "customerRate": 2.1, + "days": 3, + "amount": 0.92, + "status": "cancelled", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:33:14.202Z", + "updatedAt": "2021-05-09T21:33:14.202Z" + } + ] + }, + { + "id": "311a692f-18bc-4eb6-a6d0-06cf3dbd1637", + "resourceBookingId": "d4134cc8-d306-45e2-bb76-cf3707b6df3e", + "userHandle": "amy_admin", + "projectId": 111, + "startDate": "2021-05-30", + "endDate": "2021-06-05", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-09T21:26:30.875Z", + "updatedAt": "2021-05-09T21:46:49.092Z", + "payments": [ + { + "id": "875c7250-50fa-453f-99d0-e76260648cd1", + "workPeriodId": "311a692f-18bc-4eb6-a6d0-06cf3dbd1637", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 13.07, + "customerRate": 10.1, + "days": 5, + "amount": 13.07, + "status": "cancelled", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:31:50.023Z", + "updatedAt": "2021-05-09T21:31:50.023Z" + } + ] + } + ] + }, + { + "id": "62c3f0c9-2bf0-4f24-8647-2c802a39cbcb", + "projectId": 16870, + "userId": "acdf9ebe-8358-4bd3-9374-1d86cf27e5f4", + "jobId": "fe8da845-5313-496f-b859-9824bd06a0db", + "status": "placed", + "startDate": "2021-01-21", + "endDate": "2021-02-21", + "memberRate": 114.33, + "customerRate": 258.37, + "rateType": "weekly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-01T09:30:59.306Z", + "updatedAt": "2021-05-30T11:48:56.459Z", + "workPeriods": [ + { + "id": "97cb1bad-772a-4f1e-a5a3-f0b19ae766f2", + "resourceBookingId": "62c3f0c9-2bf0-4f24-8647-2c802a39cbcb", + "userHandle": "newwayenjoy", + "projectId": 16870, + "startDate": "2021-02-21", + "endDate": "2021-02-27", + "daysWorked": 0, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "no-days", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:48:57.210Z", + "updatedAt": "2021-05-30T16:12:01.358Z", + "payments": [] + }, + { + "id": "55b66454-3a29-4163-9d97-7ecd2e805f71", + "resourceBookingId": "62c3f0c9-2bf0-4f24-8647-2c802a39cbcb", + "userHandle": "newwayenjoy", + "projectId": 16870, + "startDate": "2021-01-17", + "endDate": "2021-01-23", + "daysWorked": 2, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:48:57.225Z", + "updatedAt": "2021-05-30T16:12:01.359Z", + "payments": [] + }, + { + "id": "5bc5686b-95b3-49d7-9c8e-50f1dfdcb82e", + "resourceBookingId": "62c3f0c9-2bf0-4f24-8647-2c802a39cbcb", + "userHandle": "newwayenjoy", + "projectId": 16870, + "startDate": "2021-02-07", + "endDate": "2021-02-13", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:57.306Z", + "updatedAt": "2021-05-30T16:04:57.957Z", + "payments": [] + }, + { + "id": "77dcf745-bd59-40d8-b563-75a4d5354d29", + "resourceBookingId": "62c3f0c9-2bf0-4f24-8647-2c802a39cbcb", + "userHandle": "newwayenjoy", + "projectId": 16870, + "startDate": "2021-02-14", + "endDate": "2021-02-20", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:57.208Z", + "updatedAt": "2021-05-30T16:04:30.745Z", + "payments": [] + }, + { + "id": "1fa1f111-6574-47b0-8d12-6832541d496c", + "resourceBookingId": "62c3f0c9-2bf0-4f24-8647-2c802a39cbcb", + "userHandle": "newwayenjoy", + "projectId": 16870, + "startDate": "2021-01-31", + "endDate": "2021-02-06", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:57.244Z", + "updatedAt": "2021-05-30T16:05:42.410Z", + "payments": [] + }, + { + "id": "4c626a59-e591-4e7a-88cb-1d601b9b8493", + "resourceBookingId": "62c3f0c9-2bf0-4f24-8647-2c802a39cbcb", + "userHandle": "newwayenjoy", + "projectId": 16870, + "startDate": "2021-01-24", + "endDate": "2021-01-30", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:57.302Z", + "updatedAt": "2021-05-30T16:05:10.190Z", + "payments": [] + } + ] + }, + { + "id": "0da35f26-f0cc-4f4d-b239-68c11b9a1fa3", + "projectId": 17103, + "userId": "8fe0c1c3-e63e-4047-9854-01f03b166bd8", + "jobId": "feef8b66-989d-4ec7-bdb0-59ca05c95003", + "status": "closed", + "startDate": "2021-01-02", + "endDate": "2021-02-02", + "memberRate": 85.22, + "customerRate": 170.64, + "rateType": "weekly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-01T10:25:45.827Z", + "updatedAt": "2021-05-30T11:49:17.657Z", + "workPeriods": [ + { + "id": "0466ddf6-83ba-41ee-b299-4abb2b5f8a3b", + "resourceBookingId": "0da35f26-f0cc-4f4d-b239-68c11b9a1fa3", + "userHandle": "marathon_zhang", + "projectId": 17103, + "startDate": "2020-12-27", + "endDate": "2021-01-02", + "daysWorked": 0, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "no-days", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:49:18.405Z", + "updatedAt": "2021-05-30T16:12:15.134Z", + "payments": [] + }, + { + "id": "bd92f07b-4b57-4486-9101-254578cf32f8", + "resourceBookingId": "0da35f26-f0cc-4f4d-b239-68c11b9a1fa3", + "userHandle": "marathon_zhang", + "projectId": 17103, + "startDate": "2021-01-17", + "endDate": "2021-01-23", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:18.505Z", + "updatedAt": "2021-05-30T16:03:42.520Z", + "payments": [] + }, + { + "id": "9c976d1a-f395-4889-ac9b-38846a083dcb", + "resourceBookingId": "0da35f26-f0cc-4f4d-b239-68c11b9a1fa3", + "userHandle": "marathon_zhang", + "projectId": 17103, + "startDate": "2021-01-24", + "endDate": "2021-01-30", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:18.500Z", + "updatedAt": "2021-05-30T16:04:11.932Z", + "payments": [] + }, + { + "id": "62bf7ac9-bea9-4f96-8a28-2a3a8dbbc48f", + "resourceBookingId": "0da35f26-f0cc-4f4d-b239-68c11b9a1fa3", + "userHandle": "marathon_zhang", + "projectId": 17103, + "startDate": "2021-01-03", + "endDate": "2021-01-09", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:18.439Z", + "updatedAt": "2021-05-30T16:04:50.801Z", + "payments": [] + }, + { + "id": "05fb419d-927c-4264-b346-905ba7a55f49", + "resourceBookingId": "0da35f26-f0cc-4f4d-b239-68c11b9a1fa3", + "userHandle": "marathon_zhang", + "projectId": 17103, + "startDate": "2021-01-31", + "endDate": "2021-02-06", + "daysWorked": 2, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:49:18.492Z", + "updatedAt": "2021-05-30T16:12:15.133Z", + "payments": [] + }, + { + "id": "c4b535c4-0c6f-4420-930e-0103aea68057", + "resourceBookingId": "0da35f26-f0cc-4f4d-b239-68c11b9a1fa3", + "userHandle": "marathon_zhang", + "projectId": 17103, + "startDate": "2021-01-10", + "endDate": "2021-01-16", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:18.490Z", + "updatedAt": "2021-05-30T16:03:36.317Z", + "payments": [] + } + ] + }, + { + "id": "3f12b87c-9915-4ce1-89e5-535a3c0337f4", + "projectId": 16714, + "userId": "4b00d029-c87b-47b2-bfe2-0ab80d8b5774", + "jobId": "fc0240f0-8c8f-40ce-a551-e83b45673098", + "status": "sourcing", + "startDate": "2021-01-01", + "endDate": "2021-02-01", + "memberRate": 106.51, + "customerRate": 296.66, + "rateType": "daily", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-01-25T13:10:26.146Z", + "updatedAt": "2021-05-30T11:41:11.436Z", + "workPeriods": [ + { + "id": "15cbf62c-67d9-4f4a-92dc-546cb0afac32", + "resourceBookingId": "3f12b87c-9915-4ce1-89e5-535a3c0337f4", + "userHandle": "nkumar2", + "projectId": 16714, + "startDate": "2020-12-27", + "endDate": "2021-01-02", + "daysWorked": 1, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:41:12.216Z", + "updatedAt": "2021-05-30T16:12:06.801Z", + "payments": [] + }, + { + "id": "5c01c872-eb1e-4161-8e54-791f4ffe7bba", + "resourceBookingId": "3f12b87c-9915-4ce1-89e5-535a3c0337f4", + "userHandle": "nkumar2", + "projectId": 16714, + "startDate": "2021-01-10", + "endDate": "2021-01-16", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:41:12.223Z", + "updatedAt": "2021-05-30T16:04:56.201Z", + "payments": [] + }, + { + "id": "1073cd3c-8fc3-4642-b71b-ed49e3628952", + "resourceBookingId": "3f12b87c-9915-4ce1-89e5-535a3c0337f4", + "userHandle": "nkumar2", + "projectId": 16714, + "startDate": "2021-01-31", + "endDate": "2021-02-06", + "daysWorked": 1, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:41:12.278Z", + "updatedAt": "2021-05-30T16:12:06.800Z", + "payments": [] + }, + { + "id": "1d912726-4d5e-4063-9651-bcf51fd4f42e", + "resourceBookingId": "3f12b87c-9915-4ce1-89e5-535a3c0337f4", + "userHandle": "nkumar2", + "projectId": 16714, + "startDate": "2021-01-24", + "endDate": "2021-01-30", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:41:12.274Z", + "updatedAt": "2021-05-30T16:05:47.699Z", + "payments": [] + }, + { + "id": "f5ab8f98-7e4b-4cf9-a1e5-6a15ab6bad91", + "resourceBookingId": "3f12b87c-9915-4ce1-89e5-535a3c0337f4", + "userHandle": "nkumar2", + "projectId": 16714, + "startDate": "2021-01-03", + "endDate": "2021-01-09", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:41:12.251Z", + "updatedAt": "2021-05-30T16:02:51.923Z", + "payments": [] + }, + { + "id": "c20620e6-17de-41f5-8a0a-089683550b2f", + "resourceBookingId": "3f12b87c-9915-4ce1-89e5-535a3c0337f4", + "userHandle": "nkumar2", + "projectId": 16714, + "startDate": "2021-01-17", + "endDate": "2021-01-23", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:41:12.260Z", + "updatedAt": "2021-05-30T16:03:39.019Z", + "payments": [] + } + ] + }, + { + "id": "e8e5ba0d-d506-4f76-b920-e6efcee29611", + "projectId": 17091, + "userId": "b870a229-e954-482d-b270-a39fcf2aec53", + "jobId": "fb8b92f6-4ffb-4ba6-8c38-c2d4a151f76b", + "status": "placed", + "startDate": "2021-01-01", + "endDate": "2021-02-01", + "memberRate": 4.07, + "customerRate": 132.43, + "rateType": "weekly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-01T09:53:14.352Z", + "updatedAt": "2021-05-30T11:48:17.788Z", + "workPeriods": [ + { + "id": "73224384-4ac4-402e-8c6e-e04c64ef34da", + "resourceBookingId": "e8e5ba0d-d506-4f76-b920-e6efcee29611", + "userHandle": "jimsun", + "projectId": 17091, + "startDate": "2020-12-27", + "endDate": "2021-01-02", + "daysWorked": 1, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:48:18.557Z", + "updatedAt": "2021-05-30T16:11:38.205Z", + "payments": [] + }, + { + "id": "bcadfe78-7237-45e9-bd77-cba366ef9cf5", + "resourceBookingId": "e8e5ba0d-d506-4f76-b920-e6efcee29611", + "userHandle": "jimsun", + "projectId": 17091, + "startDate": "2021-01-17", + "endDate": "2021-01-23", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:18.549Z", + "updatedAt": "2021-05-30T16:03:44.298Z", + "payments": [] + }, + { + "id": "b04da80e-eff3-4be3-8849-f39f6af417b9", + "resourceBookingId": "e8e5ba0d-d506-4f76-b920-e6efcee29611", + "userHandle": "jimsun", + "projectId": 17091, + "startDate": "2021-01-03", + "endDate": "2021-01-09", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:18.561Z", + "updatedAt": "2021-05-30T16:03:59.366Z", + "payments": [] + }, + { + "id": "788dae21-92c8-4ae8-9e10-4e394f22cb73", + "resourceBookingId": "e8e5ba0d-d506-4f76-b920-e6efcee29611", + "userHandle": "jimsun", + "projectId": 17091, + "startDate": "2021-01-10", + "endDate": "2021-01-16", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:18.554Z", + "updatedAt": "2021-05-30T16:04:28.730Z", + "payments": [] + }, + { + "id": "eaffd373-e0f8-4798-ae42-24fb9bebeef3", + "resourceBookingId": "e8e5ba0d-d506-4f76-b920-e6efcee29611", + "userHandle": "jimsun", + "projectId": 17091, + "startDate": "2021-01-24", + "endDate": "2021-01-30", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:18.552Z", + "updatedAt": "2021-05-30T16:03:06.211Z", + "payments": [] + }, + { + "id": "31436a53-4c2e-40fc-98f2-2b6e3e36aa2b", + "resourceBookingId": "e8e5ba0d-d506-4f76-b920-e6efcee29611", + "userHandle": "jimsun", + "projectId": 17091, + "startDate": "2021-01-31", + "endDate": "2021-02-06", + "daysWorked": 1, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:48:18.565Z", + "updatedAt": "2021-05-30T16:11:38.208Z", + "payments": [] + } + ] + }, + { + "id": "48bd8a8b-40fb-459a-b5db-f22de90c2799", + "projectId": 16870, + "userId": "2bba34d5-20e4-46d6-bfc1-05736b17afbb", + "jobId": "fe539bef-9119-4a8c-b7b0-915e7e3a3ba3", + "status": "closed", + "startDate": "2021-01-02", + "endDate": "2021-02-02", + "memberRate": 18.4, + "customerRate": 30.14, + "rateType": "weekly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-01T03:43:44.374Z", + "updatedAt": "2021-05-30T11:49:00.956Z", + "workPeriods": [ + { + "id": "b9768ae4-ae40-4bb9-8bc2-970c9f36f0bf", + "resourceBookingId": "48bd8a8b-40fb-459a-b5db-f22de90c2799", + "userHandle": "GunaK-TopCoder", + "projectId": 16870, + "startDate": "2020-12-27", + "endDate": "2021-01-02", + "daysWorked": 0, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "no-days", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:49:01.820Z", + "updatedAt": "2021-05-30T16:12:04.121Z", + "payments": [] + }, + { + "id": "77ac0f07-d4ae-463e-a9db-437623a29958", + "resourceBookingId": "48bd8a8b-40fb-459a-b5db-f22de90c2799", + "userHandle": "GunaK-TopCoder", + "projectId": 16870, + "startDate": "2021-01-03", + "endDate": "2021-01-09", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:01.793Z", + "updatedAt": "2021-05-30T16:04:31.663Z", + "payments": [] + }, + { + "id": "1f5d3abe-fe2b-4961-831c-b7bbdf76da82", + "resourceBookingId": "48bd8a8b-40fb-459a-b5db-f22de90c2799", + "userHandle": "GunaK-TopCoder", + "projectId": 16870, + "startDate": "2021-01-17", + "endDate": "2021-01-23", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:01.732Z", + "updatedAt": "2021-05-30T16:05:43.321Z", + "payments": [] + }, + { + "id": "1c526f5f-d9e0-4e16-8421-cee4e8154a3c", + "resourceBookingId": "48bd8a8b-40fb-459a-b5db-f22de90c2799", + "userHandle": "GunaK-TopCoder", + "projectId": 16870, + "startDate": "2021-01-24", + "endDate": "2021-01-30", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:01.802Z", + "updatedAt": "2021-05-30T16:05:48.592Z", + "payments": [] + }, + { + "id": "b7bce7db-65dc-4447-8865-f6e8a84a867e", + "resourceBookingId": "48bd8a8b-40fb-459a-b5db-f22de90c2799", + "userHandle": "GunaK-TopCoder", + "projectId": 16870, + "startDate": "2021-01-10", + "endDate": "2021-01-16", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:01.698Z", + "updatedAt": "2021-05-30T16:03:48.778Z", + "payments": [] + }, + { + "id": "a475c2fa-c5ce-4a30-bdd8-d4fad1e6308c", + "resourceBookingId": "48bd8a8b-40fb-459a-b5db-f22de90c2799", + "userHandle": "GunaK-TopCoder", + "projectId": 16870, + "startDate": "2021-01-31", + "endDate": "2021-02-06", + "daysWorked": 2, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:49:01.795Z", + "updatedAt": "2021-05-30T16:12:04.120Z", + "payments": [] + } + ] + }, + { + "id": "de7e5be7-c8a9-416b-b8d0-d3faff274a40", + "projectId": 16781, + "userId": "7eea7c2f-5a46-4646-82bd-db4ac528378d", + "jobId": "ff3feeae-d4f7-457c-bff7-215be5efe2b8", + "status": "sourcing", + "startDate": "2021-01-11", + "endDate": "2021-02-11", + "memberRate": 61.33, + "customerRate": 196.21, + "rateType": "weekly", + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-01-12T10:49:14.209Z", + "updatedAt": "2021-05-30T11:48:22.088Z", + "workPeriods": [ + { + "id": "41217a15-4231-480c-91bc-492cbbe95113", + "resourceBookingId": "de7e5be7-c8a9-416b-b8d0-d3faff274a40", + "userHandle": "ZeroChance", + "projectId": 16781, + "startDate": "2021-02-07", + "endDate": "2021-02-13", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:48:22.909Z", + "updatedAt": "2021-05-30T16:11:40.871Z", + "payments": [] + }, + { + "id": "cd2ff33c-70d9-4b47-a1f2-d3a32febb22d", + "resourceBookingId": "de7e5be7-c8a9-416b-b8d0-d3faff274a40", + "userHandle": "ZeroChance", + "projectId": 16781, + "startDate": "2021-01-24", + "endDate": "2021-01-30", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:22.945Z", + "updatedAt": "2021-05-30T16:03:28.495Z", + "payments": [] + }, + { + "id": "354f7ab0-b9e3-4afd-a082-0ef0bc02ae44", + "resourceBookingId": "de7e5be7-c8a9-416b-b8d0-d3faff274a40", + "userHandle": "ZeroChance", + "projectId": 16781, + "startDate": "2021-01-31", + "endDate": "2021-02-06", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:22.902Z", + "updatedAt": "2021-05-30T16:05:23.620Z", + "payments": [] + }, + { + "id": "e3edac07-0c38-4f5a-a62d-b1fcc037e6c9", + "resourceBookingId": "de7e5be7-c8a9-416b-b8d0-d3faff274a40", + "userHandle": "ZeroChance", + "projectId": 16781, + "startDate": "2021-01-17", + "endDate": "2021-01-23", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:22.907Z", + "updatedAt": "2021-05-30T16:03:11.591Z", + "payments": [] + }, + { + "id": "4703c8d8-7e7b-4ee3-8cea-08c3d15de835", + "resourceBookingId": "de7e5be7-c8a9-416b-b8d0-d3faff274a40", + "userHandle": "ZeroChance", + "projectId": 16781, + "startDate": "2021-01-10", + "endDate": "2021-01-16", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:22.912Z", + "updatedAt": "2021-05-30T16:05:12.956Z", + "payments": [] + } + ] + }, + { + "id": "d2f7dc2e-bed6-4549-b6c6-0616840782fb", + "projectId": 16762, + "userId": "595edbcd-f4d1-468e-a422-50bf61e2fa87", + "jobId": "fe481d1c-cf87-49c1-9370-695f9f754041", + "status": "placed", + "startDate": "2021-01-11", + "endDate": "2021-02-11", + "memberRate": 66, + "customerRate": 146.2, + "rateType": "daily", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-01-12T10:58:55.040Z", + "updatedAt": "2021-05-30T11:48:26.483Z", + "workPeriods": [ + { + "id": "f040a900-cd3e-4ebf-9a52-10db19e90e83", + "resourceBookingId": "d2f7dc2e-bed6-4549-b6c6-0616840782fb", + "userHandle": "sachin-kumar", + "projectId": 16762, + "startDate": "2021-01-31", + "endDate": "2021-02-06", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:27.249Z", + "updatedAt": "2021-05-30T16:02:59.987Z", + "payments": [] + }, + { + "id": "ecb9c0a7-0438-482d-9c8b-6ad6ffba2586", + "resourceBookingId": "d2f7dc2e-bed6-4549-b6c6-0616840782fb", + "userHandle": "sachin-kumar", + "projectId": 16762, + "startDate": "2021-01-24", + "endDate": "2021-01-30", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:27.266Z", + "updatedAt": "2021-05-30T16:03:04.382Z", + "payments": [] + }, + { + "id": "98f6ced4-7a27-4dd7-bf51-5bba41091f03", + "resourceBookingId": "d2f7dc2e-bed6-4549-b6c6-0616840782fb", + "userHandle": "sachin-kumar", + "projectId": 16762, + "startDate": "2021-01-10", + "endDate": "2021-01-16", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:27.256Z", + "updatedAt": "2021-05-30T16:04:13.737Z", + "payments": [] + }, + { + "id": "02281a71-46c3-4850-a243-737616ef78dc", + "resourceBookingId": "d2f7dc2e-bed6-4549-b6c6-0616840782fb", + "userHandle": "sachin-kumar", + "projectId": 16762, + "startDate": "2021-02-07", + "endDate": "2021-02-13", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:48:27.259Z", + "updatedAt": "2021-05-30T16:11:43.711Z", + "payments": [] + }, + { + "id": "248b0c82-8f49-482c-bd71-f3127acdefd8", + "resourceBookingId": "d2f7dc2e-bed6-4549-b6c6-0616840782fb", + "userHandle": "sachin-kumar", + "projectId": 16762, + "startDate": "2021-01-17", + "endDate": "2021-01-23", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:27.311Z", + "updatedAt": "2021-05-30T16:05:37.170Z", + "payments": [] + } + ] + }, + { + "id": "c4e86eae-ead3-49b7-90ab-92c3b4a3be0c", + "projectId": 111, + "userId": "a2ffdeed-704d-4cf7-b70a-93fcf61de598", + "jobId": "b28f4e67-324f-4ada-a23a-c27499053ed4", + "status": "closed", + "startDate": "2021-05-10", + "endDate": "2021-06-15", + "memberRate": 13.23, + "customerRate": 13, + "rateType": "hourly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": null, + "createdAt": "2021-05-09T21:27:15.093Z", + "updatedAt": "2021-05-09T21:27:15.093Z", + "workPeriods": [ + { + "id": "94dde794-b730-4e05-8ea6-dcc5b541d43e", + "resourceBookingId": "c4e86eae-ead3-49b7-90ab-92c3b4a3be0c", + "userHandle": "lakshmiaconnmgr", + "projectId": 111, + "startDate": "2021-05-23", + "endDate": "2021-05-29", + "daysWorked": 3, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-09T21:27:15.991Z", + "updatedAt": "2021-05-09T21:46:02.038Z", + "payments": [ + { + "id": "c7013bf0-17b5-4b15-826b-385fad41caf4", + "workPeriodId": "94dde794-b730-4e05-8ea6-dcc5b541d43e", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 10.82, + "customerRate": 29.89, + "days": 3, + "amount": 6.49, + "status": "cancelled", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:33:20.680Z", + "updatedAt": "2021-05-09T21:33:20.680Z" + }, + { + "id": "be9706ac-c6cb-4fff-894b-8719bcf634dc", + "workPeriodId": "94dde794-b730-4e05-8ea6-dcc5b541d43e", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 10.82, + "customerRate": 29.89, + "days": 2, + "amount": 4.33, + "status": "cancelled", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:33:21.933Z", + "updatedAt": "2021-05-09T21:33:21.933Z" + } + ] + }, + { + "id": "6a567293-7189-4b14-82c9-57bd3d0eab20", + "resourceBookingId": "c4e86eae-ead3-49b7-90ab-92c3b4a3be0c", + "userHandle": "lakshmiaconnmgr", + "projectId": 111, + "startDate": "2021-05-09", + "endDate": "2021-05-15", + "daysWorked": 3, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-09T21:27:15.959Z", + "updatedAt": "2021-05-09T21:46:07.315Z", + "payments": [ + { + "id": "e386f5a1-2856-4cc5-8304-1598e5683a0f", + "workPeriodId": "6a567293-7189-4b14-82c9-57bd3d0eab20", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 24.03, + "customerRate": 24.11, + "days": 3, + "amount": 14.42, + "status": "cancelled", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:32:47.852Z", + "updatedAt": "2021-05-09T21:32:47.852Z" + } + ] + }, + { + "id": "fd6034b3-b6a0-4a3f-9a5d-fc077c08c680", + "resourceBookingId": "c4e86eae-ead3-49b7-90ab-92c3b4a3be0c", + "userHandle": "lakshmiaconnmgr", + "projectId": 111, + "startDate": "2021-05-30", + "endDate": "2021-06-05", + "daysWorked": 5, + "daysPaid": 4, + "paymentTotal": 23.45, + "paymentStatus": "partially-completed", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-09T21:27:16.013Z", + "updatedAt": "2021-05-09T21:45:53.796Z", + "payments": [ + { + "id": "6e1a114f-bfac-4ab8-93d6-e47206200540", + "workPeriodId": "fd6034b3-b6a0-4a3f-9a5d-fc077c08c680", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 29.32, + "customerRate": 29.89, + "days": 1, + "amount": 5.86, + "status": "completed", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:34:40.036Z", + "updatedAt": "2021-05-09T21:34:40.036Z" + }, + { + "id": "10fd3b3e-f5b2-42cc-91d4-54c73c003aae", + "workPeriodId": "fd6034b3-b6a0-4a3f-9a5d-fc077c08c680", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 29.32, + "customerRate": 29.89, + "days": 1, + "amount": 5.86, + "status": "completed", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:34:37.374Z", + "updatedAt": "2021-05-09T21:34:37.374Z" + }, + { + "id": "fbc2d96f-f6c6-4a4d-b737-14a3564b7f70", + "workPeriodId": "fd6034b3-b6a0-4a3f-9a5d-fc077c08c680", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 29.32, + "customerRate": 29.89, + "days": 1, + "amount": 5.86, + "status": "cancelled", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:34:38.700Z", + "updatedAt": "2021-05-09T21:34:38.700Z" + }, + { + "id": "fc577d14-78e8-404c-a17b-ab496e4041d8", + "workPeriodId": "fd6034b3-b6a0-4a3f-9a5d-fc077c08c680", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 29.32, + "customerRate": 29.89, + "days": 2, + "amount": 11.73, + "status": "completed", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:34:41.520Z", + "updatedAt": "2021-05-09T21:34:41.520Z" + } + ] + }, + { + "id": "ac0ae325-8d77-4a73-bd85-5361165801cd", + "resourceBookingId": "c4e86eae-ead3-49b7-90ab-92c3b4a3be0c", + "userHandle": "lakshmiaconnmgr", + "projectId": 111, + "startDate": "2021-06-06", + "endDate": "2021-06-12", + "daysWorked": 3, + "daysPaid": 3, + "paymentTotal": 8.25, + "paymentStatus": "completed", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-09T21:27:15.951Z", + "updatedAt": "2021-05-09T21:46:12.086Z", + "payments": [ + { + "id": "00640d2d-8330-445a-b022-aa687033b2b3", + "workPeriodId": "ac0ae325-8d77-4a73-bd85-5361165801cd", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 13.74, + "customerRate": 14.57, + "days": 1, + "amount": 2.75, + "status": "completed", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:33:54.315Z", + "updatedAt": "2021-05-09T21:33:54.315Z" + }, + { + "id": "05d09e2b-02a0-4d33-b6db-0f69a98154c6", + "workPeriodId": "ac0ae325-8d77-4a73-bd85-5361165801cd", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 13.74, + "customerRate": 14.57, + "days": 2, + "amount": 5.5, + "status": "completed", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:33:53.131Z", + "updatedAt": "2021-05-09T21:33:53.131Z" + } + ] + }, + { + "id": "4ae26d58-1910-4ace-9f09-4c62c8df6031", + "resourceBookingId": "c4e86eae-ead3-49b7-90ab-92c3b4a3be0c", + "userHandle": "lakshmiaconnmgr", + "projectId": 111, + "startDate": "2021-06-13", + "endDate": "2021-06-19", + "daysWorked": 3, + "daysPaid": 3, + "paymentTotal": 9.37, + "paymentStatus": "completed", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-09T21:27:15.972Z", + "updatedAt": "2021-05-09T21:45:57.739Z", + "payments": [ + { + "id": "e623d9c7-caa9-4e58-83f1-44741b1169f8", + "workPeriodId": "4ae26d58-1910-4ace-9f09-4c62c8df6031", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 15.61, + "customerRate": 2.1, + "days": 3, + "amount": 9.37, + "status": "completed", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:32:19.371Z", + "updatedAt": "2021-05-09T21:32:19.371Z" + } + ] + }, + { + "id": "9d914249-82f2-422e-9ba6-c281da411266", + "resourceBookingId": "c4e86eae-ead3-49b7-90ab-92c3b4a3be0c", + "userHandle": "lakshmiaconnmgr", + "projectId": 111, + "startDate": "2021-05-16", + "endDate": "2021-05-22", + "daysWorked": 5, + "daysPaid": 5, + "paymentTotal": 113.23, + "paymentStatus": "completed", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-09T21:27:16.017Z", + "updatedAt": "2021-05-09T21:46:21.053Z", + "payments": [ + { + "id": "6036c7cc-b180-4f50-8163-5fd2541c66b5", + "workPeriodId": "9d914249-82f2-422e-9ba6-c281da411266", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 113.23, + "customerRate": 9.46, + "days": 5, + "amount": 113.23, + "status": "completed", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:33:40.984Z", + "updatedAt": "2021-05-09T21:33:40.984Z" + } + ] + } + ] + }, + { + "id": "1ad758ab-c19f-4247-954a-4581420aba8a", + "projectId": 17363, + "userId": "dbf68f12-69a4-4592-a0ab-cf68d9ed7ae4", + "jobId": "fd48d96e-b0f2-43b7-8a48-f4fa194d6bc8", + "status": "placed", + "startDate": "2021-01-11", + "endDate": "2021-02-11", + "memberRate": 114.33, + "customerRate": 217.99, + "rateType": "weekly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-27T11:25:35.292Z", + "updatedAt": "2021-05-30T11:49:08.019Z", + "workPeriods": [ + { + "id": "8ff2339f-d90a-4ac2-9798-3158d0746d53", + "resourceBookingId": "1ad758ab-c19f-4247-954a-4581420aba8a", + "userHandle": "vishalgoel", + "projectId": 17363, + "startDate": "2021-02-07", + "endDate": "2021-02-13", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:49:08.875Z", + "updatedAt": "2021-05-30T16:12:09.701Z", + "payments": [] + }, + { + "id": "c4c8588e-68a4-4b82-be91-a3d98661ffba", + "resourceBookingId": "1ad758ab-c19f-4247-954a-4581420aba8a", + "userHandle": "vishalgoel", + "projectId": 17363, + "startDate": "2021-01-17", + "endDate": "2021-01-23", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:08.879Z", + "updatedAt": "2021-05-30T16:03:35.487Z", + "payments": [] + }, + { + "id": "5ecaa40c-1fb3-4df7-9870-6fc3c2bc1bca", + "resourceBookingId": "1ad758ab-c19f-4247-954a-4581420aba8a", + "userHandle": "vishalgoel", + "projectId": 17363, + "startDate": "2021-01-10", + "endDate": "2021-01-16", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:08.877Z", + "updatedAt": "2021-05-30T16:04:53.463Z", + "payments": [] + }, + { + "id": "38afaa09-32da-4d81-b2f5-0c5e31af617f", + "resourceBookingId": "1ad758ab-c19f-4247-954a-4581420aba8a", + "userHandle": "vishalgoel", + "projectId": 17363, + "startDate": "2021-01-31", + "endDate": "2021-02-06", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:08.867Z", + "updatedAt": "2021-05-30T16:05:21.960Z", + "payments": [] + }, + { + "id": "83cb4174-6ee3-4557-97c1-120c46054af6", + "resourceBookingId": "1ad758ab-c19f-4247-954a-4581420aba8a", + "userHandle": "vishalgoel", + "projectId": 17363, + "startDate": "2021-01-24", + "endDate": "2021-01-30", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:08.882Z", + "updatedAt": "2021-05-30T16:04:22.560Z", + "payments": [] + } + ] + }, + { + "id": "07f73049-e51a-4394-b61f-b75418afa908", + "projectId": 16739, + "userId": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "jobId": "fc5ba131-566f-46fe-8501-79c593241896", + "status": "placed", + "startDate": "2021-01-11", + "endDate": "2021-02-11", + "memberRate": 66, + "customerRate": 114.05, + "rateType": "weekly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-01-12T10:59:20.006Z", + "updatedAt": "2021-05-30T11:49:21.188Z", + "workPeriods": [ + { + "id": "7ff4804e-2a65-4f8b-af5b-24b58c066fd4", + "resourceBookingId": "07f73049-e51a-4394-b61f-b75418afa908", + "userHandle": "nkumartest", + "projectId": 16739, + "startDate": "2021-02-07", + "endDate": "2021-02-13", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:49:22.068Z", + "updatedAt": "2021-05-30T16:12:16.993Z", + "payments": [] + }, + { + "id": "410e034d-ee48-4a18-aa65-679ef7efcb80", + "resourceBookingId": "07f73049-e51a-4394-b61f-b75418afa908", + "userHandle": "nkumartest", + "projectId": 16739, + "startDate": "2021-01-17", + "endDate": "2021-01-23", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:21.961Z", + "updatedAt": "2021-05-30T16:05:16.466Z", + "payments": [] + }, + { + "id": "d99a524f-c8a4-4d46-a42c-dbcddd65b6db", + "resourceBookingId": "07f73049-e51a-4394-b61f-b75418afa908", + "userHandle": "nkumartest", + "projectId": 16739, + "startDate": "2021-01-31", + "endDate": "2021-02-06", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:22.017Z", + "updatedAt": "2021-05-30T16:03:19.706Z", + "payments": [] + }, + { + "id": "5c4bb82b-e617-4c91-861f-5e0825d43c53", + "resourceBookingId": "07f73049-e51a-4394-b61f-b75418afa908", + "userHandle": "nkumartest", + "projectId": 16739, + "startDate": "2021-01-10", + "endDate": "2021-01-16", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:21.977Z", + "updatedAt": "2021-05-30T16:04:55.294Z", + "payments": [] + }, + { + "id": "da043aba-161e-4894-a3d5-d63678ac89b0", + "resourceBookingId": "07f73049-e51a-4394-b61f-b75418afa908", + "userHandle": "nkumartest", + "projectId": 16739, + "startDate": "2021-01-24", + "endDate": "2021-01-30", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:21.974Z", + "updatedAt": "2021-05-30T16:03:18.831Z", + "payments": [] + } + ] + }, + { + "id": "016312f6-72cf-486b-be8f-956ca4b2171e", + "projectId": 16706, + "userId": "4b00d029-c87b-47b2-bfe2-0ab80d8b5774", + "jobId": "fc2b006d-997b-49c3-a414-59ee54a48f9f", + "status": "sourcing", + "startDate": "2021-01-01", + "endDate": "2021-02-01", + "memberRate": 114.33, + "customerRate": 67.93, + "rateType": "weekly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-01-26T08:27:38.010Z", + "updatedAt": "2021-05-30T11:40:20.936Z", + "workPeriods": [ + { + "id": "a2e2905a-efd7-45ba-a891-f0523b4b1351", + "resourceBookingId": "016312f6-72cf-486b-be8f-956ca4b2171e", + "userHandle": "nkumar2", + "projectId": 16706, + "startDate": "2021-01-17", + "endDate": "2021-01-23", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:40:21.794Z", + "updatedAt": "2021-05-30T16:04:08.375Z", + "payments": [] + }, + { + "id": "6629d501-d17f-4261-a4d1-ed51d2a4b533", + "resourceBookingId": "016312f6-72cf-486b-be8f-956ca4b2171e", + "userHandle": "nkumar2", + "projectId": 16706, + "startDate": "2021-01-24", + "endDate": "2021-01-30", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:40:21.784Z", + "updatedAt": "2021-05-30T16:04:46.695Z", + "payments": [] + }, + { + "id": "42ca2389-e8a6-42c5-8a97-8d47531d2f23", + "resourceBookingId": "016312f6-72cf-486b-be8f-956ca4b2171e", + "userHandle": "nkumar2", + "projectId": 16706, + "startDate": "2021-01-10", + "endDate": "2021-01-16", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:40:21.766Z", + "updatedAt": "2021-05-30T16:05:14.728Z", + "payments": [] + }, + { + "id": "b3101b68-cc83-4a5c-aa33-0c5220e4b78f", + "resourceBookingId": "016312f6-72cf-486b-be8f-956ca4b2171e", + "userHandle": "nkumar2", + "projectId": 16706, + "startDate": "2021-01-31", + "endDate": "2021-02-06", + "daysWorked": 1, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:40:21.780Z", + "updatedAt": "2021-05-30T16:12:19.637Z", + "payments": [] + }, + { + "id": "149f2401-f2c2-4e3f-98fe-44148820cd5e", + "resourceBookingId": "016312f6-72cf-486b-be8f-956ca4b2171e", + "userHandle": "nkumar2", + "projectId": 16706, + "startDate": "2020-12-27", + "endDate": "2021-01-02", + "daysWorked": 1, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:40:21.757Z", + "updatedAt": "2021-05-30T16:12:19.636Z", + "payments": [] + }, + { + "id": "e002f23e-8358-4f49-8770-af19aa23708e", + "resourceBookingId": "016312f6-72cf-486b-be8f-956ca4b2171e", + "userHandle": "nkumar2", + "projectId": 16706, + "startDate": "2021-01-03", + "endDate": "2021-01-09", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:40:21.710Z", + "updatedAt": "2021-05-30T16:03:14.321Z", + "payments": [] + } + ] + }, + { + "id": "d5de4575-c977-4f4b-bd5b-bb82360dd365", + "projectId": 111, + "userId": "6d0509c7-5f12-4d84-9a19-8e80ef7ddd66", + "jobId": "a8adb1f8-a6ee-48b1-8661-33bd851b726e", + "status": "closed", + "startDate": "2021-03-27", + "endDate": "2021-04-27", + "memberRate": 13.23, + "customerRate": 13, + "rateType": "hourly", + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:26:16.403Z", + "updatedAt": "2021-05-09T21:26:16.403Z", + "workPeriods": [ + { + "id": "b0758857-0221-47a5-a444-e263e5d9e1cf", + "resourceBookingId": "d5de4575-c977-4f4b-bd5b-bb82360dd365", + "userHandle": "aaaa", + "projectId": 111, + "startDate": "2021-03-21", + "endDate": "2021-03-27", + "daysWorked": 5, + "daysPaid": 5, + "paymentTotal": 27.06, + "paymentStatus": "completed", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-09T21:26:17.187Z", + "updatedAt": "2021-05-09T21:46:59.354Z", + "payments": [ + { + "id": "9785ae89-05dc-4bcc-a030-52bd0e681d41", + "workPeriodId": "b0758857-0221-47a5-a444-e263e5d9e1cf", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 27.06, + "customerRate": 22.77, + "days": 5, + "amount": 27.06, + "status": "cancelled", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:34:01.410Z", + "updatedAt": "2021-05-09T21:34:01.410Z" + }, + { + "id": "c8be508d-2eb5-4712-8bd7-1b28e870abc2", + "workPeriodId": "b0758857-0221-47a5-a444-e263e5d9e1cf", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 27.06, + "customerRate": 22.77, + "days": 5, + "amount": 27.06, + "status": "completed", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:34:02.733Z", + "updatedAt": "2021-05-09T21:34:02.733Z" + } + ] + }, + { + "id": "176db0d0-474f-4590-831a-547d596c01b4", + "resourceBookingId": "d5de4575-c977-4f4b-bd5b-bb82360dd365", + "userHandle": "aaaa", + "projectId": 111, + "startDate": "2021-03-28", + "endDate": "2021-04-03", + "daysWorked": 5, + "daysPaid": 5, + "paymentTotal": 6.11, + "paymentStatus": "completed", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-09T21:26:17.168Z", + "updatedAt": "2021-05-09T21:47:05.373Z", + "payments": [ + { + "id": "c3b71f96-7680-459b-82b2-f6eb3c3f6c8f", + "workPeriodId": "176db0d0-474f-4590-831a-547d596c01b4", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 6.11, + "customerRate": 14.63, + "days": 1, + "amount": 1.22, + "status": "completed", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:31:18.342Z", + "updatedAt": "2021-05-09T21:31:18.342Z" + }, + { + "id": "3ed31706-0e99-4084-81f4-b126a1a68db6", + "workPeriodId": "176db0d0-474f-4590-831a-547d596c01b4", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 6.11, + "customerRate": 14.63, + "days": 4, + "amount": 4.89, + "status": "completed", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:31:17.193Z", + "updatedAt": "2021-05-09T21:31:17.193Z" + } + ] + }, + { + "id": "8c9db4fd-78ad-4e59-acba-462487b74c3a", + "resourceBookingId": "d5de4575-c977-4f4b-bd5b-bb82360dd365", + "userHandle": "aaaa", + "projectId": 111, + "startDate": "2021-04-18", + "endDate": "2021-04-24", + "daysWorked": 2, + "daysPaid": 2, + "paymentTotal": 10.98, + "paymentStatus": "completed", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-09T21:26:17.200Z", + "updatedAt": "2021-05-09T21:47:25.687Z", + "payments": [ + { + "id": "f65930b7-d61d-4923-bdab-54848661f151", + "workPeriodId": "8c9db4fd-78ad-4e59-acba-462487b74c3a", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 27.46, + "customerRate": 25.57, + "days": 1, + "amount": 5.49, + "status": "completed", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:33:06.108Z", + "updatedAt": "2021-05-09T21:33:06.108Z" + }, + { + "id": "8eb8fc37-5ab0-4480-8806-3d3c57ab38e1", + "workPeriodId": "8c9db4fd-78ad-4e59-acba-462487b74c3a", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 27.46, + "customerRate": 25.57, + "days": 1, + "amount": 5.49, + "status": "completed", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:33:07.419Z", + "updatedAt": "2021-05-09T21:33:07.419Z" + } + ] + }, + { + "id": "9b455e21-e186-4622-923a-f115d23549d1", + "resourceBookingId": "d5de4575-c977-4f4b-bd5b-bb82360dd365", + "userHandle": "aaaa", + "projectId": 111, + "startDate": "2021-04-25", + "endDate": "2021-05-01", + "daysWorked": 2, + "daysPaid": 2, + "paymentTotal": 9.13, + "paymentStatus": "completed", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-09T21:26:17.161Z", + "updatedAt": "2021-05-09T21:47:19.034Z", + "payments": [ + { + "id": "10584b23-5ab2-44e2-a927-e020c08e4f84", + "workPeriodId": "9b455e21-e186-4622-923a-f115d23549d1", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 22.82, + "customerRate": 10.1, + "days": 2, + "amount": 9.13, + "status": "cancelled", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:33:29.348Z", + "updatedAt": "2021-05-09T21:33:29.348Z" + }, + { + "id": "6d59a499-44e3-41e2-8368-5baee86dd8ab", + "workPeriodId": "9b455e21-e186-4622-923a-f115d23549d1", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 22.82, + "customerRate": 10.1, + "days": 2, + "amount": 9.13, + "status": "completed", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:33:28.108Z", + "updatedAt": "2021-05-09T21:33:28.108Z" + } + ] + }, + { + "id": "5a174833-cb08-49f5-b077-cffb8e60ca01", + "resourceBookingId": "d5de4575-c977-4f4b-bd5b-bb82360dd365", + "userHandle": "aaaa", + "projectId": 111, + "startDate": "2021-04-04", + "endDate": "2021-04-10", + "daysWorked": 5, + "daysPaid": 3, + "paymentTotal": 2.95, + "paymentStatus": "partially-completed", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-09T21:26:17.165Z", + "updatedAt": "2021-05-09T21:47:12.015Z", + "payments": [ + { + "id": "663f11df-7832-431a-a46e-ad8c890ae52b", + "workPeriodId": "5a174833-cb08-49f5-b077-cffb8e60ca01", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 4.91, + "customerRate": 24.11, + "days": 5, + "amount": 4.91, + "status": "cancelled", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:32:32.606Z", + "updatedAt": "2021-05-09T21:32:32.606Z" + }, + { + "id": "69445cbf-6d94-49a5-b2aa-65459ec78594", + "workPeriodId": "5a174833-cb08-49f5-b077-cffb8e60ca01", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 4.91, + "customerRate": 24.11, + "days": 3, + "amount": 2.95, + "status": "completed", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:32:33.664Z", + "updatedAt": "2021-05-09T21:32:33.664Z" + } + ] + }, + { + "id": "18881107-cc17-4087-9b2b-a74f04187f73", + "resourceBookingId": "d5de4575-c977-4f4b-bd5b-bb82360dd365", + "userHandle": "aaaa", + "projectId": 111, + "startDate": "2021-04-11", + "endDate": "2021-04-17", + "daysWorked": 2, + "daysPaid": 1, + "paymentTotal": 4.56, + "paymentStatus": "partially-completed", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-09T21:26:17.202Z", + "updatedAt": "2021-05-09T21:47:30.586Z", + "payments": [ + { + "id": "dd8f5c08-d6a1-4fd2-b6bd-85fb6425d13d", + "workPeriodId": "18881107-cc17-4087-9b2b-a74f04187f73", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 22.82, + "customerRate": 2.32, + "days": 1, + "amount": 4.56, + "status": "completed", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:31:25.690Z", + "updatedAt": "2021-05-09T21:31:25.690Z" + }, + { + "id": "c456755e-0432-4656-848b-64f9c5dc8f25", + "workPeriodId": "18881107-cc17-4087-9b2b-a74f04187f73", + "challengeId": "00000000-0000-0000-0000-000000000000", + "memberRate": 22.82, + "customerRate": 2.32, + "days": 2, + "amount": 9.13, + "status": "cancelled", + "statusDetails": null, + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-09T21:31:27.102Z", + "updatedAt": "2021-05-09T21:31:27.102Z" + } + ] + } + ] + }, + { + "id": "04cb749b-6e23-4e5b-b5a9-f2b4d25a94a6", + "projectId": 16718, + "userId": "085fc95d-0336-4572-a641-6c8334e7f0c9", + "jobId": "fb2f5f9b-5874-4dcd-af94-727fc0409760", + "status": "sourcing", + "startDate": "2021-01-01", + "endDate": "2021-02-01", + "memberRate": 114.33, + "customerRate": 100.25, + "rateType": "weekly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-01-26T08:27:33.886Z", + "updatedAt": "2021-05-30T11:49:22.899Z", + "workPeriods": [ + { + "id": "f8d56b84-b374-4975-81f8-7fab96463243", + "resourceBookingId": "04cb749b-6e23-4e5b-b5a9-f2b4d25a94a6", + "userHandle": "george0095", + "projectId": 16718, + "startDate": "2021-01-03", + "endDate": "2021-01-09", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:23.666Z", + "updatedAt": "2021-05-30T16:02:49.121Z", + "payments": [] + }, + { + "id": "ddcfc959-d749-45dc-9e9f-f18a893f9e1a", + "resourceBookingId": "04cb749b-6e23-4e5b-b5a9-f2b4d25a94a6", + "userHandle": "george0095", + "projectId": 16718, + "startDate": "2020-12-27", + "endDate": "2021-01-02", + "daysWorked": 1, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:49:23.644Z", + "updatedAt": "2021-05-30T16:12:17.859Z", + "payments": [] + }, + { + "id": "a322ee7e-7f23-4f9f-b2d8-286b574efd7f", + "resourceBookingId": "04cb749b-6e23-4e5b-b5a9-f2b4d25a94a6", + "userHandle": "george0095", + "projectId": 16718, + "startDate": "2021-01-24", + "endDate": "2021-01-30", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:23.681Z", + "updatedAt": "2021-05-30T16:04:07.452Z", + "payments": [] + }, + { + "id": "77f9b42c-6e67-4363-8b43-aa0b70a904e1", + "resourceBookingId": "04cb749b-6e23-4e5b-b5a9-f2b4d25a94a6", + "userHandle": "george0095", + "projectId": 16718, + "startDate": "2021-01-17", + "endDate": "2021-01-23", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:23.734Z", + "updatedAt": "2021-05-30T16:04:29.823Z", + "payments": [] + }, + { + "id": "20fc029b-108a-4f12-aec9-ba36619d4ce7", + "resourceBookingId": "04cb749b-6e23-4e5b-b5a9-f2b4d25a94a6", + "userHandle": "george0095", + "projectId": 16718, + "startDate": "2021-01-31", + "endDate": "2021-02-06", + "daysWorked": 1, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:49:23.730Z", + "updatedAt": "2021-05-30T16:12:17.860Z", + "payments": [] + }, + { + "id": "662f11e5-c02e-460d-989e-1396ff4f00a6", + "resourceBookingId": "04cb749b-6e23-4e5b-b5a9-f2b4d25a94a6", + "userHandle": "george0095", + "projectId": 16718, + "startDate": "2021-01-10", + "endDate": "2021-01-16", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:23.678Z", + "updatedAt": "2021-05-30T16:04:45.827Z", + "payments": [] + } + ] + }, + { + "id": "f40f43a8-b7b0-4181-967c-26e4e070f95e", + "projectId": 16870, + "userId": "b851684b-1071-47c3-8719-bdae96aa0e6d", + "jobId": "fed687e1-4257-48bb-806c-38712f9bf14f", + "status": "placed", + "startDate": "2021-01-11", + "endDate": "2021-02-11", + "memberRate": 115.29, + "customerRate": 278.45, + "rateType": "weekly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-04-29T09:50:13.905Z", + "updatedAt": "2021-05-30T11:48:15.196Z", + "workPeriods": [ + { + "id": "e95f0541-bc37-4c1e-a619-029753c1a69a", + "resourceBookingId": "f40f43a8-b7b0-4181-967c-26e4e070f95e", + "userHandle": "zxx.lotus", + "projectId": 16870, + "startDate": "2021-01-10", + "endDate": "2021-01-16", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:16.045Z", + "updatedAt": "2021-05-30T16:03:08.035Z", + "payments": [] + }, + { + "id": "cb6114ca-1624-4239-8243-aee05f8b5fe5", + "resourceBookingId": "f40f43a8-b7b0-4181-967c-26e4e070f95e", + "userHandle": "zxx.lotus", + "projectId": 16870, + "startDate": "2021-01-31", + "endDate": "2021-02-06", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:16.042Z", + "updatedAt": "2021-05-30T16:03:29.374Z", + "payments": [] + }, + { + "id": "f382c2c8-fe32-42f3-b960-29c345ab0264", + "resourceBookingId": "f40f43a8-b7b0-4181-967c-26e4e070f95e", + "userHandle": "zxx.lotus", + "projectId": 16870, + "startDate": "2021-02-07", + "endDate": "2021-02-13", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:48:16.004Z", + "updatedAt": "2021-05-30T16:11:36.370Z", + "payments": [] + }, + { + "id": "9215b576-8f67-4511-88f9-76000d6c8326", + "resourceBookingId": "f40f43a8-b7b0-4181-967c-26e4e070f95e", + "userHandle": "zxx.lotus", + "projectId": 16870, + "startDate": "2021-01-24", + "endDate": "2021-01-30", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:16.008Z", + "updatedAt": "2021-05-30T16:04:19.062Z", + "payments": [] + }, + { + "id": "333bcf25-25cc-4a4e-a6d7-2666a1326d68", + "resourceBookingId": "f40f43a8-b7b0-4181-967c-26e4e070f95e", + "userHandle": "zxx.lotus", + "projectId": 16870, + "startDate": "2021-01-17", + "endDate": "2021-01-23", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:16.001Z", + "updatedAt": "2021-05-30T16:05:26.263Z", + "payments": [] + } + ] + }, + { + "id": "7827dee4-012a-4fd2-9fb3-5b96913121a2", + "projectId": 16762, + "userId": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "jobId": "fe481d1c-cf87-49c1-9370-695f9f754041", + "status": "placed", + "startDate": "2021-01-01", + "endDate": "2021-02-01", + "memberRate": 61.33, + "customerRate": 84.88, + "rateType": "weekly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-01-12T10:53:32.373Z", + "updatedAt": "2021-05-30T11:48:49.532Z", + "workPeriods": [ + { + "id": "3ad03850-ebe9-4227-8b30-1303b20bbd31", + "resourceBookingId": "7827dee4-012a-4fd2-9fb3-5b96913121a2", + "userHandle": "pshah_manager", + "projectId": 16762, + "startDate": "2021-01-03", + "endDate": "2021-01-09", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:50.292Z", + "updatedAt": "2021-05-30T16:05:19.240Z", + "payments": [] + }, + { + "id": "2ea4bffd-2519-422f-8baa-a0f74b3b398b", + "resourceBookingId": "7827dee4-012a-4fd2-9fb3-5b96913121a2", + "userHandle": "pshah_manager", + "projectId": 16762, + "startDate": "2021-01-10", + "endDate": "2021-01-16", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:50.340Z", + "updatedAt": "2021-05-30T16:05:30.731Z", + "payments": [] + }, + { + "id": "e1099a6a-7c6b-465d-bb1b-517c3fbd06f1", + "resourceBookingId": "7827dee4-012a-4fd2-9fb3-5b96913121a2", + "userHandle": "pshah_manager", + "projectId": 16762, + "startDate": "2020-12-27", + "endDate": "2021-01-02", + "daysWorked": 1, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:48:50.297Z", + "updatedAt": "2021-05-30T16:11:57.610Z", + "payments": [] + }, + { + "id": "a154b1fb-06d3-4cfd-97d3-0a810a1c4317", + "resourceBookingId": "7827dee4-012a-4fd2-9fb3-5b96913121a2", + "userHandle": "pshah_manager", + "projectId": 16762, + "startDate": "2021-01-24", + "endDate": "2021-01-30", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:50.279Z", + "updatedAt": "2021-05-30T16:04:09.261Z", + "payments": [] + }, + { + "id": "a35207bd-ac1d-4539-b7bb-7a923c8a6f7f", + "resourceBookingId": "7827dee4-012a-4fd2-9fb3-5b96913121a2", + "userHandle": "pshah_manager", + "projectId": 16762, + "startDate": "2021-01-31", + "endDate": "2021-02-06", + "daysWorked": 1, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:48:50.330Z", + "updatedAt": "2021-05-30T16:11:57.609Z", + "payments": [] + }, + { + "id": "b34361ca-eb0e-47f7-86d9-3bccbb6839d5", + "resourceBookingId": "7827dee4-012a-4fd2-9fb3-5b96913121a2", + "userHandle": "pshah_manager", + "projectId": 16762, + "startDate": "2021-01-17", + "endDate": "2021-01-23", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:50.288Z", + "updatedAt": "2021-05-30T16:03:55.011Z", + "payments": [] + } + ] + }, + { + "id": "0eae9b44-6764-46c4-ba13-4cec37bf8574", + "projectId": 17324, + "userId": "4709473d-f060-4102-87f8-4d51ff0b34c1", + "jobId": "fefd2618-9b66-4431-9874-1d02d7a37d90", + "status": "placed", + "startDate": "2021-01-11", + "endDate": "2021-02-11", + "memberRate": 271.93, + "customerRate": 188.33, + "rateType": "weekly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-20T06:52:40.679Z", + "updatedAt": "2021-05-30T11:49:15.876Z", + "workPeriods": [ + { + "id": "f28bd617-dce3-47c0-a9ab-6b2ff321d206", + "resourceBookingId": "0eae9b44-6764-46c4-ba13-4cec37bf8574", + "userHandle": "TCConnCopilot", + "projectId": 17324, + "startDate": "2021-02-07", + "endDate": "2021-02-13", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:49:16.700Z", + "updatedAt": "2021-05-30T16:12:14.202Z", + "payments": [] + }, + { + "id": "c447a850-2549-4c6a-ad3e-47cb6b26ac0b", + "resourceBookingId": "0eae9b44-6764-46c4-ba13-4cec37bf8574", + "userHandle": "TCConnCopilot", + "projectId": 17324, + "startDate": "2021-01-24", + "endDate": "2021-01-30", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:16.706Z", + "updatedAt": "2021-05-30T16:03:37.121Z", + "payments": [] + }, + { + "id": "66732a8f-7bab-4e46-8eda-c58f28344114", + "resourceBookingId": "0eae9b44-6764-46c4-ba13-4cec37bf8574", + "userHandle": "TCConnCopilot", + "projectId": 17324, + "startDate": "2021-01-31", + "endDate": "2021-02-06", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:16.759Z", + "updatedAt": "2021-05-30T16:04:44.983Z", + "payments": [] + }, + { + "id": "444fbe9a-616e-443a-a1b5-aadfe7c617ff", + "resourceBookingId": "0eae9b44-6764-46c4-ba13-4cec37bf8574", + "userHandle": "TCConnCopilot", + "projectId": 17324, + "startDate": "2021-01-10", + "endDate": "2021-01-16", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:16.687Z", + "updatedAt": "2021-05-30T16:05:13.852Z", + "payments": [] + }, + { + "id": "50865971-2fd2-4576-a799-8ab438e9dd75", + "resourceBookingId": "0eae9b44-6764-46c4-ba13-4cec37bf8574", + "userHandle": "TCConnCopilot", + "projectId": 17324, + "startDate": "2021-01-17", + "endDate": "2021-01-23", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:16.701Z", + "updatedAt": "2021-05-30T16:05:05.541Z", + "payments": [] + } + ] + }, + { + "id": "0957b870-fc53-4343-8dbf-ebd3994b5734", + "projectId": 17103, + "userId": "9e4b1242-9b14-4159-bd0b-de7fa1803ca9", + "jobId": "feef8b66-989d-4ec7-bdb0-59ca05c95003", + "status": "cancelled", + "startDate": "2021-01-21", + "endDate": "2021-02-21", + "memberRate": 61.33, + "customerRate": 196.21, + "rateType": "weekly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-01T10:25:50.725Z", + "updatedAt": "2021-05-30T11:49:19.410Z", + "workPeriods": [ + { + "id": "f04d5bb8-abba-4447-92f0-005e823238f8", + "resourceBookingId": "0957b870-fc53-4343-8dbf-ebd3994b5734", + "userHandle": "ApolloZhang", + "projectId": 17103, + "startDate": "2021-02-21", + "endDate": "2021-02-27", + "daysWorked": 0, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "no-days", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:49:20.193Z", + "updatedAt": "2021-05-30T16:12:15.996Z", + "payments": [] + }, + { + "id": "fe874682-2ba6-4f42-929b-efc9e05adafd", + "resourceBookingId": "0957b870-fc53-4343-8dbf-ebd3994b5734", + "userHandle": "ApolloZhang", + "projectId": 17103, + "startDate": "2021-02-14", + "endDate": "2021-02-20", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:20.197Z", + "updatedAt": "2021-05-30T15:58:40.816Z", + "payments": [] + }, + { + "id": "217f124d-37db-49a8-9cac-187c5c8b2905", + "resourceBookingId": "0957b870-fc53-4343-8dbf-ebd3994b5734", + "userHandle": "ApolloZhang", + "projectId": 17103, + "startDate": "2021-02-07", + "endDate": "2021-02-13", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:20.202Z", + "updatedAt": "2021-05-30T16:05:38.038Z", + "payments": [] + }, + { + "id": "b826c9b8-12f5-4567-bd62-df524bb690a2", + "resourceBookingId": "0957b870-fc53-4343-8dbf-ebd3994b5734", + "userHandle": "ApolloZhang", + "projectId": 17103, + "startDate": "2021-01-31", + "endDate": "2021-02-06", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:20.194Z", + "updatedAt": "2021-05-30T16:03:47.803Z", + "payments": [] + }, + { + "id": "3e6436c6-f6d4-4b33-8027-1269b167554f", + "resourceBookingId": "0957b870-fc53-4343-8dbf-ebd3994b5734", + "userHandle": "ApolloZhang", + "projectId": 17103, + "startDate": "2021-01-24", + "endDate": "2021-01-30", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:20.200Z", + "updatedAt": "2021-05-30T16:05:18.330Z", + "payments": [] + }, + { + "id": "56f49073-e651-479c-967c-8ba58e36b8e6", + "resourceBookingId": "0957b870-fc53-4343-8dbf-ebd3994b5734", + "userHandle": "ApolloZhang", + "projectId": 17103, + "startDate": "2021-01-17", + "endDate": "2021-01-23", + "daysWorked": 2, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:49:20.236Z", + "updatedAt": "2021-05-30T16:12:15.994Z", + "payments": [] + } + ] + }, + { + "id": "f88e8c6b-565a-41ca-a8b4-72351fc140fe", + "projectId": 17232, + "userId": "1ab93e53-71f6-4c50-ab48-9446229b6451", + "jobId": "ff76b81d-f49b-4019-b50e-c7932a818f19", + "status": "placed", + "startDate": "2021-01-01", + "endDate": "2021-02-01", + "memberRate": 18.4, + "customerRate": 84.88, + "rateType": "weekly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-17T13:12:55.459Z", + "updatedAt": "2021-05-30T11:48:11.067Z", + "workPeriods": [ + { + "id": "e84de57c-d131-4431-8e46-9452218d30e7", + "resourceBookingId": "f88e8c6b-565a-41ca-a8b4-72351fc140fe", + "userHandle": "droopy74", + "projectId": 17232, + "startDate": "2021-01-03", + "endDate": "2021-01-09", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:12.550Z", + "updatedAt": "2021-05-30T16:03:08.981Z", + "payments": [] + }, + { + "id": "97dabae3-74dd-45f6-ab83-53e4a828c4a6", + "resourceBookingId": "f88e8c6b-565a-41ca-a8b4-72351fc140fe", + "userHandle": "droopy74", + "projectId": 17232, + "startDate": "2020-12-27", + "endDate": "2021-01-02", + "daysWorked": 1, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:48:12.488Z", + "updatedAt": "2021-05-30T16:11:34.545Z", + "payments": [] + }, + { + "id": "75c345fa-9e34-46a9-8cf0-46245495110d", + "resourceBookingId": "f88e8c6b-565a-41ca-a8b4-72351fc140fe", + "userHandle": "droopy74", + "projectId": 17232, + "startDate": "2021-01-24", + "endDate": "2021-01-30", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:12.586Z", + "updatedAt": "2021-05-30T16:04:33.475Z", + "payments": [] + }, + { + "id": "20242864-9dd6-4376-85fb-1402297e4597", + "resourceBookingId": "f88e8c6b-565a-41ca-a8b4-72351fc140fe", + "userHandle": "droopy74", + "projectId": 17232, + "startDate": "2021-01-17", + "endDate": "2021-01-23", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:12.497Z", + "updatedAt": "2021-05-30T16:05:41.521Z", + "payments": [] + }, + { + "id": "c0c613e3-845a-45c0-85fe-41c063d9df3d", + "resourceBookingId": "f88e8c6b-565a-41ca-a8b4-72351fc140fe", + "userHandle": "droopy74", + "projectId": 17232, + "startDate": "2021-01-31", + "endDate": "2021-02-06", + "daysWorked": 1, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:48:12.493Z", + "updatedAt": "2021-05-30T16:11:34.546Z", + "payments": [] + }, + { + "id": "b53b6f48-0a07-434e-a03d-f5d9ab772e60", + "resourceBookingId": "f88e8c6b-565a-41ca-a8b4-72351fc140fe", + "userHandle": "droopy74", + "projectId": 17232, + "startDate": "2021-01-10", + "endDate": "2021-01-16", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:12.515Z", + "updatedAt": "2021-05-30T16:03:53.254Z", + "payments": [] + } + ] + }, + { + "id": "f667a667-6026-4d93-89bb-358aced982e5", + "projectId": 16870, + "userId": "2bba34d5-20e4-46d6-bfc1-05736b17afbb", + "jobId": "fed687e1-4257-48bb-806c-38712f9bf14f", + "status": "placed", + "startDate": "2021-01-03", + "endDate": "2021-02-03", + "memberRate": 61.4, + "customerRate": 114.05, + "rateType": "daily", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-04-29T09:28:04.405Z", + "updatedAt": "2021-05-30T11:48:13.500Z", + "workPeriods": [ + { + "id": "d44b8f1a-46b7-43a8-afd6-d2d13bd02fa5", + "resourceBookingId": "f667a667-6026-4d93-89bb-358aced982e5", + "userHandle": "GunaK-TopCoder", + "projectId": 16870, + "startDate": "2021-01-03", + "endDate": "2021-01-09", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:14.367Z", + "updatedAt": "2021-05-30T16:03:23.275Z", + "payments": [] + }, + { + "id": "7011b330-8509-4f60-a2db-c0f5c9b5837b", + "resourceBookingId": "f667a667-6026-4d93-89bb-358aced982e5", + "userHandle": "GunaK-TopCoder", + "projectId": 16870, + "startDate": "2021-01-31", + "endDate": "2021-02-06", + "daysWorked": 3, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:48:14.320Z", + "updatedAt": "2021-05-30T16:11:35.512Z", + "payments": [] + }, + { + "id": "8252cd13-4351-4a86-9315-521963f329f5", + "resourceBookingId": "f667a667-6026-4d93-89bb-358aced982e5", + "userHandle": "GunaK-TopCoder", + "projectId": 16870, + "startDate": "2021-01-24", + "endDate": "2021-01-30", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:14.322Z", + "updatedAt": "2021-05-30T16:04:23.465Z", + "payments": [] + }, + { + "id": "259d8de1-1c56-49d0-936d-d5fcbdcc5a8a", + "resourceBookingId": "f667a667-6026-4d93-89bb-358aced982e5", + "userHandle": "GunaK-TopCoder", + "projectId": 16870, + "startDate": "2021-01-10", + "endDate": "2021-01-16", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:14.314Z", + "updatedAt": "2021-05-30T16:05:34.486Z", + "payments": [] + }, + { + "id": "1dd649b8-f536-4285-989d-56c45f1fca4d", + "resourceBookingId": "f667a667-6026-4d93-89bb-358aced982e5", + "userHandle": "GunaK-TopCoder", + "projectId": 16870, + "startDate": "2021-01-17", + "endDate": "2021-01-23", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:14.325Z", + "updatedAt": "2021-05-30T16:05:45.949Z", + "payments": [] + } + ] + }, + { + "id": "d84082de-9a09-4e9b-b5ab-4024f67687c5", + "projectId": 17103, + "userId": "fa5f4dc4-2992-4066-b4cc-16ceb5d1c1b7", + "jobId": "feef8b66-989d-4ec7-bdb0-59ca05c95003", + "status": "placed", + "startDate": "2021-01-11", + "endDate": "2021-02-11", + "memberRate": 287.14, + "customerRate": 258.37, + "rateType": "daily", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-02T06:00:42.366Z", + "updatedAt": "2021-05-30T11:48:23.808Z", + "workPeriods": [ + { + "id": "b60da405-cee8-41c9-919b-98d9acfd9f74", + "resourceBookingId": "d84082de-9a09-4e9b-b5ab-4024f67687c5", + "userHandle": "rtuthaya", + "projectId": 17103, + "startDate": "2021-01-17", + "endDate": "2021-01-23", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:24.607Z", + "updatedAt": "2021-05-30T16:03:52.385Z", + "payments": [] + }, + { + "id": "19110441-201e-449b-a350-661c50fb1387", + "resourceBookingId": "d84082de-9a09-4e9b-b5ab-4024f67687c5", + "userHandle": "rtuthaya", + "projectId": 17103, + "startDate": "2021-01-24", + "endDate": "2021-01-30", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:24.639Z", + "updatedAt": "2021-05-30T16:05:49.510Z", + "payments": [] + }, + { + "id": "1f12ada9-d0e6-43df-abe5-8a78850b20b4", + "resourceBookingId": "d84082de-9a09-4e9b-b5ab-4024f67687c5", + "userHandle": "rtuthaya", + "projectId": 17103, + "startDate": "2021-02-07", + "endDate": "2021-02-13", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:48:24.601Z", + "updatedAt": "2021-05-30T16:11:41.938Z", + "payments": [] + }, + { + "id": "1e94f892-ae25-4233-b9b0-81aa70c00b1e", + "resourceBookingId": "d84082de-9a09-4e9b-b5ab-4024f67687c5", + "userHandle": "rtuthaya", + "projectId": 17103, + "startDate": "2021-01-10", + "endDate": "2021-01-16", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:24.604Z", + "updatedAt": "2021-05-30T16:05:45.069Z", + "payments": [] + }, + { + "id": "4d7f0350-b2f0-4f31-acc3-6555c3756fdd", + "resourceBookingId": "d84082de-9a09-4e9b-b5ab-4024f67687c5", + "userHandle": "rtuthaya", + "projectId": 17103, + "startDate": "2021-01-31", + "endDate": "2021-02-06", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:24.637Z", + "updatedAt": "2021-05-30T16:05:08.370Z", + "payments": [] + } + ] + }, + { + "id": "e673b52e-738d-47f9-bf37-68f6b5ed1926", + "projectId": 16870, + "userId": "60d3e956-820b-4d59-a30b-9309b838fac5", + "jobId": "fe539bef-9119-4a8c-b7b0-915e7e3a3ba3", + "status": "placed", + "startDate": "2021-01-01", + "endDate": "2021-02-01", + "memberRate": 60.63, + "customerRate": 132.43, + "rateType": "weekly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-04-30T08:09:51.618Z", + "updatedAt": "2021-05-30T11:48:20.311Z", + "workPeriods": [ + { + "id": "6ad492cf-4d90-4608-8dd5-13aaafad12e2", + "resourceBookingId": "e673b52e-738d-47f9-bf37-68f6b5ed1926", + "userHandle": "Hypernova", + "projectId": 16870, + "startDate": "2020-12-27", + "endDate": "2021-01-02", + "daysWorked": 1, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:48:21.194Z", + "updatedAt": "2021-05-30T16:11:39.976Z", + "payments": [] + }, + { + "id": "61134c36-5e69-469c-bc50-75648f7949ca", + "resourceBookingId": "e673b52e-738d-47f9-bf37-68f6b5ed1926", + "userHandle": "Hypernova", + "projectId": 16870, + "startDate": "2021-01-10", + "endDate": "2021-01-16", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:21.187Z", + "updatedAt": "2021-05-30T16:04:51.659Z", + "payments": [] + }, + { + "id": "f095424c-9a15-4f37-b8e4-1cd685f17451", + "resourceBookingId": "e673b52e-738d-47f9-bf37-68f6b5ed1926", + "userHandle": "Hypernova", + "projectId": 16870, + "startDate": "2021-01-31", + "endDate": "2021-02-06", + "daysWorked": 1, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:48:21.198Z", + "updatedAt": "2021-05-30T16:11:39.977Z", + "payments": [] + }, + { + "id": "f79b0a83-5f72-4e9c-bffe-4ebf694db7f4", + "resourceBookingId": "e673b52e-738d-47f9-bf37-68f6b5ed1926", + "userHandle": "Hypernova", + "projectId": 16870, + "startDate": "2021-01-17", + "endDate": "2021-01-23", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:21.107Z", + "updatedAt": "2021-05-30T16:02:50.987Z", + "payments": [] + }, + { + "id": "c75ee2eb-a7c0-4eb8-83f9-860ce22d1b03", + "resourceBookingId": "e673b52e-738d-47f9-bf37-68f6b5ed1926", + "userHandle": "Hypernova", + "projectId": 16870, + "startDate": "2021-01-03", + "endDate": "2021-01-09", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:21.104Z", + "updatedAt": "2021-05-30T16:03:34.616Z", + "payments": [] + }, + { + "id": "b0aad7c5-bafb-4cae-90ca-832334505e9b", + "resourceBookingId": "e673b52e-738d-47f9-bf37-68f6b5ed1926", + "userHandle": "Hypernova", + "projectId": 16870, + "startDate": "2021-01-24", + "endDate": "2021-01-30", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:21.192Z", + "updatedAt": "2021-05-30T16:03:58.410Z", + "payments": [] + } + ] + }, + { + "id": "9e6e2bd4-1e4d-401b-871b-2c8fe8f44b54", + "projectId": 16899, + "userId": "5bc40e16-4fdb-40f1-93fe-de465789e1b2", + "jobId": "fe270791-bc24-4f6a-8c1b-b897f5d97d2f", + "status": "placed", + "startDate": "2021-01-11", + "endDate": "2021-02-11", + "memberRate": 271.93, + "customerRate": 102.37, + "rateType": "weekly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-01T09:45:15.939Z", + "updatedAt": "2021-05-30T11:48:39.054Z", + "workPeriods": [ + { + "id": "eeea5cf0-513c-4d1a-9318-a376aa86c28f", + "resourceBookingId": "9e6e2bd4-1e4d-401b-871b-2c8fe8f44b54", + "userHandle": "ramag", + "projectId": 16899, + "startDate": "2021-01-17", + "endDate": "2021-01-23", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:39.879Z", + "updatedAt": "2021-05-30T16:03:01.733Z", + "payments": [] + }, + { + "id": "ab2c5ad4-165f-48d2-bf1c-005b56e049ce", + "resourceBookingId": "9e6e2bd4-1e4d-401b-871b-2c8fe8f44b54", + "userHandle": "ramag", + "projectId": 16899, + "startDate": "2021-02-07", + "endDate": "2021-02-13", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:48:39.824Z", + "updatedAt": "2021-05-30T16:11:51.073Z", + "payments": [] + }, + { + "id": "aed553d8-4eb4-45a8-86f0-3c21f81c7570", + "resourceBookingId": "9e6e2bd4-1e4d-401b-871b-2c8fe8f44b54", + "userHandle": "ramag", + "projectId": 16899, + "startDate": "2021-01-24", + "endDate": "2021-01-30", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:39.870Z", + "updatedAt": "2021-05-30T16:04:00.297Z", + "payments": [] + }, + { + "id": "4c9a7d50-8014-4ff2-9867-98dc66e466ac", + "resourceBookingId": "9e6e2bd4-1e4d-401b-871b-2c8fe8f44b54", + "userHandle": "ramag", + "projectId": 16899, + "startDate": "2021-01-10", + "endDate": "2021-01-16", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:39.838Z", + "updatedAt": "2021-05-30T16:05:09.308Z", + "payments": [] + }, + { + "id": "d5c4716f-e26a-4d3f-a57d-2410d7537ecd", + "resourceBookingId": "9e6e2bd4-1e4d-401b-871b-2c8fe8f44b54", + "userHandle": "ramag", + "projectId": 16899, + "startDate": "2021-01-31", + "endDate": "2021-02-06", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:39.820Z", + "updatedAt": "2021-05-30T16:03:21.454Z", + "payments": [] + } + ] + }, + { + "id": "72829b1f-9183-4660-815f-d3e80d38a5a9", + "projectId": 17290, + "userId": "0eaf032f-f376-47cc-b7aa-668685efac90", + "jobId": "fe600350-0a6d-4dac-922f-a6a7d285daa1", + "status": "placed", + "startDate": "2021-01-01", + "endDate": "2021-02-01", + "memberRate": 106.51, + "customerRate": 111.21, + "rateType": "weekly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-18T08:18:13.123Z", + "updatedAt": "2021-05-30T11:48:52.915Z", + "workPeriods": [ + { + "id": "e6b70714-8bd6-47ce-9e58-f04d3c25ee28", + "resourceBookingId": "72829b1f-9183-4660-815f-d3e80d38a5a9", + "userHandle": "gliu", + "projectId": 17290, + "startDate": "2021-01-24", + "endDate": "2021-01-30", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:53.719Z", + "updatedAt": "2021-05-30T16:03:09.841Z", + "payments": [] + }, + { + "id": "b6c1f079-e5cb-46a0-a6bf-5988ec013c4c", + "resourceBookingId": "72829b1f-9183-4660-815f-d3e80d38a5a9", + "userHandle": "gliu", + "projectId": 17290, + "startDate": "2021-01-03", + "endDate": "2021-01-09", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:53.776Z", + "updatedAt": "2021-05-30T16:03:49.745Z", + "payments": [] + }, + { + "id": "064d2511-9af6-4d6a-be4f-79eebacc6345", + "resourceBookingId": "72829b1f-9183-4660-815f-d3e80d38a5a9", + "userHandle": "gliu", + "projectId": 17290, + "startDate": "2021-01-31", + "endDate": "2021-02-06", + "daysWorked": 1, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:48:53.778Z", + "updatedAt": "2021-05-30T16:11:59.550Z", + "payments": [] + }, + { + "id": "c8c69543-1598-43e4-9ef6-8a569ebdf831", + "resourceBookingId": "72829b1f-9183-4660-815f-d3e80d38a5a9", + "userHandle": "gliu", + "projectId": 17290, + "startDate": "2020-12-27", + "endDate": "2021-01-02", + "daysWorked": 1, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:48:53.716Z", + "updatedAt": "2021-05-30T16:11:59.551Z", + "payments": [] + }, + { + "id": "0d237fa9-3fe9-48dc-82b8-7027edddc5a1", + "resourceBookingId": "72829b1f-9183-4660-815f-d3e80d38a5a9", + "userHandle": "gliu", + "projectId": 17290, + "startDate": "2021-01-10", + "endDate": "2021-01-16", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:53.731Z", + "updatedAt": "2021-05-30T16:05:57.480Z", + "payments": [] + }, + { + "id": "7bc96a71-deda-4cde-b8b0-f809cea1398a", + "resourceBookingId": "72829b1f-9183-4660-815f-d3e80d38a5a9", + "userHandle": "gliu", + "projectId": 17290, + "startDate": "2021-01-17", + "endDate": "2021-01-23", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:53.710Z", + "updatedAt": "2021-05-30T16:04:26.082Z", + "payments": [] + } + ] + }, + { + "id": "c666e835-4145-406e-b6bb-8b0f98ed8f68", + "projectId": 17290, + "userId": "1f6ca39c-0620-4de0-9bb2-d64d4ce26b42", + "jobId": "fe600350-0a6d-4dac-922f-a6a7d285daa1", + "status": "placed", + "startDate": "2021-01-11", + "endDate": "2021-02-11", + "memberRate": 4.07, + "customerRate": 296.66, + "rateType": "weekly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-18T07:05:53.664Z", + "updatedAt": "2021-05-30T11:48:33.177Z", + "workPeriods": [ + { + "id": "e29735b3-cf81-4877-8fd5-6d346a1824f0", + "resourceBookingId": "c666e835-4145-406e-b6bb-8b0f98ed8f68", + "userHandle": "suacoustic", + "projectId": 17290, + "startDate": "2021-01-17", + "endDate": "2021-01-23", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:33.942Z", + "updatedAt": "2021-05-30T16:03:12.511Z", + "payments": [] + }, + { + "id": "df0b3604-7ee9-4862-a8d1-abe8a2142f77", + "resourceBookingId": "c666e835-4145-406e-b6bb-8b0f98ed8f68", + "userHandle": "suacoustic", + "projectId": 17290, + "startDate": "2021-01-31", + "endDate": "2021-02-06", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:33.954Z", + "updatedAt": "2021-05-30T16:03:15.193Z", + "payments": [] + }, + { + "id": "9a480e44-2026-4327-a220-715ace30743e", + "resourceBookingId": "c666e835-4145-406e-b6bb-8b0f98ed8f68", + "userHandle": "suacoustic", + "projectId": 17290, + "startDate": "2021-01-10", + "endDate": "2021-01-16", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:33.952Z", + "updatedAt": "2021-05-30T16:04:12.811Z", + "payments": [] + }, + { + "id": "b6147962-6666-4534-8b73-0c7f9a7052e8", + "resourceBookingId": "c666e835-4145-406e-b6bb-8b0f98ed8f68", + "userHandle": "suacoustic", + "projectId": 17290, + "startDate": "2021-02-07", + "endDate": "2021-02-13", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:48:33.959Z", + "updatedAt": "2021-05-30T16:11:47.528Z", + "payments": [] + }, + { + "id": "47ac2474-d9e9-416d-afa8-fea8fb4f2a6c", + "resourceBookingId": "c666e835-4145-406e-b6bb-8b0f98ed8f68", + "userHandle": "suacoustic", + "projectId": 17290, + "startDate": "2021-01-24", + "endDate": "2021-01-30", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:33.940Z", + "updatedAt": "2021-05-30T16:05:12.030Z", + "payments": [] + } + ] + }, + { + "id": "5b93498d-eecf-4798-ad62-0dea8b4aa49e", + "projectId": 16781, + "userId": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "jobId": "ff3feeae-d4f7-457c-bff7-215be5efe2b8", + "status": "placed", + "startDate": "2021-01-01", + "endDate": "2021-02-01", + "memberRate": 54.02, + "customerRate": 217.99, + "rateType": "weekly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-01-12T15:02:15.210Z", + "updatedAt": "2021-05-30T11:48:59.149Z", + "workPeriods": [ + { + "id": "d062e2fe-2446-4fb5-b0b3-0577cd57fd7c", + "resourceBookingId": "5b93498d-eecf-4798-ad62-0dea8b4aa49e", + "userHandle": "nkumartest", + "projectId": 16781, + "startDate": "2021-01-17", + "endDate": "2021-01-23", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:59.909Z", + "updatedAt": "2021-05-30T16:03:24.198Z", + "payments": [] + }, + { + "id": "bdd60068-9e8d-4c43-8440-48a066ba4396", + "resourceBookingId": "5b93498d-eecf-4798-ad62-0dea8b4aa49e", + "userHandle": "nkumartest", + "projectId": 16781, + "startDate": "2021-01-31", + "endDate": "2021-02-06", + "daysWorked": 1, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:48:59.921Z", + "updatedAt": "2021-05-30T16:12:03.178Z", + "payments": [] + }, + { + "id": "a0eec246-3b4d-41b6-9d54-b892513bd727", + "resourceBookingId": "5b93498d-eecf-4798-ad62-0dea8b4aa49e", + "userHandle": "nkumartest", + "projectId": 16781, + "startDate": "2021-01-10", + "endDate": "2021-01-16", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:00.007Z", + "updatedAt": "2021-05-30T16:04:10.173Z", + "payments": [] + }, + { + "id": "752f3cf3-a9c2-487c-93ae-22d21af10403", + "resourceBookingId": "5b93498d-eecf-4798-ad62-0dea8b4aa49e", + "userHandle": "nkumartest", + "projectId": 16781, + "startDate": "2021-01-24", + "endDate": "2021-01-30", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:00.041Z", + "updatedAt": "2021-05-30T16:04:34.403Z", + "payments": [] + }, + { + "id": "5be5a577-32cd-4557-8d11-bb5723dd7be2", + "resourceBookingId": "5b93498d-eecf-4798-ad62-0dea8b4aa49e", + "userHandle": "nkumartest", + "projectId": 16781, + "startDate": "2021-01-03", + "endDate": "2021-01-09", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:59.998Z", + "updatedAt": "2021-05-30T16:04:57.065Z", + "payments": [] + }, + { + "id": "e9ff7b7f-05ec-45f9-a09e-b2c24017b59b", + "resourceBookingId": "5b93498d-eecf-4798-ad62-0dea8b4aa49e", + "userHandle": "nkumartest", + "projectId": 16781, + "startDate": "2020-12-27", + "endDate": "2021-01-02", + "daysWorked": 1, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:48:59.974Z", + "updatedAt": "2021-05-30T16:12:03.180Z", + "payments": [] + } + ] + }, + { + "id": "a74df62a-dba0-4214-8f8e-5e071f359afe", + "projectId": 17363, + "userId": "c40cdb0a-4fac-4ca1-8052-d92001858887", + "jobId": "fd48d96e-b0f2-43b7-8a48-f4fa194d6bc8", + "status": "placed", + "startDate": "2021-01-01", + "endDate": "2021-02-01", + "memberRate": 235.26, + "customerRate": 84.88, + "rateType": "hourly", + "billingAccountId": 80000071, + "createdBy": "71c5e6a8-51d9-4fb5-91ce-d974642531af", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-28T04:41:39.728Z", + "updatedAt": "2021-05-30T11:48:34.793Z", + "workPeriods": [ + { + "id": "2570737c-02b4-4b90-b692-45dcc5774215", + "resourceBookingId": "a74df62a-dba0-4214-8f8e-5e071f359afe", + "userHandle": "ApolloChang", + "projectId": 17363, + "startDate": "2020-12-27", + "endDate": "2021-01-02", + "daysWorked": 1, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:48:35.576Z", + "updatedAt": "2021-05-30T16:11:48.431Z", + "payments": [] + }, + { + "id": "789b83d2-3278-4c90-a5c1-3aa96e61db4b", + "resourceBookingId": "a74df62a-dba0-4214-8f8e-5e071f359afe", + "userHandle": "ApolloChang", + "projectId": 17363, + "startDate": "2021-01-03", + "endDate": "2021-01-09", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:35.600Z", + "updatedAt": "2021-05-30T16:04:27.884Z", + "payments": [] + }, + { + "id": "764fec45-842e-4d06-b009-29ba4c9c116c", + "resourceBookingId": "a74df62a-dba0-4214-8f8e-5e071f359afe", + "userHandle": "ApolloChang", + "projectId": 17363, + "startDate": "2021-01-24", + "endDate": "2021-01-30", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:35.588Z", + "updatedAt": "2021-05-30T16:04:32.547Z", + "payments": [] + }, + { + "id": "00fa978f-e2c4-4cab-8da9-e6b0dce80258", + "resourceBookingId": "a74df62a-dba0-4214-8f8e-5e071f359afe", + "userHandle": "ApolloChang", + "projectId": 17363, + "startDate": "2021-01-17", + "endDate": "2021-01-23", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:35.585Z", + "updatedAt": "2021-05-30T16:06:04.649Z", + "payments": [] + }, + { + "id": "daa54d7d-84f5-4f62-b58c-4c09ec26dd1a", + "resourceBookingId": "a74df62a-dba0-4214-8f8e-5e071f359afe", + "userHandle": "ApolloChang", + "projectId": 17363, + "startDate": "2021-01-31", + "endDate": "2021-02-06", + "daysWorked": 1, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:48:35.581Z", + "updatedAt": "2021-05-30T16:11:48.432Z", + "payments": [] + }, + { + "id": "94a897e9-6291-4206-a0b1-74c35ff06a6e", + "resourceBookingId": "a74df62a-dba0-4214-8f8e-5e071f359afe", + "userHandle": "ApolloChang", + "projectId": 17363, + "startDate": "2021-01-10", + "endDate": "2021-01-16", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:35.596Z", + "updatedAt": "2021-05-30T16:04:17.285Z", + "payments": [] + } + ] + }, + { + "id": "caf8fde9-2137-48fb-b388-24a1801eacf3", + "projectId": 17103, + "userId": "d8e11333-af08-4149-a270-b355001b44e7", + "jobId": "feef8b66-989d-4ec7-bdb0-59ca05c95003", + "status": "placed", + "startDate": "2021-01-01", + "endDate": "2021-02-01", + "memberRate": 240.84, + "customerRate": 100.25, + "rateType": "weekly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-01T12:20:21.613Z", + "updatedAt": "2021-05-30T11:48:28.143Z", + "workPeriods": [ + { + "id": "d0571318-a0be-4263-bfe9-eba783ba8957", + "resourceBookingId": "caf8fde9-2137-48fb-b388-24a1801eacf3", + "userHandle": "mvarlie", + "projectId": 17103, + "startDate": "2021-01-24", + "endDate": "2021-01-30", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:28.918Z", + "updatedAt": "2021-05-30T16:03:25.073Z", + "payments": [] + }, + { + "id": "9fd57023-518e-42e3-a998-6098ae49a3fb", + "resourceBookingId": "caf8fde9-2137-48fb-b388-24a1801eacf3", + "userHandle": "mvarlie", + "projectId": 17103, + "startDate": "2021-01-17", + "endDate": "2021-01-23", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:28.905Z", + "updatedAt": "2021-05-30T16:04:11.041Z", + "payments": [] + }, + { + "id": "b473e949-0a6e-452c-b626-6cc79ee61d1c", + "resourceBookingId": "caf8fde9-2137-48fb-b388-24a1801eacf3", + "userHandle": "mvarlie", + "projectId": 17103, + "startDate": "2021-01-10", + "endDate": "2021-01-16", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:28.924Z", + "updatedAt": "2021-05-30T16:03:54.140Z", + "payments": [] + }, + { + "id": "b952458d-12a9-4398-b549-3fe44d3814dd", + "resourceBookingId": "caf8fde9-2137-48fb-b388-24a1801eacf3", + "userHandle": "mvarlie", + "projectId": 17103, + "startDate": "2021-01-31", + "endDate": "2021-02-06", + "daysWorked": 1, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:48:28.922Z", + "updatedAt": "2021-05-30T16:11:44.684Z", + "payments": [] + }, + { + "id": "f206743e-f797-40a8-8dee-634fb0f08e08", + "resourceBookingId": "caf8fde9-2137-48fb-b388-24a1801eacf3", + "userHandle": "mvarlie", + "projectId": 17103, + "startDate": "2021-01-03", + "endDate": "2021-01-09", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:28.873Z", + "updatedAt": "2021-05-30T16:02:57.423Z", + "payments": [] + }, + { + "id": "ef0f5c89-c979-4504-9b20-54b110a1495a", + "resourceBookingId": "caf8fde9-2137-48fb-b388-24a1801eacf3", + "userHandle": "mvarlie", + "projectId": 17103, + "startDate": "2020-12-27", + "endDate": "2021-01-02", + "daysWorked": 1, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:48:28.915Z", + "updatedAt": "2021-05-30T16:11:44.683Z", + "payments": [] + } + ] + }, + { + "id": "c8cb4245-83d9-4c59-b595-f032b53b2cbc", + "projectId": 16899, + "userId": "47034de0-698d-4e1b-a10b-ae4b8c59288e", + "jobId": "fe270791-bc24-4f6a-8c1b-b897f5d97d2f", + "status": "placed", + "startDate": "2021-01-01", + "endDate": "2021-02-01", + "memberRate": 4.07, + "customerRate": 258.37, + "rateType": "monthly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-01T09:36:02.161Z", + "updatedAt": "2021-05-30T11:48:31.516Z", + "workPeriods": [ + { + "id": "0ae1abc8-3e8d-4eea-933e-ab3cfa7c6826", + "resourceBookingId": "c8cb4245-83d9-4c59-b595-f032b53b2cbc", + "userHandle": "brijgogogo", + "projectId": 16899, + "startDate": "2021-01-31", + "endDate": "2021-02-06", + "daysWorked": 1, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:48:32.269Z", + "updatedAt": "2021-05-30T16:11:46.620Z", + "payments": [] + }, + { + "id": "97fd7b67-0cd7-47fb-9017-7a7b653ef940", + "resourceBookingId": "c8cb4245-83d9-4c59-b595-f032b53b2cbc", + "userHandle": "brijgogogo", + "projectId": 16899, + "startDate": "2021-01-10", + "endDate": "2021-01-16", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:32.256Z", + "updatedAt": "2021-05-30T16:04:14.644Z", + "payments": [] + }, + { + "id": "3fe04a0d-62ff-4060-935a-4f294ee19fac", + "resourceBookingId": "c8cb4245-83d9-4c59-b595-f032b53b2cbc", + "userHandle": "brijgogogo", + "projectId": 16899, + "startDate": "2020-12-27", + "endDate": "2021-01-02", + "daysWorked": 1, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:48:32.237Z", + "updatedAt": "2021-05-30T16:11:46.621Z", + "payments": [] + }, + { + "id": "a3daf653-c87c-451b-acfc-508ef8364fbb", + "resourceBookingId": "c8cb4245-83d9-4c59-b595-f032b53b2cbc", + "userHandle": "brijgogogo", + "projectId": 16899, + "startDate": "2021-01-24", + "endDate": "2021-01-30", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:32.273Z", + "updatedAt": "2021-05-30T16:04:05.668Z", + "payments": [] + }, + { + "id": "15337715-0c4a-4036-a1d3-5aaa14a214af", + "resourceBookingId": "c8cb4245-83d9-4c59-b595-f032b53b2cbc", + "userHandle": "brijgogogo", + "projectId": 16899, + "startDate": "2021-01-03", + "endDate": "2021-01-09", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:32.252Z", + "updatedAt": "2021-05-30T16:05:51.388Z", + "payments": [] + }, + { + "id": "304a0ba1-2534-46c0-b2e9-9d85936755df", + "resourceBookingId": "c8cb4245-83d9-4c59-b595-f032b53b2cbc", + "userHandle": "brijgogogo", + "projectId": 16899, + "startDate": "2021-01-17", + "endDate": "2021-01-23", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:32.234Z", + "updatedAt": "2021-05-30T16:05:28.904Z", + "payments": [] + } + ] + }, + { + "id": "85ed4a55-1c13-45f0-bfd3-e5e0378b42ea", + "projectId": 16706, + "userId": "149c9ad0-f5d7-4192-8c61-f634f6120816", + "jobId": "fc2b006d-997b-49c3-a414-59ee54a48f9f", + "status": "sourcing", + "startDate": "2021-01-11", + "endDate": "2021-02-11", + "memberRate": 201.77, + "customerRate": 84.88, + "rateType": "weekly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-01-26T08:27:38.944Z", + "updatedAt": "2021-05-30T11:41:01.828Z", + "workPeriods": [ + { + "id": "b21eed94-dce5-42e1-9734-155594773222", + "resourceBookingId": "85ed4a55-1c13-45f0-bfd3-e5e0378b42ea", + "userHandle": "lt_dan", + "projectId": 16706, + "startDate": "2021-01-24", + "endDate": "2021-01-30", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:41:02.603Z", + "updatedAt": "2021-05-30T16:03:56.759Z", + "payments": [] + }, + { + "id": "85201917-77e0-41d1-8c76-66eefcbc23e0", + "resourceBookingId": "85ed4a55-1c13-45f0-bfd3-e5e0378b42ea", + "userHandle": "lt_dan", + "projectId": 16706, + "startDate": "2021-02-07", + "endDate": "2021-02-13", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:41:02.617Z", + "updatedAt": "2021-05-30T16:11:54.733Z", + "payments": [] + }, + { + "id": "56105e62-d690-484c-9fe8-b6d18671c9ac", + "resourceBookingId": "85ed4a55-1c13-45f0-bfd3-e5e0378b42ea", + "userHandle": "lt_dan", + "projectId": 16706, + "startDate": "2021-01-10", + "endDate": "2021-01-16", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:41:02.600Z", + "updatedAt": "2021-05-30T16:04:59.664Z", + "payments": [] + }, + { + "id": "5d6c9cf8-a6bc-43b9-af35-67812fc10db9", + "resourceBookingId": "85ed4a55-1c13-45f0-bfd3-e5e0378b42ea", + "userHandle": "lt_dan", + "projectId": 16706, + "startDate": "2021-01-31", + "endDate": "2021-02-06", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:41:02.595Z", + "updatedAt": "2021-05-30T16:04:54.450Z", + "payments": [] + }, + { + "id": "34ab1933-c9a3-4087-b220-3716d3729703", + "resourceBookingId": "85ed4a55-1c13-45f0-bfd3-e5e0378b42ea", + "userHandle": "lt_dan", + "projectId": 16706, + "startDate": "2021-01-17", + "endDate": "2021-01-23", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:41:02.645Z", + "updatedAt": "2021-05-30T16:05:24.577Z", + "payments": [] + } + ] + }, + { + "id": "9be5f15b-2114-4e35-8762-137e1d7b3740", + "projectId": 16714, + "userId": "bde2cf99-b290-40cd-a064-9b6bb7e54bea", + "jobId": "fc0240f0-8c8f-40ce-a551-e83b45673098", + "status": "sourcing", + "startDate": "2021-01-11", + "endDate": "2021-02-11", + "memberRate": 115.29, + "customerRate": 84.88, + "rateType": "weekly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-01-26T08:16:00.294Z", + "updatedAt": "2021-05-30T11:48:40.735Z", + "workPeriods": [ + { + "id": "ae316c25-ec04-4bc1-b209-798b69ed5250", + "resourceBookingId": "9be5f15b-2114-4e35-8762-137e1d7b3740", + "userHandle": "atish.chandra", + "projectId": 16714, + "startDate": "2021-01-31", + "endDate": "2021-02-06", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:41.592Z", + "updatedAt": "2021-05-30T16:04:01.125Z", + "payments": [] + }, + { + "id": "7501c035-46c4-4704-973a-595145bd2d17", + "resourceBookingId": "9be5f15b-2114-4e35-8762-137e1d7b3740", + "userHandle": "atish.chandra", + "projectId": 16714, + "startDate": "2021-02-07", + "endDate": "2021-02-13", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:48:41.588Z", + "updatedAt": "2021-05-30T16:11:52.009Z", + "payments": [] + }, + { + "id": "519b4818-8e39-4d4c-bcc6-3486816a4bc8", + "resourceBookingId": "9be5f15b-2114-4e35-8762-137e1d7b3740", + "userHandle": "atish.chandra", + "projectId": 16714, + "startDate": "2021-01-10", + "endDate": "2021-01-16", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:41.595Z", + "updatedAt": "2021-05-30T16:05:04.624Z", + "payments": [] + }, + { + "id": "13444e2f-1254-40fc-a7d9-08ca49fc7239", + "resourceBookingId": "9be5f15b-2114-4e35-8762-137e1d7b3740", + "userHandle": "atish.chandra", + "projectId": 16714, + "startDate": "2021-01-24", + "endDate": "2021-01-30", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:41.597Z", + "updatedAt": "2021-05-30T16:05:53.017Z", + "payments": [] + }, + { + "id": "66c66f68-3882-4521-9c4e-ce08e6b47ca0", + "resourceBookingId": "9be5f15b-2114-4e35-8762-137e1d7b3740", + "userHandle": "atish.chandra", + "projectId": 16714, + "startDate": "2021-01-17", + "endDate": "2021-01-23", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:41.579Z", + "updatedAt": "2021-05-30T16:04:44.142Z", + "payments": [] + } + ] + }, + { + "id": "80693c90-7714-47ac-b8d9-b1c93aed910f", + "projectId": 16805, + "userId": "13330208-ab10-4ca3-9fd1-a132fbf7ac4e", + "jobId": "fc58382a-31d7-44b7-bfe5-2d671300f8d9", + "status": "placed", + "startDate": "2021-01-01", + "endDate": "2021-02-01", + "memberRate": 4.79, + "customerRate": 146.2, + "rateType": "weekly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-01-19T11:04:22.566Z", + "updatedAt": "2021-05-30T11:48:46.861Z", + "workPeriods": [ + { + "id": "f2a85b87-8e75-4db9-b29c-a3c170101ed6", + "resourceBookingId": "80693c90-7714-47ac-b8d9-b1c93aed910f", + "userHandle": "Soumyajit_Lotus", + "projectId": 16805, + "startDate": "2021-01-17", + "endDate": "2021-01-23", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:47.631Z", + "updatedAt": "2021-05-30T16:02:54.605Z", + "payments": [] + }, + { + "id": "e6801711-327e-4387-a7f0-d592b49b1ba3", + "resourceBookingId": "80693c90-7714-47ac-b8d9-b1c93aed910f", + "userHandle": "Soumyajit_Lotus", + "projectId": 16805, + "startDate": "2021-01-10", + "endDate": "2021-01-16", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:47.726Z", + "updatedAt": "2021-05-30T16:03:10.690Z", + "payments": [] + }, + { + "id": "cd44a405-c77a-4f6d-95a7-c10de740eb29", + "resourceBookingId": "80693c90-7714-47ac-b8d9-b1c93aed910f", + "userHandle": "Soumyajit_Lotus", + "projectId": 16805, + "startDate": "2021-01-03", + "endDate": "2021-01-09", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:47.728Z", + "updatedAt": "2021-05-30T16:03:27.679Z", + "payments": [] + }, + { + "id": "6565d172-61c4-4357-a01f-b8e6bf179e2f", + "resourceBookingId": "80693c90-7714-47ac-b8d9-b1c93aed910f", + "userHandle": "Soumyajit_Lotus", + "projectId": 16805, + "startDate": "2021-01-31", + "endDate": "2021-02-06", + "daysWorked": 1, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:48:47.638Z", + "updatedAt": "2021-05-30T16:11:55.746Z", + "payments": [] + }, + { + "id": "f7c8a1e8-76c6-4eee-bb99-15cce5cb8b1f", + "resourceBookingId": "80693c90-7714-47ac-b8d9-b1c93aed910f", + "userHandle": "Soumyajit_Lotus", + "projectId": 16805, + "startDate": "2020-12-27", + "endDate": "2021-01-02", + "daysWorked": 1, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:48:47.648Z", + "updatedAt": "2021-05-30T16:11:55.747Z", + "payments": [] + }, + { + "id": "a71105ef-a2b8-4163-b2de-9ddcaa8329bb", + "resourceBookingId": "80693c90-7714-47ac-b8d9-b1c93aed910f", + "userHandle": "Soumyajit_Lotus", + "projectId": 16805, + "startDate": "2021-01-24", + "endDate": "2021-01-30", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:47.731Z", + "updatedAt": "2021-05-30T16:04:02.955Z", + "payments": [] + } + ] + }, + { + "id": "87db42ad-f3fa-4325-99f4-d5ac6e938219", + "projectId": 17232, + "userId": "8e6bfd51-fd78-45fa-9234-172976168f29", + "jobId": "ff76b81d-f49b-4019-b50e-c7932a818f19", + "status": "placed", + "startDate": "2021-01-11", + "endDate": "2021-02-11", + "memberRate": 225.34, + "customerRate": 170.64, + "rateType": "monthly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-18T04:01:23.725Z", + "updatedAt": "2021-05-30T11:48:44.244Z", + "workPeriods": [ + { + "id": "eeda07cc-8a10-4337-ab8d-e1107e4072a0", + "resourceBookingId": "87db42ad-f3fa-4325-99f4-d5ac6e938219", + "userHandle": "cyber-guard", + "projectId": 17232, + "startDate": "2021-01-10", + "endDate": "2021-01-16", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:45.002Z", + "updatedAt": "2021-05-30T16:03:02.635Z", + "payments": [] + }, + { + "id": "7aaa313f-62be-4483-80b2-87a95b4a0b8c", + "resourceBookingId": "87db42ad-f3fa-4325-99f4-d5ac6e938219", + "userHandle": "cyber-guard", + "projectId": 17232, + "startDate": "2021-01-31", + "endDate": "2021-02-06", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:45.006Z", + "updatedAt": "2021-05-30T16:04:26.995Z", + "payments": [] + }, + { + "id": "c0568bd9-1523-494d-bb3b-4b7a89026de9", + "resourceBookingId": "87db42ad-f3fa-4325-99f4-d5ac6e938219", + "userHandle": "cyber-guard", + "projectId": 17232, + "startDate": "2021-02-07", + "endDate": "2021-02-13", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:48:45.074Z", + "updatedAt": "2021-05-30T16:11:53.758Z", + "payments": [] + }, + { + "id": "4f7b2806-cdc4-40de-979e-82573123b1ce", + "resourceBookingId": "87db42ad-f3fa-4325-99f4-d5ac6e938219", + "userHandle": "cyber-guard", + "projectId": 17232, + "startDate": "2021-01-24", + "endDate": "2021-01-30", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:45.076Z", + "updatedAt": "2021-05-30T16:05:06.523Z", + "payments": [] + }, + { + "id": "3a652bb3-69b2-4e9b-b6e7-804568a9a76b", + "resourceBookingId": "87db42ad-f3fa-4325-99f4-d5ac6e938219", + "userHandle": "cyber-guard", + "projectId": 17232, + "startDate": "2021-01-17", + "endDate": "2021-01-23", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:45.012Z", + "updatedAt": "2021-05-30T16:05:20.251Z", + "payments": [] + } + ] + }, + { + "id": "905654a2-e07d-47a3-b577-c03d100bc94a", + "projectId": 17300, + "userId": "6719d9dc-beca-4731-a4be-a214152ccadf", + "jobId": "fd13ad99-f16a-4362-9274-80f5f38895c3", + "status": "placed", + "startDate": "2021-01-11", + "endDate": "2021-02-11", + "memberRate": 66, + "customerRate": 132.43, + "rateType": "daily", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-19T07:40:44.211Z", + "updatedAt": "2021-05-30T11:48:42.523Z", + "workPeriods": [ + { + "id": "6ca0c12a-eecb-4d12-b40d-89a19f2c38ad", + "resourceBookingId": "905654a2-e07d-47a3-b577-c03d100bc94a", + "userHandle": "vimal123", + "projectId": 17300, + "startDate": "2021-02-07", + "endDate": "2021-02-13", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:48:43.331Z", + "updatedAt": "2021-05-30T16:11:52.856Z", + "payments": [] + }, + { + "id": "92f9e88b-bc75-4934-9c3f-cdb3a846e545", + "resourceBookingId": "905654a2-e07d-47a3-b577-c03d100bc94a", + "userHandle": "vimal123", + "projectId": 17300, + "startDate": "2021-01-24", + "endDate": "2021-01-30", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:43.339Z", + "updatedAt": "2021-05-30T16:04:18.164Z", + "payments": [] + }, + { + "id": "11084a75-bae7-4c93-a2fc-44ff691b6ded", + "resourceBookingId": "905654a2-e07d-47a3-b577-c03d100bc94a", + "userHandle": "vimal123", + "projectId": 17300, + "startDate": "2021-01-17", + "endDate": "2021-01-23", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:43.335Z", + "updatedAt": "2021-05-30T16:05:54.898Z", + "payments": [] + }, + { + "id": "6c3a492a-d2bf-4740-91b0-0d877b044268", + "resourceBookingId": "905654a2-e07d-47a3-b577-c03d100bc94a", + "userHandle": "vimal123", + "projectId": 17300, + "startDate": "2021-01-10", + "endDate": "2021-01-16", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:43.275Z", + "updatedAt": "2021-05-30T16:04:41.476Z", + "payments": [] + }, + { + "id": "bc7af7e8-873a-4ddf-a3a5-8b5f0db41827", + "resourceBookingId": "905654a2-e07d-47a3-b577-c03d100bc94a", + "userHandle": "vimal123", + "projectId": 17300, + "startDate": "2021-01-31", + "endDate": "2021-02-06", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:43.254Z", + "updatedAt": "2021-05-30T16:03:45.211Z", + "payments": [] + } + ] + }, + { + "id": "72db31b8-f05c-497c-9bc6-b9f6692569a0", + "projectId": 16718, + "userId": "a953dce3-8dd3-413f-b253-0ca76ff59f36", + "jobId": "fb2f5f9b-5874-4dcd-af94-727fc0409760", + "status": "sourcing", + "startDate": "2021-01-11", + "endDate": "2021-02-11", + "memberRate": 269.46, + "customerRate": 138.32, + "rateType": "monthly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-01-26T08:24:56.376Z", + "updatedAt": "2021-05-30T11:48:51.233Z", + "workPeriods": [ + { + "id": "0ed78625-e5f0-4f05-b326-632a002d150a", + "resourceBookingId": "72db31b8-f05c-497c-9bc6-b9f6692569a0", + "userHandle": "centurionme", + "projectId": 16718, + "startDate": "2021-02-07", + "endDate": "2021-02-13", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:48:52.006Z", + "updatedAt": "2021-05-30T16:11:58.578Z", + "payments": [] + }, + { + "id": "279989ed-1e9e-45e9-bdb8-26c03d396344", + "resourceBookingId": "72db31b8-f05c-497c-9bc6-b9f6692569a0", + "userHandle": "centurionme", + "projectId": 16718, + "startDate": "2021-01-24", + "endDate": "2021-01-30", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:51.981Z", + "updatedAt": "2021-05-30T16:05:33.514Z", + "payments": [] + }, + { + "id": "31530732-4c7a-429c-9384-c219f16590fa", + "resourceBookingId": "72db31b8-f05c-497c-9bc6-b9f6692569a0", + "userHandle": "centurionme", + "projectId": 16718, + "startDate": "2021-01-10", + "endDate": "2021-01-16", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:51.988Z", + "updatedAt": "2021-05-30T16:05:27.123Z", + "payments": [] + }, + { + "id": "91065330-b979-4b3c-b084-0e14b6be6740", + "resourceBookingId": "72db31b8-f05c-497c-9bc6-b9f6692569a0", + "userHandle": "centurionme", + "projectId": 16718, + "startDate": "2021-01-31", + "endDate": "2021-02-06", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:51.984Z", + "updatedAt": "2021-05-30T16:04:19.946Z", + "payments": [] + }, + { + "id": "06187a37-d29a-4bdb-bcb1-e0e7f57eec4a", + "resourceBookingId": "72db31b8-f05c-497c-9bc6-b9f6692569a0", + "userHandle": "centurionme", + "projectId": 16718, + "startDate": "2021-01-17", + "endDate": "2021-01-23", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:51.978Z", + "updatedAt": "2021-05-30T16:06:00.996Z", + "payments": [] + } + ] + }, + { + "id": "6a4e3e22-5241-4353-94a2-f1ec0c3002e7", + "projectId": 16870, + "userId": "cc959274-bb53-4612-a4f4-af62496b026c", + "jobId": "fe8da845-5313-496f-b859-9824bd06a0db", + "status": "placed", + "startDate": "2021-01-12", + "endDate": "2021-02-12", + "memberRate": 240.84, + "customerRate": 188.33, + "rateType": "weekly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-01T09:30:37.276Z", + "updatedAt": "2021-05-30T11:48:54.737Z", + "workPeriods": [ + { + "id": "c44339a8-5562-493d-9e59-02fded34dadd", + "resourceBookingId": "6a4e3e22-5241-4353-94a2-f1ec0c3002e7", + "userHandle": "MikeKusold", + "projectId": 16870, + "startDate": "2021-01-17", + "endDate": "2021-01-23", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:55.482Z", + "updatedAt": "2021-05-30T16:03:38.050Z", + "payments": [] + }, + { + "id": "6e8627d9-f3b9-4e56-ba48-0d4cd0572beb", + "resourceBookingId": "6a4e3e22-5241-4353-94a2-f1ec0c3002e7", + "userHandle": "MikeKusold", + "projectId": 16870, + "startDate": "2021-01-24", + "endDate": "2021-01-30", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:55.537Z", + "updatedAt": "2021-05-30T16:04:39.704Z", + "payments": [] + }, + { + "id": "36abc507-0e01-46e3-ab78-52c0e8f848b1", + "resourceBookingId": "6a4e3e22-5241-4353-94a2-f1ec0c3002e7", + "userHandle": "MikeKusold", + "projectId": 16870, + "startDate": "2021-01-31", + "endDate": "2021-02-06", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:55.539Z", + "updatedAt": "2021-05-30T16:05:22.767Z", + "payments": [] + }, + { + "id": "20b18eeb-a78f-4ff2-8a3b-fbd1cfba567c", + "resourceBookingId": "6a4e3e22-5241-4353-94a2-f1ec0c3002e7", + "userHandle": "MikeKusold", + "projectId": 16870, + "startDate": "2021-02-07", + "endDate": "2021-02-13", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:55.526Z", + "updatedAt": "2021-05-30T16:05:40.643Z", + "payments": [] + }, + { + "id": "4b8cc238-bb26-4fbf-ab74-a86c1d9a47ce", + "resourceBookingId": "6a4e3e22-5241-4353-94a2-f1ec0c3002e7", + "userHandle": "MikeKusold", + "projectId": 16870, + "startDate": "2021-01-10", + "endDate": "2021-01-16", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:48:55.532Z", + "updatedAt": "2021-05-30T16:12:00.505Z", + "payments": [] + } + ] + }, + { + "id": "a331f572-8df0-4e00-8573-6aa09431e3d9", + "projectId": 16805, + "userId": "3797d69c-0bf1-421e-b086-81e36ec1f929", + "jobId": "fc58382a-31d7-44b7-bfe5-2d671300f8d9", + "status": "placed", + "startDate": "2021-01-11", + "endDate": "2021-02-11", + "memberRate": 1.59, + "customerRate": 170.64, + "rateType": "weekly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-28T05:15:29.662Z", + "updatedAt": "2021-05-30T11:48:37.381Z", + "workPeriods": [ + { + "id": "33b3b539-5741-49af-a700-fa8e9bd4abba", + "resourceBookingId": "a331f572-8df0-4e00-8573-6aa09431e3d9", + "userHandle": "cp185035", + "projectId": 16805, + "startDate": "2021-01-24", + "endDate": "2021-01-30", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:38.136Z", + "updatedAt": "2021-05-30T16:05:25.424Z", + "payments": [] + }, + { + "id": "eca90916-ded1-49d5-8beb-582bba178dd9", + "resourceBookingId": "a331f572-8df0-4e00-8573-6aa09431e3d9", + "userHandle": "cp185035", + "projectId": 16805, + "startDate": "2021-02-07", + "endDate": "2021-02-13", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:48:38.215Z", + "updatedAt": "2021-05-30T16:11:50.205Z", + "payments": [] + }, + { + "id": "2f176676-60f7-4d27-bb79-d1183eb0b7e0", + "resourceBookingId": "a331f572-8df0-4e00-8573-6aa09431e3d9", + "userHandle": "cp185035", + "projectId": 16805, + "startDate": "2021-01-17", + "endDate": "2021-01-23", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:38.152Z", + "updatedAt": "2021-05-30T16:05:29.869Z", + "payments": [] + }, + { + "id": "0ac738d8-03be-4ba4-a86b-2a1f65666cd5", + "resourceBookingId": "a331f572-8df0-4e00-8573-6aa09431e3d9", + "userHandle": "cp185035", + "projectId": 16805, + "startDate": "2021-01-10", + "endDate": "2021-01-16", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:38.220Z", + "updatedAt": "2021-05-30T16:05:59.284Z", + "payments": [] + }, + { + "id": "b180bd57-30b3-4092-affc-c306401edd7d", + "resourceBookingId": "a331f572-8df0-4e00-8573-6aa09431e3d9", + "userHandle": "cp185035", + "projectId": 16805, + "startDate": "2021-01-31", + "endDate": "2021-02-06", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:38.150Z", + "updatedAt": "2021-05-30T16:03:57.617Z", + "payments": [] + } + ] + }, + { + "id": "c9f268af-a03f-476e-a58b-1a2bb52324e0", + "projectId": 16739, + "userId": "3ed9015f-09d8-4173-bfcd-5dcc60c52060", + "jobId": "fc5ba131-566f-46fe-8501-79c593241896", + "status": "placed", + "startDate": "2021-01-01", + "endDate": "2021-02-01", + "memberRate": 61.33, + "customerRate": 114.05, + "rateType": "hourly", + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-17T13:41:56.896Z", + "updatedAt": "2021-05-30T11:48:29.760Z", + "workPeriods": [ + { + "id": "1dc38edd-3b56-4ed3-ae6c-ea2527076b32", + "resourceBookingId": "c9f268af-a03f-476e-a58b-1a2bb52324e0", + "userHandle": "epicdoom", + "projectId": 16739, + "startDate": "2021-01-10", + "endDate": "2021-01-16", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:30.606Z", + "updatedAt": "2021-05-30T16:05:46.841Z", + "payments": [] + }, + { + "id": "212909c4-b1e9-4d12-b2ca-4175ccbb2d7f", + "resourceBookingId": "c9f268af-a03f-476e-a58b-1a2bb52324e0", + "userHandle": "epicdoom", + "projectId": 16739, + "startDate": "2021-01-31", + "endDate": "2021-02-06", + "daysWorked": 1, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:48:30.530Z", + "updatedAt": "2021-05-30T16:11:45.643Z", + "payments": [] + }, + { + "id": "d4dffbb9-2224-4429-9d7e-4bd9d33dba70", + "resourceBookingId": "c9f268af-a03f-476e-a58b-1a2bb52324e0", + "userHandle": "epicdoom", + "projectId": 16739, + "startDate": "2021-01-24", + "endDate": "2021-01-30", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:30.547Z", + "updatedAt": "2021-05-30T16:03:22.384Z", + "payments": [] + }, + { + "id": "b6b60c49-615a-4367-b644-af68485b4293", + "resourceBookingId": "c9f268af-a03f-476e-a58b-1a2bb52324e0", + "userHandle": "epicdoom", + "projectId": 16739, + "startDate": "2020-12-27", + "endDate": "2021-01-02", + "daysWorked": 1, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:48:30.540Z", + "updatedAt": "2021-05-30T16:11:45.644Z", + "payments": [] + }, + { + "id": "7d495eed-d042-4a96-beed-dc2f2c1054c1", + "resourceBookingId": "c9f268af-a03f-476e-a58b-1a2bb52324e0", + "userHandle": "epicdoom", + "projectId": 16739, + "startDate": "2021-01-17", + "endDate": "2021-01-23", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:30.527Z", + "updatedAt": "2021-05-30T16:04:25.202Z", + "payments": [] + }, + { + "id": "7468173d-6d92-4560-802e-6329ab656754", + "resourceBookingId": "c9f268af-a03f-476e-a58b-1a2bb52324e0", + "userHandle": "epicdoom", + "projectId": 16739, + "startDate": "2021-01-03", + "endDate": "2021-01-09", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:48:30.544Z", + "updatedAt": "2021-05-30T16:04:36.153Z", + "payments": [] + } + ] + }, + { + "id": "1fd9cc33-d0ae-4be2-865b-95bc95c71700", + "projectId": 17324, + "userId": "9807980a-a9e4-4f24-a48b-311fcdbf1f47", + "jobId": "fefd2618-9b66-4431-9874-1d02d7a37d90", + "status": "placed", + "startDate": "2021-01-01", + "endDate": "2021-02-01", + "memberRate": 287.14, + "customerRate": 146.2, + "rateType": "weekly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-27T05:05:05.125Z", + "updatedAt": "2021-05-30T11:49:06.302Z", + "workPeriods": [ + { + "id": "d711870a-4f78-431b-b5b5-ae5157999a0c", + "resourceBookingId": "1fd9cc33-d0ae-4be2-865b-95bc95c71700", + "userHandle": "bone2", + "projectId": 17324, + "startDate": "2021-01-17", + "endDate": "2021-01-23", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:07.137Z", + "updatedAt": "2021-05-30T16:03:20.574Z", + "payments": [] + }, + { + "id": "d0266458-f9d2-42db-a716-6f114b4a0be0", + "resourceBookingId": "1fd9cc33-d0ae-4be2-865b-95bc95c71700", + "userHandle": "bone2", + "projectId": 17324, + "startDate": "2021-01-24", + "endDate": "2021-01-30", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:07.095Z", + "updatedAt": "2021-05-30T16:03:25.900Z", + "payments": [] + }, + { + "id": "248de422-69c3-4c5b-8919-ba18113d0350", + "resourceBookingId": "1fd9cc33-d0ae-4be2-865b-95bc95c71700", + "userHandle": "bone2", + "projectId": 17324, + "startDate": "2021-01-10", + "endDate": "2021-01-16", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:07.106Z", + "updatedAt": "2021-05-30T16:05:36.306Z", + "payments": [] + }, + { + "id": "6aabe458-6e77-4fbd-9092-d811e7bbd21d", + "resourceBookingId": "1fd9cc33-d0ae-4be2-865b-95bc95c71700", + "userHandle": "bone2", + "projectId": 17324, + "startDate": "2021-01-31", + "endDate": "2021-02-06", + "daysWorked": 1, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:49:07.144Z", + "updatedAt": "2021-05-30T16:12:08.558Z", + "payments": [] + }, + { + "id": "662931c7-09a4-43d9-a838-cb275296e818", + "resourceBookingId": "1fd9cc33-d0ae-4be2-865b-95bc95c71700", + "userHandle": "bone2", + "projectId": 17324, + "startDate": "2020-12-27", + "endDate": "2021-01-02", + "daysWorked": 1, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:49:07.100Z", + "updatedAt": "2021-05-30T16:12:08.560Z", + "payments": [] + }, + { + "id": "11d7db8c-b4a9-47b0-b24a-e45d4dc5fae4", + "resourceBookingId": "1fd9cc33-d0ae-4be2-865b-95bc95c71700", + "userHandle": "bone2", + "projectId": 17324, + "startDate": "2021-01-03", + "endDate": "2021-01-09", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:07.103Z", + "updatedAt": "2021-05-30T16:05:53.988Z", + "payments": [] + } + ] + }, + { + "id": "0ffde888-a7d5-4ca7-8bd3-eea54f7c05f2", + "projectId": 17091, + "userId": "de029f4b-f07b-4f8e-bc58-d928b8d8d289", + "jobId": "fb8b92f6-4ffb-4ba6-8c38-c2d4a151f76b", + "status": "placed", + "startDate": "2021-01-11", + "endDate": "2021-02-11", + "memberRate": 271.93, + "customerRate": 258.37, + "rateType": "weekly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-01T09:46:05.754Z", + "updatedAt": "2021-05-30T11:49:14.166Z", + "workPeriods": [ + { + "id": "f234f6bb-a90f-4f2d-a205-24ac45f09246", + "resourceBookingId": "0ffde888-a7d5-4ca7-8bd3-eea54f7c05f2", + "userHandle": "kagematya", + "projectId": 17091, + "startDate": "2021-01-17", + "endDate": "2021-01-23", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:14.947Z", + "updatedAt": "2021-05-30T16:02:56.406Z", + "payments": [] + }, + { + "id": "2962c8d7-aeab-422e-aa9e-fd76a2c559d6", + "resourceBookingId": "0ffde888-a7d5-4ca7-8bd3-eea54f7c05f2", + "userHandle": "kagematya", + "projectId": 17091, + "startDate": "2021-02-07", + "endDate": "2021-02-13", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:49:15.005Z", + "updatedAt": "2021-05-30T16:12:13.268Z", + "payments": [] + }, + { + "id": "729c31fb-dcd7-4b1e-bab8-b47f2db27f12", + "resourceBookingId": "0ffde888-a7d5-4ca7-8bd3-eea54f7c05f2", + "userHandle": "kagematya", + "projectId": 17091, + "startDate": "2021-01-24", + "endDate": "2021-01-30", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:14.943Z", + "updatedAt": "2021-05-30T16:04:37.868Z", + "payments": [] + }, + { + "id": "4dff33bc-ef83-425c-a07d-f49a12e2485f", + "resourceBookingId": "0ffde888-a7d5-4ca7-8bd3-eea54f7c05f2", + "userHandle": "kagematya", + "projectId": 17091, + "startDate": "2021-01-31", + "endDate": "2021-02-06", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:14.956Z", + "updatedAt": "2021-05-30T16:05:07.460Z", + "payments": [] + }, + { + "id": "2b2aaaba-2698-4b32-b6b9-e31e040ee023", + "resourceBookingId": "0ffde888-a7d5-4ca7-8bd3-eea54f7c05f2", + "userHandle": "kagematya", + "projectId": 17091, + "startDate": "2021-01-10", + "endDate": "2021-01-16", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:14.958Z", + "updatedAt": "2021-05-30T16:05:31.643Z", + "payments": [] + } + ] + }, + { + "id": "1511406b-9d2b-43f0-99b6-2117d1012aaf", + "projectId": 16870, + "userId": "46550d28-0f34-4292-908f-02f1a34ac278", + "jobId": "fe539bef-9119-4a8c-b7b0-915e7e3a3ba3", + "status": "placed", + "startDate": "2021-01-13", + "endDate": "2021-02-13", + "memberRate": 85.22, + "customerRate": 265.1, + "rateType": "weekly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-01T08:45:58.009Z", + "updatedAt": "2021-05-30T11:49:12.395Z", + "workPeriods": [ + { + "id": "dae10e27-1bec-4004-adb9-25a09a29f58d", + "resourceBookingId": "1511406b-9d2b-43f0-99b6-2117d1012aaf", + "userHandle": "prasanna992", + "projectId": 16870, + "startDate": "2021-01-10", + "endDate": "2021-01-16", + "daysWorked": 3, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:49:13.147Z", + "updatedAt": "2021-05-30T16:12:12.417Z", + "payments": [] + }, + { + "id": "60cfd6f3-4eed-4e2f-98be-f1377648d700", + "resourceBookingId": "1511406b-9d2b-43f0-99b6-2117d1012aaf", + "userHandle": "prasanna992", + "projectId": 16870, + "startDate": "2021-02-07", + "endDate": "2021-02-13", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:13.155Z", + "updatedAt": "2021-05-30T16:04:52.604Z", + "payments": [] + }, + { + "id": "5356e3d0-fa3e-4a4a-a94b-3d58745c09f7", + "resourceBookingId": "1511406b-9d2b-43f0-99b6-2117d1012aaf", + "userHandle": "prasanna992", + "projectId": 16870, + "startDate": "2021-01-31", + "endDate": "2021-02-06", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:13.213Z", + "updatedAt": "2021-05-30T16:05:01.471Z", + "payments": [] + }, + { + "id": "394196b1-7fde-4b3e-a6f2-1d95cd93c27d", + "resourceBookingId": "1511406b-9d2b-43f0-99b6-2117d1012aaf", + "userHandle": "prasanna992", + "projectId": 16870, + "startDate": "2021-01-24", + "endDate": "2021-01-30", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:13.168Z", + "updatedAt": "2021-05-30T16:05:21.118Z", + "payments": [] + }, + { + "id": "a6fa8266-f335-4148-96a7-3f63dc66aec4", + "resourceBookingId": "1511406b-9d2b-43f0-99b6-2117d1012aaf", + "userHandle": "prasanna992", + "projectId": 16870, + "startDate": "2021-01-17", + "endDate": "2021-01-23", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:13.142Z", + "updatedAt": "2021-05-30T16:04:03.881Z", + "payments": [] + } + ] + }, + { + "id": "198fb1a7-f662-4e35-aa8b-7dd171d2f519", + "projectId": 17300, + "userId": "2bba34d5-20e4-46d6-bfc1-05736b17afbb", + "jobId": "fd13ad99-f16a-4362-9274-80f5f38895c3", + "status": "placed", + "startDate": "2021-01-01", + "endDate": "2021-02-01", + "memberRate": 104.85, + "customerRate": 138.32, + "rateType": "weekly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-20T06:52:10.333Z", + "updatedAt": "2021-05-30T11:49:09.704Z", + "workPeriods": [ + { + "id": "cdda5ed7-5ddf-4985-8856-9b691c196db3", + "resourceBookingId": "198fb1a7-f662-4e35-aa8b-7dd171d2f519", + "userHandle": "GunaK-TopCoder", + "projectId": 17300, + "startDate": "2021-01-31", + "endDate": "2021-02-06", + "daysWorked": 1, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:49:10.560Z", + "updatedAt": "2021-05-30T16:12:10.667Z", + "payments": [] + }, + { + "id": "ee556bae-58ad-4f64-a48a-ce87362bad3d", + "resourceBookingId": "198fb1a7-f662-4e35-aa8b-7dd171d2f519", + "userHandle": "GunaK-TopCoder", + "projectId": 17300, + "startDate": "2020-12-27", + "endDate": "2021-01-02", + "daysWorked": 1, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "00000000-0000-0000-0000-000000000000", + "createdAt": "2021-05-30T11:49:10.570Z", + "updatedAt": "2021-05-30T16:12:10.668Z", + "payments": [] + }, + { + "id": "52c34f5f-290c-4ff0-9d7a-30f43868f83d", + "resourceBookingId": "198fb1a7-f662-4e35-aa8b-7dd171d2f519", + "userHandle": "GunaK-TopCoder", + "projectId": 17300, + "startDate": "2021-01-17", + "endDate": "2021-01-23", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:10.568Z", + "updatedAt": "2021-05-30T16:05:03.441Z", + "payments": [] + }, + { + "id": "bd27f1a4-b7ee-4526-a21c-fd8c4955fe5e", + "resourceBookingId": "198fb1a7-f662-4e35-aa8b-7dd171d2f519", + "userHandle": "GunaK-TopCoder", + "projectId": 17300, + "startDate": "2021-01-10", + "endDate": "2021-01-16", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:10.566Z", + "updatedAt": "2021-05-30T16:03:43.365Z", + "payments": [] + }, + { + "id": "64c0b0b8-9c77-4e7c-9d0a-14541e8e0a34", + "resourceBookingId": "198fb1a7-f662-4e35-aa8b-7dd171d2f519", + "userHandle": "GunaK-TopCoder", + "projectId": 17300, + "startDate": "2021-01-03", + "endDate": "2021-01-09", + "daysWorked": 5, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:10.622Z", + "updatedAt": "2021-05-30T16:04:49.270Z", + "payments": [] + }, + { + "id": "f41169e6-e9e0-44ce-a54d-5a84a32085c6", + "resourceBookingId": "198fb1a7-f662-4e35-aa8b-7dd171d2f519", + "userHandle": "GunaK-TopCoder", + "projectId": 17300, + "startDate": "2021-01-24", + "endDate": "2021-01-30", + "daysWorked": 4, + "daysPaid": 0, + "paymentTotal": 0, + "paymentStatus": "pending", + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-30T11:49:10.558Z", + "updatedAt": "2021-05-30T16:02:52.797Z", + "payments": [] + } + ] + }, + { + "id": "d3cd14c8-9ae8-446a-b554-69240c93a20e", + "projectId": 17091, + "userId": "3e654566-0d6b-404a-a000-c8640252c0e1", + "jobId": "fb8b92f6-4ffb-4ba6-8c38-c2d4a151f76b", + "status": "placed", + "startDate": null, + "endDate": null, + "memberRate": 201.77, + "customerRate": 296.66, + "rateType": "weekly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-01T09:58:18.513Z", + "updatedAt": "2021-05-30T11:48:25.595Z", + "workPeriods": [] + }, + { + "id": "7d81f99f-e4d2-49ff-8ce5-39832ea972fe", + "projectId": 16870, + "userId": "74219092-52ee-4434-a35e-25f000369645", + "jobId": "fe8da845-5313-496f-b859-9824bd06a0db", + "status": "placed", + "startDate": null, + "endDate": null, + "memberRate": 211.1, + "customerRate": 100.25, + "rateType": "monthly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-01T09:30:42.397Z", + "updatedAt": "2021-05-30T11:48:48.669Z", + "workPeriods": [] + }, + { + "id": "e7d96c52-a7ec-40e1-be64-6ef21fab4a1e", + "projectId": 16718, + "userId": "d82d4d41-1f25-4faf-ac24-3b5f8a138fac", + "jobId": "fb2f5f9b-5874-4dcd-af94-727fc0409760", + "status": "placed", + "startDate": null, + "endDate": null, + "memberRate": 271.93, + "customerRate": 58.22, + "rateType": "hourly", + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-17T13:44:23.792Z", + "updatedAt": "2021-05-30T11:48:19.456Z", + "workPeriods": [] + }, + { + "id": "5c3536b3-7523-4706-9396-eaa44ec608bb", + "projectId": 17103, + "userId": "93814e61-3b44-40bf-acaf-477857f52f90", + "jobId": "feef8b66-989d-4ec7-bdb0-59ca05c95003", + "status": "placed", + "startDate": null, + "endDate": null, + "memberRate": 115.29, + "customerRate": 114.05, + "rateType": "weekly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-01T09:53:01.882Z", + "updatedAt": "2021-05-30T11:48:58.248Z", + "workPeriods": [] + }, + { + "id": "1553e801-61c1-4069-ac58-bcb206ac2e44", + "projectId": 16781, + "userId": "bea5b4c1-922d-4800-ae27-c2f45b7e20bc", + "jobId": "ff3feeae-d4f7-457c-bff7-215be5efe2b8", + "status": "placed", + "startDate": null, + "endDate": null, + "memberRate": 186.53, + "customerRate": 265.1, + "rateType": "weekly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-01-19T10:07:50.071Z", + "updatedAt": "2021-05-30T11:49:11.520Z", + "workPeriods": [] + }, + { + "id": "a386f79d-724e-4c13-bf85-b8e5a0394617", + "projectId": 16706, + "userId": "f21455ae-a5f1-41a7-86eb-152e0e113b6e", + "jobId": "fc2b006d-997b-49c3-a414-59ee54a48f9f", + "status": "sourcing", + "startDate": null, + "endDate": null, + "memberRate": 115.29, + "customerRate": 146.2, + "rateType": "weekly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-01-26T08:25:01.121Z", + "updatedAt": "2021-05-30T11:39:24.762Z", + "workPeriods": [] + }, + { + "id": "4141d57c-2712-4dab-8140-904ab4364e98", + "projectId": 16714, + "userId": "fc04aa5d-9c34-4dd6-be8d-10ec0e3e6d01", + "jobId": "fc0240f0-8c8f-40ce-a551-e83b45673098", + "status": "sourcing", + "startDate": null, + "endDate": null, + "memberRate": 60.63, + "customerRate": 196.21, + "rateType": "weekly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-01-25T13:12:14.707Z", + "updatedAt": "2021-05-30T11:49:03.637Z", + "workPeriods": [] + }, + { + "id": "042d8158-3cee-4289-839e-1f2a73af1859", + "projectId": 16805, + "userId": "388f9618-5a2c-4a58-b587-3b3dfbb3f584", + "jobId": "fc58382a-31d7-44b7-bfe5-2d671300f8d9", + "status": "placed", + "startDate": null, + "endDate": null, + "memberRate": 115.29, + "customerRate": 111.21, + "rateType": "monthly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-04-20T08:04:17.892Z", + "updatedAt": "2021-05-30T11:49:24.627Z", + "workPeriods": [] + }, + { + "id": "21ae6f7f-f594-496a-9d87-175fd5820286", + "projectId": 16870, + "userId": "2bba34d5-20e4-46d6-bfc1-05736b17afbb", + "jobId": "fed687e1-4257-48bb-806c-38712f9bf14f", + "status": "placed", + "startDate": null, + "endDate": null, + "memberRate": 30.29, + "customerRate": 217.99, + "rateType": "weekly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-04-20T08:04:14.718Z", + "updatedAt": "2021-05-30T11:49:05.373Z", + "workPeriods": [] + }, + { + "id": "41fb1035-3165-4ff9-a2df-62c700fb8b37", + "projectId": 17290, + "userId": "b5bc4d91-2396-467b-8f7d-9a56ffb0feb0", + "jobId": "fe600350-0a6d-4dac-922f-a6a7d285daa1", + "status": "placed", + "startDate": null, + "endDate": null, + "memberRate": 240.84, + "customerRate": 146.2, + "rateType": "weekly", + "billingAccountId": 80000071, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-18T04:01:38.141Z", + "updatedAt": "2021-05-30T11:49:02.754Z", + "workPeriods": [] + }, + { + "id": "f0738f2a-c837-42e3-acdf-0e1324d77e53", + "projectId": 16739, + "userId": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "jobId": "fc5ba131-566f-46fe-8501-79c593241896", + "status": "placed", + "startDate": null, + "endDate": null, + "memberRate": 271.93, + "customerRate": 258.37, + "rateType": "hourly", + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-05-17T13:43:44.675Z", + "updatedAt": "2021-05-30T11:48:16.870Z", + "workPeriods": [] + } + ], + "Role": [ + { + "id": "c145247d-5757-463d-9317-ff9e7026d403", + "name": "Angular Developer", + "description": "Angular is an open-source, client-side framework based on TypeScript and designed for building web applications.", + "listOfSkills": [ + "database", + "winforms", + "user interface (ui)", + "photoshop" + ], + "rates": [ + { + "global": 50, + "offShore": 10, + "inCountry": 20 + }, + { + "global": 25, + "offShore": 5, + "inCountry": 15 + } + ], + "numberOfMembers": "10", + "numberOfMembersAvailable": 8, + "imageUrl": "http://images.topcoder.com/member", + "timeToCandidate": 105, + "timeToInterview": 100, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-27T21:43:08.201Z", + "updatedAt": "2021-05-27T21:43:08.201Z" + }, + { + "id": "d7ff0289-d3ea-44d8-b39a-53bba5b5b309", + "name": "Dev Ops Engineer", + "description": "A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.", + "listOfSkills": [ + "dropwizard", + "nginx", + "machine learning", + "force.com" + ], + "rates": [ + { + "global": 50, + "offShore": 10, + "inCountry": 20, + "rate20Global": 20, + "rate30Global": 20, + "rate20OffShore": 35, + "rate30OffShore": 35, + "rate20InCountry": 15, + "rate30InCountry": 15 + }, + { + "global": 25, + "offShore": 5, + "inCountry": 15, + "rate20Global": 20, + "rate30Global": 20, + "rate20OffShore": 35, + "rate30OffShore": 35, + "rate20InCountry": 15, + "rate30InCountry": 15 + } + ], + "numberOfMembers": "10", + "numberOfMembersAvailable": 8, + "imageUrl": "http://images.topcoder.com/member", + "timeToCandidate": 105, + "timeToInterview": 100, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": null, + "createdAt": "2021-05-27T21:43:04.717Z", + "updatedAt": "2021-05-27T21:43:04.717Z" + }, + { + "id": "e7b7e818-40d4-4102-b486-09bdd21400b8", + "name": "Salesforce Developer", + "description": "A Salesforce developer is a programmer who builds Salesforce applications across various PaaS (Platform as a Service) platforms.", + "listOfSkills": [ + "docker", + ".net", + "appcelerator", + "flux" + ], + "rates": [ + { + "global": 50, + "offShore": 10, + "inCountry": 20, + "rate20Global": 20, + "rate30Global": 20, + "rate20OffShore": 35, + "rate30OffShore": 35, + "rate20InCountry": 15, + "rate30InCountry": 15 + }, + { + "global": 25, + "offShore": 5, + "inCountry": 15, + "rate20Global": 20, + "rate30Global": 20, + "rate20OffShore": 35, + "rate30OffShore": 35, + "rate20InCountry": 15, + "rate30InCountry": 15 + } + ], + "numberOfMembers": "10", + "numberOfMembersAvailable": 6, + "imageUrl": "http://images.topcoder.com/member", + "timeToCandidate": 105, + "timeToInterview": 100, + "createdBy": "00000000-0000-0000-0000-000000000000", + "updatedBy": null, + "createdAt": "2021-05-27T21:43:09.342Z", + "updatedAt": "2021-05-27T21:43:09.342Z" } - ] - } - ], - "ResourceBooking": [ - { - "id": "08f5e4b9-1088-496d-91a7-5b22a3583e3c", - "projectId": 111, - "userId": "213d2dd9-1fc3-4eda-ad97-2d56e2a84a1e", - "jobId": "2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0", - "status": "placed", - "startDate": "2021-01-25", - "endDate": "2021-01-31", - "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-03-25", - "endDate": "2021-05-31", - "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": "0a6799d7-f5d1-456b-8bf1-90619284b295", - "projectId": 111, - "userId": "6d0509c7-5f12-4d84-9a19-8e80ef7ddd66", - "jobId": "2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0", - "status": "placed", - "startDate": "2021-02-27", - "endDate": "2021-03-15", - "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": "35e1abd8-1890-4664-bb52-aade382d7b66", - "projectId": 111, - "userId": "a2ffdeed-704d-4cf7-b70a-93fcf61de598", - "jobId": "2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0", - "status": "closed", - "startDate": "2021-02-25", - "endDate": "2021-04-01", - "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": "51b45f5d-5df2-46d5-9c3d-8a1323df38dd", - "projectId": 111, - "userId": "dd5adacb-444d-4992-8b7b-0c349be598db", - "jobId": "2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0", - "status": "placed", - "startDate": "2021-03-18", - "endDate": "2021-05-28", - "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": "61f5d474-e41f-490b-ab58-9f983e3d4916", - "projectId": 111, - "userId": "f65e2104-2987-4136-839d-ee4632f0b2e5", - "jobId": "2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0", - "status": "placed", - "startDate": "2000-03-27", - "endDate": "2000-04-27", - "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": "8173579e-4b3c-418d-a9a1-c999caa38404", - "projectId": 111, - "userId": "bef43122-426b-4b2b-acdd-9b5b3bd1c0bf", - "jobId": "2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0", - "status": "placed", - "startDate": "2020-04-27", - "endDate": "2020-05-27", - "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" - }, - { - "id": "a098e8d8-ce5b-47d9-afee-38b050d16745", - "projectId": 111, - "userId": "4709473d-f060-4102-87f8-4d51ff0b34c1", - "jobId": "2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0", - "status": "cancelled", - "startDate": "2021-04-25", - "endDate": "2021-04-30", - "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-05-25", - "endDate": "2021-07-31", - "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": "dc4477ec-07f8-4c8e-a8fe-ffe38dd290fa", - "projectId": 111, - "userId": "e5e667ad-0950-43c2-8d1d-6e83ad7d1c7e", - "jobId": "2d5e2a52-e0dd-4cd9-8f4c-7cffa43951d0", - "status": "placed", - "startDate": "2021-07-27", - "endDate": "2021-09-27", - "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" - } - ], - "WorkPeriod": [ - { - "id": "07783b60-b726-41c2-8955-7766a27c1ec5", - "resourceBookingId": "7d967fed-9792-4768-98a7-0b644aa84f2e", - "userHandle": "sachin-wipro", - "projectId": 111, - "startDate": "2021-03-21", - "endDate": "2021-03-27", - "daysWorked": 2, - "memberRate": 4.8, - "customerRate": 4.95, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.705Z", - "updatedAt": null - }, - { - "id": "6ed667a5-275e-4f27-984b-34dff5f8a1ff", - "resourceBookingId": "dc4477ec-07f8-4c8e-a8fe-ffe38dd290fa", - "userHandle": "nskumar278", - "projectId": 111, - "startDate": "2021-08-01", - "endDate": "2021-08-07", - "daysWorked": 5, - "memberRate": 25.21, - "customerRate": 10.05, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.703Z", - "updatedAt": null - }, - { - "id": "d049e7bc-c827-482b-9ec6-b87d9289d1cd", - "resourceBookingId": "8173579e-4b3c-418d-a9a1-c999caa38404", - "userHandle": "testcat", - "projectId": 111, - "startDate": "2020-05-24", - "endDate": "2020-05-30", - "daysWorked": 3, - "memberRate": 24.46, - "customerRate": 18.76, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.806Z", - "updatedAt": null - }, - { - "id": "1b633124-f62c-4026-b679-213cf5812689", - "resourceBookingId": "51b45f5d-5df2-46d5-9c3d-8a1323df38dd", - "userHandle": "amy_admin", - "projectId": 111, - "startDate": "2021-03-28", - "endDate": "2021-04-03", - "daysWorked": 5, - "memberRate": 23.35, - "customerRate": 18.76, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.704Z", - "updatedAt": null - }, - { - "id": "30c89d78-df85-44ed-92b2-b683d8960fc2", - "resourceBookingId": "51b45f5d-5df2-46d5-9c3d-8a1323df38dd", - "userHandle": "amy_admin", - "projectId": 111, - "startDate": "2021-04-04", - "endDate": "2021-04-10", - "daysWorked": 5, - "memberRate": 3.96, - "customerRate": 4.95, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.704Z", - "updatedAt": null - }, - { - "id": "531754f3-405e-42eb-932a-c1ce7b9386e7", - "resourceBookingId": "35e1abd8-1890-4664-bb52-aade382d7b66", - "userHandle": "lakshmiaconnmgr", - "projectId": 111, - "startDate": "2021-02-28", - "endDate": "2021-03-06", - "daysWorked": 5, - "memberRate": 3.62, - "customerRate": 10.05, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.695Z", - "updatedAt": null - }, - { - "id": "442b0543-e887-42be-9ff5-5fee825526be", - "resourceBookingId": "0a6799d7-f5d1-456b-8bf1-90619284b295", - "userHandle": "aaaa", - "projectId": 111, - "startDate": "2021-03-14", - "endDate": "2021-03-20", - "daysWorked": 1, - "memberRate": 23.81, - "customerRate": 15.49, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.694Z", - "updatedAt": null - }, - { - "id": "18a73600-5ee8-484b-9747-70ea80ce2bd9", - "resourceBookingId": "7d967fed-9792-4768-98a7-0b644aa84f2e", - "userHandle": "sachin-wipro", - "projectId": 111, - "startDate": "2021-05-16", - "endDate": "2021-05-22", - "daysWorked": 5, - "memberRate": 28.76, - "customerRate": 25.9, - "paymentStatus": "completed", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.705Z", - "updatedAt": null - }, - { - "id": "5392acee-b504-4720-95fa-dab585acb607", - "resourceBookingId": "0a6799d7-f5d1-456b-8bf1-90619284b295", - "userHandle": "aaaa", - "projectId": 111, - "startDate": "2021-03-07", - "endDate": "2021-03-13", - "daysWorked": 5, - "memberRate": 14.77, - "customerRate": 26.72, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.693Z", - "updatedAt": null - }, - { - "id": "1bbc86c8-8c74-4d78-9706-25c4c99721f3", - "resourceBookingId": "35e1abd8-1890-4664-bb52-aade382d7b66", - "userHandle": "lakshmiaconnmgr", - "projectId": 111, - "startDate": "2021-03-21", - "endDate": "2021-03-27", - "daysWorked": 5, - "memberRate": 3.62, - "customerRate": 25.9, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.695Z", - "updatedAt": null - }, - { - "id": "8b7b49de-29b1-4a0c-bb67-e70cc700fcfd", - "resourceBookingId": "51b45f5d-5df2-46d5-9c3d-8a1323df38dd", - "userHandle": "amy_admin", - "projectId": 111, - "startDate": "2021-04-25", - "endDate": "2021-05-01", - "daysWorked": 5, - "memberRate": 24.68, - "customerRate": 23.15, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.704Z", - "updatedAt": null - }, - { - "id": "b8a8b558-0cb9-46d0-ba9d-2222f3fbdb63", - "resourceBookingId": "dc4477ec-07f8-4c8e-a8fe-ffe38dd290fa", - "userHandle": "nskumar278", - "projectId": 111, - "startDate": "2021-09-05", - "endDate": "2021-09-11", - "daysWorked": 5, - "memberRate": 27.42, - "customerRate": 27.91, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.703Z", - "updatedAt": null - }, - { - "id": "f70509c0-baed-4ff1-8022-12441251f7af", - "resourceBookingId": "51b45f5d-5df2-46d5-9c3d-8a1323df38dd", - "userHandle": "amy_admin", - "projectId": 111, - "startDate": "2021-03-14", - "endDate": "2021-03-20", - "daysWorked": 2, - "memberRate": 30.24, - "customerRate": 9.88, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.704Z", - "updatedAt": null - }, - { - "id": "da8abd64-2878-4e09-b3b1-41a27a0576d4", - "resourceBookingId": "dc4477ec-07f8-4c8e-a8fe-ffe38dd290fa", - "userHandle": "nskumar278", - "projectId": 111, - "startDate": "2021-09-12", - "endDate": "2021-09-18", - "daysWorked": 5, - "memberRate": 16.86, - "customerRate": 4.05, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.703Z", - "updatedAt": null - }, - { - "id": "b5261ee2-bc4d-4c3a-9d30-6703bfdcfbc5", - "resourceBookingId": "51b45f5d-5df2-46d5-9c3d-8a1323df38dd", - "userHandle": "amy_admin", - "projectId": 111, - "startDate": "2021-05-23", - "endDate": "2021-05-29", - "daysWorked": 5, - "memberRate": 24.68, - "customerRate": 27.91, - "paymentStatus": "completed", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.704Z", - "updatedAt": null - }, - { - "id": "829165cb-0150-48e7-995c-f5b4d1a51d3b", - "resourceBookingId": "dc4477ec-07f8-4c8e-a8fe-ffe38dd290fa", - "userHandle": "nskumar278", - "projectId": 111, - "startDate": "2021-09-26", - "endDate": "2021-10-02", - "daysWorked": 1, - "memberRate": 4.8, - "customerRate": 10.59, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.703Z", - "updatedAt": null - }, - { - "id": "2430fb35-826a-4e9f-8fb6-8dbcb035d505", - "resourceBookingId": "dc4477ec-07f8-4c8e-a8fe-ffe38dd290fa", - "userHandle": "nskumar278", - "projectId": 111, - "startDate": "2021-08-22", - "endDate": "2021-08-28", - "daysWorked": 5, - "memberRate": 6.18, - "customerRate": 4.05, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.703Z", - "updatedAt": null - }, - { - "id": "c7ff2acc-a4c2-4e8b-a905-813dd9d1b293", - "resourceBookingId": "35e1abd8-1890-4664-bb52-aade382d7b66", - "userHandle": "lakshmiaconnmgr", - "projectId": 111, - "startDate": "2021-03-28", - "endDate": "2021-04-03", - "daysWorked": 4, - "memberRate": 24.46, - "customerRate": 4.05, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.695Z", - "updatedAt": null - }, - { - "id": "731db5d7-bb79-45f4-b1b2-9f60d30f7966", - "resourceBookingId": "08f5e4b9-1088-496d-91a7-5b22a3583e3c", - "userHandle": "ritesh_cs", - "projectId": 111, - "startDate": "2021-01-31", - "endDate": "2021-02-06", - "daysWorked": 0, - "memberRate": 27.42, - "customerRate": 4.4, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.775Z", - "updatedAt": null - }, - { - "id": "b682660e-488e-4033-aaf3-ef37248abc90", - "resourceBookingId": "0a6799d7-f5d1-456b-8bf1-90619284b295", - "userHandle": "aaaa", - "projectId": 111, - "startDate": "2021-02-21", - "endDate": "2021-02-27", - "daysWorked": 0, - "memberRate": 24.46, - "customerRate": 2.55, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.693Z", - "updatedAt": null - }, - { - "id": "b4566e24-4fa8-4e82-9950-f62134bb00df", - "resourceBookingId": "dc4477ec-07f8-4c8e-a8fe-ffe38dd290fa", - "userHandle": "nskumar278", - "projectId": 111, - "startDate": "2021-08-29", - "endDate": "2021-09-04", - "daysWorked": 5, - "memberRate": 4.8, - "customerRate": 4.4, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.703Z", - "updatedAt": null - }, - { - "id": "584c931b-da72-416e-a011-eac5fe34f42f", - "resourceBookingId": "dc4477ec-07f8-4c8e-a8fe-ffe38dd290fa", - "userHandle": "nskumar278", - "projectId": 111, - "startDate": "2021-07-25", - "endDate": "2021-07-31", - "daysWorked": 4, - "memberRate": 14.77, - "customerRate": 4.4, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.703Z", - "updatedAt": null - }, - { - "id": "703bc625-9144-4a9f-a91b-445e171d8ea9", - "resourceBookingId": "dc4477ec-07f8-4c8e-a8fe-ffe38dd290fa", - "userHandle": "nskumar278", - "projectId": 111, - "startDate": "2021-09-19", - "endDate": "2021-09-25", - "daysWorked": 5, - "memberRate": 27.42, - "customerRate": 5.77, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.703Z", - "updatedAt": null - }, - { - "id": "c9685cb2-9f4a-497e-ae99-deed7b16cc34", - "resourceBookingId": "35e1abd8-1890-4664-bb52-aade382d7b66", - "userHandle": "lakshmiaconnmgr", - "projectId": 111, - "startDate": "2021-03-07", - "endDate": "2021-03-13", - "daysWorked": 5, - "memberRate": 14.77, - "customerRate": 16.55, - "paymentStatus": "completed", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.695Z", - "updatedAt": null - }, - { - "id": "428fec88-b305-4816-b5ef-be2b4e91c21a", - "resourceBookingId": "7d967fed-9792-4768-98a7-0b644aa84f2e", - "userHandle": "sachin-wipro", - "projectId": 111, - "startDate": "2021-04-04", - "endDate": "2021-04-10", - "daysWorked": 5, - "memberRate": 8.55, - "customerRate": 16.55, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.705Z", - "updatedAt": null - }, - { - "id": "374e2065-40cb-4651-a55c-81a0675dc00d", - "resourceBookingId": "8173579e-4b3c-418d-a9a1-c999caa38404", - "userHandle": "testcat", - "projectId": 111, - "startDate": "2020-05-17", - "endDate": "2020-05-23", - "daysWorked": 5, - "memberRate": 16.86, - "customerRate": 1.89, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.806Z", - "updatedAt": null - }, - { - "id": "4bfdc253-e39a-4cfa-9a45-2cfc6e93cc6f", - "resourceBookingId": "61f5d474-e41f-490b-ab58-9f983e3d4916", - "userHandle": "sonu628", - "projectId": 111, - "startDate": "2000-04-16", - "endDate": "2000-04-22", - "daysWorked": 5, - "memberRate": 20.16, - "customerRate": 13.92, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.858Z", - "updatedAt": null - }, - { - "id": "0ba1a0b3-7bee-4fe6-9083-d36d8ca9d052", - "resourceBookingId": "35e1abd8-1890-4664-bb52-aade382d7b66", - "userHandle": "lakshmiaconnmgr", - "projectId": 111, - "startDate": "2021-03-14", - "endDate": "2021-03-20", - "daysWorked": 5, - "memberRate": 24.46, - "customerRate": 1.44, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.695Z", - "updatedAt": null - }, - { - "id": "6da7d347-7492-43b1-a49d-8a6e1daf9b22", - "resourceBookingId": "51b45f5d-5df2-46d5-9c3d-8a1323df38dd", - "userHandle": "amy_admin", - "projectId": 111, - "startDate": "2021-04-18", - "endDate": "2021-04-24", - "daysWorked": 5, - "memberRate": 25.21, - "customerRate": 1.44, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.704Z", - "updatedAt": null - }, - { - "id": "8c8cedf3-0bb6-4063-8a3a-faf1626da384", - "resourceBookingId": "61f5d474-e41f-490b-ab58-9f983e3d4916", - "userHandle": "sonu628", - "projectId": 111, - "startDate": "2000-04-09", - "endDate": "2000-04-15", - "daysWorked": 5, - "memberRate": 14.77, - "customerRate": 4.95, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.858Z", - "updatedAt": null - }, - { - "id": "10394696-47f4-4761-8d14-ffdf012cde23", - "resourceBookingId": "d38a6223-3f91-4300-9ecb-6e5fee173625", - "userHandle": "nithyaasworld", - "projectId": 111, - "startDate": "2021-07-25", - "endDate": "2021-07-31", - "daysWorked": 5, - "memberRate": 3.62, - "customerRate": 4.95, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.706Z", - "updatedAt": null - }, - { - "id": "64de2244-6fcf-45ac-8a89-a9b3420e4476", - "resourceBookingId": "7d967fed-9792-4768-98a7-0b644aa84f2e", - "userHandle": "sachin-wipro", - "projectId": 111, - "startDate": "2021-04-18", - "endDate": "2021-04-24", - "daysWorked": 5, - "memberRate": 22.57, - "customerRate": 18.23, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.705Z", - "updatedAt": null - }, - { - "id": "2cbe3836-5961-4d58-b8f7-44b84ddf3fc5", - "resourceBookingId": "7d967fed-9792-4768-98a7-0b644aa84f2e", - "userHandle": "sachin-wipro", - "projectId": 111, - "startDate": "2021-04-11", - "endDate": "2021-04-17", - "daysWorked": 5, - "memberRate": 25.21, - "customerRate": 2.64, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.705Z", - "updatedAt": null - }, - { - "id": "bc8611f0-4ac2-49b2-b776-59ed2b759d1d", - "resourceBookingId": "d38a6223-3f91-4300-9ecb-6e5fee173625", - "userHandle": "nithyaasworld", - "projectId": 111, - "startDate": "2021-07-04", - "endDate": "2021-07-10", - "daysWorked": 5, - "memberRate": 16.86, - "customerRate": 5.77, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.706Z", - "updatedAt": null - }, - { - "id": "9b6fc85b-3694-4e6c-9ebf-fe9ccf7881ba", - "resourceBookingId": "d38a6223-3f91-4300-9ecb-6e5fee173625", - "userHandle": "nithyaasworld", - "projectId": 111, - "startDate": "2021-06-13", - "endDate": "2021-06-19", - "daysWorked": 5, - "memberRate": 14.77, - "customerRate": 15.86, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.706Z", - "updatedAt": null - }, - { - "id": "4a2c581f-c626-44cb-8ada-58f0172e8b4d", - "resourceBookingId": "d38a6223-3f91-4300-9ecb-6e5fee173625", - "userHandle": "nithyaasworld", - "projectId": 111, - "startDate": "2021-05-30", - "endDate": "2021-06-05", - "daysWorked": 5, - "memberRate": 28.76, - "customerRate": 15.49, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.706Z", - "updatedAt": null - }, - { - "id": "90d99323-ba57-4a18-b50f-78f387033c70", - "resourceBookingId": "61f5d474-e41f-490b-ab58-9f983e3d4916", - "userHandle": "sonu628", - "projectId": 111, - "startDate": "2000-04-02", - "endDate": "2000-04-08", - "daysWorked": 5, - "memberRate": 24.46, - "customerRate": 25.9, - "paymentStatus": "completed", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.858Z", - "updatedAt": null - }, - { - "id": "5ddc132b-3205-45e3-bfe9-f1a4f939885e", - "resourceBookingId": "51b45f5d-5df2-46d5-9c3d-8a1323df38dd", - "userHandle": "amy_admin", - "projectId": 111, - "startDate": "2021-03-21", - "endDate": "2021-03-27", - "daysWorked": 5, - "memberRate": 21.53, - "customerRate": 25.9, - "paymentStatus": "completed", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.704Z", - "updatedAt": null - }, - { - "id": "437d4281-43ec-4de3-85e4-51d298388ce5", - "resourceBookingId": "0a6799d7-f5d1-456b-8bf1-90619284b295", - "userHandle": "aaaa", - "projectId": 111, - "startDate": "2021-02-28", - "endDate": "2021-03-06", - "daysWorked": 5, - "memberRate": 26.19, - "customerRate": 28.03, - "paymentStatus": "completed", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.693Z", - "updatedAt": null - }, - { - "id": "a35bb205-361b-4b2d-9828-55501ae9d190", - "resourceBookingId": "d38a6223-3f91-4300-9ecb-6e5fee173625", - "userHandle": "nithyaasworld", - "projectId": 111, - "startDate": "2021-07-11", - "endDate": "2021-07-17", - "daysWorked": 5, - "memberRate": 27.42, - "customerRate": 28.03, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.706Z", - "updatedAt": null - }, - { - "id": "40ae1e8f-24be-4b51-885c-51f08e15f0df", - "resourceBookingId": "08f5e4b9-1088-496d-91a7-5b22a3583e3c", - "userHandle": "ritesh_cs", - "projectId": 111, - "startDate": "2021-01-24", - "endDate": "2021-01-30", - "daysWorked": 5, - "memberRate": 16.86, - "customerRate": 28.03, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.775Z", - "updatedAt": null - }, - { - "id": "e19bddc5-38ac-43c9-8273-bc9069de26b3", - "resourceBookingId": "61f5d474-e41f-490b-ab58-9f983e3d4916", - "userHandle": "sonu628", - "projectId": 111, - "startDate": "2000-04-23", - "endDate": "2000-04-29", - "daysWorked": 5, - "memberRate": 6.18, - "customerRate": 9.12, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.858Z", - "updatedAt": null - }, - { - "id": "bf61dad8-841a-4913-93f6-b2ae516b8b11", - "resourceBookingId": "d38a6223-3f91-4300-9ecb-6e5fee173625", - "userHandle": "nithyaasworld", - "projectId": 111, - "startDate": "2021-06-06", - "endDate": "2021-06-12", - "daysWorked": 5, - "memberRate": 6.18, - "customerRate": 4.4, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.706Z", - "updatedAt": null - }, - { - "id": "93b0f03b-219b-41d5-bb1e-f125651b1b0e", - "resourceBookingId": "8173579e-4b3c-418d-a9a1-c999caa38404", - "userHandle": "testcat", - "projectId": 111, - "startDate": "2020-05-03", - "endDate": "2020-05-09", - "daysWorked": 5, - "memberRate": 24.46, - "customerRate": 1.89, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.806Z", - "updatedAt": null - }, - { - "id": "93e69f99-cb1c-418e-aa41-ab2181b4bcfd", - "resourceBookingId": "d38a6223-3f91-4300-9ecb-6e5fee173625", - "userHandle": "nithyaasworld", - "projectId": 111, - "startDate": "2021-06-27", - "endDate": "2021-07-03", - "daysWorked": 5, - "memberRate": 17.2, - "customerRate": 13.92, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.706Z", - "updatedAt": null - }, - { - "id": "619a0835-730f-47ec-820e-3959821aec51", - "resourceBookingId": "7d967fed-9792-4768-98a7-0b644aa84f2e", - "userHandle": "sachin-wipro", - "projectId": 111, - "startDate": "2021-05-30", - "endDate": "2021-06-05", - "daysWorked": 1, - "memberRate": 4.8, - "customerRate": 13.92, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.705Z", - "updatedAt": null - }, - { - "id": "558b4685-4932-492e-99e1-2830c10f8275", - "resourceBookingId": "7d967fed-9792-4768-98a7-0b644aa84f2e", - "userHandle": "sachin-wipro", - "projectId": 111, - "startDate": "2021-04-25", - "endDate": "2021-05-01", - "daysWorked": 5, - "memberRate": 4.8, - "customerRate": 13.92, - "paymentStatus": "pending", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.705Z", - "updatedAt": null - }, - { - "id": "84431dac-019d-4987-9817-15f5f000d2db", - "resourceBookingId": "61f5d474-e41f-490b-ab58-9f983e3d4916", - "userHandle": "sonu628", - "projectId": 111, - "startDate": "2000-03-26", - "endDate": "2000-04-01", - "daysWorked": 5, - "memberRate": 27.42, - "customerRate": 4.05, - "paymentStatus": "partially-completed", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.858Z", - "updatedAt": null - }, - { - "id": "f575df2d-f170-4251-9042-b17ca5e99ca5", - "resourceBookingId": "51b45f5d-5df2-46d5-9c3d-8a1323df38dd", - "userHandle": "amy_admin", - "projectId": 111, - "startDate": "2021-05-02", - "endDate": "2021-05-08", - "daysWorked": 5, - "memberRate": 4.82, - "customerRate": 4.05, - "paymentStatus": "completed", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.704Z", - "updatedAt": null - }, - { - "id": "3829c216-ef3f-466c-93da-3a88a961442f", - "resourceBookingId": "51b45f5d-5df2-46d5-9c3d-8a1323df38dd", - "userHandle": "amy_admin", - "projectId": 111, - "startDate": "2021-05-09", - "endDate": "2021-05-15", - "daysWorked": 5, - "memberRate": 6.18, - "customerRate": 4.4, - "paymentStatus": "cancelled", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.704Z", - "updatedAt": null - }, - { - "id": "bd54bcaf-5278-467f-a166-865048774d0e", - "resourceBookingId": "a098e8d8-ce5b-47d9-afee-38b050d16745", - "userHandle": "TCConnCopilot", - "projectId": 111, - "startDate": "2021-04-25", - "endDate": "2021-05-01", - "daysWorked": 5, - "memberRate": 16.86, - "customerRate": 1.89, - "paymentStatus": "partially-completed", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.696Z", - "updatedAt": null - }, - { - "id": "7f8f3a25-b1d2-4e36-a543-fcaae57a32f5", - "resourceBookingId": "dc4477ec-07f8-4c8e-a8fe-ffe38dd290fa", - "userHandle": "nskumar278", - "projectId": 111, - "startDate": "2021-08-15", - "endDate": "2021-08-21", - "daysWorked": 5, - "memberRate": 8.13, - "customerRate": 1.89, - "paymentStatus": "cancelled", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.703Z", - "updatedAt": null - }, - { - "id": "6e1dc024-d437-4d9f-92e9-561db713a19a", - "resourceBookingId": "dc4477ec-07f8-4c8e-a8fe-ffe38dd290fa", - "userHandle": "nskumar278", - "projectId": 111, - "startDate": "2021-08-08", - "endDate": "2021-08-14", - "daysWorked": 5, - "memberRate": 3.62, - "customerRate": 18.14, - "paymentStatus": "partially-completed", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.703Z", - "updatedAt": null - }, - { - "id": "c5f6ae8f-2976-46d1-bd66-58eeb58ca045", - "resourceBookingId": "d38a6223-3f91-4300-9ecb-6e5fee173625", - "userHandle": "nithyaasworld", - "projectId": 111, - "startDate": "2021-06-20", - "endDate": "2021-06-26", - "daysWorked": 5, - "memberRate": 25.41, - "customerRate": 13.92, - "paymentStatus": "cancelled", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.706Z", - "updatedAt": null - }, - { - "id": "0f480aa7-1c5d-42fe-aad6-c774e58c2e17", - "resourceBookingId": "7d967fed-9792-4768-98a7-0b644aa84f2e", - "userHandle": "sachin-wipro", - "projectId": 111, - "startDate": "2021-05-09", - "endDate": "2021-05-15", - "daysWorked": 5, - "memberRate": 4.82, - "customerRate": 4.95, - "paymentStatus": "cancelled", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.705Z", - "updatedAt": null - }, - { - "id": "098ca553-6ea4-4cae-a18e-762f47e93d82", - "resourceBookingId": "51b45f5d-5df2-46d5-9c3d-8a1323df38dd", - "userHandle": "amy_admin", - "projectId": 111, - "startDate": "2021-05-16", - "endDate": "2021-05-22", - "daysWorked": 5, - "memberRate": 3.96, - "customerRate": 4.95, - "paymentStatus": "completed", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.704Z", - "updatedAt": null - }, - { - "id": "729a2396-2b33-4185-8ce8-d929dbf4a472", - "resourceBookingId": "7d967fed-9792-4768-98a7-0b644aa84f2e", - "userHandle": "sachin-wipro", - "projectId": 111, - "startDate": "2021-05-23", - "endDate": "2021-05-29", - "daysWorked": 5, - "memberRate": 17.2, - "customerRate": 4.95, - "paymentStatus": "completed", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.705Z", - "updatedAt": null - }, - { - "id": "9bfbd49a-e6bb-45c3-965d-ed4f95f0878a", - "resourceBookingId": "d38a6223-3f91-4300-9ecb-6e5fee173625", - "userHandle": "nithyaasworld", - "projectId": 111, - "startDate": "2021-07-18", - "endDate": "2021-07-24", - "daysWorked": 5, - "memberRate": 23.35, - "customerRate": 5.77, - "paymentStatus": "completed", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.706Z", - "updatedAt": null - }, - { - "id": "dcc310cf-ea4a-4637-9bf5-5baaabea67b3", - "resourceBookingId": "d38a6223-3f91-4300-9ecb-6e5fee173625", - "userHandle": "nithyaasworld", - "projectId": 111, - "startDate": "2021-05-23", - "endDate": "2021-05-29", - "daysWorked": 4, - "memberRate": 14.77, - "customerRate": 1.44, - "paymentStatus": "partially-completed", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.706Z", - "updatedAt": null - }, - { - "id": "309f65e8-b0b5-4cbb-ba60-9b36ccba4bd5", - "resourceBookingId": "51b45f5d-5df2-46d5-9c3d-8a1323df38dd", - "userHandle": "amy_admin", - "projectId": 111, - "startDate": "2021-04-11", - "endDate": "2021-04-17", - "daysWorked": 5, - "memberRate": 14.77, - "customerRate": 15.49, - "paymentStatus": "completed", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.704Z", - "updatedAt": null - }, - { - "id": "1e2c732e-ac1f-47ad-939b-22b2078124e5", - "resourceBookingId": "7d967fed-9792-4768-98a7-0b644aa84f2e", - "userHandle": "sachin-wipro", - "projectId": 111, - "startDate": "2021-03-28", - "endDate": "2021-04-03", - "daysWorked": 5, - "memberRate": 17.2, - "customerRate": 15.49, - "paymentStatus": "partially-completed", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.705Z", - "updatedAt": null - }, - { - "id": "2463003f-ee60-4aba-b989-b63babcd9b8b", - "resourceBookingId": "7d967fed-9792-4768-98a7-0b644aa84f2e", - "userHandle": "sachin-wipro", - "projectId": 111, - "startDate": "2021-05-02", - "endDate": "2021-05-08", - "daysWorked": 5, - "memberRate": 4.8, - "customerRate": 15.49, - "paymentStatus": "cancelled", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.705Z", - "updatedAt": null - }, - { - "id": "6a1180b8-38af-4bd0-8a5f-a60626e0bc95", - "resourceBookingId": "8173579e-4b3c-418d-a9a1-c999caa38404", - "userHandle": "testcat", - "projectId": 111, - "startDate": "2020-04-26", - "endDate": "2020-05-02", - "daysWorked": 5, - "memberRate": 26.19, - "customerRate": 28.03, - "paymentStatus": "completed", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.806Z", - "updatedAt": null - }, - { - "id": "b21f921a-4b23-423d-814b-d31f5cba7f64", - "resourceBookingId": "35e1abd8-1890-4664-bb52-aade382d7b66", - "userHandle": "lakshmiaconnmgr", - "projectId": 111, - "startDate": "2021-02-21", - "endDate": "2021-02-27", - "daysWorked": 2, - "memberRate": 15.77, - "customerRate": 28.03, - "paymentStatus": "partially-completed", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.695Z", - "updatedAt": null - }, - { - "id": "4db82b0b-4d6f-4e9a-b957-ab405b2c2df2", - "resourceBookingId": "8173579e-4b3c-418d-a9a1-c999caa38404", - "userHandle": "testcat", - "projectId": 111, - "startDate": "2020-05-10", - "endDate": "2020-05-16", - "daysWorked": 5, - "memberRate": 24.46, - "customerRate": 28.03, - "paymentStatus": "partially-completed", - "createdBy": "00000000-0000-0000-0000-000000000000", - "updatedBy": null, - "createdAt": "2021-04-21T20:24:52.806Z", - "updatedAt": null - } - ], - "WorkPeriodPayment": [ - { - "id": "2c488b36-0868-4db6-8978-20b1ce174496", - "workPeriodId": "07783b60-b726-41c2-8955-7766a27c1ec5", - "challengeId": "0de972b8-6cc9-4625-9760-1c77561c29e9", - "amount": 200, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T19:13:23.714Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "d0f61c2d-271c-48b2-8416-50c1c32ad32b", - "workPeriodId": "098ca553-6ea4-4cae-a18e-762f47e93d82", - "challengeId": "aa8c1945-904c-42a7-9b00-1e4f9a49dcdb", - "amount": 450, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T22:01:45.361Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "90bb43bd-d9e7-4eab-a46b-ab03338be11a", - "workPeriodId": "0ba1a0b3-7bee-4fe6-9083-d36d8ca9d052", - "challengeId": "8b6f4040-d7ae-4264-b60b-b1171c9365e4", - "amount": 400, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T22:01:45.390Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "58681a3e-2266-4153-afd5-7be218966da2", - "workPeriodId": "0f480aa7-1c5d-42fe-aad6-c774e58c2e17", - "challengeId": "2bafdd9a-ab4a-4624-8a06-7b1adfb8dac2", - "amount": 1200, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T22:01:45.326Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "b342d615-d36d-48b2-a3e8-1f498b58ab68", - "workPeriodId": "10394696-47f4-4761-8d14-ffdf012cde23", - "challengeId": "0de972b8-6cc9-4625-9760-1c77561c29e9", - "amount": 400, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-16T19:13:23.714Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "63cec011-7714-4ab6-944f-e76b9fa2bd1a", - "workPeriodId": "18a73600-5ee8-484b-9747-70ea80ce2bd9", - "challengeId": "1bdf092e-e117-4d42-bb5d-e49816171c0d", - "amount": 500, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T22:01:45.523Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "8a0c0877-b88a-420b-a3f7-645c18793b4b", - "workPeriodId": "1b633124-f62c-4026-b679-213cf5812689", - "challengeId": "4332acc6-3a33-4b7b-af4c-bd2c1ffcfb8e", - "amount": 1400, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T22:01:45.325Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "04ef47ac-8f4d-402f-b9fd-48b2b1d9003d", - "workPeriodId": "1bbc86c8-8c74-4d78-9706-25c4c99721f3", - "challengeId": "fa909769-f5f7-41fb-94bb-80db62e21a5e", - "amount": 800, - "status": "cancelled", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T22:01:45.326Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "84c1c956-e03d-4e19-a5a8-a4086c9658eb", - "workPeriodId": "1e2c732e-ac1f-47ad-939b-22b2078124e5", - "challengeId": "604910b2-7644-4b9d-a185-0054e61c83fc", - "amount": 1800, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T22:01:45.324Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "c051c3da-34bb-4deb-8921-04e5d2fa0bcc", - "workPeriodId": "2430fb35-826a-4e9f-8fb6-8dbcb035d505", - "challengeId": "25fd805c-49cd-443f-ba0d-813c33a6d8ad", - "amount": 400, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T22:01:45.390Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "cc13acfd-fc06-40e5-aefe-5050429ee4f2", - "workPeriodId": "2463003f-ee60-4aba-b989-b63babcd9b8b", - "challengeId": "0de972b8-6cc9-4625-9760-1c77561c29e9", - "amount": 1200, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T19:13:23.714Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "58c6431a-061a-41bd-a3bd-c8effba62e11", - "workPeriodId": "2cbe3836-5961-4d58-b8f7-44b84ddf3fc5", - "challengeId": "0de972b8-6cc9-4625-9760-1c77561c29e9", - "amount": 900, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T19:13:23.714Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "efe0e4b5-e6dd-4c1a-a0e5-1f5e0ff91df9", - "workPeriodId": "309f65e8-b0b5-4cbb-ba60-9b36ccba4bd5", - "challengeId": "01332fa9-0505-416d-9084-39b136dbd300", - "amount": 1200, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T22:01:45.390Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "298ac627-e6d7-47b0-ad1d-83de291addf7", - "workPeriodId": "30c89d78-df85-44ed-92b2-b683d8960fc2", - "challengeId": "f7e40a0c-a302-4989-a3bd-7587fee3c367", - "amount": 300, - "status": "cancelled", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "createdAt": "2021-04-14T19:13:23.714Z", - "updatedAt": "2021-04-16T19:13:23.714Z" - }, - { - "id": "bf80eca9-8323-4f96-9a3b-8553d6f1e0ce", - "workPeriodId": "374e2065-40cb-4651-a55c-81a0675dc00d", - "challengeId": "03c69d02-9188-436e-b4c9-08f39e46f413", - "amount": 800, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T22:01:45.390Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "338d2d7d-2c59-4513-b560-55e8982fd7c7", - "workPeriodId": "3829c216-ef3f-466c-93da-3a88a961442f", - "challengeId": "2a0db660-def2-4117-90e8-01cd1271c726", - "amount": 1400, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T22:01:45.390Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "491f6e93-e80f-46eb-9637-ee84fe7ace9b", - "workPeriodId": "40ae1e8f-24be-4b51-885c-51f08e15f0df", - "challengeId": "c2b7a2cc-4633-4f3a-ab39-f7122a6890b6", - "amount": 1600, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T22:01:45.390Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "cb94d710-fa3c-4333-b8a9-39ec053a665d", - "workPeriodId": "428fec88-b305-4816-b5ef-be2b4e91c21a", - "challengeId": "93f594e9-5396-416a-8212-87bee614a38f", - "amount": 1200, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T19:13:23.714Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "155eaab2-ef74-484c-b1d7-6534dde58b66", - "workPeriodId": "437d4281-43ec-4de3-85e4-51d298388ce5", - "challengeId": "5ba2d9df-b3ba-4f5f-bee5-228eb46b2c37", - "amount": 600, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T22:01:45.361Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "11c07a5c-a077-4719-83ba-c48db7e63c01", - "workPeriodId": "442b0543-e887-42be-9ff5-5fee825526be", - "challengeId": "d7c21199-a435-41b8-a2ac-5e5bdd021c5e", - "amount": 1400, - "status": "cancelled", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T19:13:23.714Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "4ce8cf4a-2585-4454-81d4-e5446c9a3f75", - "workPeriodId": "4a2c581f-c626-44cb-8ada-58f0172e8b4d", - "challengeId": "ee9bcdd0-0d0d-4414-88cb-d14255f996a5", - "amount": 350, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "createdAt": "2021-04-14T19:13:23.714Z", - "updatedAt": "2021-04-16T19:13:23.714Z" - }, - { - "id": "8ff6188f-b4e6-4f6e-b2d4-2a622ae50c4f", - "workPeriodId": "4bfdc253-e39a-4cfa-9a45-2cfc6e93cc6f", - "challengeId": "f151a5a1-6b28-4f59-bdde-6e73498faa84", - "amount": 450, - "status": "cancelled", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T22:01:45.326Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "5192e519-30f5-42d6-877f-5c2b786d91c7", - "workPeriodId": "4db82b0b-4d6f-4e9a-b957-ab405b2c2df2", - "challengeId": "93f594e9-5396-416a-8212-87bee614a38f", - "amount": 600, - "status": "cancelled", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "createdAt": "2021-04-14T19:13:23.714Z", - "updatedAt": "2021-04-16T19:13:23.714Z" - }, - { - "id": "8ca85158-a850-4cae-97f0-5873a9225ff8", - "workPeriodId": "531754f3-405e-42eb-932a-c1ce7b9386e7", - "challengeId": "b42b8f40-9a4d-45d1-814e-59da5c7a1fd9", - "amount": 1200, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T19:13:23.714Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "4a81c6a3-18d9-441b-ae64-3aa9def336ef", - "workPeriodId": "5392acee-b504-4720-95fa-dab585acb607", - "challengeId": "78154e5c-feed-4dbf-84ec-775395139211", - "amount": 200, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "createdAt": "2021-04-14T19:13:23.714Z", - "updatedAt": "2021-04-16T19:13:23.714Z" - }, - { - "id": "a26b8cae-a1df-4843-a192-0735f235bf78", - "workPeriodId": "558b4685-4932-492e-99e1-2830c10f8275", - "challengeId": "0de972b8-6cc9-4625-9760-1c77561c29e9", - "amount": 600, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T19:13:23.714Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "a94b6f43-de89-4fd2-9a1d-d8a2cce02702", - "workPeriodId": "584c931b-da72-416e-a011-eac5fe34f42f", - "challengeId": "d55fae30-3072-462e-b8bd-eb2eec664e65", - "amount": 1600, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T22:01:45.324Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "eb63dfc7-14d7-4cae-a25e-3e33a04601cf", - "workPeriodId": "5ddc132b-3205-45e3-bfe9-f1a4f939885e", - "challengeId": "0de972b8-6cc9-4625-9760-1c77561c29e9", - "amount": 300, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T19:13:23.714Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "d827ed01-5153-4774-8450-bace2521a6d1", - "workPeriodId": "619a0835-730f-47ec-820e-3959821aec51", - "challengeId": "d40cb9c5-b3bd-45a1-802c-a50fefb020b9", - "amount": 1000, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T22:01:45.326Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "f950e52e-5a52-4ee8-af5f-e6c42e9b400b", - "workPeriodId": "64de2244-6fcf-45ac-8a89-a9b3420e4476", - "challengeId": "6c04d456-bb38-43c8-a538-f5cc6caaa540", - "amount": 800, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T19:13:23.714Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "283f9c3b-7f0a-4792-9661-ced7cbdb340d", - "workPeriodId": "6a1180b8-38af-4bd0-8a5f-a60626e0bc95", - "challengeId": "9a995b78-0542-41be-a926-f3df57c2f873", - "amount": 400, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T22:01:45.361Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "09ea6f03-4489-496c-817c-e9279a58c0ad", - "workPeriodId": "6da7d347-7492-43b1-a49d-8a6e1daf9b22", - "challengeId": "78154e5c-feed-4dbf-84ec-775395139211", - "amount": 400, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T19:13:23.714Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "7d782624-243e-497b-90ca-cc00ae29ebf2", - "workPeriodId": "6e1dc024-d437-4d9f-92e9-561db713a19a", - "challengeId": "afcbc3bc-9077-4978-bf9c-acddb48e6518", - "amount": 800, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T22:01:45.324Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "11918ff9-5f18-445d-ae90-762b3ebe44ca", - "workPeriodId": "6ed667a5-275e-4f27-984b-34dff5f8a1ff", - "challengeId": "c89d357f-afd1-4757-824f-2cf94e2890c6", - "amount": 250, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T22:01:45.361Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "9fe78619-5c1c-4b22-8d6f-ebf9a9502432", - "workPeriodId": "703bc625-9144-4a9f-a91b-445e171d8ea9", - "challengeId": "6c04d456-bb38-43c8-a538-f5cc6caaa540", - "amount": 400, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T19:13:23.714Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "7cf85ce0-ef8c-4152-8623-9a1325db6daa", - "workPeriodId": "729a2396-2b33-4185-8ce8-d929dbf4a472", - "challengeId": "fbf8efda-fe4b-4b72-99dd-573b79d27bd8", - "amount": 200, - "status": "cancelled", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T22:01:45.390Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "e8aee371-1f26-4475-8459-9c134fa6f3c6", - "workPeriodId": "731db5d7-bb79-45f4-b1b2-9f60d30f7966", - "challengeId": "ee9bcdd0-0d0d-4414-88cb-d14255f996a5", - "amount": 700, - "status": "cancelled", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T19:13:23.714Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "dec8615b-c823-4fff-bc77-fa0614b8d09c", - "workPeriodId": "7f8f3a25-b1d2-4e36-a543-fcaae57a32f5", - "challengeId": "fe3e4056-82e3-4df4-b699-a1f3d8ab5e53", - "amount": 700, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T22:01:45.390Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "c4e316ca-a46f-4fbc-96a6-6fe6665c3b49", - "workPeriodId": "829165cb-0150-48e7-995c-f5b4d1a51d3b", - "challengeId": "d937a822-4a9b-40db-afe6-fe1285e3f7f9", - "amount": 900, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T22:01:45.324Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "12b0bcfc-59ae-478c-bb32-cb18d1d0244c", - "workPeriodId": "84431dac-019d-4987-9817-15f5f000d2db", - "challengeId": "a07ea88f-c52b-4023-8730-c4364efd0dd2", - "amount": 600, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T22:01:45.361Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "8c9ed23c-12c7-4a8b-8e91-6fd3b3fc43a4", - "workPeriodId": "8b7b49de-29b1-4a0c-bb67-e70cc700fcfd", - "challengeId": "0de972b8-6cc9-4625-9760-1c77561c29e9", - "amount": 450, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T19:13:23.714Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "621d793b-0ead-4d99-a119-e32af526ece7", - "workPeriodId": "8c8cedf3-0bb6-4063-8a3a-faf1626da384", - "challengeId": "ad04dcee-9a3c-4345-b0b5-783ce98e94b2", - "amount": 900, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T22:01:45.390Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "56cb3aef-531b-4a26-817e-4b9629212c9a", - "workPeriodId": "90d99323-ba57-4a18-b50f-78f387033c70", - "challengeId": "0de972b8-6cc9-4625-9760-1c77561c29e9", - "amount": 450, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T19:13:23.714Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "a1ffc559-703a-4c35-8ba3-73a03c3454af", - "workPeriodId": "93b0f03b-219b-41d5-bb1e-f125651b1b0e", - "challengeId": "9fca67f9-3641-4982-8a82-e86b1850efc8", - "amount": 600, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T22:01:45.326Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "a5904ae3-7524-4709-b798-20c4a2193f10", - "workPeriodId": "93e69f99-cb1c-418e-aa41-ab2181b4bcfd", - "challengeId": "ed56a1c7-a965-4ab6-9cf0-0d7c14cd7db3", - "amount": 400, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T22:01:45.361Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "821b38e8-657d-4f72-b27a-dd975c506ced", - "workPeriodId": "9b6fc85b-3694-4e6c-9ebf-fe9ccf7881ba", - "challengeId": "61f5185b-4ee1-4df3-9c6f-52f5bf0cbfc5", - "amount": 500, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T22:01:45.361Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "2417df2c-8e29-4868-aeb8-5ec0ff67713e", - "workPeriodId": "9bfbd49a-e6bb-45c3-965d-ed4f95f0878a", - "challengeId": "f01ba8da-c891-472d-9ed6-74b91ed9b407", - "amount": 400, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T19:13:23.714Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "5116d4ea-2c1a-4be6-b335-bd531b8d5734", - "workPeriodId": "a35bb205-361b-4b2d-9828-55501ae9d190", - "challengeId": "b42b8f40-9a4d-45d1-814e-59da5c7a1fd9", - "amount": 600, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "createdAt": "2021-04-14T19:13:23.714Z", - "updatedAt": "2021-04-16T19:13:23.714Z" - }, - { - "id": "8fdfe90b-2155-4a71-a610-4689106ced34", - "workPeriodId": "b21f921a-4b23-423d-814b-d31f5cba7f64", - "challengeId": "963784fd-4174-458c-a311-a5b8333d66ab", - "amount": 300, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T22:01:45.361Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "dd9c842a-f577-43c2-8f17-cc940f26f0d8", - "workPeriodId": "b4566e24-4fa8-4e82-9950-f62134bb00df", - "challengeId": "b67cbbc5-3384-4ea6-8504-d3fe83a6e238", - "amount": 700, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T22:01:45.326Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "7e41ca7f-d3c0-4d70-9daf-ee52c93695c7", - "workPeriodId": "b5261ee2-bc4d-4c3a-9d30-6703bfdcfbc5", - "challengeId": "9d49655f-99f6-4e67-9819-a117ef746272", - "amount": 500, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T22:01:45.361Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "b8d44e83-922c-4c2c-8567-5764794e03f3", - "workPeriodId": "b682660e-488e-4033-aaf3-ef37248abc90", - "challengeId": "d7c21199-a435-41b8-a2ac-5e5bdd021c5e", - "amount": 700, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "createdAt": "2021-04-14T19:13:23.714Z", - "updatedAt": "2021-04-16T19:13:23.714Z" - }, - { - "id": "c117de76-965f-4069-aefb-8dd97f95112c", - "workPeriodId": "b8a8b558-0cb9-46d0-ba9d-2222f3fbdb63", - "challengeId": "59d08064-e1b4-4e78-82d8-b2d7ffa6f0b1", - "amount": 900, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T22:01:45.523Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "fda2013c-da68-4601-8d13-d0f4cffd081c", - "workPeriodId": "bc8611f0-4ac2-49b2-b776-59ed2b759d1d", - "challengeId": "0de972b8-6cc9-4625-9760-1c77561c29e9", - "amount": 800, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T19:13:23.714Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "be07bfc8-032c-41f7-a247-a4724f65617c", - "workPeriodId": "bd54bcaf-5278-467f-a166-865048774d0e", - "challengeId": "45e33cee-7c83-4288-8187-6858b0c759eb", - "amount": 800, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T22:01:45.361Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "efa8cd14-c93f-4e6c-be53-596f02db8c96", - "workPeriodId": "bf61dad8-841a-4913-93f6-b2ae516b8b11", - "challengeId": "0de972b8-6cc9-4625-9760-1c77561c29e9", - "amount": 800, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T19:13:23.714Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "eb9c9a83-fe94-4f51-b9f0-c2d9671e87f6", - "workPeriodId": "c5f6ae8f-2976-46d1-bd66-58eeb58ca045", - "challengeId": "68e6a32e-6c31-4266-ba3b-9d2f63be4274", - "amount": 900, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T22:01:45.361Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "c20796c8-76b0-40e8-9bee-db406c93daaf", - "workPeriodId": "c7ff2acc-a4c2-4e8b-a905-813dd9d1b293", - "challengeId": "513ab4c6-0aa4-482b-a184-87f8447b145b", - "amount": 1800, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T22:01:45.390Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "8fad32f7-cb40-416f-ab24-86cf1c7870ef", - "workPeriodId": "c9685cb2-9f4a-497e-ae99-deed7b16cc34", - "challengeId": "f7e40a0c-a302-4989-a3bd-7587fee3c367", - "amount": 600, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T19:13:23.714Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "310384cb-6e85-4f7d-a6d2-8c03ca27871d", - "workPeriodId": "d049e7bc-c827-482b-9ec6-b87d9289d1cd", - "challengeId": "0de972b8-6cc9-4625-9760-1c77561c29e9", - "amount": 900, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T19:13:23.714Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "2a122a93-e778-4eb9-868c-5f38b8b9bb4e", - "workPeriodId": "da8abd64-2878-4e09-b3b1-41a27a0576d4", - "challengeId": "25a7c442-427b-4b6d-9c41-112dbd420c0d", - "amount": 800, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T19:13:23.714Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "767897c3-bbc2-4b1a-9843-5a6bd82e29b0", - "workPeriodId": "dcc310cf-ea4a-4637-9bf5-5baaabea67b3", - "challengeId": "61044188-965e-40df-94c4-9fa9a9499b25", - "amount": 1000, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T22:01:45.523Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "50f7a6fa-a04d-4873-8fd0-037be2f14425", - "workPeriodId": "e19bddc5-38ac-43c9-8273-bc9069de26b3", - "challengeId": "419fbb3d-921d-4613-a87e-337f38d21885", - "amount": 600, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T22:01:45.523Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "11ea987f-f218-4d2b-b656-0741208539f2", - "workPeriodId": "f575df2d-f170-4251-9042-b17ca5e99ca5", - "challengeId": "0de972b8-6cc9-4625-9760-1c77561c29e9", - "amount": 600, - "status": "completed", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-16T19:13:23.714Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - }, - { - "id": "2519d7f9-81c8-448c-aec2-aa78d6d6a962", - "workPeriodId": "f70509c0-baed-4ff1-8022-12441251f7af", - "challengeId": "fd051497-6050-4edf-b8f7-780128f64dc5", - "amount": 300, - "status": "cancelled", - "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", - "updatedBy": null, - "createdAt": "2021-04-14T22:01:45.324Z", - "updatedAt": "2021-04-21T20:19:56.934Z" - } - ] -} + ] +} \ No newline at end of file diff --git a/data/stopWords.json b/data/stopWords.json new file mode 100644 index 00000000..dded6681 --- /dev/null +++ b/data/stopWords.json @@ -0,0 +1,574 @@ +[ + "dr", + "dra", + "mr", + "ms", + "a", + "a's", + "able", + "about", + "above", + "according", + "accordingly", + "across", + "actually", + "after", + "afterwards", + "again", + "against", + "ain't", + "all", + "allow", + "allows", + "almost", + "alone", + "along", + "already", + "also", + "although", + "always", + "am", + "among", + "amongst", + "an", + "and", + "another", + "any", + "anybody", + "anyhow", + "anyone", + "anything", + "anyway", + "anyways", + "anywhere", + "apart", + "appear", + "appreciate", + "appropriate", + "are", + "aren't", + "around", + "as", + "aside", + "ask", + "asking", + "associated", + "at", + "available", + "away", + "awfully", + "b", + "be", + "became", + "because", + "become", + "becomes", + "becoming", + "been", + "before", + "beforehand", + "behind", + "being", + "believe", + "below", + "beside", + "besides", + "best", + "better", + "between", + "beyond", + "both", + "brief", + "but", + "by", + "c'mon", + "c's", + "came", + "can", + "can't", + "cannot", + "cant", + "cause", + "causes", + "certain", + "certainly", + "changes", + "clearly", + "co", + "come", + "comes", + "concerning", + "consequently", + "consider", + "considering", + "contain", + "containing", + "contains", + "corresponding", + "could", + "couldn't", + "course", + "currently", + "d", + "definitely", + "described", + "despite", + "did", + "didn't", + "different", + "do", + "does", + "doesn't", + "doing", + "don't", + "done", + "down", + "downwards", + "during", + "e", + "each", + "edu", + "eg", + "eight", + "either", + "else", + "elsewhere", + "enough", + "entirely", + "especially", + "et", + "etc", + "even", + "ever", + "every", + "everybody", + "everyone", + "everything", + "everywhere", + "ex", + "exactly", + "example", + "except", + "f", + "far", + "few", + "fifth", + "first", + "five", + "followed", + "following", + "follows", + "for", + "former", + "formerly", + "forth", + "four", + "from", + "further", + "furthermore", + "g", + "get", + "gets", + "getting", + "given", + "gives", + "goes", + "going", + "gone", + "got", + "gotten", + "greetings", + "h", + "had", + "hadn't", + "happens", + "hardly", + "has", + "hasn't", + "have", + "haven't", + "having", + "he", + "he's", + "hello", + "help", + "hence", + "her", + "here", + "here's", + "hereafter", + "hereby", + "herein", + "hereupon", + "hers", + "herself", + "hi", + "him", + "himself", + "his", + "hither", + "hopefully", + "how", + "howbeit", + "however", + "i", + "i'd", + "i'll", + "i'm", + "i've", + "ie", + "if", + "ignored", + "immediate", + "in", + "inasmuch", + "inc", + "indeed", + "indicate", + "indicated", + "indicates", + "inner", + "insofar", + "instead", + "into", + "inward", + "is", + "isn't", + "it", + "it'd", + "it'll", + "it's", + "its", + "itself", + "j", + "just", + "k", + "keep", + "keeps", + "kept", + "know", + "knows", + "known", + "l", + "last", + "lately", + "later", + "latter", + "latterly", + "least", + "lest", + "let", + "let's", + "like", + "liked", + "likely", + "little", + "look", + "looking", + "looks", + "ltd", + "m", + "mainly", + "many", + "may", + "maybe", + "me", + "mean", + "meanwhile", + "merely", + "might", + "more", + "moreover", + "most", + "mostly", + "much", + "must", + "my", + "myself", + "n", + "name", + "namely", + "nd", + "near", + "nearly", + "necessary", + "need", + "needs", + "neither", + "never", + "nevertheless", + "new", + "next", + "nine", + "no", + "nobody", + "non", + "none", + "noone", + "nor", + "normally", + "not", + "nothing", + "novel", + "now", + "nowhere", + "o", + "obviously", + "of", + "off", + "often", + "oh", + "ok", + "okay", + "old", + "on", + "once", + "one", + "ones", + "only", + "onto", + "or", + "other", + "others", + "otherwise", + "ought", + "our", + "ours", + "ourselves", + "out", + "outside", + "over", + "overall", + "own", + "p", + "particular", + "particularly", + "per", + "perhaps", + "placed", + "please", + "plus", + "point", + "possible", + "presumably", + "probably", + "provides", + "q", + "que", + "quite", + "qv", + "rather", + "rd", + "re", + "really", + "reasonably", + "regarding", + "regardless", + "regards", + "relatively", + "respectively", + "right", + "s", + "said", + "same", + "saw", + "say", + "saying", + "says", + "second", + "secondly", + "see", + "seeing", + "seem", + "seemed", + "seeming", + "seems", + "seen", + "self", + "selves", + "sensible", + "sent", + "serious", + "seriously", + "seven", + "several", + "shall", + "she", + "should", + "shouldn't", + "since", + "six", + "so", + "some", + "somebody", + "somehow", + "someone", + "something", + "sometime", + "sometimes", + "somewhat", + "somewhere", + "soon", + "sorry", + "specified", + "specify", + "specifying", + "still", + "strong", + "sub", + "such", + "sup", + "sure", + "t", + "t's", + "take", + "taken", + "tell", + "tends", + "th", + "than", + "thank", + "thanks", + "thanx", + "that", + "that's", + "thats", + "the", + "their", + "theirs", + "them", + "themselves", + "then", + "thence", + "there", + "there's", + "thereafter", + "thereby", + "therefore", + "therein", + "theres", + "thereupon", + "these", + "they", + "they'd", + "they'll", + "they're", + "they've", + "think", + "third", + "this", + "thorough", + "thoroughly", + "those", + "though", + "three", + "through", + "throughout", + "thru", + "thus", + "to", + "together", + "too", + "took", + "toward", + "towards", + "tried", + "tries", + "truly", + "try", + "trying", + "twice", + "two", + "u", + "un", + "under", + "unfortunately", + "unless", + "unlikely", + "until", + "unto", + "up", + "upon", + "us", + "use", + "used", + "useful", + "uses", + "using", + "usually", + "uucp", + "v", + "value", + "various", + "very", + "via", + "viz", + "vs", + "w", + "want", + "wants", + "was", + "wasn't", + "way", + "we", + "we'd", + "we'll", + "we're", + "we've", + "welcome", + "well", + "went", + "were", + "weren't", + "what", + "what's", + "whatever", + "when", + "whence", + "whenever", + "where", + "where's", + "whereafter", + "whereas", + "whereby", + "wherein", + "whereupon", + "wherever", + "whether", + "which", + "while", + "whither", + "who", + "who's", + "whoever", + "whole", + "whom", + "whose", + "why", + "will", + "willing", + "wish", + "with", + "within", + "without", + "won't", + "wonder", + "would", + "would", + "wouldn't", + "x", + "y", + "yes", + "yet", + "you", + "you'd", + "you'll", + "you're", + "you've", + "your", + "yours", + "yourself", + "yourselves", + "z", + "zero" +] \ 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 a6afdc2b..39fabfb8 100644 --- a/docs/Topcoder-bookings-api.postman_collection.json +++ b/docs/Topcoder-bookings-api.postman_collection.json @@ -1,6 +1,6 @@ { "info": { - "_postman_id": "3f80d93d-6ca3-4645-970d-a9e533394e2e", + "_postman_id": "3a5bab78-49d6-4dca-9aea-e8688564ac98", "name": "Topcoder-bookings-api", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" }, @@ -33,7 +33,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": "{\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 \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", "options": { "raw": { "language": "json" @@ -77,7 +77,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": "{\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 \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", "options": { "raw": { "language": "json" @@ -103,8 +103,7 @@ "listen": "test", "script": { "exec": [ - "var data = JSON.parse(responseBody);\r", - "postman.setEnvironmentVariable(\"jobId\",data.id);" + "var data = JSON.parse(responseBody);" ], "type": "text/javascript" } @@ -121,7 +120,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": "{\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 \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", "options": { "raw": { "language": "json" @@ -165,7 +164,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": "{\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 \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", "options": { "raw": { "language": "json" @@ -208,7 +207,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 \"56fdc405-eccc-4189-9e83-c78abf844f50\",\n \"f91ae184-aba2-4485-a8cb-9336988c05ab\",\n \"edfc7b4f-636f-44bd-96fc-949ffc58e38b\",\n \"4ca63bb6-f515-4ab0-a6bc-c2d8531e084f\",\n \"ee03c041-d53b-4c08-b7d9-80d7461da3e4\"\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 \"56fdc405-eccc-4189-9e83-c78abf844f50\",\n \"f91ae184-aba2-4485-a8cb-9336988c05ab\",\n \"edfc7b4f-636f-44bd-96fc-949ffc58e38b\",\n \"4ca63bb6-f515-4ab0-a6bc-c2d8531e084f\",\n \"ee03c041-d53b-4c08-b7d9-80d7461da3e4\"\n ],\n \"title\": \"Dummy title - at most 64 characters\",\n \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", "options": { "raw": { "language": "json" @@ -251,7 +250,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 \"56fdc405-eccc-4189-9e83-c78abf844f50\",\n \"f91ae184-aba2-4485-a8cb-9336988c05ab\",\n \"edfc7b4f-636f-44bd-96fc-949ffc58e38b\",\n \"4ca63bb6-f515-4ab0-a6bc-c2d8531e084f\",\n \"ee03c041-d53b-4c08-b7d9-80d7461da3e4\"\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 \"56fdc405-eccc-4189-9e83-c78abf844f50\",\n \"f91ae184-aba2-4485-a8cb-9336988c05ab\",\n \"edfc7b4f-636f-44bd-96fc-949ffc58e38b\",\n \"4ca63bb6-f515-4ab0-a6bc-c2d8531e084f\",\n \"ee03c041-d53b-4c08-b7d9-80d7461da3e4\"\n ],\n \"title\": \"Dummy title - at most 64 characters\",\n \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", "options": { "raw": { "language": "json" @@ -491,6 +490,113 @@ }, "response": [] }, + { + "name": "search jobs with request body", + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"jobIds\": [\"{{jobId}}\",\"{{jobIdCreatedByM2M}}\"]\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "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": [] + }, { "name": "search jobs with with m2m all", "request": { @@ -884,7 +990,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\": \"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": "{\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 \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", "options": { "raw": { "language": "json" @@ -917,7 +1023,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\": \"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": "{\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 \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", "options": { "raw": { "language": "json" @@ -950,7 +1056,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\": \"fractional\",\n \"skills\": [\n \"3fa85f64-5717-4562-b3fc-2c963f66afa6\",\n \"cc41ddc4-cacc-4570-9bdb-1229c12b9784\"\n ],\n \"status\": \"sourcing\",\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\": \"fractional\",\n \"skills\": [\n \"3fa85f64-5717-4562-b3fc-2c963f66afa6\",\n \"cc41ddc4-cacc-4570-9bdb-1229c12b9784\"\n ],\n \"status\": \"sourcing\",\n \"title\": \"Dummy title - at most 64 characters\",\n \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", "options": { "raw": { "language": "json" @@ -996,7 +1102,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"projectId\": {{projectId}},\n \"externalId\": \"1212\",\n \"description\": \"Dummy Description updated\",\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 \"23e00d92-207a-4b5b-b3c9-4c5662644941\"\n ],\n \"title\": \"Dummy title - at most 64 characters\"\n}", + "raw": "{\n \"projectId\": {{projectId}},\n \"externalId\": \"1212\",\n \"description\": \"Dummy Description updated\",\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 \"23e00d92-207a-4b5b-b3c9-4c5662644941\"\n ],\n \"title\": \"Dummy title - at most 64 characters\",\n \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", "options": { "raw": { "language": "json" @@ -1029,7 +1135,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"projectId\": {{projectId}},\n \"externalId\": \"1212\",\n \"description\": \"Dummy Description updated\",\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 \"23e00d92-207a-4b5b-b3c9-4c5662644941\"\n ],\n \"title\": \"Dummy title - at most 64 characters\"\n}", + "raw": "{\n \"projectId\": {{projectId}},\n \"externalId\": \"1212\",\n \"description\": \"Dummy Description updated\",\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 \"23e00d92-207a-4b5b-b3c9-4c5662644941\"\n ],\n \"title\": \"Dummy title - at most 64 characters\",\n \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", "options": { "raw": { "language": "json" @@ -1062,7 +1168,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\": \"fractional\",\n \"skills\": [\n \"3fa85f64-5717-4562-b3fc-2c963f66afa6\",\n \"cc41ddc4-cacc-4570-9bdb-1229c12b9784\"\n ],\n \"status\": \"sourcing\",\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\": \"fractional\",\n \"skills\": [\n \"3fa85f64-5717-4562-b3fc-2c963f66afa6\",\n \"cc41ddc4-cacc-4570-9bdb-1229c12b9784\"\n ],\n \"status\": \"sourcing\",\n \"title\": \"Dummy title - at most 64 characters\",\n \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", "options": { "raw": { "language": "json" @@ -1095,7 +1201,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\": \"fractional\",\n \"skills\": [\n \"3fa85f64-5717-4562-b3fc-2c963f66afa6\",\n \"cc41ddc4-cacc-4570-9bdb-1229c12b9784\"\n ],\n \"status\": \"sourcing\",\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\": \"fractional\",\n \"skills\": [\n \"3fa85f64-5717-4562-b3fc-2c963f66afa6\",\n \"cc41ddc4-cacc-4570-9bdb-1229c12b9784\"\n ],\n \"status\": \"sourcing\",\n \"title\": \"Dummy title - at most 64 characters\",\n \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", "options": { "raw": { "language": "json" @@ -1128,7 +1234,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": "{\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 \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", "options": { "raw": { "language": "json" @@ -1161,7 +1267,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": "{\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 \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", "options": { "raw": { "language": "json" @@ -1194,7 +1300,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 \"3fa85f64-5717-4562-b3fc-2c963f66afa6\"\n ],\n \"status\": \"sourcing\",\n \"title\": \"Dummy title - at most 64 characters\"\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 \"3fa85f64-5717-4562-b3fc-2c963f66afa6\"\n ],\n \"status\": \"sourcing\",\n \"title\": \"Dummy title - at most 64 characters\",\n \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", "options": { "raw": { "language": "json" @@ -1240,7 +1346,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"description\": \"Dummy Description updated 2\",\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 \"23e00d92-207a-4b5b-b3c9-4c5662644941\"\n ],\n \"title\": \"Dummy title - at most 64 characters\"\n}", + "raw": "{\n \"description\": \"Dummy Description updated 2\",\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 \"23e00d92-207a-4b5b-b3c9-4c5662644941\"\n ],\n \"title\": \"Dummy title - at most 64 characters\",\n \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", "options": { "raw": { "language": "json" @@ -1273,7 +1379,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"description\": \"Dummy Description updated 2\",\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 \"23e00d92-207a-4b5b-b3c9-4c5662644941\"\n ],\n \"title\": \"Dummy title - at most 64 characters\"\n}", + "raw": "{\n \"description\": \"Dummy Description updated 2\",\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 \"23e00d92-207a-4b5b-b3c9-4c5662644941\"\n ],\n \"title\": \"Dummy title - at most 64 characters\",\n \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", "options": { "raw": { "language": "json" @@ -1306,7 +1412,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 \"3fa85f64-5717-4562-b3fc-2c963f66afa6\"\n ],\n \"status\": \"sourcing\",\n \"title\": \"Dummy title - at most 64 characters\"\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 \"3fa85f64-5717-4562-b3fc-2c963f66afa6\"\n ],\n \"status\": \"sourcing\",\n \"title\": \"Dummy title - at most 64 characters\",\n \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", "options": { "raw": { "language": "json" @@ -1339,7 +1445,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 \"3fa85f64-5717-4562-b3fc-2c963f66afa6\"\n ],\n \"status\": \"sourcing\",\n \"title\": \"Dummy title - at most 64 characters\"\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 \"3fa85f64-5717-4562-b3fc-2c963f66afa6\"\n ],\n \"status\": \"sourcing\",\n \"title\": \"Dummy title - at most 64 characters\",\n \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", "options": { "raw": { "language": "json" @@ -1600,7 +1706,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"jobId\": \"{{jobId}}\",\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", + "raw": "{\n \"jobId\": \"{{jobId}}\",\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\",\n \"remark\": \"excellent\"\n}", "options": { "raw": { "language": "json" @@ -1644,7 +1750,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"jobId\": \"{{jobIdCreatedByM2M}}\",\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", + "raw": "{\n \"jobId\": \"{{jobIdCreatedByM2M}}\",\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\",\n \"remark\": \"excellent\"\n}", "options": { "raw": { "language": "json" @@ -1688,7 +1794,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"jobId\": \"{{jobId}}\",\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", + "raw": "{\n \"jobId\": \"{{jobId}}\",\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\",\n \"remark\": \"excellent\"\n}", "options": { "raw": { "language": "json" @@ -1732,7 +1838,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"jobId\": \"{{jobId}}\",\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", + "raw": "{\n \"jobId\": \"{{jobId}}\",\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\",\n \"remark\": \"excellent\"\n}", "options": { "raw": { "language": "json" @@ -1776,7 +1882,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"jobId\": \"{{jobId}}\",\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", + "raw": "{\n \"jobId\": \"{{jobId}}\",\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\",\n \"remark\": \"excellent\"\n}", "options": { "raw": { "language": "json" @@ -1819,7 +1925,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"jobId\": \"{{jobId}}\",\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", + "raw": "{\n \"jobId\": \"{{jobId}}\",\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\",\n \"remark\": \"excellent\"\n}", "options": { "raw": { "language": "json" @@ -2565,7 +2671,7 @@ ], "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\": \"{{jobId}}\",\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\n \"status\": \"selected\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\",\n \"remark\": \"excellent\"\n}", "options": { "raw": { "language": "json" @@ -2598,7 +2704,7 @@ ], "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}", + "raw": "{\n \"jobId\": \"{{jobIdCreatedByM2M}}\",\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\n \"status\": \"selected\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\",\n \"remark\": \"excellent\"\n}", "options": { "raw": { "language": "json" @@ -2631,7 +2737,7 @@ ], "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\": \"{{jobId}}\",\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\n \"status\": \"selected\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\",\n \"remark\": \"excellent\"\n}", "options": { "raw": { "language": "json" @@ -2664,7 +2770,7 @@ ], "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\": \"{{jobId}}\",\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\n \"status\": \"selected\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\",\n \"remark\": \"excellent\"\n}", "options": { "raw": { "language": "json" @@ -2697,7 +2803,7 @@ ], "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\": \"{{jobId}}\",\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\n \"status\": \"selected\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\",\n \"remark\": \"excellent\"\n}", "options": { "raw": { "language": "json" @@ -2730,7 +2836,7 @@ ], "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\": \"{{jobId}}\",\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\n \"status\": \"selected\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\",\n \"remark\": \"excellent\"\n}", "options": { "raw": { "language": "json" @@ -2763,7 +2869,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"status\": \"selected\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", + "raw": "{\n \"status\": \"selected\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\",\n \"remark\": \"excellent\"\n}", "options": { "raw": { "language": "json" @@ -2796,7 +2902,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"status\": \"selected\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", + "raw": "{\n \"status\": \"selected\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\",\n \"remark\": \"excellent\"\n}", "options": { "raw": { "language": "json" @@ -2829,7 +2935,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"status\": \"selected\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", + "raw": "{\n \"status\": \"selected\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\",\n \"remark\": \"excellent\"\n}", "options": { "raw": { "language": "json" @@ -2862,7 +2968,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"status\": \"selected\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", + "raw": "{\n \"status\": \"selected\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\",\n \"remark\": \"excellent\"\n}", "options": { "raw": { "language": "json" @@ -2895,7 +3001,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"status\": \"selected\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", + "raw": "{\n \"status\": \"selected\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\",\n \"remark\": \"excellent\"\n}", "options": { "raw": { "language": "json" @@ -2928,7 +3034,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"status\": \"selected\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}", + "raw": "{\n \"status\": \"selected\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\",\n \"remark\": \"excellent\"\n}", "options": { "raw": { "language": "json" @@ -3118,7 +3224,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"projectId\": {{projectId}},\n \"externalId\": \"88774632\",\n \"description\": \"Dummy Description\",\n \"startDate\": \"2020-09-27\",\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": "{\n \"projectId\": {{projectId}},\n \"externalId\": \"88774632\",\n \"description\": \"Dummy Description\",\n \"startDate\": \"2020-09-27\",\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 \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", "options": { "raw": { "language": "json" @@ -3167,7 +3273,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"jobId\": \"{{jobId}}\",\n \"userId\": \"95e7970f-12b4-43b7-ab35-38c34bf033c7\",\n \"externalId\": \"88774631\",\n \"resume\": \"http://example.com\"\n}", + "raw": "{\n \"jobId\": \"{{jobId}}\",\n \"userId\": \"95e7970f-12b4-43b7-ab35-38c34bf033c7\",\n \"externalId\": \"88774631\",\n \"resume\": \"http://example.com\",\n \"remark\": \"excellent\"\n}", "options": { "raw": { "language": "json" @@ -3216,7 +3322,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"jobId\": \"{{jobId}}\",\n \"userId\": \"95e7970f-12b4-43b7-ab35-38c34bf033c7\",\n \"externalId\": \"88774631\",\n \"resume\": \"http://example.com\"\n}", + "raw": "{\n \"jobId\": \"{{jobId}}\",\n \"userId\": \"95e7970f-12b4-43b7-ab35-38c34bf033c7\",\n \"externalId\": \"88774631\",\n \"resume\": \"http://example.com\",\n \"remark\": \"excellent\"\n}", "options": { "raw": { "language": "json" @@ -3265,7 +3371,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"jobId\": \"{{jobId}}\",\n \"userId\": \"95e7970f-12b4-43b7-ab35-38c34bf033c7\",\n \"externalId\": \"88774631\",\n \"resume\": \"http://example.com\"\n}", + "raw": "{\n \"jobId\": \"{{jobId}}\",\n \"userId\": \"95e7970f-12b4-43b7-ab35-38c34bf033c7\",\n \"externalId\": \"88774631\",\n \"resume\": \"http://example.com\",\n \"remark\": \"excellent\"\n}", "options": { "raw": { "language": "json" @@ -3314,7 +3420,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"jobId\": \"{{jobId}}\",\n \"userId\": \"95e7970f-12b4-43b7-ab35-38c34bf033c7\",\n \"externalId\": \"88774631\",\n \"resume\": \"http://example.com\"\n}", + "raw": "{\n \"jobId\": \"{{jobId}}\",\n \"userId\": \"95e7970f-12b4-43b7-ab35-38c34bf033c7\",\n \"externalId\": \"88774631\",\n \"resume\": \"http://example.com\",\n \"remark\": \"excellent\"\n}", "options": { "raw": { "language": "json" @@ -3363,7 +3469,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"jobId\": \"{{jobId}}\",\n \"userId\": \"95e7970f-12b4-43b7-ab35-38c34bf033c7\",\n \"externalId\": \"88774631\",\n \"resume\": \"http://example.com\"\n}", + "raw": "{\n \"jobId\": \"{{jobId}}\",\n \"userId\": \"95e7970f-12b4-43b7-ab35-38c34bf033c7\",\n \"externalId\": \"88774631\",\n \"resume\": \"http://example.com\",\n \"remark\": \"excellent\"\n}", "options": { "raw": { "language": "json" @@ -7839,7 +7945,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": "{\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 \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", "options": { "raw": { "language": "json" @@ -7865,8 +7971,13 @@ "listen": "test", "script": { "exec": [ - "var data = JSON.parse(responseBody);\r", - "postman.setEnvironmentVariable(\"jobIdCreatedByM2M\",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(\"jobIdCreatedByM2M\", response.id);\r", + " }\r", + "});" ], "type": "text/javascript" } @@ -7883,7 +7994,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": "{\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 \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", "options": { "raw": { "language": "json" @@ -7905,71 +8016,4708 @@ ] }, { - "name": "create resource booking with booking manager", - "event": [ + "name": "Extended Search Scenarios", + "item": [ { - "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", - "});" + "name": "search RB sortBy id", + "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}}" + } ], - "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-27\",\r\n \"endDate\": \"2020-10-27\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"billingAccountId\": 80000071\r\n}", - "options": { - "raw": { - "language": "json" + "url": { + "raw": "{{URL}}/resourceBookings?page=1&perPage=5&sortBy=id&sortOrder=asc", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings" + ], + "query": [ + { + "key": "page", + "value": "1" + }, + { + "key": "perPage", + "value": "5" + }, + { + "key": "sortBy", + "value": "id" + }, + { + "key": "sortOrder", + "value": "asc" + }, + { + "key": "sortOrder", + "value": "desc", + "disabled": true + }, + { + "key": "fields", + "value": "id", + "disabled": true + }, + { + "key": "status", + "value": "placed", + "disabled": true + }, + { + "key": "fields", + "value": "id,status", + "disabled": true + }, + { + "key": "startDate", + "value": "2021-01-11", + "disabled": true + }, + { + "key": "fields", + "value": "id,startDate", + "disabled": true + }, + { + "key": "endDate", + "value": "2021-02-11", + "disabled": true + }, + { + "key": "fields", + "value": "id,endDate", + "disabled": true + }, + { + "key": "rateType", + "value": "weekly", + "disabled": true + }, + { + "key": "fields", + "value": "id,rateType", + "disabled": true + }, + { + "key": "jobId", + "value": "fc58382a-31d7-44b7-bfe5-2d671300f8d9", + "disabled": true + }, + { + "key": "fields", + "value": "id,jobId", + "disabled": true + }, + { + "key": "projectId", + "value": "16870", + "disabled": true + }, + { + "key": "projectIds", + "value": "16870,16805,16739,17091", + "disabled": true + }, + { + "key": "fields", + "value": "id,projectId", + "disabled": true + }, + { + "key": "workPeriods.paymentStatus", + "value": "pending", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.paymentStatus", + "disabled": true + }, + { + "key": "workPeriods.startDate", + "value": "2021-01-03", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate", + "disabled": true + }, + { + "key": "workPeriods.endDate", + "value": "2021-01-09", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.endDate", + "disabled": true + }, + { + "key": "workPeriods.userHandle", + "value": "GunaK-TopCoder", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.userHandle", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods", + "disabled": true + } + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/resourceBookings", - "host": [ - "{{URL}}" - ], - "path": [ - "resourceBookings" - ] - } - }, - "response": [] - }, - { - "name": "search work periods of newly created resource booking", - "event": [ { - "listen": "test", - "script": { - "exec": [ - "pm.test('Status code is 200', function () {\r", - " pm.response.to.have.status(200);\r", - "});" - ], + "name": "search RB sortBy status", + "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}}/resourceBookings?page=1&perPage=5&sortBy=status&sortOrder=asc", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings" + ], + "query": [ + { + "key": "page", + "value": "1" + }, + { + "key": "perPage", + "value": "5" + }, + { + "key": "sortBy", + "value": "status" + }, + { + "key": "sortOrder", + "value": "asc" + }, + { + "key": "sortOrder", + "value": "desc", + "disabled": true + }, + { + "key": "fields", + "value": "id,status", + "disabled": true + }, + { + "key": "status", + "value": "placed", + "disabled": true + }, + { + "key": "startDate", + "value": "2021-01-11", + "disabled": true + }, + { + "key": "fields", + "value": "id,status,startDate", + "disabled": true + }, + { + "key": "endDate", + "value": "2021-02-11", + "disabled": true + }, + { + "key": "fields", + "value": "id,status,endDate", + "disabled": true + }, + { + "key": "rateType", + "value": "weekly", + "disabled": true + }, + { + "key": "fields", + "value": "id,status,rateType", + "disabled": true + }, + { + "key": "jobId", + "value": "fc58382a-31d7-44b7-bfe5-2d671300f8d9", + "disabled": true + }, + { + "key": "fields", + "value": "id,status,jobId", + "disabled": true + }, + { + "key": "projectId", + "value": "16870", + "disabled": true + }, + { + "key": "projectIds", + "value": "16870,16805,16739,17091", + "disabled": true + }, + { + "key": "fields", + "value": "id,status,projectId", + "disabled": true + }, + { + "key": "workPeriods.paymentStatus", + "value": "pending", + "disabled": true + }, + { + "key": "fields", + "value": "id,status,workPeriods.id,workPeriods.paymentStatus", + "disabled": true + }, + { + "key": "workPeriods.startDate", + "value": "2021-01-03", + "disabled": true + }, + { + "key": "fields", + "value": "id,status,workPeriods.id,workPeriods.startDate", + "disabled": true + }, + { + "key": "workPeriods.endDate", + "value": "2021-01-09", + "disabled": true + }, + { + "key": "fields", + "value": "id,status,workPeriods.id,workPeriods.endDate", + "disabled": true + }, + { + "key": "workPeriods.userHandle", + "value": "GunaK-TopCoder", + "disabled": true + }, + { + "key": "fields", + "value": "id,status,workPeriods.id,workPeriods.userHandle", + "disabled": true + }, + { + "key": "fields", + "value": "id,status,workPeriods", + "disabled": true + } + ] + } + }, + "response": [] + }, + { + "name": "search RB sortBy rateType", + "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}}/resourceBookings?page=1&perPage=5&sortBy=rateType&sortOrder=asc", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings" + ], + "query": [ + { + "key": "page", + "value": "1" + }, + { + "key": "perPage", + "value": "5" + }, + { + "key": "sortBy", + "value": "rateType" + }, + { + "key": "sortOrder", + "value": "asc" + }, + { + "key": "sortOrder", + "value": "desc", + "disabled": true + }, + { + "key": "fields", + "value": "id,rateType", + "disabled": true + }, + { + "key": "status", + "value": "placed", + "disabled": true + }, + { + "key": "fields", + "value": "id,rateType,status", + "disabled": true + }, + { + "key": "startDate", + "value": "2021-01-11", + "disabled": true + }, + { + "key": "fields", + "value": "id,rateType,startDate", + "disabled": true + }, + { + "key": "endDate", + "value": "2021-02-11", + "disabled": true + }, + { + "key": "fields", + "value": "id,rateType,endDate", + "disabled": true + }, + { + "key": "rateType", + "value": "weekly", + "disabled": true + }, + { + "key": "fields", + "value": "id,rateType", + "disabled": true + }, + { + "key": "jobId", + "value": "fc58382a-31d7-44b7-bfe5-2d671300f8d9", + "disabled": true + }, + { + "key": "fields", + "value": "id,rateType,jobId", + "disabled": true + }, + { + "key": "projectId", + "value": "16870", + "disabled": true + }, + { + "key": "projectIds", + "value": "16870,16805,16739,17091", + "disabled": true + }, + { + "key": "fields", + "value": "id,rateType,projectId", + "disabled": true + }, + { + "key": "workPeriods.paymentStatus", + "value": "pending", + "disabled": true + }, + { + "key": "fields", + "value": "id,rateType,workPeriods.id,workPeriods.paymentStatus", + "disabled": true + }, + { + "key": "workPeriods.startDate", + "value": "2021-01-03", + "disabled": true + }, + { + "key": "fields", + "value": "id,rateType,workPeriods.id,workPeriods.startDate", + "disabled": true + }, + { + "key": "workPeriods.endDate", + "value": "2021-01-09", + "disabled": true + }, + { + "key": "fields", + "value": "id,rateType,workPeriods.id,workPeriods.endDate", + "disabled": true + }, + { + "key": "workPeriods.userHandle", + "value": "GunaK-TopCoder", + "disabled": true + }, + { + "key": "fields", + "value": "id,rateType,workPeriods.id,workPeriods.userHandle", + "disabled": true + }, + { + "key": "fields", + "value": "id,rateType,workPeriods", + "disabled": true + } + ] + } + }, + "response": [] + }, + { + "name": "search RB sortBy startDate", + "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}}/resourceBookings?page=1&perPage=10&sortBy=startDate&sortOrder=asc", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings" + ], + "query": [ + { + "key": "page", + "value": "1" + }, + { + "key": "perPage", + "value": "10" + }, + { + "key": "sortBy", + "value": "startDate" + }, + { + "key": "sortOrder", + "value": "asc" + }, + { + "key": "sortOrder", + "value": "desc", + "disabled": true + }, + { + "key": "fields", + "value": "id,startDate", + "disabled": true + }, + { + "key": "status", + "value": "placed", + "disabled": true + }, + { + "key": "fields", + "value": "id,startDate,status", + "disabled": true + }, + { + "key": "startDate", + "value": "2021-01-11", + "disabled": true + }, + { + "key": "fields", + "value": "id,startDate", + "disabled": true + }, + { + "key": "endDate", + "value": "2021-02-11", + "disabled": true + }, + { + "key": "fields", + "value": "id,startDate,endDate", + "disabled": true + }, + { + "key": "rateType", + "value": "weekly", + "disabled": true + }, + { + "key": "fields", + "value": "id,startDate,rateType", + "disabled": true + }, + { + "key": "jobId", + "value": "fc58382a-31d7-44b7-bfe5-2d671300f8d9", + "disabled": true + }, + { + "key": "fields", + "value": "id,startDate,jobId", + "disabled": true + }, + { + "key": "projectId", + "value": "16870", + "disabled": true + }, + { + "key": "projectIds", + "value": "16870,16805,16739,17091", + "disabled": true + }, + { + "key": "fields", + "value": "id,startDate,projectId", + "disabled": true + }, + { + "key": "workPeriods.paymentStatus", + "value": "pending", + "disabled": true + }, + { + "key": "fields", + "value": "id,startDate,workPeriods.id,workPeriods.paymentStatus", + "disabled": true + }, + { + "key": "workPeriods.startDate", + "value": "2021-01-03", + "disabled": true + }, + { + "key": "fields", + "value": "id,startDate,workPeriods.id,workPeriods.startDate", + "disabled": true + }, + { + "key": "workPeriods.endDate", + "value": "2021-01-09", + "disabled": true + }, + { + "key": "fields", + "value": "id,startDate,workPeriods.id,workPeriods.endDate", + "disabled": true + }, + { + "key": "workPeriods.userHandle", + "value": "GunaK-TopCoder", + "disabled": true + }, + { + "key": "fields", + "value": "id,startDate,workPeriods.id,workPeriods.userHandle", + "disabled": true + }, + { + "key": "fields", + "value": "id,startDate,workPeriods", + "disabled": true + } + ] + } + }, + "response": [] + }, + { + "name": "search RB sortBy endDate", + "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}}/resourceBookings?page=1&perPage=10&sortBy=endDate&sortOrder=asc", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings" + ], + "query": [ + { + "key": "page", + "value": "1" + }, + { + "key": "perPage", + "value": "10" + }, + { + "key": "sortBy", + "value": "endDate" + }, + { + "key": "sortOrder", + "value": "asc" + }, + { + "key": "sortOrder", + "value": "desc", + "disabled": true + }, + { + "key": "fields", + "value": "id,endDate", + "disabled": true + }, + { + "key": "status", + "value": "placed", + "disabled": true + }, + { + "key": "fields", + "value": "id,endDate,status", + "disabled": true + }, + { + "key": "startDate", + "value": "2021-01-11", + "disabled": true + }, + { + "key": "fields", + "value": "id,endDate,startDate", + "disabled": true + }, + { + "key": "endDate", + "value": "2021-02-11", + "disabled": true + }, + { + "key": "fields", + "value": "id,endDate", + "disabled": true + }, + { + "key": "rateType", + "value": "weekly", + "disabled": true + }, + { + "key": "fields", + "value": "id,endDate,rateType", + "disabled": true + }, + { + "key": "jobId", + "value": "fc58382a-31d7-44b7-bfe5-2d671300f8d9", + "disabled": true + }, + { + "key": "fields", + "value": "id,endDate,jobId", + "disabled": true + }, + { + "key": "projectId", + "value": "16870", + "disabled": true + }, + { + "key": "projectIds", + "value": "16870,16805,16739,17091", + "disabled": true + }, + { + "key": "fields", + "value": "id,endDate,projectId", + "disabled": true + }, + { + "key": "workPeriods.paymentStatus", + "value": "pending", + "disabled": true + }, + { + "key": "fields", + "value": "id,endDate,workPeriods.id,workPeriods.paymentStatus", + "disabled": true + }, + { + "key": "workPeriods.startDate", + "value": "2021-01-03", + "disabled": true + }, + { + "key": "fields", + "value": "id,endDate,workPeriods.id,workPeriods.startDate", + "disabled": true + }, + { + "key": "workPeriods.endDate", + "value": "2021-01-09", + "disabled": true + }, + { + "key": "fields", + "value": "id,endDate,workPeriods.id,workPeriods.endDate", + "disabled": true + }, + { + "key": "workPeriods.userHandle", + "value": "GunaK-TopCoder", + "disabled": true + }, + { + "key": "fields", + "value": "id,endDate,workPeriods.id,workPeriods.userHandle", + "disabled": true + }, + { + "key": "fields", + "value": "id,endDate,workPeriods", + "disabled": true + } + ] + } + }, + "response": [] + }, + { + "name": "search RB sortBy customerRate", + "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}}/resourceBookings?page=1&perPage=5&sortBy=customerRate&sortOrder=asc", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings" + ], + "query": [ + { + "key": "page", + "value": "1" + }, + { + "key": "perPage", + "value": "5" + }, + { + "key": "sortBy", + "value": "customerRate" + }, + { + "key": "sortOrder", + "value": "asc" + }, + { + "key": "sortOrder", + "value": "desc", + "disabled": true + }, + { + "key": "fields", + "value": "id,customerRate", + "disabled": true + }, + { + "key": "status", + "value": "placed", + "disabled": true + }, + { + "key": "fields", + "value": "id,customerRate,status", + "disabled": true + }, + { + "key": "startDate", + "value": "2021-01-11", + "disabled": true + }, + { + "key": "fields", + "value": "id,customerRate,startDate", + "disabled": true + }, + { + "key": "endDate", + "value": "2021-02-11", + "disabled": true + }, + { + "key": "fields", + "value": "id,customerRate,endDate", + "disabled": true + }, + { + "key": "rateType", + "value": "weekly", + "disabled": true + }, + { + "key": "fields", + "value": "id,customerRate,rateType", + "disabled": true + }, + { + "key": "jobId", + "value": "fc58382a-31d7-44b7-bfe5-2d671300f8d9", + "disabled": true + }, + { + "key": "fields", + "value": "id,customerRate,jobId", + "disabled": true + }, + { + "key": "projectId", + "value": "16870", + "disabled": true + }, + { + "key": "projectIds", + "value": "16870,16805,16739,17091", + "disabled": true + }, + { + "key": "fields", + "value": "id,customerRate,projectId", + "disabled": true + }, + { + "key": "workPeriods.paymentStatus", + "value": "pending", + "disabled": true + }, + { + "key": "fields", + "value": "id,customerRate,workPeriods.id,workPeriods.paymentStatus", + "disabled": true + }, + { + "key": "workPeriods.startDate", + "value": "2021-01-03", + "disabled": true + }, + { + "key": "fields", + "value": "id,customerRate,workPeriods.id,workPeriods.startDate", + "disabled": true + }, + { + "key": "workPeriods.endDate", + "value": "2021-01-09", + "disabled": true + }, + { + "key": "fields", + "value": "id,customerRate,workPeriods.id,workPeriods.endDate", + "disabled": true + }, + { + "key": "workPeriods.userHandle", + "value": "GunaK-TopCoder", + "disabled": true + }, + { + "key": "fields", + "value": "id,customerRate,workPeriods.id,workPeriods.userHandle", + "disabled": true + }, + { + "key": "fields", + "value": "id,customerRate,workPeriods", + "disabled": true + } + ] + } + }, + "response": [] + }, + { + "name": "search RB sortBy memberRate", + "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}}/resourceBookings?page=1&perPage=5&sortBy=memberRate&sortOrder=asc", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings" + ], + "query": [ + { + "key": "page", + "value": "1" + }, + { + "key": "perPage", + "value": "5" + }, + { + "key": "sortBy", + "value": "memberRate" + }, + { + "key": "sortOrder", + "value": "asc" + }, + { + "key": "sortOrder", + "value": "desc", + "disabled": true + }, + { + "key": "fields", + "value": "id,memberRate", + "disabled": true + }, + { + "key": "status", + "value": "placed", + "disabled": true + }, + { + "key": "fields", + "value": "id,memberRate,status", + "disabled": true + }, + { + "key": "startDate", + "value": "2021-01-11", + "disabled": true + }, + { + "key": "fields", + "value": "id,memberRate,startDate", + "disabled": true + }, + { + "key": "endDate", + "value": "2021-02-11", + "disabled": true + }, + { + "key": "fields", + "value": "id,memberRate,endDate", + "disabled": true + }, + { + "key": "rateType", + "value": "weekly", + "disabled": true + }, + { + "key": "fields", + "value": "id,memberRate,rateType", + "disabled": true + }, + { + "key": "jobId", + "value": "fc58382a-31d7-44b7-bfe5-2d671300f8d9", + "disabled": true + }, + { + "key": "fields", + "value": "id,memberRate,jobId", + "disabled": true + }, + { + "key": "projectId", + "value": "16870", + "disabled": true + }, + { + "key": "projectIds", + "value": "16870,16805,16739,17091", + "disabled": true + }, + { + "key": "fields", + "value": "id,memberRate,projectId", + "disabled": true + }, + { + "key": "workPeriods.paymentStatus", + "value": "pending", + "disabled": true + }, + { + "key": "fields", + "value": "id,memberRate,workPeriods.id,workPeriods.paymentStatus", + "disabled": true + }, + { + "key": "workPeriods.startDate", + "value": "2021-01-03", + "disabled": true + }, + { + "key": "fields", + "value": "id,memberRate,workPeriods.id,workPeriods.startDate", + "disabled": true + }, + { + "key": "workPeriods.endDate", + "value": "2021-01-09", + "disabled": true + }, + { + "key": "fields", + "value": "id,memberRate,workPeriods.id,workPeriods.endDate", + "disabled": true + }, + { + "key": "workPeriods.userHandle", + "value": "GunaK-TopCoder", + "disabled": true + }, + { + "key": "fields", + "value": "id,memberRate,workPeriods.id,workPeriods.userHandle", + "disabled": true + }, + { + "key": "fields", + "value": "id,memberRate,workPeriods", + "disabled": true + } + ] + } + }, + "response": [] + }, + { + "name": "search RB sortBy workPeriods.userHandle", + "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}}/resourceBookings?page=1&perPage=10&sortBy=workPeriods.userHandle&workPeriods.startDate=2021-01-03&sortOrder=asc&fields=id,workPeriods.id,workPeriods.startDate,workPeriods.userHandle", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings" + ], + "query": [ + { + "key": "page", + "value": "1" + }, + { + "key": "perPage", + "value": "10" + }, + { + "key": "sortBy", + "value": "workPeriods.userHandle" + }, + { + "key": "workPeriods.startDate", + "value": "2021-01-03" + }, + { + "key": "sortOrder", + "value": "asc" + }, + { + "key": "sortOrder", + "value": "desc", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.userHandle" + }, + { + "key": "status", + "value": "placed", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.userHandle,status", + "disabled": true + }, + { + "key": "startDate", + "value": "2021-01-01", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.userHandle,startDate", + "disabled": true + }, + { + "key": "endDate", + "value": "2021-02-01", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.userHandle,endDate", + "disabled": true + }, + { + "key": "rateType", + "value": "weekly", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.userHandle,rateType", + "disabled": true + }, + { + "key": "jobId", + "value": "fc58382a-31d7-44b7-bfe5-2d671300f8d9", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.userHandle,jobId", + "disabled": true + }, + { + "key": "projectId", + "value": "16870", + "disabled": true + }, + { + "key": "projectIds", + "value": "16870,16805,16739,17091", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.userHandle,projectId", + "disabled": true + }, + { + "key": "workPeriods.paymentStatus", + "value": "pending", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.userHandle,workPeriods.paymentStatus", + "disabled": true + }, + { + "key": "workPeriods.endDate", + "value": "2021-01-09", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.userHandle,workPeriods.endDate", + "disabled": true + }, + { + "key": "workPeriods.userHandle", + "value": "GunaK-TopCoder", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.userHandle", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods", + "disabled": true + } + ] + } + }, + "response": [] + }, + { + "name": "search RB sortBy workPeriods.daysWorked", + "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}}/resourceBookings?page=1&perPage=10&sortBy=workPeriods.daysWorked&workPeriods.startDate=2021-01-10&sortOrder=asc&fields=id,workPeriods.id,workPeriods.startDate,workPeriods.daysWorked", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings" + ], + "query": [ + { + "key": "page", + "value": "1" + }, + { + "key": "perPage", + "value": "10" + }, + { + "key": "sortBy", + "value": "workPeriods.daysWorked" + }, + { + "key": "workPeriods.startDate", + "value": "2021-01-10" + }, + { + "key": "sortOrder", + "value": "asc" + }, + { + "key": "sortOrder", + "value": "desc", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.daysWorked" + }, + { + "key": "status", + "value": "placed", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.daysWorked,status", + "disabled": true + }, + { + "key": "startDate", + "value": "2021-01-01", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.daysWorked,startDate", + "disabled": true + }, + { + "key": "endDate", + "value": "2021-02-01", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.daysWorked,endDate", + "disabled": true + }, + { + "key": "rateType", + "value": "weekly", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.daysWorked,rateType", + "disabled": true + }, + { + "key": "jobId", + "value": "fc58382a-31d7-44b7-bfe5-2d671300f8d9", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.daysWorked,jobId", + "disabled": true + }, + { + "key": "projectId", + "value": "16870", + "disabled": true + }, + { + "key": "projectIds", + "value": "16870,16805,16739,17091", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.daysWorked,projectId", + "disabled": true + }, + { + "key": "workPeriods.paymentStatus", + "value": "pending", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.daysWorked,workPeriods.paymentStatus", + "disabled": true + }, + { + "key": "workPeriods.endDate", + "value": "2021-01-16", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.daysWorked,workPeriods.endDate", + "disabled": true + }, + { + "key": "workPeriods.userHandle", + "value": "GunaK-TopCoder", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.daysWorked,workPeriods.userHandle", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods", + "disabled": true + } + ] + } + }, + "response": [] + }, + { + "name": "search RB sortBy workPeriods.daysPaid", + "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}}/resourceBookings?page=1&perPage=5&sortBy=workPeriods.daysPaid&workPeriods.startDate=2021-01-03&sortOrder=asc&fields=id,workPeriods.id,workPeriods.startDate,workPeriods.daysPaid", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings" + ], + "query": [ + { + "key": "page", + "value": "1" + }, + { + "key": "perPage", + "value": "5" + }, + { + "key": "sortBy", + "value": "workPeriods.daysPaid" + }, + { + "key": "workPeriods.startDate", + "value": "2021-01-03" + }, + { + "key": "sortOrder", + "value": "asc" + }, + { + "key": "sortOrder", + "value": "desc", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.daysPaid" + }, + { + "key": "status", + "value": "placed", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.daysPaid,status", + "disabled": true + }, + { + "key": "startDate", + "value": "2021-01-01", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.daysPaid,startDate", + "disabled": true + }, + { + "key": "endDate", + "value": "2021-02-01", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.daysPaid,endDate", + "disabled": true + }, + { + "key": "rateType", + "value": "weekly", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.daysPaid,rateType", + "disabled": true + }, + { + "key": "jobId", + "value": "fc58382a-31d7-44b7-bfe5-2d671300f8d9", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.daysPaid,jobId", + "disabled": true + }, + { + "key": "projectId", + "value": "16870", + "disabled": true + }, + { + "key": "projectIds", + "value": "16870,16805,16739,17091", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.daysPaid,projectId", + "disabled": true + }, + { + "key": "workPeriods.paymentStatus", + "value": "pending", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.daysPaid,workPeriods.paymentStatus", + "disabled": true + }, + { + "key": "workPeriods.endDate", + "value": "2021-01-09", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.daysPaid,workPeriods.endDate", + "disabled": true + }, + { + "key": "workPeriods.userHandle", + "value": "GunaK-TopCoder", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.daysPaid,workPeriods.userHandle", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods", + "disabled": true + } + ] + } + }, + "response": [] + }, + { + "name": "search RB sortBy workPeriods.paymentTotal", + "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}}/resourceBookings?page=1&perPage=5&sortBy=workPeriods.paymentTotal&workPeriods.startDate=2021-01-03&sortOrder=asc&fields=id,workPeriods.id,workPeriods.startDate,workPeriods.paymentTotal", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings" + ], + "query": [ + { + "key": "page", + "value": "1" + }, + { + "key": "perPage", + "value": "5" + }, + { + "key": "sortBy", + "value": "workPeriods.paymentTotal" + }, + { + "key": "workPeriods.startDate", + "value": "2021-01-03" + }, + { + "key": "sortOrder", + "value": "asc" + }, + { + "key": "sortOrder", + "value": "desc", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.paymentTotal" + }, + { + "key": "status", + "value": "placed", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.paymentTotal,status", + "disabled": true + }, + { + "key": "startDate", + "value": "2021-01-01", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.paymentTotal,startDate", + "disabled": true + }, + { + "key": "endDate", + "value": "2021-02-01", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.paymentTotal,endDate", + "disabled": true + }, + { + "key": "rateType", + "value": "weekly", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.paymentTotal,rateType", + "disabled": true + }, + { + "key": "jobId", + "value": "fc58382a-31d7-44b7-bfe5-2d671300f8d9", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.paymentTotal,jobId", + "disabled": true + }, + { + "key": "projectId", + "value": "16870", + "disabled": true + }, + { + "key": "projectIds", + "value": "16870,16805,16739,17091", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.paymentTotal,projectId", + "disabled": true + }, + { + "key": "workPeriods.paymentStatus", + "value": "pending", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.paymentTotal,workPeriods.paymentStatus", + "disabled": true + }, + { + "key": "workPeriods.endDate", + "value": "2021-01-09", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.paymentTotal,workPeriods.endDate", + "disabled": true + }, + { + "key": "workPeriods.userHandle", + "value": "GunaK-TopCoder", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.paymentTotal,workPeriods.userHandle", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods", + "disabled": true + } + ] + } + }, + "response": [] + }, + { + "name": "search RB sortBy workPeriods.paymentStatus", + "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}}/resourceBookings?page=1&perPage=5&sortBy=workPeriods.paymentStatus&workPeriods.startDate=2021-01-03&sortOrder=asc&fields=id,workPeriods.id,workPeriods.startDate,workPeriods.paymentStatus", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings" + ], + "query": [ + { + "key": "page", + "value": "1" + }, + { + "key": "perPage", + "value": "5" + }, + { + "key": "sortBy", + "value": "workPeriods.paymentStatus" + }, + { + "key": "workPeriods.startDate", + "value": "2021-01-03" + }, + { + "key": "sortOrder", + "value": "asc" + }, + { + "key": "sortOrder", + "value": "desc", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.paymentStatus" + }, + { + "key": "status", + "value": "placed", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.paymentStatus,status", + "disabled": true + }, + { + "key": "startDate", + "value": "2021-01-01", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.paymentStatus,startDate", + "disabled": true + }, + { + "key": "endDate", + "value": "2021-02-01", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.paymentStatus,endDate", + "disabled": true + }, + { + "key": "rateType", + "value": "weekly", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.paymentStatus,rateType", + "disabled": true + }, + { + "key": "jobId", + "value": "fc58382a-31d7-44b7-bfe5-2d671300f8d9", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.paymentStatus,jobId", + "disabled": true + }, + { + "key": "projectId", + "value": "16870", + "disabled": true + }, + { + "key": "projectIds", + "value": "16870,16805,16739,17091", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.paymentStatus,projectId", + "disabled": true + }, + { + "key": "workPeriods.paymentStatus", + "value": "pending", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.paymentStatus,workPeriods.paymentStatus", + "disabled": true + }, + { + "key": "workPeriods.endDate", + "value": "2021-01-09", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.paymentStatus,workPeriods.endDate", + "disabled": true + }, + { + "key": "workPeriods.userHandle", + "value": "GunaK-TopCoder", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods.id,workPeriods.startDate,workPeriods.paymentStatus,workPeriods.userHandle", + "disabled": true + }, + { + "key": "fields", + "value": "id,workPeriods", + "disabled": true + } + ] + } + }, + "response": [] + } + ] + }, + { + "name": "create resource booking 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(\"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-27\",\r\n \"endDate\": \"2020-10-27\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"billingAccountId\": 80000071\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/resourceBookings", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings" + ] + } + }, + "response": [] + }, + { + "name": "search work periods of newly created resource booking", + "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}}/work-periods?sortBy=startDate&sortOrder=asc&resourceBookingId={{resourceBookingId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "work-periods" + ], + "query": [ + { + "key": "page", + "value": "1", + "disabled": true + }, + { + "key": "perPage", + "value": "5", + "disabled": true + }, + { + "key": "sortBy", + "value": "startDate" + }, + { + "key": "sortOrder", + "value": "asc" + }, + { + "key": "resourceBookingId", + "value": "{{resourceBookingId}}" + }, + { + "key": "resourceBookingIds", + "value": "{{resourceBookingId}},{{resourceBookingId}}", + "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": "create resource booking 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(\"resourceBookingIdCreatedByM2M\", response.id);\r", + " }\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_m2m_create_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-12-27\",\r\n \"endDate\": \"2021-01-27\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"billingAccountId\": 80000071\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/resourceBookings", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings" + ] + } + }, + "response": [] + }, + { + "name": "search work periods of newly created resource booking", + "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}}/work-periods?sortBy=startDate&sortOrder=asc&resourceBookingId={{resourceBookingIdCreatedByM2M}}", + "host": [ + "{{URL}}" + ], + "path": [ + "work-periods" + ], + "query": [ + { + "key": "page", + "value": "1", + "disabled": true + }, + { + "key": "perPage", + "value": "5", + "disabled": true + }, + { + "key": "sortBy", + "value": "startDate" + }, + { + "key": "sortOrder", + "value": "asc" + }, + { + "key": "resourceBookingId", + "value": "{{resourceBookingIdCreatedByM2M}}" + }, + { + "key": "resourceBookingIds", + "value": "{{resourceBookingIdCreatedByM2M}},{{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": "create resource booking with m2m all", + "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(\"resourceBookingIdCreatedByM2M\", response.id);\r", + " }\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_m2m_all_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-27\",\r\n \"endDate\": \"2020-10-27\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 10,\r\n \"rateType\": \"hourly\",\r\n \"billingAccountId\": 80000071\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/resourceBookings", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings" + ] + } + }, + "response": [] + }, + { + "name": "create resource booking 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": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_connectUser}}" + } + ], + "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 \"billingAccountId\": 80000071\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/resourceBookings", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings" + ] + } + }, + "response": [] + }, + { + "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": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "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-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" + } + } + }, + "url": { + "raw": "{{URL}}/resourceBookings", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings" + ] + } + }, + "response": [] + }, + { + "name": "create resource booking 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": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_userId_not_exist}}" + } + ], + "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 \"billingAccountId\": 80000071\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/resourceBookings", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings" + ] + } + }, + "response": [] + }, + { + "name": "create resource booking 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": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer invalid_token" + } + ], + "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-27\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"billingAccountId\": 80000071\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/resourceBookings", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings" + ] + } + }, + "response": [] + }, + { + "name": "get resource booking 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}}/resourceBookings/{{resourceBookingId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings", + "{{resourceBookingId}}" + ] + } + }, + "response": [] + }, + { + "name": "get resource booking 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_resource_booking}}" + } + ], + "url": { + "raw": "{{URL}}/resourceBookings/{{resourceBookingIdCreatedByM2M}}", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings", + "{{resourceBookingIdCreatedByM2M}}" + ] + } + }, + "response": [] + }, + { + "name": "get resource booking 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}}/resourceBookings/{{resourceBookingId}}?fromDb=true", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings", + "{{resourceBookingId}}" + ], + "query": [ + { + "key": "fromDb", + "value": "true" + } + ] + } + }, + "response": [] + }, + { + "name": "get resource booking 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}}/resourceBookings/{{resourceBookingId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings", + "{{resourceBookingId}}" + ] + } + }, + "response": [] + }, + { + "name": "get resource booking with member", + "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(\"userId: 8547899 the user is not a member of project 111\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_member}}" + } + ], + "url": { + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings", + "{{resourceBookingId}}" + ] + } + }, + "response": [] + }, + { + "name": "get resource booking with parameters 1", + "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", + " _.each(['id','projectId','status','startDate','endDate','billingAccountId','userId','jobId','rateType','memberRate','customerRate','createdBy','updatedBy','createdAt','updatedAt'], field => {\r", + " pm.expect(response).to.have.property(field)\r", + " })\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "url": { + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}?fields=id,projectId,status,startDate,endDate,billingAccountId,userId,jobId,rateType,memberRate,customerRate,createdBy,updatedBy,createdAt,updatedAt,deletedAt", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings", + "{{resourceBookingId}}" + ], + "query": [ + { + "key": "fields", + "value": "id,projectId,status,startDate,endDate,billingAccountId,userId,jobId,rateType,memberRate,customerRate,createdBy,updatedBy,createdAt,updatedAt,deletedAt" + } + ] + } + }, + "response": [] + }, + { + "name": "get resource booking with parameters 1 fromDb", + "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", + " _.each(['id','projectId','status','startDate','endDate','billingAccountId','userId','jobId','rateType','memberRate','customerRate','createdBy','updatedBy','createdAt','updatedAt'], field => {\r", + " pm.expect(response).to.have.property(field)\r", + " })\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "url": { + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}?fields=id,projectId,status,startDate,endDate,billingAccountId,userId,jobId,rateType,memberRate,customerRate,createdBy,updatedBy,createdAt,updatedAt,deletedAt&fromDb=true", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings", + "{{resourceBookingId}}" + ], + "query": [ + { + "key": "fields", + "value": "id,projectId,status,startDate,endDate,billingAccountId,userId,jobId,rateType,memberRate,customerRate,createdBy,updatedBy,createdAt,updatedAt,deletedAt" + }, + { + "key": "fromDb", + "value": "true" + } + ] + } + }, + "response": [] + }, + { + "name": "get resource booking with parameters 2", + "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", + " _.each(['id','projectId','status','startDate','endDate','billingAccountId','userId','jobId','rateType','memberRate','customerRate','createdBy','updatedBy','createdAt','updatedAt','workPeriods'], field => {\r", + " pm.expect(response).to.have.property(field)\r", + " })\r", + " _.each(['id','projectId','paymentStatus','startDate','endDate','userHandle','resourceBookingId','daysWorked','daysPaid','paymentTotal','createdBy','updatedBy','createdAt','updatedAt'], field => {\r", + " pm.expect(response.workPeriods[0]).to.have.property(field)\r", + " })\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "url": { + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}?fields=workPeriods,id,projectId,status,startDate,endDate,billingAccountId,userId,jobId,rateType,memberRate,customerRate,createdBy,updatedBy,createdAt,updatedAt,deletedAt", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings", + "{{resourceBookingId}}" + ], + "query": [ + { + "key": "fields", + "value": "workPeriods,id,projectId,status,startDate,endDate,billingAccountId,userId,jobId,rateType,memberRate,customerRate,createdBy,updatedBy,createdAt,updatedAt,deletedAt" + } + ] + } + }, + "response": [] + }, + { + "name": "get resource booking with parameters 2 fromDb", + "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", + " _.each(['id','projectId','status','startDate','endDate','billingAccountId','userId','jobId','rateType','memberRate','customerRate','createdBy','updatedBy','createdAt','updatedAt','workPeriods'], field => {\r", + " pm.expect(response).to.have.property(field)\r", + " })\r", + " _.each(['id','projectId','paymentStatus','startDate','endDate','userHandle','resourceBookingId','daysWorked','daysPaid','paymentTotal','createdBy','updatedBy','createdAt','updatedAt'], field => {\r", + " pm.expect(response.workPeriods[0]).to.have.property(field)\r", + " })\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "url": { + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}?fields=workPeriods,id,projectId,status,startDate,endDate,billingAccountId,userId,jobId,rateType,memberRate,customerRate,createdBy,updatedBy,createdAt,updatedAt,deletedAt&fromDb=true", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings", + "{{resourceBookingId}}" + ], + "query": [ + { + "key": "fields", + "value": "workPeriods,id,projectId,status,startDate,endDate,billingAccountId,userId,jobId,rateType,memberRate,customerRate,createdBy,updatedBy,createdAt,updatedAt,deletedAt" + }, + { + "key": "fromDb", + "value": "true" + } + ] + } + }, + "response": [] + }, + { + "name": "get resource booking with parameters 3", + "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", + " _.each(['id','projectId','status','startDate','endDate'], field => {\r", + " pm.expect(response).to.have.property(field)\r", + " })\r", + " _.each(['id','projectId','startDate','endDate','daysWorked'], field => {\r", + " pm.expect(response.workPeriods[0]).to.have.property(field)\r", + " })\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "url": { + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}?fields=workPeriods.id,workPeriods.projectId,workPeriods.startDate,workPeriods.endDate,workPeriods.daysWorked,id,projectId,status,startDate,endDate", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings", + "{{resourceBookingId}}" + ], + "query": [ + { + "key": "fields", + "value": "workPeriods.id,workPeriods.projectId,workPeriods.startDate,workPeriods.endDate,workPeriods.daysWorked,id,projectId,status,startDate,endDate" + } + ] + } + }, + "response": [] + }, + { + "name": "get resource booking with parameters 3 fromDb", + "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", + " _.each(['id','projectId','status','startDate','endDate'], field => {\r", + " pm.expect(response).to.have.property(field)\r", + " })\r", + " _.each(['id','projectId','startDate','endDate','daysWorked'], field => {\r", + " pm.expect(response.workPeriods[0]).to.have.property(field)\r", + " })\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "url": { + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}?fields=workPeriods.id,workPeriods.projectId,workPeriods.startDate,workPeriods.endDate,workPeriods.daysWorked,id,projectId,status,startDate,endDate&fromDb=true", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings", + "{{resourceBookingId}}" + ], + "query": [ + { + "key": "fields", + "value": "workPeriods.id,workPeriods.projectId,workPeriods.startDate,workPeriods.endDate,workPeriods.daysWorked,id,projectId,status,startDate,endDate" + }, + { + "key": "fromDb", + "value": "true" + } + ] + } + }, + "response": [] + }, + { + "name": "get resource booking with parameters 4", + "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 don't have access to view memberRate and paymentTotal\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_connectUser}}" + } + ], + "url": { + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}?fields=memberRate", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings", + "{{resourceBookingId}}" + ], + "query": [ + { + "key": "fields", + "value": "memberRate" + } + ] + } + }, + "response": [] + }, + { + "name": "get resource booking with parameters 4 fromDb", + "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 don't have access to view memberRate and paymentTotal\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_connectUser}}" + } + ], + "url": { + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}?fields=memberRate&fromDb=true", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings", + "{{resourceBookingId}}" + ], + "query": [ + { + "key": "fields", + "value": "memberRate" + }, + { + "key": "fromDb", + "value": "true" + } + ] + } + }, + "response": [] + }, + { + "name": "get resource booking with parameters 5", + "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 don't have access to view workPeriods\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_m2m_all_resource_booking}}" + } + ], + "url": { + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}?fields=workPeriods", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings", + "{{resourceBookingId}}" + ], + "query": [ + { + "key": "fields", + "value": "workPeriods" + } + ] + } + }, + "response": [] + }, + { + "name": "get resource booking with parameters 5 fromDb", + "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 don't have access to view workPeriods\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_m2m_all_resource_booking}}" + } + ], + "url": { + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}?fields=workPeriods&fromDb=true", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings", + "{{resourceBookingId}}" + ], + "query": [ + { + "key": "fields", + "value": "workPeriods" + }, + { + "key": "fromDb", + "value": "true" + } + ] + } + }, + "response": [] + }, + { + "name": "search resource bookings 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}}/resourceBookings", + "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-27", + "disabled": true + }, + { + "key": "endDate", + "value": "2020-09-27", + "disabled": true + }, + { + "key": "rateType", + "value": "hourly", + "disabled": true + }, + { + "key": "status", + "value": "assigned", + "disabled": true + }, + { + "key": "projectIds", + "value": "111, 16705", + "disabled": true + } + ] + } + }, + "response": [] + }, + { + "name": "search resource bookings 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_resource_booking}}" + } + ], + "url": { + "raw": "{{URL}}/resourceBookings", + "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-27", + "disabled": true + }, + { + "key": "endDate", + "value": "2020-09-27", + "disabled": true + }, + { + "key": "rateType", + "value": "hourly", + "disabled": true + }, + { + "key": "status", + "value": "assigned", + "disabled": true + } + ] + } + }, + "response": [] + }, + { + "name": "search resource bookings 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}}/resourceBookings?sortOrder=desc", + "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-27", + "disabled": true + }, + { + "key": "endDate", + "value": "2020-09-27", + "disabled": true + }, + { + "key": "rateType", + "value": "hourly", + "disabled": true + }, + { + "key": "sortOrder", + "value": "desc" + } + ] + } + }, + "response": [] + }, + { + "name": "search resource bookings with member", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_member}}" + } + ], + "url": { + "raw": "{{URL}}/resourceBookings?sortOrder=desc", + "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-27", + "disabled": true + }, + { + "key": "endDate", + "value": "2020-09-27", + "disabled": true + }, + { + "key": "rateType", + "value": "hourly", + "disabled": true + }, + { + "key": "sortOrder", + "value": "desc" + } + ] + } + }, + "response": [] + }, + { + "name": "search resource bookings 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": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer invalid_token" + } + ], + "url": { + "raw": "{{URL}}/resourceBookings?sortOrder=desc", + "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-27", + "disabled": true + }, + { + "key": "endDate", + "value": "2020-09-27", + "disabled": true + }, + { + "key": "rateType", + "value": "hourly", + "disabled": true + }, + { + "key": "sortOrder", + "value": "desc" + } + ] + } + }, + "response": [] + }, + { + "name": "search resource bookings with parameters 1", + "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", + " _.each(['id','projectId','status','startDate','endDate','billingAccountId','userId','jobId','rateType','memberRate','customerRate','createdBy','updatedBy','createdAt','updatedAt'], field => {\r", + " pm.expect(response[0]).to.have.property(field)\r", + " })\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "url": { + "raw": "{{URL}}/resourceBookings?fields=id,projectId,status,startDate,endDate,billingAccountId,userId,jobId,rateType,memberRate,customerRate,createdBy,updatedBy,createdAt,updatedAt,deletedAt", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings" + ], + "query": [ + { + "key": "fields", + "value": "id,projectId,status,startDate,endDate,billingAccountId,userId,jobId,rateType,memberRate,customerRate,createdBy,updatedBy,createdAt,updatedAt,deletedAt" + } + ] + } + }, + "response": [] + }, + { + "name": "search resource bookings with parameters 2", + "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", + " _.each(['id','projectId','status','startDate','endDate','billingAccountId','userId','jobId','rateType','memberRate','customerRate','createdBy','updatedBy','createdAt','updatedAt','workPeriods'], field => {\r", + " pm.expect(response[0]).to.have.property(field)\r", + " })\r", + " _.each(['id','projectId','paymentStatus','startDate','endDate','userHandle','resourceBookingId','daysWorked','daysPaid','paymentTotal','createdBy','updatedBy','createdAt','updatedAt'], field => {\r", + " pm.expect(response[0].workPeriods[0]).to.have.property(field)\r", + " })\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "url": { + "raw": "{{URL}}/resourceBookings?fields=workPeriods,id,projectId,status,startDate,endDate,billingAccountId,userId,jobId,rateType,memberRate,customerRate,createdBy,updatedBy,createdAt,updatedAt,deletedAt", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings" + ], + "query": [ + { + "key": "fields", + "value": "workPeriods,id,projectId,status,startDate,endDate,billingAccountId,userId,jobId,rateType,memberRate,customerRate,createdBy,updatedBy,createdAt,updatedAt,deletedAt" + } + ] + } + }, + "response": [] + }, + { + "name": "search resource bookings with parameters 3", + "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", + " _.each(['id','projectId','status','startDate','endDate'], field => {\r", + " pm.expect(response[0]).to.have.property(field)\r", + " })\r", + " _.each(['id','projectId','startDate','endDate','daysWorked'], field => {\r", + " pm.expect(response[0].workPeriods[0]).to.have.property(field)\r", + " })\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "url": { + "raw": "{{URL}}/resourceBookings?fields=workPeriods.id,workPeriods.projectId,workPeriods.startDate,workPeriods.endDate,workPeriods.daysWorked,id,projectId,status,startDate,endDate", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings" + ], + "query": [ + { + "key": "fields", + "value": "workPeriods.id,workPeriods.projectId,workPeriods.startDate,workPeriods.endDate,workPeriods.daysWorked,id,projectId,status,startDate,endDate" + } + ] + } + }, + "response": [] + }, + { + "name": "search resource bookings with parameters 4", + "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}}/resourceBookings?fields=workPeriods.id,workPeriods.projectId,workPeriods.startDate,workPeriods.endDate,workPeriods.daysWorked,id,projectId,status,startDate,endDate,customerRate&workPeriods.startDate=2020-10-25&sortBy=customerRate&sortOrder=asc", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings" + ], + "query": [ + { + "key": "fields", + "value": "workPeriods.id,workPeriods.projectId,workPeriods.startDate,workPeriods.endDate,workPeriods.daysWorked,id,projectId,status,startDate,endDate,customerRate" + }, + { + "key": "workPeriods.startDate", + "value": "2020-10-25" + }, + { + "key": "sortBy", + "value": "customerRate" + }, + { + "key": "sortOrder", + "value": "asc" + } + ] + } + }, + "response": [] + }, + { + "name": "search resource bookings with parameters 5", + "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}}/resourceBookings?fields=workPeriods.id,workPeriods.projectId,workPeriods.startDate,workPeriods.endDate,workPeriods.daysWorked,id,projectId,status,startDate,endDate,customerRate,memberRate&workPeriods.startDate=2020-10-25&sortBy=workPeriods.daysWorked&sortOrder=desc", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings" + ], + "query": [ + { + "key": "fields", + "value": "workPeriods.id,workPeriods.projectId,workPeriods.startDate,workPeriods.endDate,workPeriods.daysWorked,id,projectId,status,startDate,endDate,customerRate,memberRate" + }, + { + "key": "workPeriods.startDate", + "value": "2020-10-25" + }, + { + "key": "sortBy", + "value": "workPeriods.daysWorked" + }, + { + "key": "sortOrder", + "value": "desc" + } + ] + } + }, + "response": [] + }, + { + "name": "search resource bookings with parameters 6", + "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}}/resourceBookings?fields=workPeriods.id,workPeriods.projectId,workPeriods.userHandle,workPeriods.startDate,workPeriods.endDate,workPeriods.daysWorked,id,projectId,status,startDate,endDate,customerRate,memberRate&projectId=111&workPeriods.startDate=2020-10-18&sortBy=workPeriods.userHandle&sortOrder=desc", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings" + ], + "query": [ + { + "key": "fields", + "value": "workPeriods.id,workPeriods.projectId,workPeriods.userHandle,workPeriods.startDate,workPeriods.endDate,workPeriods.daysWorked,id,projectId,status,startDate,endDate,customerRate,memberRate" + }, + { + "key": "projectId", + "value": "111" + }, + { + "key": "workPeriods.startDate", + "value": "2020-10-18" + }, + { + "key": "sortBy", + "value": "workPeriods.userHandle" + }, + { + "key": "sortOrder", + "value": "desc" + } + ] + } + }, + "response": [] + }, + { + "name": "search resource bookings with parameters 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(\"Can not filter or sort by some field which is not included in fields\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "url": { + "raw": "{{URL}}/resourceBookings?fields=id&projectId=111", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings" + ], + "query": [ + { + "key": "fields", + "value": "id" + }, + { + "key": "projectId", + "value": "111" + } + ] + } + }, + "response": [] + }, + { + "name": "search resource bookings with parameters 8", + "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(\"Can not filter or sort by some field which is not included in fields\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "url": { + "raw": "{{URL}}/resourceBookings?fields=workPeriods&sortBy=customerRate", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings" + ], + "query": [ + { + "key": "fields", + "value": "workPeriods" + }, + { + "key": "sortBy", + "value": "customerRate" + } + ] + } + }, + "response": [] + }, + { + "name": "search resource bookings with parameters 9", + "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(\"Can not filter or sort by some field which is not included in fields\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "url": { + "raw": "{{URL}}/resourceBookings?sortBy=workPeriods.paymentStatus", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings" + ], + "query": [ + { + "key": "sortBy", + "value": "workPeriods.paymentStatus" + } + ] + } + }, + "response": [] + }, + { + "name": "search resource bookings with parameters 10", + "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(\"Can not sort by workPeriod field without filtering by workPeriods.startDate or workPeriods.endDate\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "url": { + "raw": "{{URL}}/resourceBookings?fields=workPeriods&sortBy=workPeriods.paymentStatus", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings" + ], + "query": [ + { + "key": "fields", + "value": "workPeriods" + }, + { + "key": "sortBy", + "value": "workPeriods.paymentStatus" + } + ] + } + }, + "response": [] + }, + { + "name": "search resource bookings with parameters 11", + "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 don't have access to view memberRate and paymentTotal\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_connectUser}}" + } + ], + "url": { + "raw": "{{URL}}/resourceBookings?fields=memberRate,projectId&projectId=111", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings" + ], + "query": [ + { + "key": "fields", + "value": "memberRate,projectId" + }, + { + "key": "projectId", + "value": "111" + } + ] + } + }, + "response": [] + }, + { + "name": "search resource bookings with parameters 12", + "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 don't have access to view workPeriods\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_m2m_all_resource_booking}}" + } + ], + "url": { + "raw": "{{URL}}/resourceBookings?fields=workPeriods", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings" + ], + "query": [ + { + "key": "fields", + "value": "workPeriods" + } + ] + } + }, + "response": [] + }, + { + "name": "put resource booking 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 \"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" + } + } + }, + "url": { + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings", + "{{resourceBookingId}}" + ] + } + }, + "response": [] + }, + { + "name": "search extended work periods of resource booking", + "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}}/work-periods?sortBy=startDate&sortOrder=asc&resourceBookingId={{resourceBookingId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "work-periods" + ], + "query": [ + { + "key": "page", + "value": "1", + "disabled": true + }, + { + "key": "perPage", + "value": "5", + "disabled": true + }, + { + "key": "sortBy", + "value": "startDate" + }, + { + "key": "sortOrder", + "value": "asc" + }, + { + "key": "resourceBookingId", + "value": "{{resourceBookingId}}" + }, + { + "key": "resourceBookingIds", + "value": "{{resourceBookingId}},{{resourceBookingId}}", + "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": "put resource booking 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_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-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" + } + } + }, + "url": { + "raw": "{{URL}}/resourceBookings/{{resourceBookingIdCreatedByM2M}}", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings", + "{{resourceBookingIdCreatedByM2M}}" + ] + } + }, + "response": [] + }, + { + "name": "search reduced work periods of resource booking", + "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}}/work-periods?sortBy=startDate&sortOrder=asc&resourceBookingId={{resourceBookingIdCreatedByM2M}}", + "host": [ + "{{URL}}" + ], + "path": [ + "work-periods" + ], + "query": [ + { + "key": "page", + "value": "1", + "disabled": true + }, + { + "key": "perPage", + "value": "5", + "disabled": true + }, + { + "key": "sortBy", + "value": "startDate" + }, + { + "key": "sortOrder", + "value": "asc" + }, + { + "key": "resourceBookingId", + "value": "{{resourceBookingIdCreatedByM2M}}" + }, + { + "key": "resourceBookingIds", + "value": "{{resourceBookingIdCreatedByM2M}},{{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": "put resource booking 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 \"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" + } + } + }, + "url": { + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings", + "{{resourceBookingId}}" + ] + } + }, + "response": [] + }, + { + "name": "put 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": "PUT", + "header": [ + { + "key": "Authorization", + "type": "text", + "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-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" + } + } + }, + "url": { + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings", + "{{resourceBookingId}}" + ] + } + }, + "response": [] + }, + { + "name": "put resource booking 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 \"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" + } + } + }, + "url": { + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings", + "{{resourceBookingId}}" + ] + } + }, + "response": [] + }, + { + "name": "put resource booking 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": "GET", + "method": "PUT", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer invalid_token" + } + ], + "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\": \"placed\",\r\n \"billingAccountId\": 80000071\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings", + "{{resourceBookingId}}" + ] + } + }, + "response": [] + }, + { + "name": "patch resource booking 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", @@ -7977,85 +12725,229 @@ "value": "Bearer {{token_bookingManager}}" } ], + "body": { + "mode": "raw", + "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" + } + } + }, "url": { - "raw": "{{URL}}/work-periods?sortBy=startDate&sortOrder=asc&resourceBookingId={{resourceBookingId}}", + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", "host": [ "{{URL}}" ], "path": [ - "work-periods" + "resourceBookings", + "{{resourceBookingId}}" + ] + } + }, + "response": [] + }, + { + "name": "patch resource booking 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_resource_booking}}" + } + ], + "body": { + "mode": "raw", + "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" + } + } + }, + "url": { + "raw": "{{URL}}/resourceBookings/{{resourceBookingIdCreatedByM2M}}", + "host": [ + "{{URL}}" ], - "query": [ - { - "key": "page", - "value": "1", - "disabled": true - }, - { - "key": "perPage", - "value": "5", - "disabled": true - }, - { - "key": "sortBy", - "value": "startDate" - }, - { - "key": "sortOrder", - "value": "asc" - }, - { - "key": "resourceBookingId", - "value": "{{resourceBookingId}}" - }, - { - "key": "resourceBookingIds", - "value": "{{resourceBookingId}},{{resourceBookingId}}", - "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 + "path": [ + "resourceBookings", + "{{resourceBookingIdCreatedByM2M}}" + ] + } + }, + "response": [] + }, + { + "name": "patch resource booking 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 \"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" + } + } + }, + "url": { + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings", + "{{resourceBookingId}}" + ] + } + }, + "response": [] + }, + { + "name": "patch 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": "PATCH", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_member}}" + } + ], + "body": { + "mode": "raw", + "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" + } + } + }, + "url": { + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings", + "{{resourceBookingId}}" + ] + } + }, + "response": [] + }, + { + "name": "patch resource booking 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 \"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" } + } + }, + "url": { + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings", + "{{resourceBookingId}}" ] } }, "response": [] }, { - "name": "create resource booking with m2m create", + "name": "patch resource booking with invalid token", "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(\"resourceBookingIdCreatedByM2M\", response.id);\r", - " }\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(\"Invalid Token.\")\r", "});" ], "type": "text/javascript" @@ -8063,17 +12955,17 @@ } ], "request": { - "method": "POST", + "method": "PATCH", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_m2m_create_resource_booking}}" + "value": "Bearer invalid_token" } ], "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-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" @@ -8081,19 +12973,20 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings", + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings" + "resourceBookings", + "{{resourceBookingId}}" ] } }, "response": [] }, { - "name": "search work periods of newly created resource booking", + "name": "search work periods", "event": [ { "listen": "test", @@ -8101,6 +12994,8 @@ "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(\"workPeriodIdForPaid\", response[0].id);\r", "});" ], "type": "text/javascript" @@ -8117,7 +13012,7 @@ } ], "url": { - "raw": "{{URL}}/work-periods?sortBy=startDate&sortOrder=asc&resourceBookingId={{resourceBookingIdCreatedByM2M}}", + "raw": "{{URL}}/work-periods?perPage=1&sortBy=startDate&sortOrder=asc&resourceBookingId={{resourceBookingId}}", "host": [ "{{URL}}" ], @@ -8132,8 +13027,7 @@ }, { "key": "perPage", - "value": "5", - "disabled": true + "value": "1" }, { "key": "sortBy", @@ -8145,11 +13039,11 @@ }, { "key": "resourceBookingId", - "value": "{{resourceBookingIdCreatedByM2M}}" + "value": "{{resourceBookingId}}" }, { "key": "resourceBookingIds", - "value": "{{resourceBookingIdCreatedByM2M}},{{resourceBookingIdCreatedByM2M}}", + "value": "{{resourceBookingId}},{{resourceBookingId}}", "disabled": true }, { @@ -8183,16 +13077,14 @@ "response": [] }, { - "name": "create resource booking with connect user", + "name": "post process payment for work period", "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" @@ -8205,12 +13097,12 @@ { "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-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 \"workPeriodId\": \"{{workPeriodIdForPaid}}\"\r\n}", "options": { "raw": { "language": "json" @@ -8218,28 +13110,26 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings", + "raw": "{{URL}}/work-period-payments", "host": [ "{{URL}}" ], "path": [ - "resourceBookings" + "work-period-payments" ] } }, "response": [] }, { - "name": "create resource booking with member", + "name": "patch resource booking to cancelled", "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 400', function () {\r", + " pm.response.to.have.status(400);\r", "});" ], "type": "text/javascript" @@ -8247,17 +13137,17 @@ } ], "request": { - "method": "POST", + "method": "PATCH", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_member}}" + "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-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\": \"cancelled\",\r\n \"billingAccountId\": 80000071\r\n}", "options": { "raw": { "language": "json" @@ -8265,19 +13155,20 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings", + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings" + "resourceBookings", + "{{resourceBookingId}}" ] } }, "response": [] }, { - "name": "create resource booking with user id not exist", + "name": "patch resource booking to reduce", "event": [ { "listen": "test", @@ -8285,8 +13176,6 @@ "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" @@ -8294,17 +13183,17 @@ } ], "request": { - "method": "POST", + "method": "PATCH", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_userId_not_exist}}" + "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-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 \"startDate\": \"2020-10-04\",\r\n \"billingAccountId\": 80000071\r\n}", "options": { "raw": { "language": "json" @@ -8312,28 +13201,27 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings", + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings" + "resourceBookings", + "{{resourceBookingId}}" ] } }, "response": [] }, { - "name": "create resource booking with invalid token", + "name": "patch resource booking set dates null", "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", + "pm.test('Status code is 400', function () {\r", + " pm.response.to.have.status(400);\r", "});" ], "type": "text/javascript" @@ -8341,17 +13229,17 @@ } ], "request": { - "method": "POST", + "method": "PATCH", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer invalid_token" + "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-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 \"startDate\": null,\r\n \"endDate\": null\r\n}", "options": { "raw": { "language": "json" @@ -8359,26 +13247,29 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings", + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings" + "resourceBookings", + "{{resourceBookingId}}" ] } }, "response": [] }, { - "name": "get resource booking with booking manager", + "name": "delete resource booking with member", "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 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" @@ -8386,14 +13277,23 @@ } ], "request": { - "method": "GET", + "method": "DELETE", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_member}}" } ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", "host": [ @@ -8408,14 +13308,16 @@ "response": [] }, { - "name": "get resource booking with m2m read", + "name": "delete resource booking with connect user", "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 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" @@ -8423,36 +13325,45 @@ } ], "request": { - "method": "GET", + "method": "DELETE", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_m2m_read_resource_booking}}" + "value": "Bearer {{token_connectUser}}" } ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingIdCreatedByM2M}}", + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", "host": [ "{{URL}}" ], "path": [ "resourceBookings", - "{{resourceBookingIdCreatedByM2M}}" + "{{resourceBookingId}}" ] } }, "response": [] }, { - "name": "get resource booking with booking manager from db", + "name": "delete resource booking with booking manager", "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", "});" ], "type": "text/javascript" @@ -8460,7 +13371,7 @@ } ], "request": { - "method": "GET", + "method": "DELETE", "header": [ { "key": "Authorization", @@ -8468,34 +13379,85 @@ "value": "Bearer {{token_bookingManager}}" } ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}?fromDb=true", + "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", "host": [ "{{URL}}" ], "path": [ "resourceBookings", "{{resourceBookingId}}" - ], - "query": [ - { - "key": "fromDb", - "value": "true" + ] + } + }, + "response": [] + }, + { + "name": "delete resource booking 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_resource_booking}}" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" } + } + }, + "url": { + "raw": "{{URL}}/resourceBookings/{{resourceBookingIdCreatedByM2M}}", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings", + "{{resourceBookingIdCreatedByM2M}}" ] } }, "response": [] }, { - "name": "get resource booking with connect user", + "name": "delete resource booking with invalid token", "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 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" @@ -8503,14 +13465,23 @@ } ], "request": { - "method": "GET", + "method": "DELETE", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_connectUser}}" + "value": "Bearer invalid_token" } ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", "host": [ @@ -8523,18 +13494,126 @@ } }, "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 \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\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\": \"2021-06-01\",\r\n \"endDate\": \"2021-08-01\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"billingAccountId\": 80000071\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/resourceBookings", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings" + ] + } + }, + "response": [] + } + ] }, { - "name": "get resource booking with member", + "name": "create work period", "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 405', function () {\r", + " pm.response.to.have.status(405);\r", " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"userId: 8547899 the user is not a member of project 111\")\r", + " pm.expect(response.message).to.eq(\"The requested HTTP method is not supported.\")\r", "});" ], "type": "text/javascript" @@ -8542,29 +13621,37 @@ } ], "request": { - "method": "GET", + "method": "POST", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_member}}" + "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}}/resourceBookings/{{resourceBookingId}}", + "raw": "{{URL}}/work-periods", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resourceBookingId}}" + "work-periods" ] } }, "response": [] }, { - "name": "search resource bookings with booking manager", + "name": "search work periods", "event": [ { "listen": "test", @@ -8572,6 +13659,12 @@ "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(\"workPeriodId-1\", response[0].id);\r", + " pm.environment.set(\"workPeriodId-2\", response[1].id);\r", + " pm.environment.set(\"workPeriodId-3\", response[2].id);\r", + " pm.environment.set(\"workPeriodId-4\", response[3].id);\r", + " pm.environment.set(\"workPeriodId-5\", response[4].id);\r", "});" ], "type": "text/javascript" @@ -8588,12 +13681,12 @@ } ], "url": { - "raw": "{{URL}}/resourceBookings", + "raw": "{{URL}}/work-periods?sortBy=startDate&sortOrder=asc&resourceBookingId={{resourceBookingId}}&perPage=5", "host": [ "{{URL}}" ], "path": [ - "resourceBookings" + "work-periods" ], "query": [ { @@ -8602,44 +13695,50 @@ "disabled": true }, { - "key": "perPage", - "value": "5", - "disabled": true + "key": "sortBy", + "value": "startDate" }, { - "key": "sortBy", - "value": "id", + "key": "sortOrder", + "value": "asc" + }, + { + "key": "resourceBookingId", + "value": "{{resourceBookingId}}" + }, + { + "key": "resourceBookingIds", + "value": "{{resourceBookingId}},{{resourceBookingId}}", "disabled": true }, { - "key": "sortOrder", - "value": "desc", + "key": "paymentStatus", + "value": "pending", "disabled": true }, { "key": "startDate", - "value": "2020-09-27", + "value": "2021-03-14", "disabled": true }, { "key": "endDate", - "value": "2020-09-27", + "value": "2021-03-20", "disabled": true }, { - "key": "rateType", - "value": "hourly", + "key": "userHandle", + "value": "pshah_manager", "disabled": true }, { - "key": "status", - "value": "assigned", + "key": "projectId", + "value": "16843", "disabled": true }, { - "key": "projectIds", - "value": "111, 16705", - "disabled": true + "key": "perPage", + "value": "5" } ] } @@ -8647,7 +13746,81 @@ "response": [] }, { - "name": "search resource bookings with m2m all", + "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}}/work-periods/{{workPeriodId-1}}", + "host": [ + "{{URL}}" + ], + "path": [ + "work-periods", + "{{workPeriodId-1}}" + ] + } + }, + "response": [] + }, + { + "name": "get work period with m2m read 1", + "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}}/work-periods/{{workPeriodId-2}}", + "host": [ + "{{URL}}" + ], + "path": [ + "work-periods", + "{{workPeriodId-2}}" + ] + } + }, + "response": [] + }, + { + "name": "get work period with m2m read 2", "event": [ { "listen": "test", @@ -8667,65 +13840,24 @@ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_m2m_all_resource_booking}}" + "value": "Bearer {{token_m2m_read_work_period_and_payment}}" } ], "url": { - "raw": "{{URL}}/resourceBookings", + "raw": "{{URL}}/work-periods/{{workPeriodId-3}}", "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-27", - "disabled": true - }, - { - "key": "endDate", - "value": "2020-09-27", - "disabled": true - }, - { - "key": "rateType", - "value": "hourly", - "disabled": true - }, - { - "key": "status", - "value": "assigned", - "disabled": true - } + "work-periods", + "{{workPeriodId-3}}" ] } }, "response": [] }, { - "name": "search resource bookings with connect user", + "name": "get work period with booking manager from db", "event": [ { "listen": "test", @@ -8745,51 +13877,22 @@ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_connectUser}}" + "value": "Bearer {{token_bookingManager}}" } ], "url": { - "raw": "{{URL}}/resourceBookings?sortOrder=desc", + "raw": "{{URL}}/work-periods/{{workPeriodId-4}}?fromDb=true", "host": [ "{{URL}}" ], "path": [ - "resourceBookings" + "work-periods", + "{{workPeriodId-4}}" ], "query": [ { - "key": "page", - "value": "4", - "disabled": true - }, - { - "key": "perPage", - "value": "3", - "disabled": true - }, - { - "key": "sortBy", - "value": "id", - "disabled": true - }, - { - "key": "startDate", - "value": "2020-09-27", - "disabled": true - }, - { - "key": "endDate", - "value": "2020-09-27", - "disabled": true - }, - { - "key": "rateType", - "value": "hourly", - "disabled": true - }, - { - "key": "sortOrder", - "value": "desc" + "key": "fromDb", + "value": "true" } ] } @@ -8797,13 +13900,15 @@ "response": [] }, { - "name": "search resource bookings with member", + "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" } @@ -8815,59 +13920,24 @@ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_member}}" + "value": "Bearer {{token_connectUser}}" } ], "url": { - "raw": "{{URL}}/resourceBookings?sortOrder=desc", + "raw": "{{URL}}/work-periods/{{workPeriodId-5}}", "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-27", - "disabled": true - }, - { - "key": "endDate", - "value": "2020-09-27", - "disabled": true - }, - { - "key": "rateType", - "value": "hourly", - "disabled": true - }, - { - "key": "sortOrder", - "value": "desc" - } + "work-periods", + "{{workPeriodId-5}}" ] } }, "response": [] }, { - "name": "search resource bookings with invalid token", + "name": "get work period with member", "event": [ { "listen": "test", @@ -8875,8 +13945,6 @@ "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" @@ -8889,59 +13957,24 @@ { "key": "Authorization", "type": "text", - "value": "Bearer invalid_token" + "value": "Bearer {{token_member}}" } ], "url": { - "raw": "{{URL}}/resourceBookings?sortOrder=desc", + "raw": "{{URL}}/work-periods/{{workPeriodId-1}}", "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-27", - "disabled": true - }, - { - "key": "endDate", - "value": "2020-09-27", - "disabled": true - }, - { - "key": "rateType", - "value": "hourly", - "disabled": true - }, - { - "key": "sortOrder", - "value": "desc" - } + "work-periods", + "{{workPeriodId-1}}" ] } }, "response": [] }, { - "name": "put resource booking with booking manager", + "name": "search work periods with booking manager", "event": [ { "listen": "test", @@ -8956,7 +13989,7 @@ } ], "request": { - "method": "PUT", + "method": "GET", "header": [ { "key": "Authorization", @@ -8964,30 +13997,77 @@ "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-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" + "url": { + "raw": "{{URL}}/work-periods", + "host": [ + "{{URL}}" + ], + "path": [ + "work-periods" + ], + "query": [ + { + "key": "page", + "value": "1", + "disabled": true + }, + { + "key": "perPage", + "value": "35", + "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 } - } - }, - "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", - "host": [ - "{{URL}}" - ], - "path": [ - "resourceBookings", - "{{resourceBookingId}}" ] } }, "response": [] }, { - "name": "search extended work periods of resource booking", + "name": "search work periods with m2m all 1", "event": [ { "listen": "test", @@ -9007,11 +14087,11 @@ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_m2m_all_work_period}}" } ], "url": { - "raw": "{{URL}}/work-periods?sortBy=startDate&sortOrder=asc&resourceBookingId={{resourceBookingId}}", + "raw": "{{URL}}/work-periods", "host": [ "{{URL}}" ], @@ -9031,19 +14111,22 @@ }, { "key": "sortBy", - "value": "startDate" + "value": "id", + "disabled": true }, { "key": "sortOrder", - "value": "asc" + "value": "desc", + "disabled": true }, { "key": "resourceBookingId", - "value": "{{resourceBookingId}}" + "value": "{{resourceBookingId}}", + "disabled": true }, { "key": "resourceBookingIds", - "value": "{{resourceBookingId}},{{resourceBookingId}}", + "value": "{{resourceBookingId}},{{resourceBookingIdCreatedByM2M}}", "disabled": true }, { @@ -9077,7 +14160,7 @@ "response": [] }, { - "name": "put resource booking with m2m update", + "name": "search work periods with m2m all 2", "event": [ { "listen": "test", @@ -9092,38 +14175,85 @@ } ], "request": { - "method": "PUT", + "method": "GET", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_m2m_update_resource_booking}}" + "value": "Bearer {{token_m2m_all_work_period_and_payment}}" } ], - "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\": \"placed\",\r\n \"billingAccountId\": 80000071\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingIdCreatedByM2M}}", + "raw": "{{URL}}/work-periods", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resourceBookingIdCreatedByM2M}}" + "work-periods" + ], + "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 reduced work periods of resource booking", + "name": "search work periods with connect user", "event": [ { "listen": "test", @@ -9143,11 +14273,11 @@ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_connectUser}}" } ], "url": { - "raw": "{{URL}}/work-periods?sortBy=startDate&sortOrder=asc&resourceBookingId={{resourceBookingIdCreatedByM2M}}", + "raw": "{{URL}}/work-periods", "host": [ "{{URL}}" ], @@ -9167,19 +14297,22 @@ }, { "key": "sortBy", - "value": "startDate" + "value": "id", + "disabled": true }, { "key": "sortOrder", - "value": "asc" + "value": "desc", + "disabled": true }, { "key": "resourceBookingId", - "value": "{{resourceBookingIdCreatedByM2M}}" + "value": "{{resourceBookingId}}", + "disabled": true }, { "key": "resourceBookingIds", - "value": "{{resourceBookingIdCreatedByM2M}},{{resourceBookingIdCreatedByM2M}}", + "value": "{{resourceBookingId}},{{resourceBookingIdCreatedByM2M}}", "disabled": true }, { @@ -9213,112 +14346,94 @@ "response": [] }, { - "name": "put resource booking 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" - } - } - ], + "name": "search work periods with member", "request": { - "method": "PUT", + "method": "GET", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_connectUser}}" + "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-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" - } - } - }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "raw": "{{URL}}/work-periods", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resourceBookingId}}" - ] - } - }, - "response": [] - }, - { - "name": "put 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": "PUT", - "header": [ - { - "key": "Authorization", - "type": "text", - "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-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" + "work-periods" + ], + "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 } - } - }, - "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", - "host": [ - "{{URL}}" - ], - "path": [ - "resourceBookings", - "{{resourceBookingId}}" ] } }, "response": [] }, { - "name": "put resource booking with user id not exist", + "name": "search work periods with invalid 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", + "pm.test('Status code is 401', function () {\r", + " pm.response.to.have.status(401);\r", "});" ], "type": "text/javascript" @@ -9326,47 +14441,92 @@ } ], "request": { - "method": "PUT", + "method": "GET", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_userId_not_exist}}" + "value": "Bearer invalid_token" } ], - "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\": \"placed\",\r\n \"billingAccountId\": 80000071\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "raw": "{{URL}}/work-periods", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resourceBookingId}}" + "work-periods" + ], + "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 resource booking with invalid token", + "name": "put work period", "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", + "pm.test('Status code is 404', function () {\r", + " pm.response.to.have.status(404);\r", "});" ], "type": "text/javascript" @@ -9379,12 +14539,12 @@ { "key": "Authorization", "type": "text", - "value": "Bearer invalid_token" + "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-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}", + "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" @@ -9392,20 +14552,20 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "raw": "{{URL}}/work-periods/{{workPeriodId-1}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resourceBookingId}}" + "work-periods", + "{{workPeriodId-1}}" ] } }, "response": [] }, { - "name": "patch resource booking with booking manager", + "name": "patch work period with booking manager", "event": [ { "listen": "test", @@ -9430,7 +14590,7 @@ ], "body": { "mode": "raw", - "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}", + "raw": "{\r\n \"daysWorked\": 3\r\n}", "options": { "raw": { "language": "json" @@ -9438,20 +14598,20 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "raw": "{{URL}}/work-periods/{{workPeriodId-1}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resourceBookingId}}" + "work-periods", + "{{workPeriodId-1}}" ] } }, "response": [] }, { - "name": "patch resource booking with m2m update", + "name": "patch work period with m2m update", "event": [ { "listen": "test", @@ -9471,12 +14631,12 @@ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_m2m_update_resource_booking}}" + "value": "Bearer {{token_m2m_update_work_period}}" } ], "body": { "mode": "raw", - "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}", + "raw": "{\r\n \"daysWorked\": 4\r\n}", "options": { "raw": { "language": "json" @@ -9484,20 +14644,20 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingIdCreatedByM2M}}", + "raw": "{{URL}}/work-periods/{{workPeriodId-2}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resourceBookingIdCreatedByM2M}}" + "work-periods", + "{{workPeriodId-2}}" ] } }, "response": [] }, { - "name": "patch resource booking with connect user", + "name": "patch work period with connect user", "event": [ { "listen": "test", @@ -9524,7 +14684,7 @@ ], "body": { "mode": "raw", - "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}", + "raw": "{\r\n \"daysWorked\": 3\r\n}", "options": { "raw": { "language": "json" @@ -9532,20 +14692,20 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "raw": "{{URL}}/work-periods/{{workPeriodId-3}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resourceBookingId}}" + "work-periods", + "{{workPeriodId-3}}" ] } }, "response": [] }, { - "name": "patch resource booking with member", + "name": "patch work period with member", "event": [ { "listen": "test", @@ -9572,7 +14732,7 @@ ], "body": { "mode": "raw", - "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}", + "raw": "{\r\n \"daysWorked\": 3\r\n}", "options": { "raw": { "language": "json" @@ -9580,20 +14740,20 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "raw": "{{URL}}/work-periods/{{workPeriodId-4}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resourceBookingId}}" + "work-periods", + "{{workPeriodId-4}}" ] } }, "response": [] }, { - "name": "patch resource booking with user id not exist", + "name": "patch work period with user id not exist", "event": [ { "listen": "test", @@ -9620,7 +14780,7 @@ ], "body": { "mode": "raw", - "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}", + "raw": "{\r\n \"daysWorked\": 3\r\n}", "options": { "raw": { "language": "json" @@ -9628,20 +14788,20 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "raw": "{{URL}}/work-periods/{{workPeriodId-5}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resourceBookingId}}" + "work-periods", + "{{workPeriodId-5}}" ] } }, "response": [] }, { - "name": "patch resource booking with invalid token", + "name": "patch work period with invalid token", "event": [ { "listen": "test", @@ -9668,7 +14828,7 @@ ], "body": { "mode": "raw", - "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}", + "raw": "{\r\n \"daysWorked\": 3\r\n}", "options": { "raw": { "language": "json" @@ -9676,118 +14836,29 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "raw": "{{URL}}/work-periods/{{workPeriodId-1}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resourceBookingId}}" + "work-periods", + "{{workPeriodId-1}}" ] } }, "response": [] }, { - "name": "search work periods", + "name": "patch work period with invalid parameter 1", "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.environment.set(\"workPeriodIdForPaid\", response[0].id);\r", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "GET", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } - ], - "url": { - "raw": "{{URL}}/work-periods?perPage=1&sortBy=startDate&sortOrder=asc&resourceBookingId={{resourceBookingId}}", - "host": [ - "{{URL}}" - ], - "path": [ - "work-periods" - ], - "query": [ - { - "key": "page", - "value": "1", - "disabled": true - }, - { - "key": "perPage", - "value": "1" - }, - { - "key": "sortBy", - "value": "startDate" - }, - { - "key": "sortOrder", - "value": "asc" - }, - { - "key": "resourceBookingId", - "value": "{{resourceBookingId}}" - }, - { - "key": "resourceBookingIds", - "value": "{{resourceBookingId}},{{resourceBookingId}}", - "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": "patch work period set status to completed", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test('Status code is 200', function () {\r", - " pm.response.to.have.status(200);\r", + " pm.expect(response.message).to.eq(\"\\\"data.daysWorked\\\" must be a number\")\r", "});" ], "type": "text/javascript" @@ -9805,7 +14876,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"paymentStatus\": \"completed\"\r\n}", + "raw": "{\r\n \"daysWorked\": \"two\"\r\n}", "options": { "raw": { "language": "json" @@ -9813,20 +14884,20 @@ } }, "url": { - "raw": "{{URL}}/work-periods/{{workPeriodIdForPaid}}", + "raw": "{{URL}}/work-periods/{{workPeriodId-1}}", "host": [ "{{URL}}" ], "path": [ "work-periods", - "{{workPeriodIdForPaid}}" + "{{workPeriodId-1}}" ] } }, "response": [] }, { - "name": "patch resource booking to cancelled", + "name": "patch work period with invalid parameter 2", "event": [ { "listen": "test", @@ -9834,6 +14905,8 @@ "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 greater than or equal to 0\")\r", "});" ], "type": "text/javascript" @@ -9851,7 +14924,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"status\": \"cancelled\",\r\n \"billingAccountId\": 80000071\r\n}", + "raw": "{\r\n \"daysWorked\": -1\r\n}", "options": { "raw": { "language": "json" @@ -9859,20 +14932,20 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "raw": "{{URL}}/work-periods/{{workPeriodId-1}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resourceBookingId}}" + "work-periods", + "{{workPeriodId-1}}" ] } }, "response": [] }, { - "name": "patch resource booking to reduce", + "name": "patch work period with invalid parameter 3", "event": [ { "listen": "test", @@ -9880,6 +14953,8 @@ "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 less than or equal to 5\")\r", "});" ], "type": "text/javascript" @@ -9897,7 +14972,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"startDate\": \"2020-10-04\",\r\n \"billingAccountId\": 80000071\r\n}", + "raw": "{\r\n \"daysWorked\": 6\r\n}", "options": { "raw": { "language": "json" @@ -9905,29 +14980,29 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "raw": "{{URL}}/work-periods/{{workPeriodId-1}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resourceBookingId}}" + "work-periods", + "{{workPeriodId-1}}" ] } }, "response": [] }, { - "name": "delete resource booking with member", + "name": "patch work period with invalid parameter 4", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 403', function () {\r", - " pm.response.to.have.status(403);\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(\"You are not allowed to perform this action!\")\r", + " pm.expect(response.message).to.eq(\"Maximum allowed daysWorked is (4)\")\r", "});" ], "type": "text/javascript" @@ -9935,17 +15010,17 @@ } ], "request": { - "method": "DELETE", + "method": "PATCH", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_member}}" + "value": "Bearer {{token_bookingManager}}" } ], "body": { "mode": "raw", - "raw": "", + "raw": "{\r\n \"daysWorked\": 5\r\n}", "options": { "raw": { "language": "json" @@ -9953,29 +15028,29 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "raw": "{{URL}}/work-periods/{{workPeriodId-1}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resourceBookingId}}" + "work-periods", + "{{workPeriodId-1}}" ] } }, "response": [] }, { - "name": "delete resource booking with connect user", + "name": "post process payment for work period 5 days", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 403', function () {\r", - " pm.response.to.have.status(403);\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(\"You are not allowed to perform this action!\")\r", + " pm.expect(response.message).to.eq(\"Days cannot be more than not paid days which is 3\")\r", "});" ], "type": "text/javascript" @@ -9983,17 +15058,17 @@ } ], "request": { - "method": "DELETE", + "method": "POST", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_connectUser}}" + "value": "Bearer {{token_bookingManager}}" } ], "body": { "mode": "raw", - "raw": "", + "raw": "{\r\n \"workPeriodId\": \"{{workPeriodId-1}}\",\r\n \"days\": 5\r\n}", "options": { "raw": { "language": "json" @@ -10001,27 +15076,26 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "raw": "{{URL}}/work-period-payments", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resourceBookingId}}" + "work-period-payments" ] } }, "response": [] }, { - "name": "delete resource booking with booking manager", + "name": "post process payment for work period 2 days", "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 200', function () {\r", + " pm.response.to.have.status(200);\r", "});" ], "type": "text/javascript" @@ -10029,7 +15103,7 @@ } ], "request": { - "method": "DELETE", + "method": "POST", "header": [ { "key": "Authorization", @@ -10039,7 +15113,7 @@ ], "body": { "mode": "raw", - "raw": "", + "raw": "{\r\n \"workPeriodId\": \"{{workPeriodId-1}}\",\r\n \"days\": 2\r\n}", "options": { "raw": { "language": "json" @@ -10047,27 +15121,28 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "raw": "{{URL}}/work-period-payments", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resourceBookingId}}" + "work-period-payments" ] } }, "response": [] }, { - "name": "delete resource booking with m2m delete", + "name": "patch work period with invalid parameter 5", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 204', function () {\r", - " pm.response.to.have.status(204);\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(\"Cannot update daysWorked (1) to the value less than daysPaid (2)\")\r", "});" ], "type": "text/javascript" @@ -10075,17 +15150,17 @@ } ], "request": { - "method": "DELETE", + "method": "PATCH", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_m2m_delete_resource_booking}}" + "value": "Bearer {{token_bookingManager}}" } ], "body": { "mode": "raw", - "raw": "", + "raw": "{\r\n \"daysWorked\": 1\r\n}", "options": { "raw": { "language": "json" @@ -10093,29 +15168,29 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingIdCreatedByM2M}}", + "raw": "{{URL}}/work-periods/{{workPeriodId-1}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resourceBookingIdCreatedByM2M}}" + "work-periods", + "{{workPeriodId-1}}" ] } }, "response": [] }, { - "name": "delete resource booking with invalid token", + "name": "delete work period", "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 404', function () {\r", + " pm.response.to.have.status(404);\r", " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"Invalid Token.\")\r", + " pm.expect(response.message).to.eq(\"The requested resource cannot be found.\")\r", "});" ], "type": "text/javascript" @@ -10128,7 +15203,7 @@ { "key": "Authorization", "type": "text", - "value": "Bearer invalid_token" + "value": "Bearer {{token_bookingManager}}" } ], "body": { @@ -10141,13 +15216,13 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{resourceBookingId}}", + "raw": "{{URL}}/work-periods/{{workPeriodId-1}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resourceBookingId}}" + "work-periods", + "{{workPeriodId-1}}" ] } }, @@ -10156,7 +15231,7 @@ ] }, { - "name": "Work Periods", + "name": "Work Period Payments", "item": [ { "name": "Before Test", @@ -10191,7 +15266,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": "{\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 \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", "options": { "raw": { "language": "json" @@ -10240,7 +15315,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-27\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"billingAccountId\": 80000071\r\n}", + "raw": "{\r\n \"projectId\": {{project_id_17234}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{jobId}}\",\r\n \"startDate\": \"2020-09-27\",\r\n \"endDate\": \"2020-10-27\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"billingAccountId\": 80000071\r\n}", "options": { "raw": { "language": "json" @@ -10258,11 +15333,71 @@ } }, "response": [] + }, + { + "name": "search work periods", + "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(\"workPeriodId-1\", response[0].id);\r", + " pm.environment.set(\"workPeriodId-2\", response[1].id);\r", + " pm.environment.set(\"workPeriodId-3\", response[2].id);\r", + " pm.environment.set(\"workPeriodId-4\", response[3].id);\r", + " pm.environment.set(\"workPeriodId-5\", response[4].id);\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "url": { + "raw": "{{URL}}/work-periods?sortBy=startDate&sortOrder=asc&resourceBookingId={{resourceBookingId}}&perPage=5", + "host": [ + "{{URL}}" + ], + "path": [ + "work-periods" + ], + "query": [ + { + "key": "sortBy", + "value": "startDate" + }, + { + "key": "sortOrder", + "value": "asc" + }, + { + "key": "resourceBookingId", + "value": "{{resourceBookingId}}" + }, + { + "key": "perPage", + "value": "5" + } + ] + } + }, + "response": [] } ] }, { - "name": "create work period with booking manager", + "name": "create work period payment with boooking manager", "event": [ { "listen": "test", @@ -10272,7 +15407,7 @@ " 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", + " pm.environment.set(\"workPeriodPaymentId\", response.id);\r", " }\r", "});" ], @@ -10291,7 +15426,7 @@ ], "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 \"workPeriodId\": \"{{workPeriodId-1}}\"\r\n}", "options": { "raw": { "language": "json" @@ -10299,19 +15434,19 @@ } }, "url": { - "raw": "{{URL}}/work-periods", + "raw": "{{URL}}/work-period-payments", "host": [ "{{URL}}" ], "path": [ - "work-periods" + "work-period-payments" ] } }, "response": [] }, { - "name": "create work period with m2m create", + "name": "create multiple work period payments with boooking manager", "event": [ { "listen": "test", @@ -10321,7 +15456,8 @@ " 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", + " pm.environment.set(\"workPeriodPaymentId-2\", response[0].id);\r", + " pm.environment.set(\"workPeriodPaymentId-3\", response[1].id);\r", " }\r", "});" ], @@ -10335,106 +15471,12 @@ { "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" - } - } - }, - "url": { - "raw": "{{URL}}/work-periods", - "host": [ - "{{URL}}" - ], - "path": [ - "work-periods" - ] - } - }, - "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", - "});" - ], - "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" - } - } - }, - "url": { - "raw": "{{URL}}/work-periods", - "host": [ - "{{URL}}" - ], - "path": [ - "work-periods" - ] - } - }, - "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}}" + "value": "Bearer {{token_bookingManager}}" } ], "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 \"workPeriodId\": \"{{workPeriodId-2}}\",\r\n \"days\": 3\r\n},{\r\n \"workPeriodId\": \"{{workPeriodId-3}}\",\r\n \"days\": 4\r\n}]", "options": { "raw": { "language": "json" @@ -10442,28 +15484,26 @@ } }, "url": { - "raw": "{{URL}}/work-periods", + "raw": "{{URL}}/work-period-payments", "host": [ "{{URL}}" ], "path": [ - "work-periods" + "work-period-payments" ] } }, "response": [] }, { - "name": "create work period with user id not exist", + "name": "create query work period payments with boooking 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(\"Bad Request\")\r", + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", "});" ], "type": "text/javascript" @@ -10476,12 +15516,12 @@ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_userId_not_exist}}" + "value": "Bearer {{token_bookingManager}}" } ], "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": "{\"query\": { \"workPeriods.paymentStatus\": \"pending\" } }", "options": { "raw": { "language": "json" @@ -10489,28 +15529,31 @@ } }, "url": { - "raw": "{{URL}}/work-periods", + "raw": "{{URL}}/work-period-payments/query", "host": [ "{{URL}}" ], "path": [ - "work-periods" + "work-period-payments", + "query" ] } }, "response": [] }, { - "name": "create work period with invalid token", + "name": "create work period payment with m2m create", "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", + "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(\"workPeriodPaymentIdCreatedByM2M\", response.id);\r", + " }\r", "});" ], "type": "text/javascript" @@ -10523,12 +15566,12 @@ { "key": "Authorization", "type": "text", - "value": "Bearer invalid_token" + "value": "Bearer {{token_m2m_create_work_period_payment}}" } ], "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 \"workPeriodId\": \"{{workPeriodId-2}}\"\r\n}", "options": { "raw": { "language": "json" @@ -10536,28 +15579,28 @@ } }, "url": { - "raw": "{{URL}}/work-periods", + "raw": "{{URL}}/work-period-payments", "host": [ "{{URL}}" ], "path": [ - "work-periods" + "work-period-payments" ] } }, "response": [] }, { - "name": "create work period with missing parameter 1", + "name": "create work period payment 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" @@ -10570,12 +15613,12 @@ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_connectUser}}" } ], "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 \"workPeriodId\": \"{{workPeriodId-3}}\"\r\n}", "options": { "raw": { "language": "json" @@ -10583,28 +15626,28 @@ } }, "url": { - "raw": "{{URL}}/work-periods", + "raw": "{{URL}}/work-period-payments", "host": [ "{{URL}}" ], "path": [ - "work-periods" + "work-period-payments" ] } }, "response": [] }, { - "name": "create work period with missing parameter 2", + "name": "create work period payment 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" @@ -10617,12 +15660,12 @@ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_member}}" } ], "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 \"workPeriodId\": \"{{workPeriodId-3}}\"\r\n}", "options": { "raw": { "language": "json" @@ -10630,19 +15673,19 @@ } }, "url": { - "raw": "{{URL}}/work-periods", + "raw": "{{URL}}/work-period-payments", "host": [ "{{URL}}" ], "path": [ - "work-periods" + "work-period-payments" ] } }, "response": [] }, { - "name": "create work period with missing parameter 3", + "name": "create work period payment with user id not exist", "event": [ { "listen": "test", @@ -10651,7 +15694,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\\\" is required\")\r", + " pm.expect(response.message).to.eq(\"Bad Request\")\r", "});" ], "type": "text/javascript" @@ -10664,12 +15707,12 @@ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_userId_not_exist}}" } ], "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 \"workPeriodId\": \"{{workPeriodId-3}}\"\r\n}", "options": { "raw": { "language": "json" @@ -10677,28 +15720,28 @@ } }, "url": { - "raw": "{{URL}}/work-periods", + "raw": "{{URL}}/work-period-payments", "host": [ "{{URL}}" ], "path": [ - "work-periods" + "work-period-payments" ] } }, "response": [] }, { - "name": "create work period with invalid parameter 1", + "name": "create work period payment 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" @@ -10711,12 +15754,12 @@ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer invalid_token" } ], "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}", + "raw": "{\r\n \"workPeriodId\": \"{{workPeriodId-3}}\"\r\n}", "options": { "raw": { "language": "json" @@ -10724,19 +15767,19 @@ } }, "url": { - "raw": "{{URL}}/work-periods", + "raw": "{{URL}}/work-period-payments", "host": [ "{{URL}}" ], "path": [ - "work-periods" + "work-period-payments" ] } }, "response": [] }, { - "name": "create work period with invalid parameter 2", + "name": "create work period payment with missing workPeriodId", "event": [ { "listen": "test", @@ -10745,7 +15788,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.startDate\\\" must be in YYYY-MM-DD format\")\r", + " pm.expect(response.message).to.eq(\"\\\"workPeriodPayment.workPeriodId\\\" is required\")\r", "});" ], "type": "text/javascript" @@ -10763,7 +15806,7 @@ ], "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\r\n}", "options": { "raw": { "language": "json" @@ -10771,19 +15814,19 @@ } }, "url": { - "raw": "{{URL}}/work-periods", + "raw": "{{URL}}/work-period-payments", "host": [ "{{URL}}" ], "path": [ - "work-periods" + "work-period-payments" ] } }, "response": [] }, { - "name": "create work period with invalid parameter 3", + "name": "create work period payment with invalid workPeriodId 1", "event": [ { "listen": "test", @@ -10792,7 +15835,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(\"\\\"workPeriodPayment.workPeriodId\\\" must be a valid GUID\")\r", "});" ], "type": "text/javascript" @@ -10810,7 +15853,7 @@ ], "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": "{\r\n \"workPeriodId\": \"aaa-bb-c\"\r\n}", "options": { "raw": { "language": "json" @@ -10818,19 +15861,19 @@ } }, "url": { - "raw": "{{URL}}/work-periods", + "raw": "{{URL}}/work-period-payments", "host": [ "{{URL}}" ], "path": [ - "work-periods" + "work-period-payments" ] } }, "response": [] }, { - "name": "create work period with invalid parameter 4", + "name": "create work period payment with invalid workPeriodId 2", "event": [ { "listen": "test", @@ -10839,7 +15882,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(\"\\\"workPeriodPayment.workPeriodId\\\" must be a string\")\r", "});" ], "type": "text/javascript" @@ -10857,7 +15900,7 @@ ], "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 \"workPeriodId\": 123\r\n}", "options": { "raw": { "language": "json" @@ -10865,19 +15908,19 @@ } }, "url": { - "raw": "{{URL}}/work-periods", + "raw": "{{URL}}/work-period-payments", "host": [ "{{URL}}" ], "path": [ - "work-periods" + "work-period-payments" ] } }, "response": [] }, { - "name": "create work period with invalid parameter 5", + "name": "create work period payment with invalid days 1", "event": [ { "listen": "test", @@ -10886,7 +15929,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(\"Days cannot be more than not paid days which is 0\")\r", "});" ], "type": "text/javascript" @@ -10904,7 +15947,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 \"workPeriodId\": \"{{workPeriodId-1}}\",\r\n \"days\": 1\r\n}", "options": { "raw": { "language": "json" @@ -10912,19 +15955,19 @@ } }, "url": { - "raw": "{{URL}}/work-periods", + "raw": "{{URL}}/work-period-payments", "host": [ "{{URL}}" ], "path": [ - "work-periods" + "work-period-payments" ] } }, "response": [] }, { - "name": "create work period with invalid parameter 6", + "name": "create work period payment with invalid days 2", "event": [ { "listen": "test", @@ -10933,7 +15976,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(\"\\\"workPeriodPayment.days\\\" must be less than or equal to 5\")\r", "});" ], "type": "text/javascript" @@ -10951,7 +15994,7 @@ ], "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 \"workPeriodId\": \"{{workPeriodId-3}}\",\r\n \"days\": 6\r\n}", "options": { "raw": { "language": "json" @@ -10959,19 +16002,19 @@ } }, "url": { - "raw": "{{URL}}/work-periods", + "raw": "{{URL}}/work-period-payments", "host": [ "{{URL}}" ], "path": [ - "work-periods" + "work-period-payments" ] } }, "response": [] }, { - "name": "create work period with invalid parameter 7", + "name": "create work period payment with invalid days 2 Copy", "event": [ { "listen": "test", @@ -10980,7 +16023,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(\"Days cannot be more than not paid days which is 1\")\r", "});" ], "type": "text/javascript" @@ -10998,7 +16041,7 @@ ], "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 \"workPeriodId\": \"{{workPeriodId-3}}\",\r\n \"days\": 3\r\n}", "options": { "raw": { "language": "json" @@ -11006,26 +16049,28 @@ } }, "url": { - "raw": "{{URL}}/work-periods", + "raw": "{{URL}}/work-period-payments", "host": [ "{{URL}}" ], "path": [ - "work-periods" + "work-period-payments" ] } }, "response": [] }, { - "name": "get work period with booking manager", + "name": "create work period payment with completed status", "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 409', function () {\r", + " pm.response.to.have.status(409);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"There are no days to pay for WorkPeriod: \"+pm.environment.get('workPeriodId-2'))\r", "});" ], "type": "text/javascript" @@ -11033,7 +16078,7 @@ } ], "request": { - "method": "GET", + "method": "POST", "header": [ { "key": "Authorization", @@ -11041,21 +16086,29 @@ "value": "Bearer {{token_bookingManager}}" } ], + "body": { + "mode": "raw", + "raw": "{\r\n \"workPeriodId\": \"{{workPeriodId-2}}\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId}}", + "raw": "{{URL}}/work-period-payments", "host": [ "{{URL}}" ], "path": [ - "work-periods", - "{{workPeriodId}}" + "work-period-payments" ] } }, "response": [] }, { - "name": "get work period with m2m read 1", + "name": "get work period payment with booking manager", "event": [ { "listen": "test", @@ -11075,24 +16128,24 @@ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_m2m_read_work_period}}" + "value": "Bearer {{token_bookingManager}}" } ], "url": { - "raw": "{{URL}}/work-periods/{{workPeriodIdCreatedByM2M}}", + "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId}}", "host": [ "{{URL}}" ], "path": [ - "work-periods", - "{{workPeriodIdCreatedByM2M}}" + "work-period-payments", + "{{workPeriodPaymentId}}" ] } }, "response": [] }, { - "name": "get work period with m2m read 2", + "name": "get work period payment with m2m read", "event": [ { "listen": "test", @@ -11112,24 +16165,24 @@ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_m2m_read_work_period_and_payment}}" + "value": "Bearer {{token_m2m_read_work_period_payment}}" } ], "url": { - "raw": "{{URL}}/work-periods/{{workPeriodIdCreatedByM2M}}", + "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentIdCreatedByM2M}}", "host": [ "{{URL}}" ], "path": [ - "work-periods", - "{{workPeriodIdCreatedByM2M}}" + "work-period-payments", + "{{workPeriodPaymentIdCreatedByM2M}}" ] } }, "response": [] }, { - "name": "get work period with booking manager from db", + "name": "get work period payment with booking manager from db", "event": [ { "listen": "test", @@ -11153,13 +16206,13 @@ } ], "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId}}?fromDb=true", + "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId}}?fromDb=true", "host": [ "{{URL}}" ], "path": [ - "work-periods", - "{{workPeriodId}}" + "work-period-payments", + "{{workPeriodPaymentId}}" ], "query": [ { @@ -11172,14 +16225,16 @@ "response": [] }, { - "name": "get work period with connect user", + "name": "get work period payment with connect user", "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 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" @@ -11196,150 +16251,59 @@ } ], "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId}}", - "host": [ - "{{URL}}" - ], - "path": [ - "work-periods", - "{{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}}/work-periods/{{workPeriodId}}", + "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId}}", "host": [ "{{URL}}" ], "path": [ - "work-periods", - "{{workPeriodId}}" + "work-period-payments", + "{{workPeriodPaymentId}}" ] } }, "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}}/work-periods", - "host": [ - "{{URL}}" - ], - "path": [ - "work-periods" - ], - "query": [ - { - "key": "page", - "value": "1", - "disabled": true - }, - { - "key": "perPage", - "value": "35", - "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 - } + { + "name": "get work period payment 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", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_member}}" + } + ], + "url": { + "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "work-period-payments", + "{{workPeriodPaymentId}}" ] } }, "response": [] }, { - "name": "search work periods with m2m all 1", + "name": "search work period payments with booking manager", "event": [ { "listen": "test", @@ -11359,16 +16323,16 @@ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_m2m_all_work_period}}" + "value": "Bearer {{token_bookingManager}}" } ], "url": { - "raw": "{{URL}}/work-periods", + "raw": "{{URL}}/work-period-payments", "host": [ "{{URL}}" ], "path": [ - "work-periods" + "work-period-payments" ], "query": [ { @@ -11378,12 +16342,12 @@ }, { "key": "perPage", - "value": "5", + "value": "50", "disabled": true }, { "key": "sortBy", - "value": "id", + "value": "status", "disabled": true }, { @@ -11392,38 +16356,18 @@ "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", + "key": "workPeriodId", + "value": "{{workPeriodId}}", "disabled": true }, { - "key": "userHandle", - "value": "pshah_manager", + "key": "workPeriodIds", + "value": "{{workPeriodId}},{{workPeriodIdCreatedByM2M}}", "disabled": true }, { - "key": "projectId", - "value": "16843", + "key": "status", + "value": "completed", "disabled": true } ] @@ -11432,7 +16376,7 @@ "response": [] }, { - "name": "search work periods with m2m all 2", + "name": "search work period payments with m2m all", "event": [ { "listen": "test", @@ -11452,16 +16396,16 @@ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_m2m_all_work_period_and_payment}}" + "value": "Bearer {{token_m2m_all_work_period_payment}}" } ], "url": { - "raw": "{{URL}}/work-periods", + "raw": "{{URL}}/work-period-payments", "host": [ "{{URL}}" ], "path": [ - "work-periods" + "work-period-payments" ], "query": [ { @@ -11471,12 +16415,12 @@ }, { "key": "perPage", - "value": "5", + "value": "50", "disabled": true }, { "key": "sortBy", - "value": "id", + "value": "status", "disabled": true }, { @@ -11485,38 +16429,18 @@ "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", + "key": "workPeriodId", + "value": "{{workPeriodId}}", "disabled": true }, { - "key": "userHandle", - "value": "pshah_manager", + "key": "workPeriodIds", + "value": "{{workPeriodId}},{{workPeriodIdCreatedByM2M}}", "disabled": true }, { - "key": "projectId", - "value": "16843", + "key": "status", + "value": "completed", "disabled": true } ] @@ -11525,14 +16449,16 @@ "response": [] }, { - "name": "search work periods with connect user", + "name": "search work period payments with connect user", "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 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" @@ -11549,12 +16475,12 @@ } ], "url": { - "raw": "{{URL}}/work-periods", + "raw": "{{URL}}/work-period-payments", "host": [ "{{URL}}" ], "path": [ - "work-periods" + "work-period-payments" ], "query": [ { @@ -11564,12 +16490,12 @@ }, { "key": "perPage", - "value": "5", + "value": "50", "disabled": true }, { "key": "sortBy", - "value": "id", + "value": "status", "disabled": true }, { @@ -11578,38 +16504,18 @@ "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", + "key": "workPeriodId", + "value": "{{workPeriodId}}", "disabled": true }, { - "key": "userHandle", - "value": "pshah_manager", + "key": "workPeriodIds", + "value": "{{workPeriodId}},{{workPeriodIdCreatedByM2M}}", "disabled": true }, { - "key": "projectId", - "value": "16843", + "key": "status", + "value": "completed", "disabled": true } ] @@ -11618,7 +16524,22 @@ "response": [] }, { - "name": "search work periods with member", + "name": "search work period payments 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", "header": [ @@ -11629,12 +16550,12 @@ } ], "url": { - "raw": "{{URL}}/work-periods", + "raw": "{{URL}}/work-period-payments", "host": [ "{{URL}}" ], "path": [ - "work-periods" + "work-period-payments" ], "query": [ { @@ -11644,12 +16565,12 @@ }, { "key": "perPage", - "value": "5", + "value": "50", "disabled": true }, { "key": "sortBy", - "value": "id", + "value": "status", "disabled": true }, { @@ -11658,38 +16579,18 @@ "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", + "key": "workPeriodId", + "value": "{{workPeriodId}}", "disabled": true }, { - "key": "userHandle", - "value": "pshah_manager", + "key": "workPeriodIds", + "value": "{{workPeriodId}},{{workPeriodIdCreatedByM2M}}", "disabled": true }, { - "key": "projectId", - "value": "16843", + "key": "status", + "value": "completed", "disabled": true } ] @@ -11698,7 +16599,7 @@ "response": [] }, { - "name": "search work periods with invalid token", + "name": "search work period payments with invalid token", "event": [ { "listen": "test", @@ -11706,6 +16607,8 @@ "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" @@ -11722,67 +16625,47 @@ } ], "url": { - "raw": "{{URL}}/work-periods", + "raw": "{{URL}}/work-period-payments", "host": [ "{{URL}}" ], "path": [ - "work-periods" + "work-period-payments" ], "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}}", + "value": "1", "disabled": true }, { - "key": "resourceBookingIds", - "value": "{{resourceBookingId}},{{resourceBookingIdCreatedByM2M}}", + "key": "perPage", + "value": "50", "disabled": true }, { - "key": "paymentStatus", - "value": "pending", + "key": "sortBy", + "value": "status", "disabled": true }, { - "key": "startDate", - "value": "2021-03-14", + "key": "sortOrder", + "value": "desc", "disabled": true }, { - "key": "endDate", - "value": "2021-03-20", + "key": "workPeriodId", + "value": "{{workPeriodId}}", "disabled": true }, { - "key": "userHandle", - "value": "pshah_manager", + "key": "workPeriodIds", + "value": "{{workPeriodId}},{{workPeriodIdCreatedByM2M}}", "disabled": true }, { - "key": "projectId", - "value": "111", + "key": "status", + "value": "completed", "disabled": true } ] @@ -11791,7 +16674,55 @@ "response": [] }, { - "name": "put work period with booking manager", + "name": "put work period payment", + "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 requested resource cannot be found.\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"status\": \"completed\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId}}", + "host": [ + "{{URL}}" + ], + "path": [ + "work-period-payments", + "{{workPeriodPaymentId}}" + ] + } + }, + "response": [] + }, + { + "name": "patch work period payment with boooking manager", "event": [ { "listen": "test", @@ -11806,7 +16737,7 @@ } ], "request": { - "method": "PUT", + "method": "PATCH", "header": [ { "key": "Authorization", @@ -11816,7 +16747,7 @@ ], "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\": \"cancelled\"\r\n}", "options": { "raw": { "language": "json" @@ -11824,20 +16755,20 @@ } }, "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId}}", + "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId}}", "host": [ "{{URL}}" ], "path": [ - "work-periods", - "{{workPeriodId}}" + "work-period-payments", + "{{workPeriodPaymentId}}" ] } }, "response": [] }, { - "name": "put work period with m2m update", + "name": "patch work period payment with m2m create", "event": [ { "listen": "test", @@ -11852,17 +16783,17 @@ } ], "request": { - "method": "PUT", + "method": "PATCH", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_m2m_update_work_period}}" + "value": "Bearer {{token_m2m_update_work_period_payment}}" } ], "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 \"status\": \"cancelled\"\r\n}", "options": { "raw": { "language": "json" @@ -11870,20 +16801,20 @@ } }, "url": { - "raw": "{{URL}}/work-periods/{{workPeriodIdCreatedByM2M}}", + "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentIdCreatedByM2M}}", "host": [ "{{URL}}" ], "path": [ - "work-periods", - "{{workPeriodIdCreatedByM2M}}" + "work-period-payments", + "{{workPeriodPaymentIdCreatedByM2M}}" ] } }, "response": [] }, { - "name": "put work period with connect user", + "name": "patch work period payment with connect user", "event": [ { "listen": "test", @@ -11900,7 +16831,7 @@ } ], "request": { - "method": "PUT", + "method": "PATCH", "header": [ { "key": "Authorization", @@ -11910,7 +16841,7 @@ ], "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 \"status\": \"cancelled\"\r\n}", "options": { "raw": { "language": "json" @@ -11918,20 +16849,20 @@ } }, "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId}}", + "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId}}", "host": [ "{{URL}}" ], "path": [ - "work-periods", - "{{workPeriodId}}" + "work-period-payments", + "{{workPeriodPaymentId}}" ] } }, "response": [] }, { - "name": "put work period with member", + "name": "patch work period payment with member", "event": [ { "listen": "test", @@ -11948,7 +16879,7 @@ } ], "request": { - "method": "PUT", + "method": "PATCH", "header": [ { "key": "Authorization", @@ -11958,7 +16889,7 @@ ], "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 \"status\": \"cancelled\"\r\n}", "options": { "raw": { "language": "json" @@ -11966,20 +16897,20 @@ } }, "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId}}", + "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId}}", "host": [ "{{URL}}" ], "path": [ - "work-periods", - "{{workPeriodId}}" + "work-period-payments", + "{{workPeriodPaymentId}}" ] } }, "response": [] }, { - "name": "put work period with user id not exist", + "name": "patch work period payment with user id not exist", "event": [ { "listen": "test", @@ -11996,7 +16927,7 @@ } ], "request": { - "method": "PUT", + "method": "PATCH", "header": [ { "key": "Authorization", @@ -12006,7 +16937,7 @@ ], "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 \"status\": \"cancelled\"\r\n}", "options": { "raw": { "language": "json" @@ -12014,20 +16945,20 @@ } }, "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId}}", + "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId}}", "host": [ "{{URL}}" ], "path": [ - "work-periods", - "{{workPeriodId}}" + "work-period-payments", + "{{workPeriodPaymentId}}" ] } }, "response": [] }, { - "name": "put work period with invalid token", + "name": "patch work period payment with invalid token", "event": [ { "listen": "test", @@ -12044,7 +16975,7 @@ } ], "request": { - "method": "PUT", + "method": "PATCH", "header": [ { "key": "Authorization", @@ -12054,7 +16985,7 @@ ], "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 \"status\": \"cancelled\"\r\n}", "options": { "raw": { "language": "json" @@ -12062,20 +16993,20 @@ } }, "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId}}", + "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId}}", "host": [ "{{URL}}" ], "path": [ - "work-periods", - "{{workPeriodId}}" + "work-period-payments", + "{{workPeriodPaymentId}}" ] } }, "response": [] }, { - "name": "put work period with missing parameter 1", + "name": "patch work period payment with invalid status 1", "event": [ { "listen": "test", @@ -12084,7 +17015,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.resourceBookingId\\\" is required\")\r", + " pm.expect(response.message).to.eq(\"\\\"data.status\\\" must be one of [scheduled, cancelled]\")\r", "});" ], "type": "text/javascript" @@ -12092,7 +17023,7 @@ } ], "request": { - "method": "PUT", + "method": "PATCH", "header": [ { "key": "Authorization", @@ -12102,7 +17033,7 @@ ], "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 \"status\": 123\r\n}", "options": { "raw": { "language": "json" @@ -12110,20 +17041,20 @@ } }, "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId}}", + "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId}}", "host": [ "{{URL}}" ], "path": [ - "work-periods", - "{{workPeriodId}}" + "work-period-payments", + "{{workPeriodPaymentId}}" ] } }, "response": [] }, { - "name": "put work period with missing parameter 2", + "name": "patch work period payment with invalid status 2", "event": [ { "listen": "test", @@ -12132,7 +17063,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.endDate\\\" is required\")\r", + " pm.expect(response.message).to.eq(\"\\\"data.status\\\" must be one of [scheduled, cancelled]\")\r", "});" ], "type": "text/javascript" @@ -12140,7 +17071,7 @@ } ], "request": { - "method": "PUT", + "method": "PATCH", "header": [ { "key": "Authorization", @@ -12150,7 +17081,7 @@ ], "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 \"status\": \"invalid-status\"\r\n}", "options": { "raw": { "language": "json" @@ -12158,20 +17089,20 @@ } }, "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId}}", + "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId}}", "host": [ "{{URL}}" ], "path": [ - "work-periods", - "{{workPeriodId}}" + "work-period-payments", + "{{workPeriodPaymentId}}" ] } }, "response": [] }, { - "name": "put work period with missing parameter 3", + "name": "patch work period payment with invalid status 3", "event": [ { "listen": "test", @@ -12180,7 +17111,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.paymentStatus\\\" is required\")\r", + " pm.expect(response.message).to.eq(\"You cannot schedule a WorkPeriodPayment which is cancelled\")\r", "});" ], "type": "text/javascript" @@ -12188,7 +17119,7 @@ } ], "request": { - "method": "PUT", + "method": "PATCH", "header": [ { "key": "Authorization", @@ -12198,7 +17129,7 @@ ], "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 \"status\": \"scheduled\"\r\n}", "options": { "raw": { "language": "json" @@ -12206,20 +17137,20 @@ } }, "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId}}", + "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId}}", "host": [ "{{URL}}" ], "path": [ - "work-periods", - "{{workPeriodId}}" + "work-period-payments", + "{{workPeriodPaymentId}}" ] } }, "response": [] }, { - "name": "put work period with invalid parameter 1", + "name": "patch work period payment with invalid status 4", "event": [ { "listen": "test", @@ -12228,7 +17159,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.resourceBookingId\\\" must be a valid GUID\")\r", + " pm.expect(response.message).to.eq(\"You cannot schedule a WorkPeriodPayment which is completed\")\r", "});" ], "type": "text/javascript" @@ -12236,7 +17167,7 @@ } ], "request": { - "method": "PUT", + "method": "PATCH", "header": [ { "key": "Authorization", @@ -12246,1237 +17177,1537 @@ ], "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}", + "raw": "{\r\n \"status\": \"scheduled\"\r\n}", "options": { "raw": { "language": "json" } - } - }, - "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId}}", - "host": [ - "{{URL}}" + } + }, + "url": { + "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId-2}}", + "host": [ + "{{URL}}" + ], + "path": [ + "work-period-payments", + "{{workPeriodPaymentId-2}}" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "Taas Teams", + "item": [ + { + "name": "Before Start", + "item": [ + { + "name": "create role 1", + "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(\"roleIdForTeam-1\", response.id);\r", + " }\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Dropwizard\",\n \"NGINX\",\n \"Machine Learning\",\n \"Force.com\",\n \"User Interface (Ui)\",\n \"Photoshop\",\n \"appcelerator\",\n \"Flux\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10,\n \"rate30Global\": 20,\n \"rate30InCountry\": 15,\n \"rate30OffShore\": 35,\n \"rate20Global\": 20,\n \"rate20InCountry\": 15,\n \"rate20OffShore\": 35\n },\n {\n \"global\": 25,\n \"inCountry\": 15,\n \"offShore\": 5,\n \"rate30Global\": 20,\n \"rate30InCountry\": 15,\n \"rate30OffShore\": 35,\n \"rate20Global\": 20,\n \"rate20InCountry\": 15,\n \"rate20OffShore\": 35\n }\n ],\n \"numberOfMembers\": 10,\n \"numberOfMembersAvailable\": 8,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-roles", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles" + ] + } + }, + "response": [] + }, + { + "name": "create role 2", + "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(\"roleIdForTeam-2\", response.id);\r", + " }\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Angular Developer\",\n \"description\": \"Angular is an open-source, client-side framework based on TypeScript and designed for building web applications.\",\n \"listOfSkills\": [\n \"Database\",\n \"Winforms\",\n \"User Interface (Ui)\",\n \"Photoshop\",\n \"Dropwizard\",\n \"NGINX\",\n \"Docker\",\n \".NET\"\n ],\n \"rates\": [\n {\n \"global\": 55,\n \"inCountry\": 20,\n \"offShore\": 10,\n \"rate30Global\": 20,\n \"rate30InCountry\": 15,\n \"rate30OffShore\": 35,\n \"rate20Global\": 20,\n \"rate20InCountry\": 15,\n \"rate20OffShore\": 35\n },\n {\n \"global\": 25,\n \"inCountry\": 15,\n \"offShore\": 5,\n \"rate30Global\": 20,\n \"rate30InCountry\": 15,\n \"rate30OffShore\": 35,\n \"rate20Global\": 20,\n \"rate20InCountry\": 15,\n \"rate20OffShore\": 35\n }\n ],\n \"numberOfMembers\": 10,\n \"numberOfMembersAvailable\": 8,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-roles", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles" + ] + } + }, + "response": [] + }, + { + "name": "create role 3", + "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(\"roleIdForTeam-3\", response.id);\r", + " }\r", + "});" + ], + "type": "text/javascript" + } + } ], - "path": [ - "work-periods", - "{{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", - "});" + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } ], - "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" + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Salesforce Developer\",\n \"description\": \"A Salesforce developer is a programmer who builds Salesforce applications across various PaaS (Platform as a Service) platforms.\",\n \"listOfSkills\": [\n \"Docker\",\n \".NET\",\n \"appcelerator\",\n \"Flux\",\n \"Database\",\n \"Winforms\",\n \"NGINX\",\n \"Machine Learning\"\n ],\n \"rates\": [\n {\n \"global\": 40,\n \"inCountry\": 20,\n \"offShore\": 10,\n \"rate30Global\": 20,\n \"rate30InCountry\": 15,\n \"rate30OffShore\": 35,\n \"rate20Global\": 20,\n \"rate20InCountry\": 15,\n \"rate20OffShore\": 35\n },\n {\n \"global\": 25,\n \"inCountry\": 15,\n \"offShore\": 5,\n \"rate30Global\": 20,\n \"rate30InCountry\": 15,\n \"rate30OffShore\": 35,\n \"rate20Global\": 20,\n \"rate20InCountry\": 15,\n \"rate20OffShore\": 35\n }\n ],\n \"numberOfMembers\": 10,\n \"numberOfMembersAvailable\": 6,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-roles", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId}}", - "host": [ - "{{URL}}" + { + "name": "create role Niche", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", + "});" + ], + "type": "text/javascript" + } + } ], - "path": [ - "work-periods", - "{{workPeriodId}}" - ] + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Niche\",\n \"rates\": [\n {\n \"global\": 10,\n \"inCountry\": 10,\n \"offShore\": 10\n }\n ]\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-roles", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles" + ] + } + }, + "response": [] } - }, - "response": [] + ] }, { - "name": "put work period with invalid parameter 3", - "event": [ + "name": "Create Role Search", + "item": [ { - "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", - "});" + "name": "send request with administrator using roleId", + "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(\"roleSearchRequestId1-1\", response.roleSearchRequestId);\r", + " }\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_administrator}}", + "type": "text" + } ], - "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" + "body": { + "mode": "raw", + "raw": "{\r\n \"roleId\": \"{{roleIdForTeam-1}}\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-teams/sendRoleSearchRequest", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + "sendRoleSearchRequest" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId}}", - "host": [ - "{{URL}}" - ], - "path": [ - "work-periods", - "{{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", - "});" + "name": "send request with administrator using skills", + "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(\"roleSearchRequestId1-2\", response.roleSearchRequestId);\r", + " }\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_administrator}}", + "type": "text" + } ], - "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" + "body": { + "mode": "raw", + "raw": "{\r\n \"skills\": [\r\n \"56f46882-26f3-4c39-966d-912cccea0119\",\r\n \"536865d3-e7c7-4675-b119-6df8bf411624\",\r\n \"bd417c10-d81a-45b6-85a9-d79efe86b9bb\",\r\n \"4fce6ced-3610-443c-92eb-3f6d76b34f5c\"\r\n ]\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-teams/sendRoleSearchRequest", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + "sendRoleSearchRequest" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId}}", - "host": [ - "{{URL}}" - ], - "path": [ - "work-periods", - "{{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", - "});" + "name": "send request with administrator using description", + "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(\"roleSearchRequestId1-3\", response.roleSearchRequestId);\r", + " }\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_administrator}}", + "type": "text" + } ], - "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" + "body": { + "mode": "raw", + "raw": "{\r\n \"jobDescription\": \"Should have these skills: Machine Learning, Dropwizard, NGINX, appcelerator\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-teams/sendRoleSearchRequest", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + "sendRoleSearchRequest" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId}}", - "host": [ - "{{URL}}" - ], - "path": [ - "work-periods", - "{{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", - "});" + "name": "send request with user using roleId", + "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(\"roleSearchRequestId2-1\", response.roleSearchRequestId);\r", + " }\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_member_test_2}}", + "type": "text" + } ], - "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" + "body": { + "mode": "raw", + "raw": "{\r\n \"roleId\": \"{{roleIdForTeam-2}}\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-teams/sendRoleSearchRequest", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + "sendRoleSearchRequest" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId}}", - "host": [ - "{{URL}}" - ], - "path": [ - "work-periods", - "{{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", - "});" + "name": "send request with user using skills", + "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(\"roleSearchRequestId2-2\", response.roleSearchRequestId);\r", + " }\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_member_test_2}}", + "type": "text" + } ], - "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" + "body": { + "mode": "raw", + "raw": "{\r\n \"skills\": [\r\n \"56f46882-26f3-4c39-966d-912cccea0119\",\r\n \"536865d3-e7c7-4675-b119-6df8bf411624\",\r\n \"bd417c10-d81a-45b6-85a9-d79efe86b9bb\",\r\n \"4fce6ced-3610-443c-92eb-3f6d76b34f5c\"\r\n ]\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-teams/sendRoleSearchRequest", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + "sendRoleSearchRequest" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId}}", - "host": [ - "{{URL}}" + { + "name": "send request with user using description", + "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(\"roleSearchRequestId2-3\", response.roleSearchRequestId);\r", + " }\r", + "});" + ], + "type": "text/javascript" + } + } ], - "path": [ - "work-periods", - "{{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", - "});" + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_member_test_2}}", + "type": "text" + } ], - "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" + "body": { + "mode": "raw", + "raw": "{\r\n \"jobDescription\": \"Should have these skills: Machine Learning, Dropwizard, NGINX, appcelerator\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-teams/sendRoleSearchRequest", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + "sendRoleSearchRequest" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId}}", - "host": [ - "{{URL}}" - ], - "path": [ - "work-periods", - "{{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", - "});" + "name": "send request with m2m using roleId", + "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(\"roleSearchRequestId3-1\", response.roleSearchRequestId);\r", + " }\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_m2m_create_roleSearchRequests}}", + "type": "text" + } ], - "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" + "body": { + "mode": "raw", + "raw": "{\r\n \"roleId\": \"{{roleIdForTeam-3}}\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-teams/sendRoleSearchRequest", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + "sendRoleSearchRequest" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-periods/{{workPeriodIdCreatedByM2M}}", - "host": [ - "{{URL}}" - ], - "path": [ - "work-periods", - "{{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", - "});" + "name": "send request with m2m using skills", + "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(\"roleSearchRequestId3-2\", response.roleSearchRequestId);\r", + " }\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_m2m_create_roleSearchRequests}}", + "type": "text" + } ], - "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" + "body": { + "mode": "raw", + "raw": "{\r\n \"skills\": [\r\n \"56f46882-26f3-4c39-966d-912cccea0119\",\r\n \"536865d3-e7c7-4675-b119-6df8bf411624\",\r\n \"bd417c10-d81a-45b6-85a9-d79efe86b9bb\",\r\n \"4fce6ced-3610-443c-92eb-3f6d76b34f5c\"\r\n ]\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-teams/sendRoleSearchRequest", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + "sendRoleSearchRequest" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId}}", - "host": [ - "{{URL}}" - ], - "path": [ - "work-periods", - "{{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", - "});" + "name": "send request with m2m using description", + "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(\"roleSearchRequestId3-3\", response.roleSearchRequestId);\r", + " }\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_m2m_create_roleSearchRequests}}", + "type": "text" + } ], - "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" + "body": { + "mode": "raw", + "raw": "{\r\n \"jobDescription\": \"Should have these skills: Machine Learning, Dropwizard, NGINX, appcelerator\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-teams/sendRoleSearchRequest", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + "sendRoleSearchRequest" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId}}", - "host": [ - "{{URL}}" - ], - "path": [ - "work-periods", - "{{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", - "});" + "name": "send request 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": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer invalid_token", + "type": "text" + } ], - "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" + "body": { + "mode": "raw", + "raw": "{\r\n \"jobDescription\": \"Should have these skills: Machine Learning, Dropwizard, NGINX, appcelerator\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-teams/sendRoleSearchRequest", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + "sendRoleSearchRequest" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId}}", - "host": [ - "{{URL}}" - ], - "path": [ - "work-periods", - "{{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", - "});" + "name": "send request with missing field", + "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\\\" must have at least 1 key\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_administrator}}", + "type": "text" + } ], - "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" + "body": { + "mode": "raw", + "raw": "{\r\n \r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-teams/sendRoleSearchRequest", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + "sendRoleSearchRequest" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId}}", - "host": [ - "{{URL}}" - ], - "path": [ - "work-periods", - "{{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", - "});" + "name": "send request with invalid field 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.roleId\\\" must be a valid GUID\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_administrator}}", + "type": "text" + } ], - "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" + "body": { + "mode": "raw", + "raw": "{\r\n \"roleId\": \"000\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-teams/sendRoleSearchRequest", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + "sendRoleSearchRequest" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId}}", - "host": [ - "{{URL}}" - ], - "path": [ - "work-periods", - "{{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" + "name": "send request with invalid field 2", + "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(\"id: 00000000-0000-0000-0000-000000000000 \\\"Role\\\" doesn't exists.\")\r", + "});" + ], + "type": "text/javascript" + } } - } - }, - "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId}}", - "host": [ - "{{URL}}" ], - "path": [ - "work-periods", - "{{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", - "});" + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_administrator}}", + "type": "text" + } ], - "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" + "body": { + "mode": "raw", + "raw": "{\r\n \"roleId\": \"00000000-0000-0000-0000-000000000000\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-teams/sendRoleSearchRequest", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + "sendRoleSearchRequest" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId}}", - "host": [ - "{{URL}}" - ], - "path": [ - "work-periods", - "{{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", - "});" + "name": "send request with invalid field 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.skills\\\" must be an array\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_administrator}}", + "type": "text" + } ], - "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" + "body": { + "mode": "raw", + "raw": "{\r\n \"skills\": \"00000000-0000-0000-0000-000000000000\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-teams/sendRoleSearchRequest", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + "sendRoleSearchRequest" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId}}", - "host": [ - "{{URL}}" - ], - "path": [ - "work-periods", - "{{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" + "name": "send request with invalid field 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(\"Invalid skills: [00000000-0000-0000-0000-000000000000]\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_administrator}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"skills\": [\r\n \"00000000-0000-0000-0000-000000000000\"\r\n ]\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-teams/sendRoleSearchRequest", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + "sendRoleSearchRequest" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId}}", - "host": [ - "{{URL}}" + { + "name": "send request with not matching skills", + "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.name).to.eq(\"Niche\")\r", + "});" + ], + "type": "text/javascript" + } + } ], - "path": [ - "work-periods", - "{{workPeriodId}}" - ] + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_administrator}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"skills\": [\r\n \"23e00d92-207a-4b5b-b3c9-4c5662644941\",\r\n \"7d076384-ccf6-4e43-a45d-1b24b1e624aa\",\r\n \"cbac57a3-7180-4316-8769-73af64893158\",\r\n \"a2b4bc11-c641-4a19-9eb7-33980378f82e\"\r\n ]\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-teams/sendRoleSearchRequest", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + "sendRoleSearchRequest" + ] + } + }, + "response": [] } - }, - "response": [] + ] }, { - "name": "patch work period with invalid parameter 6", - "event": [ + "name": "Create Team", + "item": [ { - "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", - "});" + "name": "create team 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(\"createTeamProjectId-1\", response.projectId);\r", + " }\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_administrator}}", + "type": "text" + } ], - "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" + "body": { + "mode": "raw", + "raw": "{\r\n \"teamName\": \"Submit Team Test 1\",\r\n \"teamDescription\":\"Submit Team Test 1 description\",\r\n \"positions\": [\r\n {\r\n \"roleName\": \"Dev Ops Engineer\",\r\n \"roleSearchRequestId\": \"{{roleSearchRequestId1-1}}\",\r\n \"numberOfResources\": 10,\r\n \"durationWeeks\": 7,\r\n \"startMonth\": \"2021-06-15\"\r\n },\r\n {\r\n \"roleName\": \"Salesforce Developer\",\r\n \"roleSearchRequestId\": \"{{roleSearchRequestId1-2}}\",\r\n \"numberOfResources\": 5,\r\n \"durationWeeks\": 5,\r\n \"startMonth\": \"2021-06-15\"\r\n }\r\n ]\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-teams/submitTeamRequest", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + "submitTeamRequest" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId}}", - "host": [ - "{{URL}}" - ], - "path": [ - "work-periods", - "{{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", - "});" + "name": "get created jobs 1", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_administrator}}", + "type": "text" + } ], - "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" + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobs?projectId={{createTeamProjectId-1}}", + "host": [ + "{{URL}}" + ], + "path": [ + "jobs" + ], + "query": [ + { + "key": "projectId", + "value": "{{createTeamProjectId-1}}" + } + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId}}", - "host": [ - "{{URL}}" - ], - "path": [ - "work-periods", - "{{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", - "});" + "name": "create team with user", + "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(\"createTeamProjectId-2\", response.projectId);\r", + " }\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_member_test_2}}", + "type": "text" + } ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "DELETE", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_member}}" - } - ], - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" + "body": { + "mode": "raw", + "raw": "{\r\n \"teamName\": \"Submit Team Test 2\",\r\n \"teamDescription\":\"Submit Team Test 2 description\",\r\n \"positions\": [\r\n {\r\n \"roleName\": \"Angular Developer\",\r\n \"roleSearchRequestId\": \"{{roleSearchRequestId2-1}}\",\r\n \"numberOfResources\": 10,\r\n \"durationWeeks\": 7,\r\n \"startMonth\": \"2021-06-15\"\r\n },\r\n {\r\n \"roleName\": \"Dev Ops Engineer\",\r\n \"roleSearchRequestId\": \"{{roleSearchRequestId2-3}}\",\r\n \"numberOfResources\": 5,\r\n \"durationWeeks\": 5,\r\n \"startMonth\": \"2021-06-15\"\r\n }\r\n ]\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-teams/submitTeamRequest", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + "submitTeamRequest" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId}}", - "host": [ - "{{URL}}" - ], - "path": [ - "work-periods", - "{{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", - "});" + "name": "get created jobs 2", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_administrator}}", + "type": "text" + } ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "DELETE", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_connectUser}}" - } - ], - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobs?projectId={{createTeamProjectId-2}}", + "host": [ + "{{URL}}" + ], + "path": [ + "jobs" + ], + "query": [ + { + "key": "projectId", + "value": "{{createTeamProjectId-2}}" + } + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId}}", - "host": [ - "{{URL}}" - ], - "path": [ - "work-periods", - "{{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", - "});" + "name": "create team with m2m", + "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(\"createTeamProjectId-3\", response.projectId);\r", + " }\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_m2m_create_teams}}", + "type": "text" + } ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "DELETE", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } - ], - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" + "body": { + "mode": "raw", + "raw": "{\r\n \"teamName\": \"Submit Team Test 3\",\r\n \"teamDescription\":\"Submit Team Test 3 description\",\r\n \"positions\": [\r\n {\r\n \"roleName\": \"Salesforce Developer\",\r\n \"roleSearchRequestId\": \"{{roleSearchRequestId3-2}}\",\r\n \"numberOfResources\": 10,\r\n \"durationWeeks\": 7,\r\n \"startMonth\": \"2021-06-15\"\r\n },\r\n {\r\n \"roleName\": \"Dev Ops Engineer\",\r\n \"roleSearchRequestId\": \"{{roleSearchRequestId3-3}}\",\r\n \"numberOfResources\": 5,\r\n \"durationWeeks\": 5,\r\n \"startMonth\": \"2021-06-15\"\r\n }\r\n ]\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-teams/submitTeamRequest", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + "submitTeamRequest" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId}}", - "host": [ - "{{URL}}" + { + "name": "get created jobs 3", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", + "});" + ], + "type": "text/javascript" + } + } ], - "path": [ - "work-periods", - "{{workPeriodId}}" - ] - } - }, - "response": [] - }, - { - "name": "delete work period with m2m delete", - "event": [ + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_administrator}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobs?projectId={{createTeamProjectId-3}}", + "host": [ + "{{URL}}" + ], + "path": [ + "jobs" + ], + "query": [ + { + "key": "projectId", + "value": "{{createTeamProjectId-3}}" + } + ] + } + }, + "response": [] + }, { - "listen": "test", - "script": { - "exec": [ - "pm.test('Status code is 204', function () {\r", - " pm.response.to.have.status(204);\r", - "});" + "name": "create team 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": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer invalid token", + "type": "text" + } ], - "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" + "body": { + "mode": "raw", + "raw": "{\r\n \"teamName\": \"Submit Team Test 1\",\r\n \"teamDescription\":\"Submit Team Test 1 description\",\r\n \"positions\": [\r\n {\r\n \"roleName\": \"Dev Ops Engineer\",\r\n \"roleSearchRequestId\": \"{{roleSearchRequestId1-1}}\",\r\n \"numberOfResources\": 10,\r\n \"durationWeeks\": 7,\r\n \"startMonth\": \"2021-06-15\"\r\n },\r\n {\r\n \"roleName\": \"Salesforce Developer\",\r\n \"roleSearchRequestId\": \"{{roleSearchRequestId1-2}}\",\r\n \"numberOfResources\": 5,\r\n \"durationWeeks\": 5,\r\n \"startMonth\": \"2021-06-15\"\r\n }\r\n ]\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-teams/submitTeamRequest", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + "submitTeamRequest" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-periods/{{workPeriodIdCreatedByM2M}}", - "host": [ - "{{URL}}" - ], - "path": [ - "work-periods", - "{{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", - "});" + "name": "create team with missing field 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.teamName\\\" is required\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_administrator}}", + "type": "text" + } ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "DELETE", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer invalid_token" - } - ], - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" + "body": { + "mode": "raw", + "raw": "{\r\n \"teamDescription\":\"Submit Team Test 1 description\",\r\n \"positions\": [\r\n {\r\n \"roleName\": \"Dev Ops Engineer\",\r\n \"roleSearchRequestId\": \"{{roleSearchRequestId1-1}}\",\r\n \"numberOfResources\": 10,\r\n \"durationWeeks\": 7,\r\n \"startMonth\": \"2021-06-15\"\r\n },\r\n {\r\n \"roleName\": \"Salesforce Developer\",\r\n \"roleSearchRequestId\": \"{{roleSearchRequestId1-2}}\",\r\n \"numberOfResources\": 5,\r\n \"durationWeeks\": 5,\r\n \"startMonth\": \"2021-06-15\"\r\n }\r\n ]\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-teams/submitTeamRequest", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + "submitTeamRequest" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId}}", - "host": [ - "{{URL}}" - ], - "path": [ - "work-periods", - "{{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", - "});" + "name": "create team with missing field 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.positions\\\" is required\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_administrator}}", + "type": "text" + } ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "DELETE", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } - ], - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" + "body": { + "mode": "raw", + "raw": "{\r\n \"teamName\": \"Submit Team Test 1\",\r\n \"teamDescription\":\"Submit Team Test 1 description\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-teams/submitTeamRequest", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + "submitTeamRequest" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId}}", - "host": [ - "{{URL}}" + { + "name": "create team with missing field 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.positions[0].roleName\\\" is required\")\r", + "});" + ], + "type": "text/javascript" + } + } ], - "path": [ - "work-periods", - "{{workPeriodId}}" - ] - } - }, - "response": [] - } - ] - }, - { - "name": "Work Period Payments", - "item": [ - { - "name": "Before Test", - "item": [ + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_administrator}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"teamName\": \"Submit Team Test 1\",\r\n \"teamDescription\":\"Submit Team Test 1 description\",\r\n \"positions\": [\r\n {\r\n \"roleSearchRequestId\": \"{{roleSearchRequestId1-1}}\",\r\n \"numberOfResources\": 10,\r\n \"durationWeeks\": 7,\r\n \"startMonth\": \"2021-06-15\"\r\n }\r\n ]\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-teams/submitTeamRequest", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + "submitTeamRequest" + ] + } + }, + "response": [] + }, { - "name": "create job", + "name": "create team with missing field 4", "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", + "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.positions[0].roleSearchRequestId\\\" is required\")\r", "});" ], "type": "text/javascript" @@ -13488,13 +18719,13 @@ "header": [ { "key": "Authorization", - "value": "Bearer {{token_bookingManager}}", + "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}", + "raw": "{\r\n \"teamName\": \"Submit Team Test 1\",\r\n \"teamDescription\":\"Submit Team Test 1 description\",\r\n \"positions\": [\r\n {\r\n \"roleName\": \"Dev Ops Engineer\",\r\n \"numberOfResources\": 10,\r\n \"durationWeeks\": 7,\r\n \"startMonth\": \"2021-06-15\"\r\n }\r\n ]\r\n}", "options": { "raw": { "language": "json" @@ -13502,30 +18733,29 @@ } }, "url": { - "raw": "{{URL}}/jobs", + "raw": "{{URL}}/taas-teams/submitTeamRequest", "host": [ "{{URL}}" ], "path": [ - "jobs" + "taas-teams", + "submitTeamRequest" ] } }, "response": [] }, { - "name": "create resource booking", + "name": "create team with missing field 5", "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", + "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.positions[0].numberOfResources\\\" is required\")\r", "});" ], "type": "text/javascript" @@ -13537,13 +18767,13 @@ "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_administrator}}", + "type": "text" } ], "body": { "mode": "raw", - "raw": "{\r\n \"projectId\": {{project_id_17234}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{jobId}}\",\r\n \"startDate\": \"2020-09-27\",\r\n \"endDate\": \"2020-10-27\",\r\n \"memberRate\": 13.23,\r\n \"customerRate\": 13,\r\n \"rateType\": \"hourly\",\r\n \"billingAccountId\": 80000071\r\n}", + "raw": "{\r\n \"teamName\": \"Submit Team Test 1\",\r\n \"teamDescription\":\"Submit Team Test 1 description\",\r\n \"positions\": [\r\n {\r\n \"roleName\": \"Dev Ops Engineer\",\r\n \"roleSearchRequestId\": \"{{roleSearchRequestId1-1}}\"\r\n }\r\n ]\r\n}", "options": { "raw": { "language": "json" @@ -13551,30 +18781,29 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings", + "raw": "{{URL}}/taas-teams/submitTeamRequest", "host": [ "{{URL}}" ], "path": [ - "resourceBookings" + "taas-teams", + "submitTeamRequest" ] } }, "response": [] }, { - "name": "create work period", + "name": "create team with invalid field 1", "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", + "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(\"id: 00000000-0000-0000-0000-000000000000 \\\"RoleSearchRequest\\\" doesn't exists.\")\r", "});" ], "type": "text/javascript" @@ -13586,13 +18815,13 @@ "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\": \"pending\"\r\n}", + "raw": "{\r\n \"teamName\": \"Submit Team Test 1\",\r\n \"teamDescription\":\"Submit Team Test 1 description\",\r\n \"positions\": [\r\n {\r\n \"roleName\": \"Dev Ops Engineer\",\r\n \"roleSearchRequestId\": \"00000000-0000-0000-0000-000000000000\",\r\n \"numberOfResources\": 10,\r\n \"durationWeeks\": 7,\r\n \"startMonth\": \"2021-06-15\"\r\n }\r\n ]\r\n}", "options": { "raw": { "language": "json" @@ -13600,30 +18829,29 @@ } }, "url": { - "raw": "{{URL}}/work-periods", + "raw": "{{URL}}/taas-teams/submitTeamRequest", "host": [ "{{URL}}" ], "path": [ - "work-periods" + "taas-teams", + "submitTeamRequest" ] } }, "response": [] }, { - "name": "create work period with m2m", + "name": "create team with invalid field 2", "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", + "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.positions\\\" must be an array\")\r", "});" ], "type": "text/javascript" @@ -13635,13 +18863,13 @@ "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_m2m_create_work_period}}" + "value": "Bearer {{token_administrator}}", + "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}", + "raw": "{\r\n \"teamName\": \"Submit Team Test 1\",\r\n \"teamDescription\":\"Submit Team Test 1 description\",\r\n \"positions\":\r\n {\r\n \"roleName\": \"Dev Ops Engineer\",\r\n \"roleSearchRequestId\": \"{{roleSearchRequestId1-1}}\",\r\n \"numberOfResources\": 10,\r\n \"durationWeeks\": 7,\r\n \"startMonth\": \"2021-06-15\"\r\n }\r\n}", "options": { "raw": { "language": "json" @@ -13649,12 +18877,13 @@ } }, "url": { - "raw": "{{URL}}/work-periods", + "raw": "{{URL}}/taas-teams/submitTeamRequest", "host": [ "{{URL}}" ], "path": [ - "work-periods" + "taas-teams", + "submitTeamRequest" ] } }, @@ -13663,830 +18892,705 @@ ] }, { - "name": "create work period payment with boooking manager", - "event": [ + "name": "Get Skills by Job Description", + "item": [ { - "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(\"workPeriodPaymentId\", 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 \"workPeriodId\": \"{{workPeriodId}}\",\r\n \"amount\": 600,\r\n \"status\": \"completed\"\r\n}", - "options": { - "raw": { - "language": "json" + "name": "get skills successfully", + "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}}/work-period-payments", - "host": [ - "{{URL}}" ], - "path": [ - "work-period-payments" - ] - } - }, - "response": [] - }, - { - "name": "create work period payment 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(\"workPeriodPaymentIdCreatedByM2M\", response.id);\r", - " }\r", - "});" + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + }, + { + "key": "Content-Type", + "type": "text", + "value": "application/json" + } ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_m2m_create_work_period_payment}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"workPeriodId\": \"{{workPeriodIdCreatedByM2M}}\",\r\n \"amount\": 600,\r\n \"status\": \"completed\"\r\n}", - "options": { - "raw": { - "language": "json" + "body": { + "mode": "raw", + "raw": "{ \"description\": \"Description A global leading healthcare company is seeking a strong Databricks Engineer to join their development team as they build their new Databricks workspace. Development efforts will contribute to the migration of data from Hadoop to Databricks to prepare data for visualization. Candidate must be well-versed in Databricks components and best practices, be an excellent problem solver and be comfortable working in a fast-moving, rapidly changing, and dynamic environment via Agile, SCRUM, and DevOps. PREFERRED QUALIFICATIONS: 2+ years of Azure Data Stack experience: Azure Data Services using ADF, ADLS, Databricks with PySpark, Azure DevOps & Azure Key Vault. Strong knowledge of various data warehousing methodologies and data modeling concepts. Hands-on experience using Azure, Azure data lake, Azure functions & Databricks Minimum 2-3+ years of Python experience (PySpark) Design & Develop Azure native solutions for Data Platform Minimum 3+ years of experience using Big Data ecosystem (Cloudera/Hortonworks) using Oozie, Hive, Impala, and Spark Expert in SQL and performance tuning\" }", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-teams/getSkillsByJobDescription", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + "getSkillsByJobDescription" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-period-payments", - "host": [ - "{{URL}}" - ], - "path": [ - "work-period-payments" - ] - } - }, - "response": [] - }, - { - "name": "create work period payment 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": "POST", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_connectUser}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"workPeriodId\": \"{{workPeriodId}}\",\r\n \"amount\": 600,\r\n \"status\": \"completed\"\r\n}", - "options": { - "raw": { - "language": "json" + "name": "get skills by 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" + } } - } - }, - "url": { - "raw": "{{URL}}/work-period-payments", - "host": [ - "{{URL}}" ], - "path": [ - "work-period-payments" - ] - } - }, - "response": [] - }, - { - "name": "create work period payment with member", - "event": [ + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer invalid_token" + }, + { + "key": "Content-Type", + "type": "text", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{ \"description\": \"Description A global leading healthcare company is seeking a strong Databricks Engineer to join their development team as they build their new Databricks workspace. Development efforts will contribute to the migration of data from Hadoop to Databricks to prepare data for visualization. Candidate must be well-versed in Databricks components and best practices, be an excellent problem solver and be comfortable working in a fast-moving, rapidly changing, and dynamic environment via Agile, SCRUM, and DevOps. PREFERRED QUALIFICATIONS: 2+ years of Azure Data Stack experience: Azure Data Services using ADF, ADLS, Databricks with PySpark, Azure DevOps & Azure Key Vault. Strong knowledge of various data warehousing methodologies and data modeling concepts. Hands-on experience using Azure, Azure data lake, Azure functions & Databricks Minimum 2-3+ years of Python experience (PySpark) Design & Develop Azure native solutions for Data Platform Minimum 3+ years of experience using Big Data ecosystem (Cloudera/Hortonworks) using Oozie, Hive, Impala, and Spark Expert in SQL and performance tuning\" }", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-teams/getSkillsByJobDescription", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + "getSkillsByJobDescription" + ] + } + }, + "response": [] + }, { - "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", - "});" + "name": "get skills by invalid field", + "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.description\\\" is not allowed to be empty\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + }, + { + "key": "Content-Type", + "type": "text", + "value": "application/json" + } ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_member}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"workPeriodId\": \"{{workPeriodId}}\",\r\n \"amount\": 600,\r\n \"status\": \"completed\"\r\n}", - "options": { - "raw": { - "language": "json" + "body": { + "mode": "raw", + "raw": "{ \"description\": \"\" }", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-teams/getSkillsByJobDescription", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + "getSkillsByJobDescription" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-period-payments", - "host": [ - "{{URL}}" + { + "name": "get skills by missing field", + "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.description\\\" is required\")\r", + "});" + ], + "type": "text/javascript" + } + } ], - "path": [ - "work-period-payments" - ] + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + }, + { + "key": "Content-Type", + "type": "text", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-teams/getSkillsByJobDescription", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-teams", + "getSkillsByJobDescription" + ] + } + }, + "response": [] } - }, - "response": [] + ] }, { - "name": "create work period payment 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" - } - } - ], + "name": "GET /taas-teams", "request": { - "method": "POST", + "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_userId_not_exist}}" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], - "body": { - "mode": "raw", - "raw": "{\r\n \"workPeriodId\": \"{{workPeriodId}}\",\r\n \"amount\": 600,\r\n \"status\": \"completed\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/work-period-payments", + "raw": "{{URL}}/taas-teams?perPage=10&page=1&name=*taas*&sortBy=lastActivityAt&sortOrder=desc", "host": [ "{{URL}}" ], "path": [ - "work-period-payments" + "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": "create work period payment 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 /taas-teams with booking manager", "request": { - "method": "POST", + "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer invalid_token" + "value": "Bearer {{token_bookingManager}}", + "type": "text" } ], - "body": { - "mode": "raw", - "raw": "{\r\n \"workPeriodId\": \"{{workPeriodId}}\",\r\n \"amount\": 600,\r\n \"status\": \"completed\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/work-period-payments", + "raw": "{{URL}}/taas-teams?perPage=10&page=1&name=*taas*&sortBy=lastActivityAt&sortOrder=desc", "host": [ "{{URL}}" ], "path": [ - "work-period-payments" + "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": "create work period payment with missing workPeriodId", - "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(\"\\\"workPeriodPayment.workPeriodId\\\" is required\")\r", - "});" - ], - "type": "text/javascript" - } - } - ], + "name": "GET /taas-teams with m2m read", "request": { - "method": "POST", + "method": "GET", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_m2m_read_taas_team}}" } ], - "body": { - "mode": "raw", - "raw": "{\r\n \"amount\": 600,\r\n \"status\": \"completed\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/work-period-payments", + "raw": "{{URL}}/taas-teams", "host": [ "{{URL}}" ], "path": [ - "work-period-payments" + "taas-teams" ] } }, "response": [] }, { - "name": "create work period payment with invalid workPeriodId 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(\"\\\"workPeriodPayment.workPeriodId\\\" must be a valid GUID\")\r", - "});" - ], - "type": "text/javascript" - } - } - ], + "name": "GET /taas-teams/:id", "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 \"workPeriodId\": \"aaa-bb-c\",\r\n \"amount\": 600,\r\n \"status\": \"completed\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/work-period-payments", + "raw": "{{URL}}/taas-teams/{{projectId}}", "host": [ "{{URL}}" ], "path": [ - "work-period-payments" + "taas-teams", + "{{projectId}}" ] } }, "response": [] }, { - "name": "create work period payment with invalid workPeriodId 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(\"\\\"workPeriodPayment.workPeriodId\\\" must be a string\")\r", - "});" - ], - "type": "text/javascript" - } - } - ], + "name": "GET /taas-teams/:id with booking manager", "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 \"workPeriodId\": 123,\r\n \"amount\": 600,\r\n \"status\": \"completed\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/work-period-payments", + "raw": "{{URL}}/taas-teams/:projectId", "host": [ "{{URL}}" ], "path": [ - "work-period-payments" + "taas-teams", + ":projectId" + ], + "variable": [ + { + "key": "projectId", + "value": "16705" + } ] } }, "response": [] }, { - "name": "create work period payment with invalid amount 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(\"\\\"workPeriodPayment.amount\\\" must be a number\")\r", - "});" - ], - "type": "text/javascript" - } - } - ], + "name": "GET /taas-teams/:id with m2m read", "request": { - "method": "POST", + "method": "GET", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_m2m_read_taas_team}}" } ], - "body": { - "mode": "raw", - "raw": "{\r\n \"workPeriodId\": \"{{workPeriodId}}\",\r\n \"amount\": \"abc\",\r\n \"status\": \"completed\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/work-period-payments", + "raw": "{{URL}}/taas-teams/{{projectId}}", "host": [ "{{URL}}" ], "path": [ - "work-period-payments" + "taas-teams", + "{{projectId}}" ] } }, "response": [] }, { - "name": "create work period payment with invalid amount 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(\"\\\"workPeriodPayment.amount\\\" must be greater than 0\")\r", - "});" - ], - "type": "text/javascript" - } - } - ], + "name": "GET /taas-teams/:id/jobs/:jobId", "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 \"workPeriodId\": \"{{workPeriodId}}\",\r\n \"amount\": 0,\r\n \"status\": \"completed\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/work-period-payments", + "raw": "{{URL}}/taas-teams/{{projectId}}/jobs/{{jobId}}", "host": [ "{{URL}}" ], "path": [ - "work-period-payments" + "taas-teams", + "{{projectId}}", + "jobs", + "{{jobId}}" ] } }, "response": [] }, { - "name": "create work period payment with invalid status 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(\"\\\"workPeriodPayment.status\\\" must be one of [completed, cancelled]\")\r", - "});" - ], - "type": "text/javascript" - } - } - ], + "name": "GET /taas-teams/:id/jobs/:jobId with booking manager", "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 \"workPeriodId\": \"{{workPeriodId}}\",\r\n \"amount\": 1200,\r\n \"status\": 123\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/work-period-payments", + "raw": "{{URL}}/taas-teams/:projectId/jobs/:jobId", "host": [ "{{URL}}" ], "path": [ - "work-period-payments" + "taas-teams", + ":projectId", + "jobs", + ":jobId" + ], + "variable": [ + { + "key": "projectId", + "value": "16705" + }, + { + "key": "jobId", + "value": "948a25a6-086f-4a96-aad5-9ccd2d3e87b2" + } ] } }, "response": [] }, { - "name": "create work period payment with invalid status 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(\"\\\"workPeriodPayment.status\\\" must be one of [completed, cancelled]\")\r", - "});" - ], - "type": "text/javascript" - } - } - ], + "name": "GET /taas-teams/:id/jobs/:jobId with m2m read", "request": { - "method": "POST", + "method": "GET", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_m2m_read_taas_team}}" } ], - "body": { - "mode": "raw", - "raw": "{\r\n \"workPeriodId\": \"{{workPeriodId}}\",\r\n \"amount\": 1200,\r\n \"status\": \"invalid-status\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { - "raw": "{{URL}}/work-period-payments", + "raw": "{{URL}}/taas-teams/{{projectId}}/jobs/{{jobId}}", "host": [ "{{URL}}" ], "path": [ - "work-period-payments" + "taas-teams", + "{{projectId}}", + "jobs", + "{{jobId}}" ] } - }, - "response": [] - }, - { - "name": "get work period payment 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" - } - } - ], + }, + "response": [] + }, + { + "name": "GET /taas-teams/skills", "request": { "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" + "value": "Bearer {{token_member}}", + "type": "text" } ], "url": { - "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId}}", + "raw": "{{URL}}/taas-teams/skills?perPage=10&page=1&orderBy=name", "host": [ "{{URL}}" ], "path": [ - "work-period-payments", - "{{workPeriodPaymentId}}" + "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": "get work period payment 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" - } - } - ], + "name": "POST /taas-teams/email - team-issue-report", "request": { - "method": "GET", + "method": "POST", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_m2m_read_work_period_payment}}" + "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}}/work-period-payments/{{workPeriodPaymentIdCreatedByM2M}}", + "raw": "{{URL}}/taas-teams/email", "host": [ "{{URL}}" ], "path": [ - "work-period-payments", - "{{workPeriodPaymentIdCreatedByM2M}}" + "taas-teams", + "email" ] } }, "response": [] }, { - "name": "get work period payment 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" - } - } - ], + "name": "POST /taas-teams/email - member-issue-report", "request": { - "method": "GET", + "method": "POST", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_bookingManager}}" + "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}}/work-period-payments/{{workPeriodPaymentId}}?fromDb=true", + "raw": "{{URL}}/taas-teams/email", "host": [ "{{URL}}" ], "path": [ - "work-period-payments", - "{{workPeriodPaymentId}}" - ], - "query": [ - { - "key": "fromDb", - "value": "true" - } + "taas-teams", + "email" ] } }, "response": [] }, { - "name": "get work period payment 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" - } - } - ], + "name": "POST /taas-teams/email - extension-request", "request": { - "method": "GET", + "method": "POST", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_connectUser}}" + "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}}/work-period-payments/{{workPeriodPaymentId}}", + "raw": "{{URL}}/taas-teams/email", "host": [ "{{URL}}" ], "path": [ - "work-period-payments", - "{{workPeriodPaymentId}}" + "taas-teams", + "email" ] } }, "response": [] }, { - "name": "get work period payment 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": "POST /taas-teams/:id/members", "request": { - "method": "GET", + "method": "POST", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_member}}" + "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}}/work-period-payments/{{workPeriodPaymentId}}", + "raw": "{{URL}}/taas-teams/:id/members", "host": [ "{{URL}}" ], "path": [ - "work-period-payments", - "{{workPeriodPaymentId}}" + "taas-teams", + ":id", + "members" + ], + "variable": [ + { + "key": "id", + "value": "16705" + } ] } }, "response": [] }, { - "name": "search work period payments 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" - } - } - ], + "name": "GET /taas-teams/:id/members", "request": { "method": "GET", "header": [ @@ -14494,51 +19598,37 @@ "key": "Authorization", "type": "text", "value": "Bearer {{token_bookingManager}}" + }, + { + "key": "Content-Type", + "type": "text", + "value": "application/json" } ], "url": { - "raw": "{{URL}}/work-period-payments", + "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": [ - "work-period-payments" + "taas-teams", + ":id", + "members" ], "query": [ { - "key": "page", - "value": "1", - "disabled": true - }, - { - "key": "perPage", - "value": "50", - "disabled": true - }, - { - "key": "sortBy", - "value": "status", - "disabled": true - }, - { - "key": "sortOrder", - "value": "desc", - "disabled": true - }, - { - "key": "workPeriodId", - "value": "{{workPeriodId}}", - "disabled": true - }, - { - "key": "workPeriodIds", - "value": "{{workPeriodId}},{{workPeriodIdCreatedByM2M}}", - "disabled": true + "key": "role", + "value": "customer" }, { - "key": "status", - "value": "completed", - "disabled": true + "key": "fields", + "value": "id,userId,role,createdAt,updatedAt,createdBy,updatedBy,handle,photoURL,workingHourStart,workingHourEnd,timeZone,email" + } + ], + "variable": [ + { + "key": "id", + "value": "16705" } ] } @@ -14546,72 +19636,41 @@ "response": [] }, { - "name": "search work period payments 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" - } - } - ], + "name": "GET /taas-teams/:id/invites", "request": { "method": "GET", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_m2m_all_work_period_payment}}" + "value": "Bearer {{token_bookingManager}}" + }, + { + "key": "Content-Type", + "type": "text", + "value": "application/json" } ], "url": { - "raw": "{{URL}}/work-period-payments", + "raw": "{{URL}}/taas-teams/:id/invites?fields=createdAt,deletedAt,role,updatedBy,createdBy,id,projectId,userId,email,deletedBy,updatedAt,status", "host": [ "{{URL}}" ], "path": [ - "work-period-payments" + "taas-teams", + ":id", + "invites" ], "query": [ { - "key": "page", - "value": "1", - "disabled": true - }, - { - "key": "perPage", - "value": "50", - "disabled": true - }, - { - "key": "sortBy", - "value": "status", - "disabled": true - }, - { - "key": "sortOrder", - "value": "desc", - "disabled": true - }, - { - "key": "workPeriodId", - "value": "{{workPeriodId}}", - "disabled": true - }, - { - "key": "workPeriodIds", - "value": "{{workPeriodId}},{{workPeriodIdCreatedByM2M}}", - "disabled": true - }, + "key": "fields", + "value": "createdAt,deletedAt,role,updatedBy,createdBy,id,projectId,userId,email,deletedBy,updatedAt,status" + } + ], + "variable": [ { - "key": "status", - "value": "completed", - "disabled": true + "key": "id", + "value": "16705" } ] } @@ -14619,74 +19678,40 @@ "response": [] }, { - "name": "search work period payments 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" - } - } - ], + "name": "DELETE /taas-teams/:id/members/:projectMemberId", "request": { - "method": "GET", + "method": "DELETE", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_connectUser}}" + "value": "Bearer {{token_bookingManager}}" + }, + { + "key": "Content-Type", + "type": "text", + "value": "application/json" } ], "url": { - "raw": "{{URL}}/work-period-payments", + "raw": "{{URL}}/taas-teams/:id/members/:projectMemberId", "host": [ "{{URL}}" ], "path": [ - "work-period-payments" + "taas-teams", + ":id", + "members", + ":projectMemberId" ], - "query": [ - { - "key": "page", - "value": "1", - "disabled": true - }, - { - "key": "perPage", - "value": "50", - "disabled": true - }, - { - "key": "sortBy", - "value": "status", - "disabled": true - }, - { - "key": "sortOrder", - "value": "desc", - "disabled": true - }, - { - "key": "workPeriodId", - "value": "{{workPeriodId}}", - "disabled": true - }, + "variable": [ { - "key": "workPeriodIds", - "value": "{{workPeriodId}},{{workPeriodIdCreatedByM2M}}", - "disabled": true + "key": "id", + "value": "16705" }, { - "key": "status", - "value": "completed", - "disabled": true + "key": "projectMemberId", + "value": "14327" } ] } @@ -14694,22 +19719,7 @@ "response": [] }, { - "name": "search work period payments 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": "GET /taas-teams/me", "request": { "method": "GET", "header": [ @@ -14720,1961 +19730,2981 @@ } ], "url": { - "raw": "{{URL}}/work-period-payments", + "raw": "{{URL}}/taas-teams/me", "host": [ "{{URL}}" ], "path": [ - "work-period-payments" - ], - "query": [ - { - "key": "page", - "value": "1", - "disabled": true - }, + "taas-teams", + "me" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "Roles", + "item": [ + { + "name": "Create Role", + "item": [ + { + "name": "create role with admin", + "event": [ { - "key": "perPage", - "value": "50", - "disabled": true + "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(\"roleId-1\", response.id);\r", + " }\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Dropwizard\",\n \"NGINX\",\n \"Machine Learning\",\n \"Force.com\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10,\n \"rate30Global\": 20,\n \"rate30InCountry\": 15,\n \"rate30OffShore\": 35,\n \"rate20Global\": 20,\n \"rate20InCountry\": 15,\n \"rate20OffShore\": 35\n },\n {\n \"global\": 25,\n \"inCountry\": 15,\n \"offShore\": 5,\n \"rate30Global\": 20,\n \"rate30InCountry\": 15,\n \"rate30OffShore\": 35,\n \"rate20Global\": 20,\n \"rate20InCountry\": 15,\n \"rate20OffShore\": 35\n }\n ],\n \"numberOfMembers\": 10,\n \"numberOfMembersAvailable\": 8,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } }, + "url": { + "raw": "{{URL}}/taas-roles", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles" + ] + } + }, + "response": [] + }, + { + "name": "create role with booking manager", + "event": [ { - "key": "sortBy", - "value": "status", - "disabled": true + "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(\"roleId-2\", response.id);\r", + " }\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_bookingManager}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Angular Developer\",\n \"description\": \"Angular is an open-source, client-side framework based on TypeScript and designed for building web applications.\",\n \"listOfSkills\": [\n \"Database\",\n \"Winforms\",\n \"User Interface (Ui)\",\n \"Photoshop\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10\n },\n {\n \"global\": 25,\n \"inCountry\": 15,\n \"offShore\": 5\n }\n ],\n \"numberOfMembers\": 10,\n \"numberOfMembersAvailable\": 8,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } }, + "url": { + "raw": "{{URL}}/taas-roles", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles" + ] + } + }, + "response": [] + }, + { + "name": "create role with m2m create", + "event": [ { - "key": "sortOrder", - "value": "desc", - "disabled": true + "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(\"roleId-3\", response.id);\r", + " }\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_m2m_create_role}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Salesforce Developer\",\n \"description\": \"A Salesforce developer is a programmer who builds Salesforce applications across various PaaS (Platform as a Service) platforms.\",\n \"listOfSkills\": [\n \"Docker\",\n \".NET\",\n \"appcelerator\",\n \"Flux\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10,\n \"rate30Global\": 20,\n \"rate30InCountry\": 15,\n \"rate30OffShore\": 35,\n \"rate20Global\": 20,\n \"rate20InCountry\": 15,\n \"rate20OffShore\": 35\n },\n {\n \"global\": 25,\n \"inCountry\": 15,\n \"offShore\": 5,\n \"rate30Global\": 20,\n \"rate30InCountry\": 15,\n \"rate30OffShore\": 35,\n \"rate20Global\": 20,\n \"rate20InCountry\": 15,\n \"rate20OffShore\": 35\n }\n ],\n \"numberOfMembers\": 10,\n \"numberOfMembersAvailable\": 6,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } }, + "url": { + "raw": "{{URL}}/taas-roles", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles" + ] + } + }, + "response": [] + }, + { + "name": "create role with connect user", + "event": [ { - "key": "workPeriodId", - "value": "{{workPeriodId}}", - "disabled": true + "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_connectUser}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Dropwizard\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10\n },\n {\n \"global\": 25,\n \"inCountry\": 15,\n \"offShore\": 5\n }\n ],\n \"numberOfMembers\": 10,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } }, + "url": { + "raw": "{{URL}}/taas-roles", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles" + ] + } + }, + "response": [] + }, + { + "name": "create role with member", + "event": [ { - "key": "workPeriodIds", - "value": "{{workPeriodId}},{{workPeriodIdCreatedByM2M}}", - "disabled": true + "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}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Dropwizard\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10\n },\n {\n \"global\": 25,\n \"inCountry\": 15,\n \"offShore\": 5\n }\n ],\n \"numberOfMembers\": 10,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } }, - { - "key": "status", - "value": "completed", - "disabled": true + "url": { + "raw": "{{URL}}/taas-roles", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles" + ] } - ] - } - }, - "response": [] - }, - { - "name": "search work period payments with invalid token", - "event": [ + }, + "response": [] + }, { - "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": "GET", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer invalid_token" - } - ], - "url": { - "raw": "{{URL}}/work-period-payments", - "host": [ - "{{URL}}" - ], - "path": [ - "work-period-payments" - ], - "query": [ + "name": "create role with invalid token", + "event": [ { - "key": "page", - "value": "1", - "disabled": true + "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": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer invalid_token" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Dropwizard\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10\n },\n {\n \"global\": 25,\n \"inCountry\": 15,\n \"offShore\": 5\n }\n ],\n \"numberOfMembers\": 10,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } }, + "url": { + "raw": "{{URL}}/taas-roles", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles" + ] + } + }, + "response": [] + }, + { + "name": "create role with existent name", + "event": [ { - "key": "perPage", - "value": "50", - "disabled": true + "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(\"Role: \\\"Dev Ops Engineer\\\" is already exists.\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Dropwizard\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10\n },\n {\n \"global\": 25,\n \"inCountry\": 15,\n \"offShore\": 5\n }\n ],\n \"numberOfMembers\": 10,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } }, + "url": { + "raw": "{{URL}}/taas-roles", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles" + ] + } + }, + "response": [] + }, + { + "name": "create role with missing parameter 1", + "event": [ { - "key": "sortBy", - "value": "status", - "disabled": true + "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(\"\\\"role.name\\\" is required\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Dropwizard\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10\n },\n {\n \"global\": 25,\n \"inCountry\": 15,\n \"offShore\": 5\n }\n ],\n \"numberOfMembers\": 10,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } }, + "url": { + "raw": "{{URL}}/taas-roles", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles" + ] + } + }, + "response": [] + }, + { + "name": "create role with missing parameter 2", + "event": [ { - "key": "sortOrder", - "value": "desc", - "disabled": true + "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(\"\\\"role.rates\\\" is required\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Dropwizard\"\n ],\n \"numberOfMembers\": 10,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } }, + "url": { + "raw": "{{URL}}/taas-roles", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles" + ] + } + }, + "response": [] + }, + { + "name": "create role with missing parameter 3", + "event": [ { - "key": "workPeriodId", - "value": "{{workPeriodId}}", - "disabled": true + "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(\"\\\"role.rates\\\" does not contain 1 required value(s)\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Dropwizard\"\n ],\n \"rates\": [\n\n ],\n \"numberOfMembers\": 10,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } }, + "url": { + "raw": "{{URL}}/taas-roles", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles" + ] + } + }, + "response": [] + }, + { + "name": "create role with missing parameter 4", + "event": [ { - "key": "workPeriodIds", - "value": "{{workPeriodId}},{{workPeriodIdCreatedByM2M}}", - "disabled": true + "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(\"\\\"role.rates[0].global\\\" is required\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Dropwizard\"\n ],\n \"rates\": [\n {\n \"inCountry\": 20,\n \"offShore\": 10\n }\n ],\n \"numberOfMembers\": 10,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } }, - { - "key": "status", - "value": "completed", - "disabled": true + "url": { + "raw": "{{URL}}/taas-roles", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles" + ] } - ] - } - }, - "response": [] - }, - { - "name": "put work period payment with boooking manager", - "event": [ + }, + "response": [] + }, { - "listen": "test", - "script": { - "exec": [ - "pm.test('Status code is 200', function () {\r", - " pm.response.to.have.status(200);\r", - "});" + "name": "create role with missing 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(\"\\\"role.rates[0].inCountry\\\" is required\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "PUT", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"workPeriodId\": \"{{workPeriodId}}\",\r\n \"amount\": 1600,\r\n \"status\": \"completed\"\r\n}", - "options": { - "raw": { - "language": "json" + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Dropwizard\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"offShore\": 10\n }\n ],\n \"numberOfMembers\": 10,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-roles", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles" + ] + } + }, + "response": [] + }, + { + "name": "create role with missing 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(\"\\\"role.rates[0].offShore\\\" is required\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Dropwizard\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20\n }\n ],\n \"numberOfMembers\": 10,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-roles", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId}}", - "host": [ - "{{URL}}" - ], - "path": [ - "work-period-payments", - "{{workPeriodPaymentId}}" - ] - } - }, - "response": [] - }, - { - "name": "put work period payment with m2m create", - "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_payment}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"workPeriodId\": \"{{workPeriodIdCreatedByM2M}}\",\r\n \"amount\": 1600,\r\n \"status\": \"completed\"\r\n}", - "options": { - "raw": { - "language": "json" + "name": "create role 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(\"\\\"role.name\\\" length must be less than or equal to 50 characters long\")\r", + "});" + ], + "type": "text/javascript" + } } - } - }, - "url": { - "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentIdCreatedByM2M}}", - "host": [ - "{{URL}}" ], - "path": [ - "work-period-payments", - "{{workPeriodPaymentIdCreatedByM2M}}" - ] - } - }, - "response": [] - }, - { - "name": "put work period payment 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", - "});" + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "PUT", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_connectUser}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"workPeriodId\": \"{{workPeriodId}}\",\r\n \"amount\": 600,\r\n \"status\": \"completed\"\r\n}", - "options": { - "raw": { - "language": "json" + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Dev Ops Engineer Dev Ops Engineer Dev Ops Engineer Dev Ops Engineer Dev Ops Engineer Dev Ops Engineer Dev Ops Engineer Dev Ops Engineer Dev Ops Engineer Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Dropwizard\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10\n }\n ],\n \"numberOfMembers\": 10,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-roles", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId}}", - "host": [ - "{{URL}}" - ], - "path": [ - "work-period-payments", - "{{workPeriodPaymentId}}" - ] - } - }, - "response": [] - }, - { - "name": "put work period payment 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", - "});" + "name": "create role 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(\"\\\"role.listOfSkills[0]\\\" length must be less than or equal to 50 characters long\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "PUT", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_member}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"workPeriodId\": \"{{workPeriodId}}\",\r\n \"amount\": 600,\r\n \"status\": \"completed\"\r\n}", - "options": { - "raw": { - "language": "json" + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Dropwizard Dropwizard Dropwizard Dropwizard Dropwizard Dropwizard Dropwizard Dropwizard Dropwizard Dropwizard Dropwizard Dropwizard Dropwizard Dropwizard Dropwizard Dropwizard\",\n \"Dropwizard\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10\n }\n ],\n \"numberOfMembers\": 10,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-roles", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId}}", - "host": [ - "{{URL}}" + { + "name": "create role 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(\"\\\"role.listOfSkills\\\" must be an array\")\r", + "});" + ], + "type": "text/javascript" + } + } ], - "path": [ - "work-period-payments", - "{{workPeriodPaymentId}}" - ] - } - }, - "response": [] - }, - { - "name": "put work period payment with user id not exist", - "event": [ + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\":\"Dropwizard\",\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10\n }\n ],\n \"numberOfMembers\": 10,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-roles", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles" + ] + } + }, + "response": [] + }, { - "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", - "});" + "name": "create role 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(\"\\\"role.rates\\\" must be an array\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "PUT", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_userId_not_exist}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"workPeriodId\": \"{{workPeriodId}}\",\r\n \"amount\": 600,\r\n \"status\": \"completed\"\r\n}", - "options": { - "raw": { - "language": "json" + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Dropwizard\"\n ],\n \"rates\": {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10\n },\n \"numberOfMembers\": 10,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-roles", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId}}", - "host": [ - "{{URL}}" - ], - "path": [ - "work-period-payments", - "{{workPeriodPaymentId}}" - ] - } - }, - "response": [] - }, - { - "name": "put work period payment 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", - "});" + "name": "create role 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(\"\\\"role.rates[0].global\\\" must be a number\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "PUT", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer invalid_token" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"workPeriodId\": \"{{workPeriodId}}\",\r\n \"amount\": 600,\r\n \"status\": \"completed\"\r\n}", - "options": { - "raw": { - "language": "json" + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Dropwizard\"\n ],\n \"rates\": [\n {\n \"global\": \"first\",\n \"inCountry\": 20,\n \"offShore\": 10\n }\n ],\n \"numberOfMembers\": 10,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-roles", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId}}", - "host": [ - "{{URL}}" - ], - "path": [ - "work-period-payments", - "{{workPeriodPaymentId}}" - ] - } - }, - "response": [] - }, - { - "name": "put work period payment with missing workPeriodId", - "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.workPeriodId\\\" is required\")\r", - "});" + "name": "create role 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(\"\\\"role.rates[0].inCountry\\\" must be a number\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "PUT", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"amount\": 600,\r\n \"status\": \"completed\"\r\n}", - "options": { - "raw": { - "language": "json" + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Dropwizard\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": \"fifty\",\n \"offShore\": 10\n }\n ],\n \"numberOfMembers\": 10,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-roles", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId}}", - "host": [ - "{{URL}}" - ], - "path": [ - "work-period-payments", - "{{workPeriodPaymentId}}" - ] - } - }, - "response": [] - }, - { - "name": "put work period payment with invalid workPeriodId 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.workPeriodId\\\" must be a valid GUID\")\r", - "});" + "name": "create role 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(\"\\\"role.numberOfMembers\\\" must be a number\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "PUT", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"workPeriodId\": \"aaa-bb-c\",\r\n \"amount\": 600,\r\n \"status\": \"completed\"\r\n}", - "options": { - "raw": { - "language": "json" + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Dropwizard\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10\n }\n ],\n \"numberOfMembers\": null,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-roles", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId}}", - "host": [ - "{{URL}}" - ], - "path": [ - "work-period-payments", - "{{workPeriodPaymentId}}" - ] - } - }, - "response": [] - }, - { - "name": "put work period payment with invalid workPeriodId 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.workPeriodId\\\" must be a string\")\r", - "});" + "name": "create role with invalid parameter 8", + "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(\"\\\"role.imageUrl\\\" must be a valid uri\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "PUT", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"workPeriodId\": 123,\r\n \"amount\": 600,\r\n \"status\": \"completed\"\r\n}", - "options": { - "raw": { - "language": "json" + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Dropwizard\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10\n }\n ],\n \"numberOfMembers\": 55,\n \"imageUrl\": \"http://\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-roles", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId}}", - "host": [ - "{{URL}}" - ], - "path": [ - "work-period-payments", - "{{workPeriodPaymentId}}" - ] - } - }, - "response": [] - }, - { - "name": "put work period payment with invalid amount 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.amount\\\" must be a number\")\r", - "});" + "name": "create role with invalid parameter 9", + "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(\"\\\"role.timeToCandidate\\\" must be less than or equal to 32767\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "PUT", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"workPeriodId\": \"{{workPeriodId}}\",\r\n \"amount\": \"abc\",\r\n \"status\": \"completed\"\r\n}", - "options": { - "raw": { - "language": "json" + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Dropwizard\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10\n }\n ],\n \"numberOfMembers\": 55,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 99999,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-roles", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId}}", - "host": [ - "{{URL}}" - ], - "path": [ - "work-period-payments", - "{{workPeriodPaymentId}}" - ] - } - }, - "response": [] - }, - { - "name": "put work period payment with invalid amount 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.amount\\\" must be greater than 0\")\r", - "});" + "name": "create role with invalid parameter 10", + "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(\"skills: \\\"teamworking,communication,problem-solving\\\" are not valid\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "PUT", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"workPeriodId\": \"{{workPeriodId}}\",\r\n \"amount\": 0,\r\n \"status\": \"completed\"\r\n}", - "options": { - "raw": { - "language": "json" + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Dev Ops Engineer 2\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Teamworking\",\n \"Communication\",\n \"Problem-Solving\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10\n }\n ],\n \"numberOfMembers\": 55,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 55,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-roles", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles" + ] } - } - }, - "url": { - "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId}}", - "host": [ - "{{URL}}" - ], - "path": [ - "work-period-payments", - "{{workPeriodPaymentId}}" - ] + }, + "response": [] } - }, - "response": [] + ] }, { - "name": "put work period payment with invalid status 1", - "event": [ + "name": "Get Role", + "item": [ { - "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.status\\\" must be one of [completed, cancelled]\")\r", - "});" + "name": "get role with admin", + "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_administrator}}" + } ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "PUT", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"workPeriodId\": \"{{workPeriodId}}\",\r\n \"amount\": 1200,\r\n \"status\": 123\r\n}", - "options": { - "raw": { - "language": "json" + "url": { + "raw": "{{URL}}/taas-roles/{{roleId-1}}", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles", + "{{roleId-1}}" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId}}", - "host": [ - "{{URL}}" - ], - "path": [ - "work-period-payments", - "{{workPeriodPaymentId}}" - ] - } - }, - "response": [] - }, - { - "name": "put work period payment with invalid status 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.status\\\" must be one of [completed, cancelled]\")\r", - "});" + "name": "get role with booking manager fromDb", + "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}}" + } ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "PUT", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"workPeriodId\": \"{{workPeriodId}}\",\r\n \"amount\": 1200,\r\n \"status\": \"invalid-status\"\r\n}", - "options": { - "raw": { - "language": "json" + "url": { + "raw": "{{URL}}/taas-roles/{{roleId-2}}?fromDb=true", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles", + "{{roleId-2}}" + ], + "query": [ + { + "key": "fromDb", + "value": "true" + } + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId}}", - "host": [ - "{{URL}}" + { + "name": "get role 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" + } + } ], - "path": [ - "work-period-payments", - "{{workPeriodPaymentId}}" - ] - } - }, - "response": [] - }, - { - "name": "patch work period payment with boooking manager", - "event": [ + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_m2m_read_role}}" + } + ], + "url": { + "raw": "{{URL}}/taas-roles/{{roleId-3}}", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles", + "{{roleId-3}}" + ] + } + }, + "response": [] + }, { - "listen": "test", - "script": { - "exec": [ - "pm.test('Status code is 200', function () {\r", - " pm.response.to.have.status(200);\r", - "});" + "name": "get role with connect user fromDb", + "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}}" + } ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "PATCH", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"workPeriodId\": \"{{workPeriodId}}\",\r\n \"amount\": 450,\r\n \"status\": \"cancelled\"\r\n}", - "options": { - "raw": { - "language": "json" + "url": { + "raw": "{{URL}}/taas-roles/{{roleId-1}}?fromDb=true", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles", + "{{roleId-1}}" + ], + "query": [ + { + "key": "fromDb", + "value": "true" + } + ] + } + }, + "response": [] + }, + { + "name": "get role with member", + "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}}/work-period-payments/{{workPeriodPaymentId}}", - "host": [ - "{{URL}}" ], - "path": [ - "work-period-payments", - "{{workPeriodPaymentId}}" - ] - } - }, - "response": [] - }, - { - "name": "patch work period payment with m2m create", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test('Status code is 200', function () {\r", - " pm.response.to.have.status(200);\r", - "});" + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_member}}" + } ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "PATCH", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_m2m_update_work_period_payment}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"workPeriodId\": \"{{workPeriodIdCreatedByM2M}}\",\r\n \"amount\": 450,\r\n \"status\": \"cancelled\"\r\n}", - "options": { - "raw": { - "language": "json" + "url": { + "raw": "{{URL}}/taas-roles/{{roleId-2}}", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles", + "{{roleId-2}}" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentIdCreatedByM2M}}", - "host": [ - "{{URL}}" - ], - "path": [ - "work-period-payments", - "{{workPeriodPaymentIdCreatedByM2M}}" - ] - } - }, - "response": [] - }, - { - "name": "patch work period payment 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", - "});" + "name": "get role 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": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer invalid token" + } ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "PATCH", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_connectUser}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"workPeriodId\": \"{{workPeriodId}}\",\r\n \"amount\": 600,\r\n \"status\": \"completed\"\r\n}", - "options": { - "raw": { - "language": "json" + "url": { + "raw": "{{URL}}/taas-roles/{{roleId-2}}", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles", + "{{roleId-2}}" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId}}", - "host": [ - "{{URL}}" - ], - "path": [ - "work-period-payments", - "{{workPeriodPaymentId}}" - ] - } - }, - "response": [] - }, - { - "name": "patch work period payment 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", - "});" + "name": "get role with invalid id", + "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(\"\\\"id\\\" must be a valid GUID\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "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_member}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"workPeriodId\": \"{{workPeriodId}}\",\r\n \"amount\": 600,\r\n \"status\": \"completed\"\r\n}", - "options": { - "raw": { - "language": "json" + "url": { + "raw": "{{URL}}/taas-roles/invalid", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles", + "invalid" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId}}", - "host": [ - "{{URL}}" - ], - "path": [ - "work-period-payments", - "{{workPeriodPaymentId}}" - ] - } - }, - "response": [] - }, - { - "name": "patch work period payment 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 \"workPeriodId\": \"{{workPeriodId}}\",\r\n \"amount\": 600,\r\n \"status\": \"completed\"\r\n}", - "options": { - "raw": { - "language": "json" + "name": "get role with missing id", + "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(\"id: 00000000-0000-0000-0000-000000000000 \\\"Role\\\" not found\")\r", + "});" + ], + "type": "text/javascript" + } } - } - }, - "url": { - "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId}}", - "host": [ - "{{URL}}" ], - "path": [ - "work-period-payments", - "{{workPeriodPaymentId}}" - ] - } - }, - "response": [] - }, - { - "name": "patch work period payment 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", - "});" + "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 invalid_token" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"workPeriodId\": \"{{workPeriodId}}\",\r\n \"amount\": 600,\r\n \"status\": \"completed\"\r\n}", - "options": { - "raw": { - "language": "json" + "url": { + "raw": "{{URL}}/taas-roles/00000000-0000-0000-0000-000000000000", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles", + "00000000-0000-0000-0000-000000000000" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId}}", - "host": [ - "{{URL}}" - ], - "path": [ - "work-period-payments", - "{{workPeriodPaymentId}}" - ] - } - }, - "response": [] - }, - { - "name": "patch work period payment with invalid workPeriodId 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.workPeriodId\\\" must be a valid GUID\")\r", - "});" + "name": "search roles with admin", + "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_administrator}}" + } ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "PATCH", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"workPeriodId\": \"aaa-bb-c\",\r\n \"amount\": 600,\r\n \"status\": \"completed\"\r\n}", - "options": { - "raw": { - "language": "json" + "url": { + "raw": "{{URL}}/taas-roles", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId}}", - "host": [ - "{{URL}}" - ], - "path": [ - "work-period-payments", - "{{workPeriodPaymentId}}" - ] - } - }, - "response": [] - }, - { - "name": "patch work period payment with invalid workPeriodId 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.workPeriodId\\\" must be a string\")\r", - "});" + "name": "search roles 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}}" + } ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "PATCH", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"workPeriodId\": 123,\r\n \"amount\": 600,\r\n \"status\": \"completed\"\r\n}", - "options": { - "raw": { - "language": "json" + "url": { + "raw": "{{URL}}/taas-roles?skillsList=dropwizard, nginx,, machine learning , FORce.com &keyword=ops e", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles" + ], + "query": [ + { + "key": "skillsList", + "value": "dropwizard, nginx,, machine learning , FORce.com " + }, + { + "key": "keyword", + "value": "ops e" + } + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId}}", - "host": [ - "{{URL}}" - ], - "path": [ - "work-period-payments", - "{{workPeriodPaymentId}}" - ] - } - }, - "response": [] - }, - { - "name": "patch work period payment with invalid amount 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.amount\\\" 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 \"workPeriodId\": \"{{workPeriodId}}\",\r\n \"amount\": \"abc\",\r\n \"status\": \"completed\"\r\n}", - "options": { - "raw": { - "language": "json" + "name": "search roles 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" + } } - } - }, - "url": { - "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId}}", - "host": [ - "{{URL}}" ], - "path": [ - "work-period-payments", - "{{workPeriodPaymentId}}" - ] - } - }, - "response": [] - }, - { - "name": "patch work period payment with invalid amount 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.amount\\\" must be greater than 0\")\r", - "});" + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_connectUser}}" + } ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "PATCH", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"workPeriodId\": \"{{workPeriodId}}\",\r\n \"amount\": 0,\r\n \"status\": \"completed\"\r\n}", - "options": { - "raw": { - "language": "json" + "url": { + "raw": "{{URL}}/taas-roles?skillsList=dataBase, ,Photoshop&keyword=sale", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles" + ], + "query": [ + { + "key": "skillsList", + "value": "dataBase, ,Photoshop" + }, + { + "key": "keyword", + "value": "sale" + } + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId}}", - "host": [ - "{{URL}}" - ], - "path": [ - "work-period-payments", - "{{workPeriodPaymentId}}" - ] - } - }, - "response": [] - }, - { - "name": "patch work period payment with invalid status 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.status\\\" must be one of [completed, cancelled]\")\r", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "PATCH", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"workPeriodId\": \"{{workPeriodId}}\",\r\n \"amount\": 1200,\r\n \"status\": 123\r\n}", - "options": { - "raw": { - "language": "json" + "name": "search roles 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" + } } - } - }, - "url": { - "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId}}", - "host": [ - "{{URL}}" ], - "path": [ - "work-period-payments", - "{{workPeriodPaymentId}}" - ] - } - }, - "response": [] - }, - { - "name": "patch work period payment with invalid status 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.status\\\" must be one of [completed, cancelled]\")\r", - "});" + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_m2m_read_role}}" + } ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "PATCH", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_bookingManager}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"workPeriodId\": \"{{workPeriodId}}\",\r\n \"amount\": 1200,\r\n \"status\": \"invalid-status\"\r\n}", - "options": { - "raw": { - "language": "json" + "url": { + "raw": "{{URL}}/taas-roles?skillsList=DOCKER,.NET&keyword=dev", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles" + ], + "query": [ + { + "key": "skillsList", + "value": "DOCKER,.NET" + }, + { + "key": "keyword", + "value": "dev" + } + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId}}", - "host": [ - "{{URL}}" - ], - "path": [ - "work-period-payments", - "{{workPeriodPaymentId}}" - ] - } - }, - "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" - }, + { + "name": "search roles with member", + "event": [ { - "key": "sortBy", - "value": "lastActivityAt", - "description": "allows: createdAt, updatedAt, lastActivityAt, id, status, name, type, best match" - }, + "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_member}}" + } + ], + "url": { + "raw": "{{URL}}/taas-roles?keyword=dev", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles" + ], + "query": [ + { + "key": "keyword", + "value": "dev" + } + ] + } + }, + "response": [] + }, + { + "name": "search roles with invalid token", + "event": [ { - "key": "sortOrder", - "value": "desc", - "description": "allows: asc, desc" + "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": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer invalid token" + } + ], + "url": { + "raw": "{{URL}}/taas-roles", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles" + ] + } + }, + "response": [] } - }, - "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" + "name": "Update Role", + "item": [ + { + "name": "update role with admin", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", + "});" + ], + "type": "text/javascript" + } + } ], - "query": [ + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Dev Ops Engineer edit\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Dropwizard\",\n \"NGINX\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10\n },\n {\n \"global\": 25,\n \"inCountry\": 15,\n \"offShore\": 5\n }\n ],\n \"numberOfMembers\": 10,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-roles/{{roleId-1}}", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles", + "{{roleId-1}}" + ] + } + }, + "response": [] + }, + { + "name": "update role with booking manager", + "event": [ { - "key": "perPage", - "value": "10" + "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": "{\n \"name\": \"Angular Developer edit\",\n \"description\": \"Angular is an open-source, client-side framework based on TypeScript and designed for building web applications.\",\n \"listOfSkills\": [\n \"Database\",\n \"Winforms\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10\n },\n {\n \"global\": 25,\n \"inCountry\": 15,\n \"offShore\": 5\n }\n ],\n \"numberOfMembers\": 10,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } }, + "url": { + "raw": "{{URL}}/taas-roles/{{roleId-2}}", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles", + "{{roleId-2}}" + ] + } + }, + "response": [] + }, + { + "name": "update role with m2m update", + "event": [ { - "key": "page", - "value": "1" + "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_role}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Salesforce Developer edit\",\n \"description\": \"A Salesforce developer is a programmer who builds Salesforce applications across various PaaS (Platform as a Service) platforms.\",\n \"listOfSkills\": [\n \"Docker\",\n \".NET\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10\n },\n {\n \"global\": 25,\n \"inCountry\": 15,\n \"offShore\": 5\n }\n ],\n \"numberOfMembers\": 10,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } }, + "url": { + "raw": "{{URL}}/taas-roles/{{roleId-3}}", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles", + "{{roleId-3}}" + ] + } + }, + "response": [] + }, + { + "name": "update role with member", + "event": [ { - "key": "name", - "value": "*taas*", - "description": "case-insensitive; support wildcard match" + "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": "{\n \"name\": \"Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Docker\",\n \".NET\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10\n },\n {\n \"global\": 25,\n \"inCountry\": 15,\n \"offShore\": 5\n }\n ],\n \"numberOfMembers\": 10,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } }, + "url": { + "raw": "{{URL}}/taas-roles/{{roleId-1}}", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles", + "{{roleId-1}}" + ] + } + }, + "response": [] + }, + { + "name": "update role with connect user", + "event": [ { - "key": "sortBy", - "value": "lastActivityAt", - "description": "allows: createdAt, updatedAt, lastActivityAt, id, status, name, type, best match" + "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": "{\n \"name\": \"Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Docker\",\n \".NET\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10\n },\n {\n \"global\": 25,\n \"inCountry\": 15,\n \"offShore\": 5\n }\n ],\n \"numberOfMembers\": 10,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } }, + "url": { + "raw": "{{URL}}/taas-roles/{{roleId-1}}", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles", + "{{roleId-1}}" + ] + } + }, + "response": [] + }, + { + "name": "update role with invalid token", + "event": [ { - "key": "sortOrder", - "value": "desc", - "description": "allows: asc, desc" + "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" + } } - ] - } - }, - "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": [ + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer invalid_token" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Docker\",\n \".NET\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10\n },\n {\n \"global\": 25,\n \"inCountry\": 15,\n \"offShore\": 5\n }\n ],\n \"numberOfMembers\": 10,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-roles/{{roleId-1}}", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles", + "{{roleId-1}}" + ] + } + }, + "response": [] + }, + { + "name": "update role with invalid id", + "event": [ { - "key": "projectId", - "value": "16705" + "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(\"\\\"id\\\" must be a valid GUID\")\r", + "});" + ], + "type": "text/javascript" + } } - ] - } - }, - "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}}" + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Docker\",\n \".NET\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10\n },\n {\n \"global\": 25,\n \"inCountry\": 15,\n \"offShore\": 5\n }\n ],\n \"numberOfMembers\": 10,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-roles/invalid", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles", + "invalid" + ] + } + }, + "response": [] + }, + { + "name": "update role with missing id", + "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(\"id: 00000000-0000-0000-0000-000000000000 \\\"Role\\\" doesn't exists.\")\r", + "});" + ], + "type": "text/javascript" + } + } ], - "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}}" + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Docker\",\n \".NET\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10\n },\n {\n \"global\": 25,\n \"inCountry\": 15,\n \"offShore\": 5\n }\n ],\n \"numberOfMembers\": 10,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-roles/00000000-0000-0000-0000-000000000000", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles", + "00000000-0000-0000-0000-000000000000" + ] + } + }, + "response": [] + }, + { + "name": "update role with existent name", + "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(\"Role: \\\"Angular Developer edit\\\" is already exists.\")\r", + "});" + ], + "type": "text/javascript" + } + } ], - "path": [ - "taas-teams", - ":projectId", - "jobs", - ":jobId" + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Angular Developer edit\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-roles/{{roleId-1}}", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles", + "{{roleId-1}}" + ] + } + }, + "response": [] + }, + { + "name": "update role 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.name\\\" length must be less than or equal to 50 characters long\")\r", + "});" + ], + "type": "text/javascript" + } + } ], - "variable": [ + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Dev Ops Engineer Dev Ops Engineer Dev Ops Engineer Dev Ops Engineer Dev Ops Engineer Dev Ops Engineer Dev Ops Engineer Dev Ops Engineer Dev Ops Engineer Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Docker\",\n \".NET\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10\n }\n ],\n \"numberOfMembers\": 10,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-roles/{{roleId-1}}", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles", + "{{roleId-1}}" + ] + } + }, + "response": [] + }, + { + "name": "update role with invalid parameter 2", + "event": [ { - "key": "projectId", - "value": "16705" + "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.listOfSkills[0]\\\" length must be less than or equal to 50 characters long\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Teamworking Teamworking Teamworking Teamworking Teamworking Teamworking Teamworking Teamworking Teamworking Teamworking Teamworking Teamworking Teamworking\",\n \"Docker\",\n \".NET\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10\n }\n ],\n \"numberOfMembers\": 10,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } }, + "url": { + "raw": "{{URL}}/taas-roles/{{roleId-1}}", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles", + "{{roleId-1}}" + ] + } + }, + "response": [] + }, + { + "name": "update role with invalid parameter 3", + "event": [ { - "key": "jobId", - "value": "948a25a6-086f-4a96-aad5-9ccd2d3e87b2" + "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.listOfSkills\\\" must be an array\")\r", + "});" + ], + "type": "text/javascript" + } } - ] - } - }, - "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}}" + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\":\"Teamworking\",\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10\n }\n ],\n \"numberOfMembers\": 10,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-roles/{{roleId-1}}", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles", + "{{roleId-1}}" + ] + } + }, + "response": [] + }, + { + "name": "update role 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(\"\\\"data.rates\\\" must be an array\")\r", + "});" + ], + "type": "text/javascript" + } + } ], - "path": [ - "taas-teams", - "skills" + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Docker\",\n \".NET\"\n ],\n \"rates\": {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10\n },\n \"numberOfMembers\": 10,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-roles/{{roleId-1}}", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles", + "{{roleId-1}}" + ] + } + }, + "response": [] + }, + { + "name": "update role 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.rates[0].global\\\" must be a number\")\r", + "});" + ], + "type": "text/javascript" + } + } ], - "query": [ - { - "key": "perPage", - "value": "10" + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Docker\",\n \".NET\"\n ],\n \"rates\": [\n {\n \"global\": \"first\",\n \"inCountry\": 20,\n \"offShore\": 10\n }\n ],\n \"numberOfMembers\": 10,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } }, + "url": { + "raw": "{{URL}}/taas-roles/{{roleId-1}}", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles", + "{{roleId-1}}" + ] + } + }, + "response": [] + }, + { + "name": "update role with invalid parameter 6", + "event": [ { - "key": "page", - "value": "1" + "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.rates[0].inCountry\\\" must be a number\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Docker\",\n \".NET\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": \"fifty\",\n \"offShore\": 10\n }\n ],\n \"numberOfMembers\": 10,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } }, - { - "key": "orderBy", - "value": "name", - "description": "possible values are defined by /v5/skills" + "url": { + "raw": "{{URL}}/taas-roles/{{roleId-1}}", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles", + "{{roleId-1}}" + ] } - ] - } - }, - "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" - } - } + "response": [] }, - "url": { - "raw": "{{URL}}/taas-teams/email", - "host": [ - "{{URL}}" + { + "name": "update role 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.numberOfMembers\\\" must be a number\")\r", + "});" + ], + "type": "text/javascript" + } + } ], - "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" + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Docker\",\n \".NET\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10\n }\n ],\n \"numberOfMembers\": \"hundred\",\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-roles/{{roleId-1}}", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles", + "{{roleId-1}}" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/taas-teams/email", - "host": [ - "{{URL}}" + { + "name": "update role with invalid parameter 8", + "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.imageUrl\\\" must be a valid uri\")\r", + "});" + ], + "type": "text/javascript" + } + } ], - "path": [ - "taas-teams", - "email" - ] - } - }, - "response": [] - }, - { - "name": "POST /taas-teams/email - extension-request", - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_member}}" + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Docker\",\n \".NET\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10\n }\n ],\n \"numberOfMembers\": 55,\n \"imageUrl\": \"http://\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-roles/{{roleId-1}}", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles", + "{{roleId-1}}" + ] + } }, - { - "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" + "response": [] + }, + { + "name": "update role with invalid parameter 9", + "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.timeToCandidate\\\" must be less than or equal to 32767\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Docker\",\n \".NET\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10\n }\n ],\n \"numberOfMembers\": 55,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 99999,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-roles/{{roleId-1}}", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles", + "{{roleId-1}}" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{URL}}/taas-teams/email", - "host": [ - "{{URL}}" + { + "name": "update role with invalid parameter 10", + "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(\"skills: \\\"teamworking\\\" are not valid\")\r", + "});" + ], + "type": "text/javascript" + } + } ], - "path": [ - "taas-teams", - "email" - ] + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Teamworking\",\n \".NET\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10\n }\n ],\n \"numberOfMembers\": 55,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 66,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-roles/{{roleId-1}}", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles", + "{{roleId-1}}" + ] + } + }, + "response": [] } - }, - "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" + "name": "Delete Role", + "item": [ + { + "name": "delete role 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" + } } - } - }, - "url": { - "raw": "{{URL}}/taas-teams/:id/members", - "host": [ - "{{URL}}" ], - "path": [ - "taas-teams", - ":id", - "members" - ], - "variable": [ - { - "key": "id", - "value": "16705" + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_connectUser}}" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-roles/{{roleId-1}}", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles", + "{{roleId-1}}" + ] } - ] - } - }, - "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}}" + "response": [] + }, + { + "name": "delete role 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" + } + } ], - "path": [ - "taas-teams", - ":id", - "members" + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_member}}" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-roles/{{roleId-1}}", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles", + "{{roleId-1}}" + ] + } + }, + "response": [] + }, + { + "name": "delete role 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" + } + } ], - "query": [ + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer invalid_token" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"teamworking\",\n \"communication\",\n \"problem-solving\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10\n },\n {\n \"global\": 25,\n \"inCountry\": 15,\n \"offShore\": 5\n }\n ],\n \"numberOfMembers\": 10,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-roles/{{roleId-1}}", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles", + "{{roleId-1}}" + ] + } + }, + "response": [] + }, + { + "name": "delete role with invalid id", + "event": [ { - "key": "role", - "value": "customer" + "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(\"\\\"id\\\" must be a valid GUID\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } }, + "url": { + "raw": "{{URL}}/taas-roles/invalid", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles", + "invalid" + ] + } + }, + "response": [] + }, + { + "name": "delete role with missing id", + "event": [ { - "key": "fields", - "value": "id,userId,role,createdAt,updatedAt,createdBy,updatedBy,handle,photoURL,workingHourStart,workingHourEnd,timeZone,email" + "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(\"id: 00000000-0000-0000-0000-000000000000 \\\"Role\\\" doesn't exists.\")\r", + "});" + ], + "type": "text/javascript" + } } ], - "variable": [ - { - "key": "id", - "value": "16705" + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-roles/00000000-0000-0000-0000-000000000000", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles", + "00000000-0000-0000-0000-000000000000" + ] } - ] - } - }, - "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": [ + "response": [] + }, + { + "name": "delete role with admin", + "event": [ { - "key": "fields", - "value": "createdAt,deletedAt,role,updatedBy,createdBy,id,projectId,userId,email,deletedBy,updatedAt,status" + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 204', function () {\r", + " pm.response.to.have.status(204);\r", + "});" + ], + "type": "text/javascript" + } } ], - "variable": [ - { - "key": "id", - "value": "16705" + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-roles/{{roleId-1}}", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles", + "{{roleId-1}}" + ] } - ] - } - }, - "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": [ + "response": [] + }, + { + "name": "delete role with booking manager", + "event": [ { - "key": "id", - "value": "16705" + "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}}/taas-roles/{{roleId-2}}", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles", + "{{roleId-2}}" + ] + } + }, + "response": [] + }, + { + "name": "delete role with m2m delete", + "event": [ { - "key": "projectMemberId", - "value": "14327" + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 204', function () {\r", + " pm.response.to.have.status(204);\r", + "});" + ], + "type": "text/javascript" + } } - ] - } - }, - "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" - ] + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_m2m_delete_role}}" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/taas-roles/{{roleId-3}}", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles", + "{{roleId-3}}" + ] + } + }, + "response": [] } - }, - "response": [] + ] } ] }, @@ -16807,7 +22837,7 @@ ], "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}", + "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 \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", "options": { "raw": { "language": "json" @@ -16861,7 +22891,7 @@ ], "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\": \"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 \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", "options": { "raw": { "language": "json" @@ -17511,7 +23541,7 @@ ], "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}", + "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 \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", "options": { "raw": { "language": "json" @@ -19148,7 +25178,7 @@ ], "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}", + "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 \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", "options": { "raw": { "language": "json" @@ -19248,7 +25278,7 @@ ], "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}", + "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 \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", "options": { "raw": { "language": "json" @@ -19324,17 +25354,284 @@ "name": "Request with Administrator Role", "item": [ { - "name": "Jobs", + "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 \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\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": [] + }, + { + "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 \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobs/{{job_id_created_by_administrator}}", + "host": [ + "{{URL}}" + ], + "path": [ + "jobs", + "{{job_id_created_by_administrator}}" + ] + } + }, + "response": [] + }, + { + "name": "✔ patch job with administrator", + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } + ], + "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 \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobs/{{job_id_created_by_administrator}}", + "host": [ + "{{URL}}" + ], + "path": [ + "jobs", + "{{job_id_created_by_administrator}}" + ] + } + }, + "response": [] + }, + { + "name": "✔ delete job with administrator", + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } + ], + "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}}" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "Job Candidates", "item": [ { - "name": "✔ create job with administrator", + "name": "✔ create job candidate with administrator", "event": [ { "listen": "test", "script": { "exec": [ "var data = JSON.parse(responseBody);\r", - "postman.setEnvironmentVariable(\"job_id_created_by_administrator\",data.id);" + "postman.setEnvironmentVariable(\"job_candidate_id_created_by_administrator\",data.id);" ], "type": "text/javascript" } @@ -19345,13 +25642,13 @@ "header": [ { "key": "Authorization", - "value": "Bearer {{token_administrator}}", - "type": "text" + "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\": \"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_administrator}}\",\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\"\r\n}", "options": { "raw": { "language": "json" @@ -19359,19 +25656,19 @@ } }, "url": { - "raw": "{{URL}}/jobs", + "raw": "{{URL}}/jobCandidates", "host": [ "{{URL}}" ], "path": [ - "jobs" + "jobCandidates" ] } }, "response": [] }, { - "name": "✔ get job with administrator", + "name": "✔ get job candidate with administrator", "request": { "method": "GET", "header": [ @@ -19382,20 +25679,20 @@ } ], "url": { - "raw": "{{URL}}/jobs/{{job_id_created_by_administrator}}", + "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_by_administrator}}", "host": [ "{{URL}}" ], "path": [ - "jobs", - "{{job_id_created_by_administrator}}" + "jobCandidates", + "{{job_candidate_id_created_by_administrator}}" ] } }, "response": [] }, { - "name": "✔ search jobs with administrator", + "name": "✔ search job candidates with administrator", "request": { "method": "GET", "header": [ @@ -19406,22 +25703,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 }, { @@ -19435,53 +25732,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": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", "disabled": true }, { "key": "status", - "value": "sourcing", - "disabled": true - }, - { - "key": "workload", - "value": "full-time", - "disabled": true - }, - { - "key": "title", - "value": "dummy", + "value": "selected", "disabled": true } ] @@ -19490,7 +25752,7 @@ "response": [] }, { - "name": "✔ put job with administrator", + "name": "✔ put job candidate with administrator", "request": { "method": "PUT", "header": [ @@ -19502,7 +25764,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\": \"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_administrator}}\",\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"status\": \"placed\",\r\n \"remark\": \"excellent\"\r\n}", "options": { "raw": { "language": "json" @@ -19510,20 +25772,20 @@ } }, "url": { - "raw": "{{URL}}/jobs/{{job_id_created_by_administrator}}", + "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_by_administrator}}", "host": [ "{{URL}}" ], "path": [ - "jobs", - "{{job_id_created_by_administrator}}" + "jobCandidates", + "{{job_candidate_id_created_by_administrator}}" ] } }, "response": [] }, { - "name": "✔ patch job with administrator", + "name": "✔ patch job candidate with administrator", "request": { "method": "PATCH", "header": [ @@ -19535,7 +25797,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\": \"selected\"\r\n}", "options": { "raw": { "language": "json" @@ -19543,20 +25805,20 @@ } }, "url": { - "raw": "{{URL}}/jobs/{{job_id_created_by_administrator}}", + "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_by_administrator}}", "host": [ "{{URL}}" ], "path": [ - "jobs", - "{{job_id_created_by_administrator}}" + "jobCandidates", + "{{job_candidate_id_created_by_administrator}}" ] } }, "response": [] }, { - "name": "✔ delete job with administrator", + "name": "✔ delete job candidate with administrator", "request": { "method": "DELETE", "header": [ @@ -19576,13 +25838,13 @@ } }, "url": { - "raw": "{{URL}}/jobs/{{job_id_created_by_administrator}}", + "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_by_administrator}}", "host": [ "{{URL}}" ], "path": [ - "jobs", - "{{job_id_created_by_administrator}}" + "jobCandidates", + "{{job_candidate_id_created_by_administrator}}" ] } }, @@ -19591,34 +25853,133 @@ ] }, { - "name": "Job Candidates", + "name": "Interviews", "item": [ { - "name": "✔ create job candidate with administrator", + "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-27\",\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 \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\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": [] + } + ] + }, + { + "name": "✔ request interview with administrator", "event": [ { "listen": "test", "script": { "exec": [ - "var data = JSON.parse(responseBody);\r", - "postman.setEnvironmentVariable(\"job_candidate_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", + " pm.environment.set(\"interview_id_created_by_administrator\", response.id);\r", + " }\r", + "});" ], "type": "text/javascript" } } ], "request": { - "method": "POST", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_administrator}}" + "value": "Bearer {{token_administrator}}", + "type": "text" } ], "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 \"templateUrl\": \"interview-30\",\r\n \"hostEmail\": \"testcustomer@yopmail.com\",\r\n \"calendarEventId\": \"dummyId\",\r\n \"status\": \"Scheduling\"\r\n}", "options": { "raw": { "language": "json" @@ -19626,115 +25987,122 @@ } }, "url": { - "raw": "{{URL}}/jobCandidates", + "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_by_administrator}}/requestInterview", "host": [ "{{URL}}" ], "path": [ - "jobCandidates" + "jobCandidates", + "{{job_candidate_id_created_by_administrator}}", + "requestInterview" ] } }, "response": [] }, { - "name": "✔ get job candidate with administrator", + "name": "✔ get interview by round 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": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_administrator}}" + "value": "Bearer {{token_administrator}}", + "type": "text" } ], "url": { - "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_by_administrator}}", + "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_by_administrator}}/interviews/{{interview_round_created_by_administrator}}", "host": [ "{{URL}}" ], "path": [ "jobCandidates", - "{{job_candidate_id_created_by_administrator}}" + "{{job_candidate_id_created_by_administrator}}", + "interviews", + "{{interview_round_created_by_administrator}}" ] } }, "response": [] }, { - "name": "✔ search job candidates with administrator", + "name": "✔ get interview by id 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": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_administrator}}" + "value": "Bearer {{token_administrator}}", + "type": "text" } ], "url": { - "raw": "{{URL}}/jobCandidates", + "raw": "{{URL}}/getInterview/{{interview_id_created_by_administrator}}", "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": "selected", - "disabled": true - } + "getInterview", + "{{interview_id_created_by_administrator}}" ] } }, "response": [] }, { - "name": "✔ put job candidate with administrator", + "name": "✔ update interview by round 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", + "method": "PATCH", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_administrator}}" + "value": "Bearer {{token_administrator}}", + "type": "text" } ], "body": { "mode": "raw", - "raw": "{\r\n \"jobId\": \"{{job_id_created_by_administrator}}\",\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"status\": \"placed\"\r\n}", + "raw": "{\r\n \"calendarEventId\": \"updated\"\r\n}", "options": { "raw": { "language": "json" @@ -19742,32 +26110,47 @@ } }, "url": { - "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_by_administrator}}", + "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_by_administrator}}/updateInterview/{{interview_round_created_by_administrator}}", "host": [ "{{URL}}" ], "path": [ "jobCandidates", - "{{job_candidate_id_created_by_administrator}}" + "{{job_candidate_id_created_by_administrator}}", + "updateInterview", + "{{interview_round_created_by_administrator}}" ] } }, "response": [] }, { - "name": "✔ patch job candidate with administrator", + "name": "✔ update interview by id 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", - "type": "text", - "value": "Bearer {{token_administrator}}" + "value": "Bearer {{token_administrator}}", + "type": "text" } ], "body": { "mode": "raw", - "raw": "{\r\n \"status\": \"selected\"\r\n}", + "raw": "{\r\n \"xaiId\": \"0edc1751-f4ca-4e8e-908a-95f6560311ab\",\r\n \"calendarEventId\": \"updated\"\r\n}", "options": { "raw": { "language": "json" @@ -19775,46 +26158,51 @@ } }, "url": { - "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_by_administrator}}", + "raw": "{{URL}}/updateInterview/{{interview_id_created_by_administrator}}", "host": [ "{{URL}}" ], "path": [ - "jobCandidates", - "{{job_candidate_id_created_by_administrator}}" + "updateInterview", + "{{interview_id_created_by_administrator}}" ] } }, "response": [] }, { - "name": "✔ delete job candidate 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}}/jobCandidates/{{job_candidate_id_created_by_administrator}}", + "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_by_administrator}}/interviews", "host": [ "{{URL}}" ], "path": [ "jobCandidates", - "{{job_candidate_id_created_by_administrator}}" + "{{job_candidate_id_created_by_administrator}}", + "interviews" ] } }, @@ -19823,20 +26211,25 @@ ] }, { - "name": "Interviews", + "name": "Resource Bookings", "item": [ { "name": "Before Test", "item": [ { - "name": "create job", + "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);" + "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" } @@ -19853,7 +26246,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"projectId\": {{projectId}},\n \"externalId\": \"88774632\",\n \"description\": \"Dummy Description\",\n \"startDate\": \"2020-09-27\",\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": "{\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 \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", "options": { "raw": { "language": "json" @@ -19871,85 +26264,35 @@ } }, "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": [] } ] }, { - "name": "✔ request interview with administrator", + "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(\"interview_round_created_by_administrator\", response.round);\r", - " pm.environment.set(\"interview_id_created_by_administrator\", response.id);\r", - " }\r", - "});" + "var data = JSON.parse(responseBody);\r", + "postman.setEnvironmentVariable(\"resource_bookings_id_created_by_administrator\",data.id);" ], "type": "text/javascript" } } ], "request": { - "method": "PATCH", + "method": "POST", "header": [ { "key": "Authorization", - "value": "Bearer {{token_administrator}}", - "type": "text" + "type": "text", + "value": "Bearer {{token_administrator}}" } ], "body": { "mode": "raw", - "raw": "{\r\n \"templateUrl\": \"interview-30\",\r\n \"hostEmail\": \"testcustomer@yopmail.com\",\r\n \"calendarEventId\": \"dummyId\",\r\n \"status\": \"Scheduling\"\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 \"billingAccountId\": 80000071\r\n}", "options": { "raw": { "language": "json" @@ -19957,122 +26300,125 @@ } }, "url": { - "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_by_administrator}}/requestInterview", - "host": [ - "{{URL}}" - ], - "path": [ - "jobCandidates", - "{{job_candidate_id_created_by_administrator}}", - "requestInterview" - ] - } - }, - "response": [] - }, - { - "name": "✔ get interview by round 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" - } + "raw": "{{URL}}/resourceBookings", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings" + ] } - ], + }, + "response": [] + }, + { + "name": "✔ get resource booking with administrator", "request": { "method": "GET", "header": [ { "key": "Authorization", - "value": "Bearer {{token_administrator}}", - "type": "text" + "type": "text", + "value": "Bearer {{token_administrator}}" } ], "url": { - "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_by_administrator}}/interviews/{{interview_round_created_by_administrator}}", + "raw": "{{URL}}/resourceBookings/{{resource_bookings_id_created_by_administrator}}", "host": [ "{{URL}}" ], "path": [ - "jobCandidates", - "{{job_candidate_id_created_by_administrator}}", - "interviews", - "{{interview_round_created_by_administrator}}" + "resourceBookings", + "{{resource_bookings_id_created_by_administrator}}" ] } }, "response": [] }, { - "name": "✔ get interview by id 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": "✔ search resource bookings with administrator", "request": { "method": "GET", "header": [ { "key": "Authorization", - "value": "Bearer {{token_administrator}}", - "type": "text" + "type": "text", + "value": "Bearer {{token_administrator}}" } ], "url": { - "raw": "{{URL}}/getInterview/{{interview_id_created_by_administrator}}", + "raw": "{{URL}}/resourceBookings", "host": [ "{{URL}}" ], "path": [ - "getInterview", - "{{interview_id_created_by_administrator}}" + "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-27", + "disabled": true + }, + { + "key": "endDate", + "value": "2020-09-27", + "disabled": true + }, + { + "key": "rateType", + "value": "hourly", + "disabled": true + }, + { + "key": "status", + "value": "sourcing", + "disabled": true + }, + { + "key": "projectIds", + "value": "111, 16705", + "disabled": true + } ] } }, "response": [] }, { - "name": "✔ update interview by round 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 resource booking with administrator", "request": { - "method": "PATCH", + "method": "PUT", "header": [ { "key": "Authorization", - "value": "Bearer {{token_administrator}}", - "type": "text" + "type": "text", + "value": "Bearer {{token_administrator}}" } ], "body": { "mode": "raw", - "raw": "{\r\n \"calendarEventId\": \"updated\"\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" @@ -20080,47 +26426,32 @@ } }, "url": { - "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_by_administrator}}/updateInterview/{{interview_round_created_by_administrator}}", + "raw": "{{URL}}/resourceBookings/{{resource_bookings_id_created_by_administrator}}", "host": [ "{{URL}}" ], "path": [ - "jobCandidates", - "{{job_candidate_id_created_by_administrator}}", - "updateInterview", - "{{interview_round_created_by_administrator}}" + "resourceBookings", + "{{resource_bookings_id_created_by_administrator}}" ] } }, "response": [] }, { - "name": "✔ update interview by id 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 resource booking with administrator", "request": { "method": "PATCH", "header": [ { "key": "Authorization", - "value": "Bearer {{token_administrator}}", - "type": "text" + "type": "text", + "value": "Bearer {{token_administrator}}" } ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiId\": \"0edc1751-f4ca-4e8e-908a-95f6560311ab\",\r\n \"calendarEventId\": \"updated\"\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" @@ -20128,51 +26459,46 @@ } }, "url": { - "raw": "{{URL}}/updateInterview/{{interview_id_created_by_administrator}}", + "raw": "{{URL}}/resourceBookings/{{resource_bookings_id_created_by_administrator}}", "host": [ "{{URL}}" ], "path": [ - "updateInterview", - "{{interview_id_created_by_administrator}}" + "resourceBookings", + "{{resource_bookings_id_created_by_administrator}}" ] } }, "response": [] }, { - "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" - } - } - ], + "name": "✔ delete resource booking with administrator", "request": { - "method": "GET", + "method": "DELETE", "header": [ { "key": "Authorization", - "value": "Bearer {{token_administrator}}", - "type": "text" + "type": "text", + "value": "Bearer {{token_administrator}}" } ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { - "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_by_administrator}}/interviews", + "raw": "{{URL}}/resourceBookings/{{resource_bookings_id_created_by_administrator}}", "host": [ "{{URL}}" ], "path": [ - "jobCandidates", - "{{job_candidate_id_created_by_administrator}}", - "interviews" + "resourceBookings", + "{{resource_bookings_id_created_by_administrator}}" ] } }, @@ -20181,7 +26507,7 @@ ] }, { - "name": "Resource Bookings", + "name": "Work Periods", "item": [ { "name": "Before Test", @@ -20216,7 +26542,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": "{\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 \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", "options": { "raw": { "language": "json" @@ -20234,18 +26560,72 @@ } }, "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-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" + } + } + }, + "url": { + "raw": "{{URL}}/resourceBookings", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings" + ] + } + }, + "response": [] } ] }, { - "name": "✔ create resource booking with administrator", + "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" } @@ -20262,7 +26642,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 \"billingAccountId\": 80000071\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" @@ -20270,19 +26650,19 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings", + "raw": "{{URL}}/work-periods", "host": [ "{{URL}}" ], "path": [ - "resourceBookings" + "work-periods" ] } }, "response": [] }, { - "name": "✔ get resource booking with administrator", + "name": "✔ get work period with administrator", "request": { "method": "GET", "header": [ @@ -20293,20 +26673,20 @@ } ], "url": { - "raw": "{{URL}}/resourceBookings/{{resource_bookings_id_created_by_administrator}}", + "raw": "{{URL}}/work-periods/{{workPeriodId_created_by_administrator}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resource_bookings_id_created_by_administrator}}" + "work-periods", + "{{workPeriodId_created_by_administrator}}" ] } }, "response": [] }, { - "name": "✔ search resource bookings with administrator", + "name": "✔ search work periods with administrator", "request": { "method": "GET", "header": [ @@ -20317,12 +26697,12 @@ } ], "url": { - "raw": "{{URL}}/resourceBookings", + "raw": "{{URL}}/work-periods", "host": [ "{{URL}}" ], "path": [ - "resourceBookings" + "work-periods" ], "query": [ { @@ -20346,28 +26726,38 @@ "disabled": true }, { - "key": "startDate", - "value": "2020-09-27", + "key": "resourceBookingId", + "value": "{{resource_bookings_id_created_by_administrator}}", "disabled": true }, { - "key": "endDate", - "value": "2020-09-27", + "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 } ] @@ -20376,7 +26766,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": [ @@ -20388,7 +26791,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\": \"placed\",\r\n \"billingAccountId\": 80000071\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" @@ -20396,20 +26799,33 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{resource_bookings_id_created_by_administrator}}", + "raw": "{{URL}}/work-periods/{{workPeriodId_created_by_administrator}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resource_bookings_id_created_by_administrator}}" + "work-periods", + "{{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": [ @@ -20421,7 +26837,7 @@ ], "body": { "mode": "raw", - "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}", + "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" @@ -20429,20 +26845,33 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{resource_bookings_id_created_by_administrator}}", + "raw": "{{URL}}/work-periods/{{workPeriodId_created_by_administrator}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resource_bookings_id_created_by_administrator}}" + "work-periods", + "{{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": [ @@ -20462,13 +26891,13 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{resource_bookings_id_created_by_administrator}}", + "raw": "{{URL}}/work-periods/{{workPeriodId_created_by_administrator}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resource_bookings_id_created_by_administrator}}" + "work-periods", + "{{workPeriodId_created_by_administrator}}" ] } }, @@ -20477,7 +26906,7 @@ ] }, { - "name": "Work Periods", + "name": "Work Period Payments", "item": [ { "name": "Before Test", @@ -20512,7 +26941,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": "{\n \"projectId\": {{project_id_17234}},\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 \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", "options": { "raw": { "language": "json" @@ -20561,7 +26990,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 \"billingAccountId\": 80000071\r\n}", + "raw": "{\r\n \"projectId\": {{project_id_17234}},\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 \"billingAccountId\": 80000071\r\n}", "options": { "raw": { "language": "json" @@ -20579,11 +27008,60 @@ } }, "response": [] + }, + { + "name": "✔ create work period 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(\"workPeriodId_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 \"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" + } + } + }, + "url": { + "raw": "{{URL}}/work-periods", + "host": [ + "{{URL}}" + ], + "path": [ + "work-periods" + ] + } + }, + "response": [] } ] }, { - "name": "✔ create work period with administrator", + "name": "✔ create work period payment with administrator", "event": [ { "listen": "test", @@ -20593,7 +27071,7 @@ " 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", + " pm.environment.set(\"workPeriodPaymentId_created_by_administrator\", response.id);\r", " }\r", "});" ], @@ -20612,7 +27090,7 @@ ], "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": "{\r\n \"workPeriodId\": \"{{workPeriodId_created_by_administrator}}\",\r\n \"amount\": 600,\r\n \"status\": \"completed\"\r\n}", "options": { "raw": { "language": "json" @@ -20620,19 +27098,78 @@ } }, "url": { - "raw": "{{URL}}/work-periods", + "raw": "{{URL}}/work-period-payments", "host": [ "{{URL}}" ], "path": [ - "work-periods" + "work-period-payments" ] } }, "response": [] }, { - "name": "✔ get work period with administrator", + "name": "✔ create multiple work period payment 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": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\"query\": { \"workPeriods.paymentStatus\": \"pending\" } }", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/work-period-payments/query", + "host": [ + "{{URL}}" + ], + "path": [ + "work-period-payments", + "query" + ] + } + }, + "response": [] + }, + { + "name": "✔ get work period payment 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": "GET", "header": [ @@ -20643,20 +27180,33 @@ } ], "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId_created_by_administrator}}", + "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId_created_by_administrator}}", "host": [ "{{URL}}" ], "path": [ - "work-periods", - "{{workPeriodId_created_by_administrator}}" + "work-period-payments", + "{{workPeriodPaymentId_created_by_administrator}}" ] } - }, - "response": [] - }, - { - "name": "✔ search work periods with administrator", + }, + "response": [] + }, + { + "name": "✔ search work period payments 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": "GET", "header": [ @@ -20667,12 +27217,12 @@ } ], "url": { - "raw": "{{URL}}/work-periods", + "raw": "{{URL}}/work-period-payments", "host": [ "{{URL}}" ], "path": [ - "work-periods" + "work-period-payments" ], "query": [ { @@ -20687,7 +27237,7 @@ }, { "key": "sortBy", - "value": "id", + "value": "status", "disabled": true }, { @@ -20696,38 +27246,18 @@ "disabled": true }, { - "key": "resourceBookingId", - "value": "{{resource_bookings_id_created_by_administrator}}", - "disabled": true - }, - { - "key": "resourceBookingIds", - "value": "{{resource_bookings_id_created_by_administrator}},{{resource_bookings_id_created_by_administrator}}", - "disabled": true - }, - { - "key": "paymentStatus", - "value": "pending", - "disabled": true - }, - { - "key": "startDate", - "value": "2021-03-07", - "disabled": true - }, - { - "key": "endDate", - "value": "2021-03-13", + "key": "workPeriodId", + "value": "{{workPeriodId_created_by_administrator}}", "disabled": true }, { - "key": "userHandle", - "value": "pshah_manager", + "key": "workPeriodIds", + "value": "{{workPeriodId_created_by_administrator}},{{workPeriodId_created_by_administrator}}", "disabled": true }, { - "key": "projectId", - "value": "111", + "key": "status", + "value": "completed", "disabled": true } ] @@ -20736,7 +27266,7 @@ "response": [] }, { - "name": "✔ put work period with administrator", + "name": "✔ put work period payment with administrator", "event": [ { "listen": "test", @@ -20761,7 +27291,7 @@ ], "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": "{\r\n \"workPeriodId\": \"{{workPeriodId_created_by_administrator}}\",\r\n \"amount\": 1600,\r\n \"status\": \"completed\"\r\n}", "options": { "raw": { "language": "json" @@ -20769,20 +27299,20 @@ } }, "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId_created_by_administrator}}", + "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId_created_by_administrator}}", "host": [ "{{URL}}" ], "path": [ - "work-periods", - "{{workPeriodId_created_by_administrator}}" + "work-period-payments", + "{{workPeriodPaymentId_created_by_administrator}}" ] } }, "response": [] }, { - "name": "✔ patch work period with administrator", + "name": "✔ patch work period payment with administrator", "event": [ { "listen": "test", @@ -20807,7 +27337,7 @@ ], "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": "{\r\n \"workPeriodId\": \"{{workPeriodId_created_by_administrator}}\",\r\n \"amount\": 450,\r\n \"status\": \"cancelled\"\r\n}", "options": { "raw": { "language": "json" @@ -20815,27 +27345,36 @@ } }, "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId_created_by_administrator}}", + "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId_created_by_administrator}}", "host": [ "{{URL}}" ], "path": [ - "work-periods", - "{{workPeriodId_created_by_administrator}}" + "work-period-payments", + "{{workPeriodPaymentId_created_by_administrator}}" ] } }, "response": [] - }, + } + ] + }, + { + "name": "Roles", + "item": [ { - "name": "✔ delete work period with administrator", + "name": "✔ create role with admin", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 204', function () {\r", - " pm.response.to.have.status(204);\r", + "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(\"roleId-1\", response.id);\r", + " }\r", "});" ], "type": "text/javascript" @@ -20843,7 +27382,7 @@ } ], "request": { - "method": "DELETE", + "method": "POST", "header": [ { "key": "Authorization", @@ -20853,7 +27392,7 @@ ], "body": { "mode": "raw", - "raw": "", + "raw": "{\n \"name\": \"Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Dropwizard\",\n \"NGINX\",\n \"Machine Learning\",\n \"Force.com\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10\n },\n {\n \"global\": 25,\n \"inCountry\": 15,\n \"offShore\": 5\n }\n ],\n \"numberOfMembers\": 10,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", "options": { "raw": { "language": "json" @@ -20861,177 +27400,92 @@ } }, "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId_created_by_administrator}}", + "raw": "{{URL}}/taas-roles", "host": [ "{{URL}}" ], "path": [ - "work-periods", - "{{workPeriodId_created_by_administrator}}" + "taas-roles" ] } }, "response": [] - } - ] - }, - { - "name": "Work Period Payments", - "item": [ + }, { - "name": "Before Test", - "item": [ + "name": "✔ get role with admin", + "event": [ { - "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" - } + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", + "});" ], - "body": { - "mode": "raw", - "raw": "{\n \"projectId\": {{project_id_17234}},\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" - } - } + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_administrator}}" + } + ], + "url": { + "raw": "{{URL}}/taas-roles/{{roleId-1}}", + "host": [ + "{{URL}}" ], - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_administrator}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"projectId\": {{project_id_17234}},\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 \"billingAccountId\": 80000071\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{URL}}/resourceBookings", - "host": [ - "{{URL}}" - ], - "path": [ - "resourceBookings" - ] - } - }, - "response": [] - }, + "path": [ + "taas-roles", + "{{roleId-1}}" + ] + } + }, + "response": [] + }, + { + "name": "✔ search roles with admin", + "event": [ { - "name": "✔ create work period 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(\"workPeriodId_created_by_administrator\", response.id);\r", - " }\r", - "});" - ], - "type": "text/javascript" - } - } + "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_administrator}}" + } + ], + "url": { + "raw": "{{URL}}/taas-roles", + "host": [ + "{{URL}}" ], - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_administrator}}" - } - ], - "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}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{URL}}/work-periods", - "host": [ - "{{URL}}" - ], - "path": [ - "work-periods" - ] - } - }, - "response": [] + "path": [ + "taas-roles" + ] } - ] + }, + "response": [] }, { - "name": "✔ create work period payment with administrator", + "name": "✔ update role with admin", "event": [ { "listen": "test", @@ -21039,10 +27493,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(\"workPeriodPaymentId_created_by_administrator\", response.id);\r", - " }\r", "});" ], "type": "text/javascript" @@ -21050,7 +27500,7 @@ } ], "request": { - "method": "POST", + "method": "PATCH", "header": [ { "key": "Authorization", @@ -21060,7 +27510,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"workPeriodId\": \"{{workPeriodId_created_by_administrator}}\",\r\n \"amount\": 600,\r\n \"status\": \"completed\"\r\n}", + "raw": "{\n \"name\": \"Dev Ops Engineer edit\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Dropwizard\",\n \"NGINX\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10\n },\n {\n \"global\": 25,\n \"inCountry\": 15,\n \"offShore\": 5\n }\n ],\n \"numberOfMembers\": 10,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", "options": { "raw": { "language": "json" @@ -21068,26 +27518,27 @@ } }, "url": { - "raw": "{{URL}}/work-period-payments", + "raw": "{{URL}}/taas-roles/{{roleId-1}}", "host": [ "{{URL}}" ], "path": [ - "work-period-payments" + "taas-roles", + "{{roleId-1}}" ] } }, "response": [] }, { - "name": "✔ get work period payment with administrator", + "name": "✔ delete role with admin", "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 204', function () {\r", + " pm.response.to.have.status(204);\r", "});" ], "type": "text/javascript" @@ -21095,7 +27546,7 @@ } ], "request": { - "method": "GET", + "method": "DELETE", "header": [ { "key": "Authorization", @@ -21103,85 +27554,209 @@ "value": "Bearer {{token_administrator}}" } ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { - "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId_created_by_administrator}}", + "raw": "{{URL}}/taas-roles/{{roleId-1}}", "host": [ "{{URL}}" ], "path": [ - "work-period-payments", - "{{workPeriodPaymentId_created_by_administrator}}" + "taas-roles", + "{{roleId-1}}" ] } }, "response": [] - }, + } + ] + } + ] + }, + { + "name": "Request with Topcoder User Role", + "item": [ + { + "name": "README", + "item": [ { - "name": "✔ search work period payments with administrator", + "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 job with member", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 200', function () {\r", - " pm.response.to.have.status(200);\r", - "});" + "var data = JSON.parse(responseBody);\r", + "postman.setEnvironmentVariable(\"job_id_created_by_member\",data.id);" ], "type": "text/javascript" } } ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_member_tester1234}}", + "type": "text" + } + ], + "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 \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobs", + "host": [ + "{{URL}}" + ], + "path": [ + "jobs" + ] + } + }, + "response": [] + }, + { + "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}}/work-period-payments", + "raw": "{{URL}}/jobs/{{job_id_created_by_member}}", "host": [ "{{URL}}" ], "path": [ - "work-period-payments" + "jobs", + "{{job_id_created_by_member}}" + ] + } + }, + "response": [] + }, + { + "name": "✔ search jobs with member filtering by \"projectId\"", + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_member_tester1234}}" + } + ], + "url": { + "raw": "{{URL}}/jobs?projectId={{project_id_16718}}", + "host": [ + "{{URL}}" + ], + "path": [ + "jobs" ], "query": [ { "key": "page", - "value": "1", + "value": "0", "disabled": true }, { "key": "perPage", - "value": "5", + "value": "3", "disabled": true }, { "key": "sortBy", - "value": "status", + "value": "id", "disabled": true }, { "key": "sortOrder", - "value": "desc", + "value": "asc", "disabled": true }, { - "key": "workPeriodId", - "value": "{{workPeriodId_created_by_administrator}}", + "key": "projectId", + "value": "{{project_id_16718}}" + }, + { + "key": "externalId", + "value": "1212", "disabled": true }, { - "key": "workPeriodIds", - "value": "{{workPeriodId_created_by_administrator}},{{workPeriodId_created_by_administrator}}", + "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": "completed", + "value": "sourcing", + "disabled": true + }, + { + "key": "workload", + "value": "full-time", + "disabled": true + }, + { + "key": "title", + "value": "dummy", "disabled": true } ] @@ -21190,32 +27765,52 @@ "response": [] }, { - "name": "✔ put work period payment 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_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\": \"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 \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", + "options": { + "raw": { + "language": "json" + } } + }, + "url": { + "raw": "{{URL}}/jobs/{{job_id_created_by_member}}", + "host": [ + "{{URL}}" + ], + "path": [ + "jobs", + "{{job_id_created_by_member}}" + ] } - ], + }, + "response": [] + }, + { + "name": "✔ patch job with member", "request": { - "method": "PUT", + "method": "PATCH", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_administrator}}" + "value": "Bearer {{token_member_tester1234}}" } ], "body": { "mode": "raw", - "raw": "{\r\n \"workPeriodId\": \"{{workPeriodId_created_by_administrator}}\",\r\n \"amount\": 1600,\r\n \"status\": \"completed\"\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 \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", "options": { "raw": { "language": "json" @@ -21223,45 +27818,32 @@ } }, "url": { - "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId_created_by_administrator}}", + "raw": "{{URL}}/jobs/{{job_id_created_by_member}}", "host": [ "{{URL}}" ], "path": [ - "work-period-payments", - "{{workPeriodPaymentId_created_by_administrator}}" + "jobs", + "{{job_id_created_by_member}}" ] } }, "response": [] }, { - "name": "✔ patch work period payment 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": "✘ delete job with member", "request": { - "method": "PATCH", + "method": "DELETE", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_administrator}}" + "value": "Bearer {{token_member_tester1234}}" } ], "body": { "mode": "raw", - "raw": "{\r\n \"workPeriodId\": \"{{workPeriodId_created_by_administrator}}\",\r\n \"amount\": 450,\r\n \"status\": \"cancelled\"\r\n}", + "raw": "", "options": { "raw": { "language": "json" @@ -21269,53 +27851,81 @@ } }, "url": { - "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId_created_by_administrator}}", + "raw": "{{URL}}/jobs/{{job_id_created_by_member}}", "host": [ "{{URL}}" ], "path": [ - "work-period-payments", - "{{workPeriodPaymentId_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" } @@ -21326,13 +27936,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" @@ -21340,19 +27950,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": [ @@ -21363,20 +27973,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": [ @@ -21387,22 +27997,22 @@ } ], "url": { - "raw": "{{URL}}/jobs?projectId={{project_id_16718}}", + "raw": "{{URL}}/jobCandidates?jobId={{job_id_created_by_member}}", "host": [ "{{URL}}" ], "path": [ - "jobs" + "jobCandidates" ], "query": [ { "key": "page", - "value": "0", + "value": "1", "disabled": true }, { "key": "perPage", - "value": "3", + "value": "1", "disabled": true }, { @@ -21416,52 +28026,17 @@ "disabled": true }, { - "key": "projectId", - "value": "{{project_id_16718}}" - }, - { - "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": "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": "selected", "disabled": true } ] @@ -21470,7 +28045,7 @@ "response": [] }, { - "name": "✔ put job with member", + "name": "✔ put job candidate with member", "request": { "method": "PUT", "header": [ @@ -21482,7 +28057,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\": \"placed\",\r\n \"remark\": \"excellent\"\r\n}", "options": { "raw": { "language": "json" @@ -21490,20 +28065,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": [ @@ -21515,7 +28090,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\": \"selected\"\r\n}", "options": { "raw": { "language": "json" @@ -21523,20 +28098,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": [ @@ -21556,13 +28131,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}}" ] } }, @@ -21571,11 +28146,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-27\",\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 \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobs", + "host": [ + "{{URL}}" + ], + "path": [ + "jobs" + ] + } + }, + "response": [] + }, { "name": "create job candidate", "event": [ @@ -21601,7 +28220,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" @@ -21619,35 +28238,88 @@ } }, "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", + " pm.environment.set(\"interview_id_created_for_member\", response.id)\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_administrator}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"templateUrl\": \"interview-30\",\r\n \"calendarEventId\": \"dummyId\",\r\n \"hostEmail\": \"testcustomer@yopmail.com\",\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 401', function () {\r", + " pm.response.to.have.status(401);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"userId: 8547899 the user is not a member of project 111\")\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 \"templateUrl\": \"interview-30\",\r\n \"hostEmail\": \"testcustomer@yopmail.com\",\r\n \"calendarEventId\": \"dummyId\",\r\n \"status\": \"Scheduling\"\r\n}", "options": { "raw": { "language": "json" @@ -21655,114 +28327,128 @@ } }, "url": { - "raw": "{{URL}}/jobCandidates", + "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_for_member}}/requestInterview", "host": [ "{{URL}}" ], "path": [ - "jobCandidates" + "jobCandidates", + "{{job_candidate_id_created_for_member}}", + "requestInterview" ] } }, "response": [] }, { - "name": "✔ get job candidate with member", + "name": "✘ get interview by round with member", + "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(\"userId: 8547899 the user is not a member of project 111\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], "request": { "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_member_tester1234}}" + "value": "Bearer {{token_member}}", + "type": "text" } ], "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": "✔ search job candidates with member filtering by \"jobId\"", + "name": "✘ get interview by id with member", + "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(\"userId: 8547899 the user is not a member of project 111\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], "request": { "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_member_tester1234}}" + "value": "Bearer {{token_member}}", + "type": "text" } ], "url": { - "raw": "{{URL}}/jobCandidates?jobId={{job_id_created_by_member}}", + "raw": "{{URL}}/getInterview/{{interview_id_created_for_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": "selected", - "disabled": true - } + "getInterview", + "{{interview_id_created_for_member}}" ] } }, "response": [] }, { - "name": "✔ put job candidate with member", + "name": "✘ update interview by round with member", + "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(\"userId: 8547899 the user is not a member of project 111\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], "request": { - "method": "PUT", + "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 \"status\": \"placed\"\r\n}", + "raw": "{\r\n \"xaiId\": \"0edc1751-f4ca-4e8e-908a-95f6560311ab\"\r\n}", "options": { "raw": { "language": "json" @@ -21770,32 +28456,49 @@ } }, "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": "✔ patch job candidate with member", + "name": "✘ update interview by id with member", + "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(\"userId: 8547899 the user is not a member of project 111\")\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\": \"selected\"\r\n}", + "raw": "{\r\n \"xaiId\": \"0edc1751-f4ca-4e8e-908a-95f6560311ab\"\r\n}", "options": { "raw": { "language": "json" @@ -21803,46 +28506,53 @@ } }, "url": { - "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_for_member}}", + "raw": "{{URL}}/updateInterview/{{interview_id_created_for_member}}", "host": [ "{{URL}}" ], "path": [ - "jobCandidates", - "{{job_candidate_id_created_for_member}}" + "updateInterview", + "{{interview_id_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 401', function () {\r", + " pm.response.to.have.status(401);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"userId: 8547899 the user is not a member of project 111\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], "request": { - "method": "DELETE", + "method": "GET", "header": [ { "key": "Authorization", - "type": "text", - "value": "Bearer {{token_member_tester1234}}" - } - ], - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" - } + "value": "Bearer {{token_member}}", + "type": "text" } - }, + ], "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" ] } }, @@ -21851,7 +28561,7 @@ ] }, { - "name": "Interviews", + "name": "Resource Bookings", "item": [ { "name": "Before Test", @@ -21864,7 +28574,7 @@ "script": { "exec": [ "var data = JSON.parse(responseBody);\r", - "postman.setEnvironmentVariable(\"job_id_created_for_member\",data.id);" + "postman.setEnvironmentVariable(\"job_id_created_by_member\",data.id);" ], "type": "text/javascript" } @@ -21875,13 +28585,13 @@ "header": [ { "key": "Authorization", - "value": "Bearer {{token_administrator}}", + "value": "Bearer {{token_member_tester1234}}", "type": "text" } ], "body": { "mode": "raw", - "raw": "{\n \"projectId\": {{projectId}},\n \"externalId\": \"88774632\",\n \"description\": \"Dummy Description\",\n \"startDate\": \"2020-09-27\",\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": "{\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 \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", "options": { "raw": { "language": "json" @@ -21901,14 +28611,14 @@ "response": [] }, { - "name": "create job candidate", + "name": "create resource booking", "event": [ { "listen": "test", "script": { "exec": [ "var data = JSON.parse(responseBody);\r", - "postman.setEnvironmentVariable(\"job_candidate_id_created_for_member\",data.id);" + "postman.setEnvironmentVariable(\"resource_booking_id_created_for_member\",data.id);" ], "type": "text/javascript" } @@ -21925,55 +28635,7 @@ ], "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": [] - }, - { - "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", - " pm.environment.set(\"interview_id_created_for_member\", response.id)\r", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "PATCH", - "header": [ - { - "key": "Authorization", - "value": "Bearer {{token_administrator}}", - "type": "text" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"templateUrl\": \"interview-30\",\r\n \"calendarEventId\": \"dummyId\",\r\n \"hostEmail\": \"testcustomer@yopmail.com\",\r\n \"status\": \"Scheduling\"\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 \"billingAccountId\": 80000071\r\n}", "options": { "raw": { "language": "json" @@ -21981,14 +28643,12 @@ } }, "url": { - "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_for_member}}/requestInterview", + "raw": "{{URL}}/resourceBookings", "host": [ "{{URL}}" ], "path": [ - "jobCandidates", - "{{job_candidate_id_created_for_member}}", - "requestInterview" + "resourceBookings" ] } }, @@ -21997,34 +28657,31 @@ ] }, { - "name": "✘ request interview with member", + "name": "✘ create resource booking with member", "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(\"userId: 8547899 the user is not a member of project 111\")\r", - "});" + "var data = JSON.parse(responseBody);\r", + "postman.setEnvironmentVariable(\"resource_booking_id_created_by_member\",data.id);" ], "type": "text/javascript" } } ], "request": { - "method": "PATCH", + "method": "POST", "header": [ { "key": "Authorization", - "value": "Bearer {{token_member}}", - "type": "text" + "type": "text", + "value": "Bearer {{token_member_tester1234}}" } ], "body": { "mode": "raw", - "raw": "{\r\n \"templateUrl\": \"interview-30\",\r\n \"hostEmail\": \"testcustomer@yopmail.com\",\r\n \"calendarEventId\": \"dummyId\",\r\n \"status\": \"Scheduling\"\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 \"billingAccountId\": 80000071\r\n}", "options": { "raw": { "language": "json" @@ -22032,128 +28689,129 @@ } }, "url": { - "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_for_member}}/requestInterview", + "raw": "{{URL}}/resourceBookings", "host": [ "{{URL}}" ], "path": [ - "jobCandidates", - "{{job_candidate_id_created_for_member}}", - "requestInterview" + "resourceBookings" ] } }, "response": [] }, { - "name": "✘ get interview by round with member", - "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(\"userId: 8547899 the user is not a member of project 111\")\r", - "});" - ], - "type": "text/javascript" - } - } - ], + "name": "✔ get resource booking with member", "request": { "method": "GET", "header": [ { "key": "Authorization", - "value": "Bearer {{token_member}}", - "type": "text" + "type": "text", + "value": "Bearer {{token_member_tester1234}}" } ], "url": { - "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_for_member}}/interviews/{{interview_round_created_for_member}}", + "raw": "{{URL}}/resourceBookings/{{resource_booking_id_created_for_member}}", "host": [ "{{URL}}" ], "path": [ - "jobCandidates", - "{{job_candidate_id_created_for_member}}", - "interviews", - "{{interview_round_created_for_member}}" + "resourceBookings", + "{{resource_booking_id_created_for_member}}" ] } }, "response": [] }, { - "name": "✘ get interview by id with member", - "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(\"userId: 8547899 the user is not a member of project 111\")\r", - "});" - ], - "type": "text/javascript" - } - } - ], + "name": "✔ search resource bookings with member filtering by \"projectId\"", "request": { "method": "GET", "header": [ { "key": "Authorization", - "value": "Bearer {{token_member}}", - "type": "text" + "type": "text", + "value": "Bearer {{token_member_tester1234}}" } ], "url": { - "raw": "{{URL}}/getInterview/{{interview_id_created_for_member}}", + "raw": "{{URL}}/resourceBookings?projectId={{project_id_16718}}", "host": [ "{{URL}}" ], "path": [ - "getInterview", - "{{interview_id_created_for_member}}" + "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-27", + "disabled": true + }, + { + "key": "endDate", + "value": "2020-09-27", + "disabled": true + }, + { + "key": "rateType", + "value": "hourly", + "disabled": true + }, + { + "key": "status", + "value": "sourcing", + "disabled": true + }, + { + "key": "projectIds", + "value": "111, 16705", + "disabled": true + }, + { + "key": "projectId", + "value": "{{project_id_16718}}" + } ] } }, "response": [] }, { - "name": "✘ update interview by round with member", - "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(\"userId: 8547899 the user is not a member of project 111\")\r", - "});" - ], - "type": "text/javascript" - } - } - ], + "name": "✘ put resource booking with member", "request": { - "method": "PATCH", + "method": "PUT", "header": [ { "key": "Authorization", - "value": "Bearer {{token_member}}", - "type": "text" + "type": "text", + "value": "Bearer {{token_member_tester1234}}" } ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiId\": \"0edc1751-f4ca-4e8e-908a-95f6560311ab\"\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" @@ -22161,49 +28819,32 @@ } }, "url": { - "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}}", - "updateInterview", - "{{interview_round_created_for_member}}" - ] - } - }, - "response": [] - }, - { - "name": "✘ update interview by id with member", - "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(\"userId: 8547899 the user is not a member of project 111\")\r", - "});" - ], - "type": "text/javascript" - } + "raw": "{{URL}}/resourceBookings/{{resource_booking_id_created_for_member}}", + "host": [ + "{{URL}}" + ], + "path": [ + "resourceBookings", + "{{resource_booking_id_created_for_member}}" + ] } - ], + }, + "response": [] + }, + { + "name": "✘ patch resource booking with member", "request": { "method": "PATCH", "header": [ { "key": "Authorization", - "value": "Bearer {{token_member}}", - "type": "text" + "type": "text", + "value": "Bearer {{token_member_tester1234}}" } ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiId\": \"0edc1751-f4ca-4e8e-908a-95f6560311ab\"\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" @@ -22211,53 +28852,46 @@ } }, "url": { - "raw": "{{URL}}/updateInterview/{{interview_id_created_for_member}}", + "raw": "{{URL}}/resourceBookings/{{resource_booking_id_created_for_member}}", "host": [ "{{URL}}" ], "path": [ - "updateInterview", - "{{interview_id_created_for_member}}" + "resourceBookings", + "{{resource_booking_id_created_for_member}}" ] } }, "response": [] }, { - "name": "✘ search interviews with member", - "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(\"userId: 8547899 the user is not a member of project 111\")\r", - "});" - ], - "type": "text/javascript" - } - } - ], + "name": "✘ delete resource booking with member", "request": { - "method": "GET", + "method": "DELETE", "header": [ { "key": "Authorization", - "value": "Bearer {{token_member}}", - "type": "text" + "type": "text", + "value": "Bearer {{token_member_tester1234}}" } ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { - "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_for_member}}/interviews", + "raw": "{{URL}}/resourceBookings/{{resource_booking_id_created_for_member}}", "host": [ "{{URL}}" ], "path": [ - "jobCandidates", - "{{job_candidate_id_created_for_member}}", - "interviews" + "resourceBookings", + "{{resource_booking_id_created_for_member}}" ] } }, @@ -22266,7 +28900,7 @@ ] }, { - "name": "Resource Bookings", + "name": "Work Periods", "item": [ { "name": "Before Test", @@ -22278,8 +28912,13 @@ "listen": "test", "script": { "exec": [ - "var data = JSON.parse(responseBody);\r", - "postman.setEnvironmentVariable(\"job_id_created_by_member\",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(\"job_id_created_by_member\", response.id);\r", + " }\r", + "});" ], "type": "text/javascript" } @@ -22296,7 +28935,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\": \"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": "{\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 \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", "options": { "raw": { "language": "json" @@ -22322,8 +28961,13 @@ "listen": "test", "script": { "exec": [ - "var data = JSON.parse(responseBody);\r", - "postman.setEnvironmentVariable(\"resource_booking_id_created_for_member\",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(\"resource_booking_id_created_for_member\", response.id);\r", + " }\r", + "});" ], "type": "text/javascript" } @@ -22358,18 +29002,70 @@ } }, "response": [] + }, + { + "name": "create work period", + "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_for_member\", 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 \"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}}/work-periods", + "host": [ + "{{URL}}" + ], + "path": [ + "work-periods" + ] + } + }, + "response": [] } ] }, { - "name": "✘ create resource booking with member", + "name": "✘ create work period with member", "event": [ { "listen": "test", "script": { "exec": [ - "var data = JSON.parse(responseBody);\r", - "postman.setEnvironmentVariable(\"resource_booking_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" } @@ -22386,7 +29082,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 \"billingAccountId\": 80000071\r\n}", + "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" @@ -22394,19 +29090,19 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings", + "raw": "{{URL}}/work-periods", "host": [ "{{URL}}" ], "path": [ - "resourceBookings" + "work-periods" ] } }, "response": [] }, { - "name": "✔ get resource booking with member", + "name": "✔ get work period with member", "request": { "method": "GET", "header": [ @@ -22417,20 +29113,26 @@ } ], "url": { - "raw": "{{URL}}/resourceBookings/{{resource_booking_id_created_for_member}}", + "raw": "{{URL}}/work-periods/{{workPeriodId_created_for_member}}?projectId=16718", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resource_booking_id_created_for_member}}" + "work-periods", + "{{workPeriodId_created_for_member}}" + ], + "query": [ + { + "key": "projectId", + "value": "16718" + } ] } }, "response": [] }, { - "name": "✔ search resource bookings with member filtering by \"projectId\"", + "name": "✔ search work periods with member", "request": { "method": "GET", "header": [ @@ -22441,12 +29143,12 @@ } ], "url": { - "raw": "{{URL}}/resourceBookings?projectId={{project_id_16718}}", + "raw": "{{URL}}/work-periods?projectId=16718", "host": [ "{{URL}}" ], "path": [ - "resourceBookings" + "work-periods" ], "query": [ { @@ -22470,33 +29172,38 @@ "disabled": true }, { - "key": "startDate", - "value": "2020-09-27", + "key": "resourceBookingId", + "value": "{{resource_booking_id_created_for_member}}", "disabled": true }, { - "key": "endDate", - "value": "2020-09-27", + "key": "resourceBookingIds", + "value": "{{resource_booking_id_created_for_member}},{{resource_booking_id_created_for_member}}", "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": "{{project_id_16718}}" + "value": "16718" } ] } @@ -22504,7 +29211,22 @@ "response": [] }, { - "name": "✘ put resource booking with member", + "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": [ @@ -22516,7 +29238,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\": \"placed\",\r\n \"billingAccountId\": 80000071\r\n}", + "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" @@ -22524,20 +29246,35 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{resource_booking_id_created_for_member}}", + "raw": "{{URL}}/work-periods/{{workPeriodId_created_for_member}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resource_booking_id_created_for_member}}" + "work-periods", + "{{workPeriodId_created_for_member}}" ] } }, "response": [] }, { - "name": "✘ patch resource booking with member", + "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": [ @@ -22549,7 +29286,7 @@ ], "body": { "mode": "raw", - "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}", + "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" @@ -22557,20 +29294,35 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{resource_booking_id_created_for_member}}", + "raw": "{{URL}}/work-periods/{{workPeriodId_created_for_member}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resource_booking_id_created_for_member}}" + "work-periods", + "{{workPeriodId_created_for_member}}" ] } - }, - "response": [] - }, - { - "name": "✘ delete resource booking with member", + }, + "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": [ @@ -22590,13 +29342,13 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{resource_booking_id_created_for_member}}", + "raw": "{{URL}}/work-periods/{{workPeriodId_created_for_member}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resource_booking_id_created_for_member}}" + "work-periods", + "{{workPeriodId_created_for_member}}" ] } }, @@ -22605,13 +29357,13 @@ ] }, { - "name": "Work Periods", + "name": "Work Period Payments", "item": [ { "name": "Before Test", "item": [ { - "name": "create job", + "name": "✔ create job", "event": [ { "listen": "test", @@ -22621,7 +29373,7 @@ " 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_member\", response.id);\r", + " pm.environment.set(\"job_id_created_for_member\", response.id);\r", " }\r", "});" ], @@ -22634,13 +29386,13 @@ "header": [ { "key": "Authorization", - "value": "Bearer {{token_member_tester1234}}", + "value": "Bearer {{token_administrator}}", "type": "text" } ], "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": "{\n \"projectId\": {{project_id_17234}},\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 \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", "options": { "raw": { "language": "json" @@ -22660,7 +29412,7 @@ "response": [] }, { - "name": "create resource booking", + "name": "✔ create resource booking", "event": [ { "listen": "test", @@ -22670,7 +29422,7 @@ " pm.response.to.have.status(200);\r", " if(pm.response.status === \"OK\"){\r", " const response = pm.response.json()\r", - " pm.environment.set(\"resource_booking_id_created_for_member\", response.id);\r", + " pm.environment.set(\"resource_bookings_id_created_for_member\", response.id);\r", " }\r", "});" ], @@ -22689,7 +29441,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 \"billingAccountId\": 80000071\r\n}", + "raw": "{\r\n \"projectId\": {{project_id_17234}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{job_id_created_for_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 \"billingAccountId\": 80000071\r\n}", "options": { "raw": { "language": "json" @@ -22709,7 +29461,7 @@ "response": [] }, { - "name": "create work period", + "name": "✔ create work period", "event": [ { "listen": "test", @@ -22738,7 +29490,7 @@ ], "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": "{\r\n \"resourceBookingId\": \"{{resource_bookings_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" @@ -22756,11 +29508,60 @@ } }, "response": [] + }, + { + "name": "✔ create work period payment", + "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(\"workPeriodPaymentId_created_for_member\", 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 \"workPeriodId\": \"{{workPeriodId_created_for_member}}\",\r\n \"amount\": 600,\r\n \"status\": \"completed\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/work-period-payments", + "host": [ + "{{URL}}" + ], + "path": [ + "work-period-payments" + ] + } + }, + "response": [] } ] }, { - "name": "✘ create work period with member", + "name": "✘ create work period payment with member", "event": [ { "listen": "test", @@ -22787,7 +29588,7 @@ ], "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": "{\r\n \"workPeriodId\": \"{{workPeriodId_created_for_member}}\",\r\n \"amount\": 600,\r\n \"status\": \"completed\"\r\n}", "options": { "raw": { "language": "json" @@ -22795,21 +29596,36 @@ } }, "url": { - "raw": "{{URL}}/work-periods", + "raw": "{{URL}}/work-period-payments", "host": [ "{{URL}}" ], "path": [ - "work-periods" + "work-period-payments" ] } }, "response": [] }, { - "name": "✔ get work period with member", + "name": "✘ create query work period payment 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": "POST", "header": [ { "key": "Authorization", @@ -22817,27 +29633,45 @@ "value": "Bearer {{token_member_tester1234}}" } ], + "body": { + "mode": "raw", + "raw": "{\"query\": { \"workPeriods.paymentStatus\": \"pending\" } }", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId_created_for_member}}?projectId=16718", + "raw": "{{URL}}/work-period-payments/query", "host": [ "{{URL}}" ], "path": [ - "work-periods", - "{{workPeriodId_created_for_member}}" - ], - "query": [ - { - "key": "projectId", - "value": "16718" - } + "work-period-payments", + "query" ] } }, "response": [] }, { - "name": "✔ search work periods with member", + "name": "✘ get work period payment 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", "header": [ @@ -22848,75 +29682,20 @@ } ], "url": { - "raw": "{{URL}}/work-periods?projectId=16718", + "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId_created_for_member}}", "host": [ "{{URL}}" ], "path": [ - "work-periods" - ], - "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" - } + "work-period-payments", + "{{workPeriodPaymentId_created_for_member}}" ] } }, "response": [] }, { - "name": "✘ put work period with member", + "name": "✘ search work period payments with member", "event": [ { "listen": "test", @@ -22933,7 +29712,7 @@ } ], "request": { - "method": "PUT", + "method": "GET", "header": [ { "key": "Authorization", @@ -22941,30 +29720,57 @@ "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}}/work-period-payments", + "host": [ + "{{URL}}" + ], + "path": [ + "work-period-payments" + ], + "query": [ + { + "key": "page", + "value": "1", + "disabled": true + }, + { + "key": "perPage", + "value": "5", + "disabled": true + }, + { + "key": "sortBy", + "value": "status", + "disabled": true + }, + { + "key": "sortOrder", + "value": "desc", + "disabled": true + }, + { + "key": "workPeriodId", + "value": "{{workPeriodPaymentId_created_for_member}}", + "disabled": true + }, + { + "key": "workPeriodIds", + "value": "{{workPeriodPaymentId_created_for_member}},{{workPeriodPaymentId_created_for_member}}", + "disabled": true + }, + { + "key": "status", + "value": "completed", + "disabled": true } - } - }, - "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId_created_for_member}}", - "host": [ - "{{URL}}" - ], - "path": [ - "work-periods", - "{{workPeriodId_created_for_member}}" ] } }, "response": [] }, { - "name": "✘ patch work period with member", + "name": "✘ put work period payment with member", "event": [ { "listen": "test", @@ -22981,7 +29787,7 @@ } ], "request": { - "method": "PATCH", + "method": "PUT", "header": [ { "key": "Authorization", @@ -22991,7 +29797,7 @@ ], "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": "{\r\n \"workPeriodId\": \"{{workPeriodId_created_for_member}}\",\r\n \"amount\": 1600,\r\n \"status\": \"completed\"\r\n}", "options": { "raw": { "language": "json" @@ -22999,20 +29805,20 @@ } }, "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId_created_for_member}}", + "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId_created_for_member}}", "host": [ "{{URL}}" ], "path": [ - "work-periods", - "{{workPeriodId_created_for_member}}" + "work-period-payments", + "{{workPeriodPaymentId_created_for_member}}" ] } }, "response": [] }, { - "name": "✘ delete work period with member", + "name": "✘ patch work period payment with member", "event": [ { "listen": "test", @@ -23029,7 +29835,7 @@ } ], "request": { - "method": "DELETE", + "method": "PATCH", "header": [ { "key": "Authorization", @@ -23039,7 +29845,7 @@ ], "body": { "mode": "raw", - "raw": "", + "raw": "{\r\n \"workPeriodId\": \"{{workPeriodId_created_for_member}}\",\r\n \"amount\": 450,\r\n \"status\": \"cancelled\"\r\n}", "options": { "raw": { "language": "json" @@ -23047,13 +29853,13 @@ } }, "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId_created_for_member}}", + "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId_created_for_member}}", "host": [ "{{URL}}" ], "path": [ - "work-periods", - "{{workPeriodId_created_for_member}}" + "work-period-payments", + "{{workPeriodPaymentId_created_for_member}}" ] } }, @@ -23062,62 +29868,13 @@ ] }, { - "name": "Work Period Payments", + "name": "Roles", "item": [ { - "name": "Before Test", + "name": "Before Start", "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(\"job_id_created_for_member\", 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\": {{project_id_17234}},\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", + "name": "✔ create role with admin", "event": [ { "listen": "test", @@ -23127,7 +29884,7 @@ " 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_for_member\", response.id);\r", + " pm.environment.set(\"roleId-1\", response.id);\r", " }\r", "});" ], @@ -23146,7 +29903,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"projectId\": {{project_id_17234}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{job_id_created_for_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 \"billingAccountId\": 80000071\r\n}", + "raw": "{\n \"name\": \"Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Dropwizard\",\n \"NGINX\",\n \"Machine Learning\",\n \"Force.com\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10\n },\n {\n \"global\": 25,\n \"inCountry\": 15,\n \"offShore\": 5\n }\n ],\n \"numberOfMembers\": 10,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", "options": { "raw": { "language": "json" @@ -23154,119 +29911,147 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings", + "raw": "{{URL}}/taas-roles", "host": [ "{{URL}}" ], "path": [ - "resourceBookings" + "taas-roles" ] } }, "response": [] - }, + } + ] + }, + { + "name": "✘ create role with member", + "event": [ { - "name": "✔ create work period", - "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_for_member\", response.id);\r", - " }\r", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_administrator}}" - } + "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 \"resourceBookingId\": \"{{resource_bookings_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}}/work-periods", - "host": [ - "{{URL}}" - ], - "path": [ - "work-periods" - ] + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "type": "text", + "value": "Bearer {{token_member}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Dropwizard\",\n \"NGINX\",\n \"Machine Learning\",\n \"Force.com\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10\n },\n {\n \"global\": 25,\n \"inCountry\": 15,\n \"offShore\": 5\n }\n ],\n \"numberOfMembers\": 10,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", + "options": { + "raw": { + "language": "json" } - }, - "response": [] + } }, + "url": { + "raw": "{{URL}}/taas-roles", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles" + ] + } + }, + "response": [] + }, + { + "name": "✔ get role with member", + "event": [ { - "name": "✔ create work period payment", - "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(\"workPeriodPaymentId_created_for_member\", response.id);\r", - " }\r", - "});" - ], - "type": "text/javascript" - } - } + "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_member}}" + } + ], + "url": { + "raw": "{{URL}}/taas-roles/{{roleId-1}}", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles", + "{{roleId-1}}" + ] + } + }, + "response": [] + }, + { + "name": "✔ search roles with member", + "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_member}}" + } + ], + "url": { + "raw": "{{URL}}/taas-roles?keyword=Dev", + "host": [ + "{{URL}}" + ], + "path": [ + "taas-roles" ], - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_administrator}}" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"workPeriodId\": \"{{workPeriodId_created_for_member}}\",\r\n \"amount\": 600,\r\n \"status\": \"completed\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{URL}}/work-period-payments", - "host": [ - "{{URL}}" - ], - "path": [ - "work-period-payments" - ] + "query": [ + { + "key": "keyword", + "value": "Dev" } - }, - "response": [] + ] } - ] + }, + "response": [] }, { - "name": "✘ create work period payment with member", + "name": "✘ update role with member", "event": [ { "listen": "test", @@ -23283,17 +30068,17 @@ } ], "request": { - "method": "POST", + "method": "PATCH", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_member_tester1234}}" + "value": "Bearer {{token_member}}" } ], "body": { "mode": "raw", - "raw": "{\r\n \"workPeriodId\": \"{{workPeriodId_created_for_member}}\",\r\n \"amount\": 600,\r\n \"status\": \"completed\"\r\n}", + "raw": "{\n \"name\": \"Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Teamworking\",\n \"Communication\",\n \"Problem-Solving\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10\n },\n {\n \"global\": 25,\n \"inCountry\": 15,\n \"offShore\": 5\n }\n ],\n \"numberOfMembers\": 10,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", "options": { "raw": { "language": "json" @@ -23301,19 +30086,20 @@ } }, "url": { - "raw": "{{URL}}/work-period-payments", + "raw": "{{URL}}/taas-roles/{{roleId-1}}", "host": [ "{{URL}}" ], "path": [ - "work-period-payments" + "taas-roles", + "{{roleId-1}}" ] } }, "response": [] }, { - "name": "✘ get work period payment with member", + "name": "✘ delete role with member", "event": [ { "listen": "test", @@ -23330,95 +30116,218 @@ } ], "request": { - "method": "GET", + "method": "DELETE", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_member_tester1234}}" + "value": "Bearer {{token_member}}" } ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { - "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId_created_for_member}}", + "raw": "{{URL}}/taas-roles/{{roleId-1}}", "host": [ "{{URL}}" ], "path": [ - "work-period-payments", - "{{workPeriodPaymentId_created_for_member}}" + "taas-roles", + "{{roleId-1}}" ] } }, "response": [] - }, + } + ] + } + ] + }, + { + "name": "Request with Connect Manager Role", + "item": [ + { + "name": "README", + "item": [ { - "name": "✘ search work period payments with member", + "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": [ - "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", - "});" + "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 \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/jobs", + "host": [ + "{{URL}}" + ], + "path": [ + "jobs" + ] + } + }, + "response": [] + }, + { + "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}}/work-period-payments", + "raw": "{{URL}}/jobs/{{job_id_created_by_connect_manager}}", "host": [ "{{URL}}" ], "path": [ - "work-period-payments" + "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 }, { "key": "sortBy", - "value": "status", + "value": "id", "disabled": true }, { "key": "sortOrder", - "value": "desc", + "value": "asc", "disabled": true }, { - "key": "workPeriodId", - "value": "{{workPeriodPaymentId_created_for_member}}", + "key": "projectId", + "value": "21", "disabled": true }, { - "key": "workPeriodIds", - "value": "{{workPeriodPaymentId_created_for_member}},{{workPeriodPaymentId_created_for_member}}", + "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": "completed", + "value": "sourcing", + "disabled": true + }, + { + "key": "workload", + "value": "full-time", + "disabled": true + }, + { + "key": "title", + "value": "dummy", "disabled": true } ] @@ -23427,34 +30336,52 @@ "response": [] }, { - "name": "✘ put work period payment 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_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\": \"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_connect_manager}}", + "host": [ + "{{URL}}" + ], + "path": [ + "jobs", + "{{job_id_created_by_connect_manager}}" + ] } - ], + }, + "response": [] + }, + { + "name": "✔ patch job with connect manager", "request": { - "method": "PUT", + "method": "PATCH", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_member_tester1234}}" + "value": "Bearer {{token_connect_manager_pshahcopmanag2}}" } ], "body": { "mode": "raw", - "raw": "{\r\n \"workPeriodId\": \"{{workPeriodId_created_for_member}}\",\r\n \"amount\": 1600,\r\n \"status\": \"completed\"\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" @@ -23462,47 +30389,32 @@ } }, "url": { - "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId_created_for_member}}", + "raw": "{{URL}}/jobs/{{job_id_created_by_connect_manager}}", "host": [ "{{URL}}" ], "path": [ - "work-period-payments", - "{{workPeriodPaymentId_created_for_member}}" + "jobs", + "{{job_id_created_by_connect_manager}}" ] } }, "response": [] }, { - "name": "✘ patch work period payment 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": "PATCH", + "method": "DELETE", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_member_tester1234}}" + "value": "Bearer {{token_connect_manager_pshahcopmanag2}}" } ], "body": { "mode": "raw", - "raw": "{\r\n \"workPeriodId\": \"{{workPeriodId_created_for_member}}\",\r\n \"amount\": 450,\r\n \"status\": \"cancelled\"\r\n}", + "raw": "", "options": { "raw": { "language": "json" @@ -23510,53 +30422,81 @@ } }, "url": { - "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId_created_for_member}}", + "raw": "{{URL}}/jobs/{{job_id_created_by_connect_manager}}", "host": [ "{{URL}}" ], "path": [ - "work-period-payments", - "{{workPeriodPaymentId_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" } @@ -23567,13 +30507,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" @@ -23581,19 +30521,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": [ @@ -23604,20 +30544,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": [ @@ -23628,22 +30568,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 }, { @@ -23657,53 +30597,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": "selected", "disabled": true } ] @@ -23712,7 +30617,7 @@ "response": [] }, { - "name": "✔ put job with connect manager", + "name": "✔ put job candidate with connect manager", "request": { "method": "PUT", "header": [ @@ -23724,7 +30629,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\": \"placed\",\r\n \"remark\": \"excellent\"\r\n}", "options": { "raw": { "language": "json" @@ -23732,20 +30637,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": [ @@ -23757,7 +30662,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\": \"selected\"\r\n}", "options": { "raw": { "language": "json" @@ -23765,20 +30670,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": [ @@ -23795,29 +30700,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-27\",\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 \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\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": [ @@ -23843,7 +30792,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" @@ -23861,35 +30810,88 @@ } }, "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", + " pm.environment.set(\"interview_id_created_for_connect_manager\", response.id);\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token_administrator}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"templateUrl\": \"interview-30\",\r\n \"calendarEventId\": \"dummyId\",\r\n \"hostEmail\": \"testcustomer@yopmail.com\",\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 401', function () {\r", + " pm.response.to.have.status(401);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"userId: 88774489 the user is not a member of project 111\")\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 \"templateUrl\": \"interview-30\",\r\n \"calendarEventId\": \"dummyId\",\r\n \"hostEmail\": \"testcustomer@yopmail.com\",\r\n \"status\": \"Scheduling\"\r\n}", "options": { "raw": { "language": "json" @@ -23897,115 +30899,128 @@ } }, "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", + "name": "✘ get interview by round with connect manager", + "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(\"userId: 88774489 the user is not a member of project 111\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], "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/{{job_candidate_id_created_for_connect_manager}}", + "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_for_connect_manager}}/interviews/{{interview_round_created_for_connect_manager}}", "host": [ "{{URL}}" ], "path": [ "jobCandidates", - "{{job_candidate_id_created_for_connect_manager}}" + "{{job_candidate_id_created_for_connect_manager}}", + "interviews", + "{{interview_round_created_for_connect_manager}}" ] } }, "response": [] }, { - "name": "✔ search job candidates with connect manager", + "name": "✘ get interview by id with connect manager", + "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(\"userId: 88774489 the user is not a member of project 111\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], "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}}/getInterview/{{interview_id_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": "selected", - "disabled": true - } + "getInterview", + "{{interview_id_created_for_connect_manager}}" ] } }, "response": [] }, { - "name": "✔ put job candidate with connect manager", + "name": "✘ update interview by round with connect manager", + "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(\"userId: 88774489 the user is not a member of project 111\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], "request": { - "method": "PUT", + "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 \"status\": \"placed\"\r\n}", + "raw": "{\r\n \"xaiId\": \"0edc1751-f4ca-4e8e-908a-95f6560311ab\"\r\n}", "options": { "raw": { "language": "json" @@ -24013,32 +31028,49 @@ } }, "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": "✔ patch job candidate with connect manager", + "name": "✘ update interview by id with connect manager", + "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(\"userId: 88774489 the user is not a member of project 111\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], "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\": \"selected\"\r\n}", + "raw": "{\r\n \"xaiId\": \"0edc1751-f4ca-4e8e-908a-95f6560311ab\"\r\n}", "options": { "raw": { "language": "json" @@ -24046,46 +31078,53 @@ } }, "url": { - "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_for_connect_manager}}", + "raw": "{{URL}}/updateInterview/{{interview_id_created_for_connect_manager}}", "host": [ "{{URL}}" ], "path": [ - "jobCandidates", - "{{job_candidate_id_created_for_connect_manager}}" + "updateInterview", + "{{interview_id_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 401', function () {\r", + " pm.response.to.have.status(401);\r", + " const response = pm.response.json()\r", + " pm.expect(response.message).to.eq(\"userId: 88774489 the user is not a member of project 111\")\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" ] } }, @@ -24094,7 +31133,7 @@ ] }, { - "name": "Interviews", + "name": "Resource Bookings", "item": [ { "name": "Before Test", @@ -24107,7 +31146,7 @@ "script": { "exec": [ "var data = JSON.parse(responseBody);\r", - "postman.setEnvironmentVariable(\"job_id_created_for_connect_manager\",data.id);" + "postman.setEnvironmentVariable(\"job_id_created_by_connect_manager\",data.id);" ], "type": "text/javascript" } @@ -24118,13 +31157,13 @@ "header": [ { "key": "Authorization", - "value": "Bearer {{token_administrator}}", + "value": "Bearer {{token_connect_manager_pshahcopmanag2}}", "type": "text" } ], "body": { "mode": "raw", - "raw": "{\n \"projectId\": {{projectId}},\n \"externalId\": \"88774632\",\n \"description\": \"Dummy Description\",\n \"startDate\": \"2020-09-27\",\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": "{\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 \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", "options": { "raw": { "language": "json" @@ -24144,14 +31183,14 @@ "response": [] }, { - "name": "create job candidate", + "name": "create resource booking", "event": [ { "listen": "test", "script": { "exec": [ "var data = JSON.parse(responseBody);\r", - "postman.setEnvironmentVariable(\"job_candidate_id_created_for_connect_manager\",data.id);" + "postman.setEnvironmentVariable(\"resource_booking_id_created_for_connect_manager\",data.id);" ], "type": "text/javascript" } @@ -24168,55 +31207,7 @@ ], "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": [] - }, - { - "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", - " pm.environment.set(\"interview_id_created_for_connect_manager\", response.id);\r", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "PATCH", - "header": [ - { - "key": "Authorization", - "value": "Bearer {{token_administrator}}", - "type": "text" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"templateUrl\": \"interview-30\",\r\n \"calendarEventId\": \"dummyId\",\r\n \"hostEmail\": \"testcustomer@yopmail.com\",\r\n \"status\": \"Scheduling\"\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 \"billingAccountId\": 80000071\r\n}", "options": { "raw": { "language": "json" @@ -24224,14 +31215,12 @@ } }, "url": { - "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_for_connect_manager}}/requestInterview", + "raw": "{{URL}}/resourceBookings", "host": [ "{{URL}}" ], "path": [ - "jobCandidates", - "{{job_candidate_id_created_for_connect_manager}}", - "requestInterview" + "resourceBookings" ] } }, @@ -24240,34 +31229,31 @@ ] }, { - "name": "✘ request interview with connect manager", + "name": "✘ create resource booking with connect manager", "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(\"userId: 88774489 the user is not a member of project 111\")\r", - "});" + "var data = JSON.parse(responseBody);\r", + "postman.setEnvironmentVariable(\"resource_booking_id_created_by_connect_manager\",data.id);" ], "type": "text/javascript" } } ], "request": { - "method": "PATCH", + "method": "POST", "header": [ { "key": "Authorization", - "value": "Bearer {{token_connect_manager_pshahcopmanag2}}", - "type": "text" + "type": "text", + "value": "Bearer {{token_connect_manager_pshahcopmanag2}}" } ], "body": { "mode": "raw", - "raw": "{\r\n \"templateUrl\": \"interview-30\",\r\n \"calendarEventId\": \"dummyId\",\r\n \"hostEmail\": \"testcustomer@yopmail.com\",\r\n \"status\": \"Scheduling\"\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 \"billingAccountId\": 80000071\r\n}", "options": { "raw": { "language": "json" @@ -24275,128 +31261,125 @@ } }, "url": { - "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_for_connect_manager}}/requestInterview", + "raw": "{{URL}}/resourceBookings", "host": [ "{{URL}}" ], "path": [ - "jobCandidates", - "{{job_candidate_id_created_for_connect_manager}}", - "requestInterview" + "resourceBookings" ] } }, "response": [] }, { - "name": "✘ get interview by round with connect manager", - "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(\"userId: 88774489 the user is not a member of project 111\")\r", - "});" - ], - "type": "text/javascript" - } - } - ], + "name": "✔ get resource booking with connect manager", "request": { "method": "GET", "header": [ { "key": "Authorization", - "value": "Bearer {{token_connect_manager_pshahcopmanag2}}", - "type": "text" + "type": "text", + "value": "Bearer {{token_connect_manager_pshahcopmanag2}}" } ], "url": { - "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_for_connect_manager}}/interviews/{{interview_round_created_for_connect_manager}}", + "raw": "{{URL}}/resourceBookings/{{resource_booking_id_created_for_connect_manager}}", "host": [ "{{URL}}" ], "path": [ - "jobCandidates", - "{{job_candidate_id_created_for_connect_manager}}", - "interviews", - "{{interview_round_created_for_connect_manager}}" + "resourceBookings", + "{{resource_booking_id_created_for_connect_manager}}" ] } }, "response": [] }, { - "name": "✘ get interview by id with connect manager", - "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(\"userId: 88774489 the user is not a member of project 111\")\r", - "});" - ], - "type": "text/javascript" - } - } - ], + "name": "✔ search resource bookings with connect manager", "request": { "method": "GET", "header": [ { "key": "Authorization", - "value": "Bearer {{token_connect_manager_pshahcopmanag2}}", - "type": "text" + "type": "text", + "value": "Bearer {{token_connect_manager_pshahcopmanag2}}" } ], "url": { - "raw": "{{URL}}/getInterview/{{interview_id_created_for_connect_manager}}", + "raw": "{{URL}}/resourceBookings", "host": [ "{{URL}}" ], "path": [ - "getInterview", - "{{interview_id_created_for_connect_manager}}" + "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-27", + "disabled": true + }, + { + "key": "endDate", + "value": "2020-09-27", + "disabled": true + }, + { + "key": "rateType", + "value": "hourly", + "disabled": true + }, + { + "key": "status", + "value": "sourcing", + "disabled": true + }, + { + "key": "projectIds", + "value": "111, 16705", + "disabled": true + } ] } }, "response": [] }, { - "name": "✘ update interview by round with connect manager", - "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(\"userId: 88774489 the user is not a member of project 111\")\r", - "});" - ], - "type": "text/javascript" - } - } - ], + "name": "✘ put resource booking with connect manager", "request": { - "method": "PATCH", + "method": "PUT", "header": [ { "key": "Authorization", - "value": "Bearer {{token_connect_manager_pshahcopmanag2}}", - "type": "text" + "type": "text", + "value": "Bearer {{token_connect_manager_pshahcopmanag2}}" } ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiId\": \"0edc1751-f4ca-4e8e-908a-95f6560311ab\"\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" @@ -24404,49 +31387,32 @@ } }, "url": { - "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_for_connect_manager}}/updateInterview/{{interview_round_created_for_connect_manager}}", + "raw": "{{URL}}/resourceBookings/{{resource_booking_id_created_for_connect_manager}}", "host": [ "{{URL}}" ], "path": [ - "jobCandidates", - "{{job_candidate_id_created_for_connect_manager}}", - "updateInterview", - "{{interview_round_created_for_connect_manager}}" + "resourceBookings", + "{{resource_booking_id_created_for_connect_manager}}" ] } }, "response": [] }, { - "name": "✘ update interview by id with connect manager", - "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(\"userId: 88774489 the user is not a member of project 111\")\r", - "});" - ], - "type": "text/javascript" - } - } - ], + "name": "✘ patch resource booking with connect manager", "request": { "method": "PATCH", "header": [ { "key": "Authorization", - "value": "Bearer {{token_connect_manager_pshahcopmanag2}}", - "type": "text" + "type": "text", + "value": "Bearer {{token_connect_manager_pshahcopmanag2}}" } ], "body": { "mode": "raw", - "raw": "{\r\n \"xaiId\": \"0edc1751-f4ca-4e8e-908a-95f6560311ab\"\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" @@ -24454,53 +31420,46 @@ } }, "url": { - "raw": "{{URL}}/updateInterview/{{interview_id_created_for_connect_manager}}", + "raw": "{{URL}}/resourceBookings/{{resource_booking_id_created_for_connect_manager}}", "host": [ "{{URL}}" ], "path": [ - "updateInterview", - "{{interview_id_created_for_connect_manager}}" + "resourceBookings", + "{{resource_booking_id_created_for_connect_manager}}" ] } }, "response": [] }, { - "name": "✘ search interviews with member", - "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(\"userId: 88774489 the user is not a member of project 111\")\r", - "});" - ], - "type": "text/javascript" - } - } - ], + "name": "✘ delete resource booking with connect manager", "request": { - "method": "GET", + "method": "DELETE", "header": [ { "key": "Authorization", - "value": "Bearer {{token_connect_manager_pshahcopmanag2}}", - "type": "text" + "type": "text", + "value": "Bearer {{token_connect_manager_pshahcopmanag2}}" } ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { - "raw": "{{URL}}/jobCandidates/{{job_candidate_id_created_for_connect_manager}}/interviews", + "raw": "{{URL}}/resourceBookings/{{resource_booking_id_created_for_connect_manager}}", "host": [ "{{URL}}" ], "path": [ - "jobCandidates", - "{{job_candidate_id_created_for_connect_manager}}", - "interviews" + "resourceBookings", + "{{resource_booking_id_created_for_connect_manager}}" ] } }, @@ -24509,7 +31468,7 @@ ] }, { - "name": "Resource Bookings", + "name": "Work Periods", "item": [ { "name": "Before Test", @@ -24521,8 +31480,13 @@ "listen": "test", "script": { "exec": [ - "var data = JSON.parse(responseBody);\r", - "postman.setEnvironmentVariable(\"job_id_created_by_connect_manager\",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(\"job_id_created_by_connect_manager\", response.id);\r", + " }\r", + "});" ], "type": "text/javascript" } @@ -24533,13 +31497,13 @@ "header": [ { "key": "Authorization", - "value": "Bearer {{token_connect_manager_pshahcopmanag2}}", + "value": "Bearer {{token_administrator}}", "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}", + "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 \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", "options": { "raw": { "language": "json" @@ -24565,8 +31529,13 @@ "listen": "test", "script": { "exec": [ - "var data = JSON.parse(responseBody);\r", - "postman.setEnvironmentVariable(\"resource_booking_id_created_for_connect_manager\",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(\"resource_booking_id_created_for_connect_manager\", response.id);\r", + " }\r", + "});" ], "type": "text/javascript" } @@ -24601,18 +31570,70 @@ } }, "response": [] + }, + { + "name": "create work period", + "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_for_connect_manager\", 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 \"resourceBookingId\": \"{{resource_booking_id_created_for_connect_manager}}\",\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}}/work-periods", + "host": [ + "{{URL}}" + ], + "path": [ + "work-periods" + ] + } + }, + "response": [] } ] }, { - "name": "✘ create resource booking with connect manager", + "name": "✘ create work period with connect manager", "event": [ { "listen": "test", "script": { "exec": [ - "var data = JSON.parse(responseBody);\r", - "postman.setEnvironmentVariable(\"resource_booking_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" } @@ -24629,7 +31650,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 \"billingAccountId\": 80000071\r\n}", + "raw": "{\r\n \"resourceBookingId\": \"{{resource_booking_id_created_for_connect_manager}}\",\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" @@ -24637,19 +31658,19 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings", + "raw": "{{URL}}/work-periods", "host": [ "{{URL}}" ], "path": [ - "resourceBookings" + "work-periods" ] } }, "response": [] }, { - "name": "✔ get resource booking with connect manager", + "name": "✔ get work period with connect manager", "request": { "method": "GET", "header": [ @@ -24660,20 +31681,20 @@ } ], "url": { - "raw": "{{URL}}/resourceBookings/{{resource_booking_id_created_for_connect_manager}}", + "raw": "{{URL}}/work-periods/{{workPeriodId_created_for_connect_manager}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resource_booking_id_created_for_connect_manager}}" + "work-periods", + "{{workPeriodId_created_for_connect_manager}}" ] } }, "response": [] }, { - "name": "✔ search resource bookings with connect manager", + "name": "✔ search work periods with connect manager", "request": { "method": "GET", "header": [ @@ -24684,12 +31705,12 @@ } ], "url": { - "raw": "{{URL}}/resourceBookings", + "raw": "{{URL}}/work-periods?projectId=16843", "host": [ "{{URL}}" ], "path": [ - "resourceBookings" + "work-periods" ], "query": [ { @@ -24713,29 +31734,38 @@ "disabled": true }, { - "key": "startDate", - "value": "2020-09-27", + "key": "resourceBookingId", + "value": "{{resource_booking_id_created_for_connect_manager}}", "disabled": true }, { - "key": "endDate", - "value": "2020-09-27", + "key": "resourceBookingIds", + "value": "{{resource_booking_id_created_for_connect_manager}},{{resource_booking_id_created_for_connect_manager}}", "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": "16843" } ] } @@ -24743,7 +31773,22 @@ "response": [] }, { - "name": "✘ put resource booking with connect manager", + "name": "✘ put work period 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" + } + } + ], "request": { "method": "PUT", "header": [ @@ -24755,7 +31800,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\": \"placed\",\r\n \"billingAccountId\": 80000071\r\n}", + "raw": "{\r\n \"resourceBookingId\": \"{{resource_booking_id_created_for_connect_manager}}\",\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" @@ -24763,20 +31808,35 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{resource_booking_id_created_for_connect_manager}}", + "raw": "{{URL}}/work-periods/{{workPeriodId_created_for_connect_manager}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resource_booking_id_created_for_connect_manager}}" + "work-periods", + "{{workPeriodId_created_for_connect_manager}}" ] } }, "response": [] }, { - "name": "✘ patch resource booking with connect manager", + "name": "✘ patch work period 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" + } + } + ], "request": { "method": "PATCH", "header": [ @@ -24788,7 +31848,7 @@ ], "body": { "mode": "raw", - "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}", + "raw": "{\r\n \"resourceBookingId\": \"{{resource_booking_id_created_for_connect_manager}}\",\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" @@ -24796,20 +31856,35 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{resource_booking_id_created_for_connect_manager}}", + "raw": "{{URL}}/work-periods/{{workPeriodId_created_for_connect_manager}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resource_booking_id_created_for_connect_manager}}" + "work-periods", + "{{workPeriodId_created_for_connect_manager}}" ] } }, "response": [] }, { - "name": "✘ delete resource booking with connect manager", + "name": "✘ delete work period 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" + } + } + ], "request": { "method": "DELETE", "header": [ @@ -24829,13 +31904,13 @@ } }, "url": { - "raw": "{{URL}}/resourceBookings/{{resource_booking_id_created_for_connect_manager}}", + "raw": "{{URL}}/work-periods/{{workPeriodId_created_for_connect_manager}}", "host": [ "{{URL}}" ], "path": [ - "resourceBookings", - "{{resource_booking_id_created_for_connect_manager}}" + "work-periods", + "{{workPeriodId_created_for_connect_manager}}" ] } }, @@ -24844,13 +31919,13 @@ ] }, { - "name": "Work Periods", + "name": "Work Period Payments", "item": [ { "name": "Before Test", "item": [ { - "name": "create job", + "name": "✔ create job", "event": [ { "listen": "test", @@ -24860,7 +31935,7 @@ " 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_connect_manager\", response.id);\r", + " pm.environment.set(\"job_id_created_for_connect_manager\", response.id);\r", " }\r", "});" ], @@ -24879,7 +31954,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\": \"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": "{\n \"projectId\": {{project_id_17234}},\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 \"minSalary\": 100,\n \"maxSalary\": 200,\n \"hoursPerWeek\": 20,\n \"jobLocation\": \"Any location\",\n \"jobTimezone\": \"GMT\",\n \"currency\": \"USD\"\n}", "options": { "raw": { "language": "json" @@ -24899,7 +31974,7 @@ "response": [] }, { - "name": "create resource booking", + "name": "✔ create resource booking", "event": [ { "listen": "test", @@ -24909,7 +31984,7 @@ " pm.response.to.have.status(200);\r", " if(pm.response.status === \"OK\"){\r", " const response = pm.response.json()\r", - " pm.environment.set(\"resource_booking_id_created_for_connect_manager\", response.id);\r", + " pm.environment.set(\"resource_bookings_id_created_for_connect_manager\", response.id);\r", " }\r", "});" ], @@ -24928,7 +32003,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 \"billingAccountId\": 80000071\r\n}", + "raw": "{\r\n \"projectId\": {{project_id_17234}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{job_id_created_for_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 \"billingAccountId\": 80000071\r\n}", "options": { "raw": { "language": "json" @@ -24948,7 +32023,7 @@ "response": [] }, { - "name": "create work period", + "name": "✔ create work period", "event": [ { "listen": "test", @@ -24977,7 +32052,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resource_booking_id_created_for_connect_manager}}\",\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 \"resourceBookingId\": \"{{resource_bookings_id_created_for_connect_manager}}\",\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" @@ -24995,11 +32070,60 @@ } }, "response": [] + }, + { + "name": "✔ create work period payment", + "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(\"workPeriodPaymentId_created_for_connect_manager\", 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 \"workPeriodId\": \"{{workPeriodId_created_for_connect_manager}}\",\r\n \"amount\": 600,\r\n \"status\": \"completed\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{URL}}/work-period-payments", + "host": [ + "{{URL}}" + ], + "path": [ + "work-period-payments" + ] + } + }, + "response": [] } ] }, { - "name": "✘ create work period with connect manager", + "name": "✘ create work period payment with connect manager", "event": [ { "listen": "test", @@ -25026,7 +32150,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resource_booking_id_created_for_connect_manager}}\",\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 \"workPeriodId\": \"{{workPeriodId_created_for_connect_manager}}\",\r\n \"amount\": 600,\r\n \"status\": \"completed\"\r\n}", "options": { "raw": { "language": "json" @@ -25034,21 +32158,36 @@ } }, "url": { - "raw": "{{URL}}/work-periods", + "raw": "{{URL}}/work-period-payments", "host": [ "{{URL}}" ], "path": [ - "work-periods" + "work-period-payments" ] } }, "response": [] }, { - "name": "✔ get work period with connect manager", + "name": "✘ create query work period payment 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" + } + } + ], "request": { - "method": "GET", + "method": "POST", "header": [ { "key": "Authorization", @@ -25056,21 +32195,45 @@ "value": "Bearer {{token_connect_manager_pshahcopmanag2}}" } ], + "body": { + "mode": "raw", + "raw": "{\"query\": { \"workPeriods.paymentStatus\": \"pending\" } }", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId_created_for_connect_manager}}", + "raw": "{{URL}}/work-period-payments/query", "host": [ "{{URL}}" ], "path": [ - "work-periods", - "{{workPeriodId_created_for_connect_manager}}" + "work-period-payments", + "query" ] } }, "response": [] }, { - "name": "✔ search work periods with connect manager", + "name": "✘ get work period payment 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" + } + } + ], "request": { "method": "GET", "header": [ @@ -25081,75 +32244,20 @@ } ], "url": { - "raw": "{{URL}}/work-periods?projectId=16843", + "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId_created_for_connect_manager}}", "host": [ "{{URL}}" ], "path": [ - "work-periods" - ], - "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_connect_manager}}", - "disabled": true - }, - { - "key": "resourceBookingIds", - "value": "{{resource_booking_id_created_for_connect_manager}},{{resource_booking_id_created_for_connect_manager}}", - "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": "16843" - } + "work-period-payments", + "{{workPeriodPaymentId_created_for_connect_manager}}" ] } }, "response": [] }, { - "name": "✘ put work period with connect manager", + "name": "✘ search work period payments with connect manager", "event": [ { "listen": "test", @@ -25166,7 +32274,7 @@ } ], "request": { - "method": "PUT", + "method": "GET", "header": [ { "key": "Authorization", @@ -25174,30 +32282,57 @@ "value": "Bearer {{token_connect_manager_pshahcopmanag2}}" } ], - "body": { - "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resource_booking_id_created_for_connect_manager}}\",\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}}/work-periods/{{workPeriodId_created_for_connect_manager}}", + "raw": "{{URL}}/work-period-payments", "host": [ "{{URL}}" ], "path": [ - "work-periods", - "{{workPeriodId_created_for_connect_manager}}" + "work-period-payments" + ], + "query": [ + { + "key": "page", + "value": "1", + "disabled": true + }, + { + "key": "perPage", + "value": "5", + "disabled": true + }, + { + "key": "sortBy", + "value": "status", + "disabled": true + }, + { + "key": "sortOrder", + "value": "desc", + "disabled": true + }, + { + "key": "workPeriodId", + "value": "{{workPeriodPaymentId_created_for_connect_manager}}", + "disabled": true + }, + { + "key": "workPeriodIds", + "value": "{{workPeriodPaymentId_created_for_connect_manager}},{{workPeriodPaymentId_created_for_connect_manager}}", + "disabled": true + }, + { + "key": "status", + "value": "completed", + "disabled": true + } ] } }, "response": [] }, { - "name": "✘ patch work period with connect manager", + "name": "✘ put work period payment with connect manager", "event": [ { "listen": "test", @@ -25214,7 +32349,7 @@ } ], "request": { - "method": "PATCH", + "method": "PUT", "header": [ { "key": "Authorization", @@ -25224,7 +32359,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"resourceBookingId\": \"{{resource_booking_id_created_for_connect_manager}}\",\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 \"workPeriodId\": \"{{workPeriodId_created_for_connect_manager}}\",\r\n \"amount\": 1600,\r\n \"status\": \"completed\"\r\n}", "options": { "raw": { "language": "json" @@ -25232,20 +32367,20 @@ } }, "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId_created_for_connect_manager}}", + "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId_created_for_connect_manager}}", "host": [ "{{URL}}" ], "path": [ - "work-periods", - "{{workPeriodId_created_for_connect_manager}}" + "work-period-payments", + "{{workPeriodPaymentId_created_for_connect_manager}}" ] } }, "response": [] }, { - "name": "✘ delete work period with connect manager", + "name": "✘ patch work period payment with connect manager", "event": [ { "listen": "test", @@ -25262,7 +32397,7 @@ } ], "request": { - "method": "DELETE", + "method": "PATCH", "header": [ { "key": "Authorization", @@ -25272,7 +32407,7 @@ ], "body": { "mode": "raw", - "raw": "", + "raw": "{\r\n \"workPeriodId\": \"{{workPeriodId_created_for_connect_manager}}\",\r\n \"amount\": 450,\r\n \"status\": \"cancelled\"\r\n}", "options": { "raw": { "language": "json" @@ -25280,13 +32415,13 @@ } }, "url": { - "raw": "{{URL}}/work-periods/{{workPeriodId_created_for_connect_manager}}", + "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId_created_for_connect_manager}}", "host": [ "{{URL}}" ], "path": [ - "work-periods", - "{{workPeriodId_created_for_connect_manager}}" + "work-period-payments", + "{{workPeriodPaymentId_created_for_connect_manager}}" ] } }, @@ -25295,160 +32430,13 @@ ] }, { - "name": "Work Period Payments", + "name": "Roles", "item": [ { - "name": "Before Test", + "name": "Before Start", "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(\"job_id_created_for_connect_manager\", 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\": {{project_id_17234}},\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(\"resource_bookings_id_created_for_connect_manager\", 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\": {{project_id_17234}},\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"jobId\": \"{{job_id_created_for_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 \"billingAccountId\": 80000071\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{URL}}/resourceBookings", - "host": [ - "{{URL}}" - ], - "path": [ - "resourceBookings" - ] - } - }, - "response": [] - }, - { - "name": "✔ create work period", - "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_for_connect_manager\", 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 \"resourceBookingId\": \"{{resource_bookings_id_created_for_connect_manager}}\",\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}}/work-periods", - "host": [ - "{{URL}}" - ], - "path": [ - "work-periods" - ] - } - }, - "response": [] - }, - { - "name": "✔ create work period payment", + "name": "✔ create role with admin", "event": [ { "listen": "test", @@ -25458,7 +32446,7 @@ " pm.response.to.have.status(200);\r", " if(pm.response.status === \"OK\"){\r", " const response = pm.response.json()\r", - " pm.environment.set(\"workPeriodPaymentId_created_for_connect_manager\", response.id);\r", + " pm.environment.set(\"roleId-1\", response.id);\r", " }\r", "});" ], @@ -25477,7 +32465,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"workPeriodId\": \"{{workPeriodId_created_for_connect_manager}}\",\r\n \"amount\": 600,\r\n \"status\": \"completed\"\r\n}", + "raw": "{\n \"name\": \"Dev Ops Engineer 2\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Dropwizard\",\n \"NGINX\",\n \"Machine Learning\",\n \"Force.com\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10\n },\n {\n \"global\": 25,\n \"inCountry\": 15,\n \"offShore\": 5\n }\n ],\n \"numberOfMembers\": 10,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", "options": { "raw": { "language": "json" @@ -25485,12 +32473,12 @@ } }, "url": { - "raw": "{{URL}}/work-period-payments", + "raw": "{{URL}}/taas-roles", "host": [ "{{URL}}" ], "path": [ - "work-period-payments" + "taas-roles" ] } }, @@ -25499,7 +32487,7 @@ ] }, { - "name": "✘ create work period payment with connect manager", + "name": "✘ create role with connect user", "event": [ { "listen": "test", @@ -25521,12 +32509,12 @@ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_connect_manager_pshahcopmanag2}}" + "value": "Bearer {{token_connectUser}}" } ], "body": { "mode": "raw", - "raw": "{\r\n \"workPeriodId\": \"{{workPeriodId_created_for_connect_manager}}\",\r\n \"amount\": 600,\r\n \"status\": \"completed\"\r\n}", + "raw": "{\n \"name\": \"Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Dropwizard\",\n \"NGINX\",\n \"Machine Learning\",\n \"Force.com\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10\n },\n {\n \"global\": 25,\n \"inCountry\": 15,\n \"offShore\": 5\n }\n ],\n \"numberOfMembers\": 10,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", "options": { "raw": { "language": "json" @@ -25534,28 +32522,26 @@ } }, "url": { - "raw": "{{URL}}/work-period-payments", + "raw": "{{URL}}/taas-roles", "host": [ "{{URL}}" ], "path": [ - "work-period-payments" + "taas-roles" ] } }, "response": [] }, { - "name": "✘ get work period payment with connect manager", + "name": "✔ get role 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", + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", "});" ], "type": "text/javascript" @@ -25568,33 +32554,31 @@ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_connect_manager_pshahcopmanag2}}" + "value": "Bearer {{token_connectUser}}" } ], "url": { - "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId_created_for_connect_manager}}", + "raw": "{{URL}}/taas-roles/{{roleId-1}}", "host": [ "{{URL}}" ], "path": [ - "work-period-payments", - "{{workPeriodPaymentId_created_for_connect_manager}}" + "taas-roles", + "{{roleId-1}}" ] } }, "response": [] }, { - "name": "✘ search work period payments with connect manager", + "name": "✔ search roles 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", + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", "});" ], "type": "text/javascript" @@ -25607,52 +32591,25 @@ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_connect_manager_pshahcopmanag2}}" + "value": "Bearer {{token_connectUser}}" } ], "url": { - "raw": "{{URL}}/work-period-payments", + "raw": "{{URL}}/taas-roles?skillsList=Dropwizard, ,NGINX&keyword=Dev", "host": [ "{{URL}}" ], "path": [ - "work-period-payments" + "taas-roles" ], "query": [ { - "key": "page", - "value": "1", - "disabled": true - }, - { - "key": "perPage", - "value": "5", - "disabled": true - }, - { - "key": "sortBy", - "value": "status", - "disabled": true - }, - { - "key": "sortOrder", - "value": "desc", - "disabled": true - }, - { - "key": "workPeriodId", - "value": "{{workPeriodPaymentId_created_for_connect_manager}}", - "disabled": true - }, - { - "key": "workPeriodIds", - "value": "{{workPeriodPaymentId_created_for_connect_manager}},{{workPeriodPaymentId_created_for_connect_manager}}", - "disabled": true + "key": "skillsList", + "value": "Dropwizard, ,NGINX" }, { - "key": "status", - "value": "completed", - "disabled": true + "key": "keyword", + "value": "Dev" } ] } @@ -25660,7 +32617,7 @@ "response": [] }, { - "name": "✘ put work period payment with connect manager", + "name": "✘ update role with connect user", "event": [ { "listen": "test", @@ -25677,17 +32634,17 @@ } ], "request": { - "method": "PUT", + "method": "PATCH", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_connect_manager_pshahcopmanag2}}" + "value": "Bearer {{token_connectUser}}" } ], "body": { "mode": "raw", - "raw": "{\r\n \"workPeriodId\": \"{{workPeriodId_created_for_connect_manager}}\",\r\n \"amount\": 1600,\r\n \"status\": \"completed\"\r\n}", + "raw": "{\n \"name\": \"Dev Ops Engineer\",\n \"description\": \"A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.\",\n \"listOfSkills\": [\n \"Teamworking\",\n \"Communication\",\n \"Problem-Solving\"\n ],\n \"rates\": [\n {\n \"global\": 50,\n \"inCountry\": 20,\n \"offShore\": 10\n },\n {\n \"global\": 25,\n \"inCountry\": 15,\n \"offShore\": 5\n }\n ],\n \"numberOfMembers\": 10,\n \"imageUrl\": \"http://images.topcoder.com/member\",\n \"timeToCandidate\": 105,\n \"timeToInterview\": 100\n}", "options": { "raw": { "language": "json" @@ -25695,20 +32652,20 @@ } }, "url": { - "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId_created_for_connect_manager}}", + "raw": "{{URL}}/taas-roles/{{roleId-1}}", "host": [ "{{URL}}" ], "path": [ - "work-period-payments", - "{{workPeriodPaymentId_created_for_connect_manager}}" + "taas-roles", + "{{roleId-1}}" ] } }, "response": [] }, { - "name": "✘ patch work period payment with connect manager", + "name": "✘ delete role with connect user", "event": [ { "listen": "test", @@ -25725,17 +32682,17 @@ } ], "request": { - "method": "PATCH", + "method": "DELETE", "header": [ { "key": "Authorization", "type": "text", - "value": "Bearer {{token_connect_manager_pshahcopmanag2}}" + "value": "Bearer {{token_connectUser}}" } ], "body": { "mode": "raw", - "raw": "{\r\n \"workPeriodId\": \"{{workPeriodId_created_for_connect_manager}}\",\r\n \"amount\": 450,\r\n \"status\": \"cancelled\"\r\n}", + "raw": "", "options": { "raw": { "language": "json" @@ -25743,13 +32700,13 @@ } }, "url": { - "raw": "{{URL}}/work-period-payments/{{workPeriodPaymentId_created_for_connect_manager}}", + "raw": "{{URL}}/taas-roles/{{roleId-1}}", "host": [ "{{URL}}" ], "path": [ - "work-period-payments", - "{{workPeriodPaymentId_created_for_connect_manager}}" + "taas-roles", + "{{roleId-1}}" ] } }, diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 0a9fe80d..a8abc4e4 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -18,6 +18,8 @@ tags: - name: ResourceBookings - name: Teams - name: WorkPeriods + - name: WorkPeriodPayments + - name: Roles paths: /jobs: post: @@ -172,7 +174,7 @@ paths: required: false schema: type: string - enum: ["hourly", "daily", "weekly", "monthly"] + enum: ["hourly", "daily", "weekly", "monthly", "annual"] description: The rate type. - in: query name: status @@ -181,6 +183,11 @@ paths: type: string enum: ["sourcing", "in-review", "assigned", "closed", "cancelled"] description: The rate type. + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/JobSearchBody" responses: "200": description: OK @@ -603,6 +610,12 @@ paths: "cancelled", "interview", "topcoder-rejected", + "applied", + "rejected-pre-screen", + "skills-test", + "phone-screen", + "job-closed", + "offered", ] description: The job candidate status. - in: query @@ -1385,6 +1398,12 @@ paths: security: - bearerAuth: [] parameters: + - in: query + name: fields + description: the field names to be returned from both ResourceBooking and WorkPeriod + required: false + schema: + type: string - in: query name: page required: false @@ -1414,6 +1433,11 @@ paths: "rateType", "customerRate", "memberRate", + "workPeriods.userHandle", + "workPeriods.daysWorked", + "workPeriods.customerRate", + "workPeriods.memberRate", + "workPeriods.paymentStatus", ] description: The sort by column. - in: query @@ -1477,6 +1501,42 @@ paths: schema: type: string description: comma separated project ids. + - in: query + name: workPeriods.paymentStatus + required: false + schema: + oneOf: + - type: array + items: + type: string + enum: + ["pending", "partially-completed", "completed", "cancelled"] + - type: string + enum: + ["pending", "partially-completed", "completed", "cancelled"] + description: comma separated payment status. + - in: query + name: workPeriods.startDate + required: false + schema: + type: string + format: date + pattern: '^\d{4}-\d{2}-\d{2}$' + description: The work period start date. + - in: query + name: workPeriods.endDate + required: false + schema: + type: string + format: date + pattern: '^\d{4}-\d{2}-\d{2}$' + description: The work period end date. + - in: query + name: workPeriods.userHandle + required: false + schema: + type: string + description: The user handle. responses: "200": @@ -1565,6 +1625,12 @@ paths: required: false schema: type: boolean + - in: query + name: fields + description: the field names to be returned from both ResourceBooking and WorkPeriod + required: false + schema: + type: string responses: "200": description: OK @@ -1773,57 +1839,6 @@ paths: schema: $ref: "#/components/schemas/Error" /work-periods: - post: - tags: - - WorkPeriods - description: | - Create Work Period. - - **Authorization** Topcoder token with write Work period scope is allowed - security: - - bearerAuth: [] - requestBody: - content: - application/json: - schema: - $ref: "#/components/schemas/WorkPeriodRequestBody" - responses: - "200": - description: OK - content: - application/json: - schema: - $ref: "#/components/schemas/WorkPeriod" - "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" get: tags: - WorkPeriods @@ -1897,9 +1912,30 @@ paths: name: paymentStatus required: false schema: - type: string - enum: ["pending", "partially-completed", "completed", "cancelled"] - description: The payment status. + oneOf: + - type: array + items: + type: string + enum: + [ + "pending", + "partially-completed", + "completed", + "in-progress", + "failed", + "no-days", + ] + - type: string + enum: + [ + "pending", + "partially-completed", + "completed", + "in-progress", + "failed", + "no-days", + ] + description: comma separated payment status. - in: query name: startDate required: false @@ -2052,61 +2088,11 @@ paths: application/json: schema: $ref: "#/components/schemas/Error" - delete: - tags: - - WorkPeriods - description: | - Delete the work period. - - **Authorization** Topcoder token with delete work period scope is allowed - security: - - bearerAuth: [] - parameters: - - in: path - name: id - description: The id of work period. - required: true - schema: - type: string - format: uuid - responses: - "204": - description: OK - "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" - put: + patch: tags: - WorkPeriods description: | - Update the work period. + Partial Update work period. **Authorization** Topcoder token with update work period scope is allowed security: @@ -2123,7 +2109,7 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/WorkPeriodRequestBody" + $ref: "#/components/schemas/WorkPeriodPatchRequestBody" responses: "200": description: OK @@ -2155,61 +2141,8 @@ paths: application/json: schema: $ref: "#/components/schemas/Error" - "500": - description: Internal Server Error - content: - application/json: - schema: - $ref: "#/components/schemas/Error" - patch: - tags: - - WorkPeriods - description: | - Partial Update work period. - - **Authorization** Topcoder token with update work period scope is allowed - security: - - bearerAuth: [] - parameters: - - in: path - name: id - description: The id of work period. - required: true - schema: - type: string - format: uuid - requestBody: - content: - application/json: - schema: - $ref: "#/components/schemas/WorkPeriodPatchRequestBody" - responses: - "200": - description: OK - content: - application/json: - schema: - $ref: "#/components/schemas/WorkPeriod" - "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 + "409": + description: Conflict content: application/json: schema: @@ -2234,14 +2167,24 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/WorkPeriodPaymentRequestBody" + oneOf: + - $ref: "#/components/schemas/WorkPeriodPaymentCreateRequestBody" + - type: array + items: + $ref: "#/components/schemas/WorkPeriodPaymentCreateRequestBody" responses: "200": description: OK content: application/json: schema: - $ref: "#/components/schemas/WorkPeriodPayment" + oneOf: + - $ref: "#/components/schemas/WorkPeriodPayment" + - type: array + items: + oneOf: + - $ref: "#/components/schemas/WorkPeriodPayment" + - $ref: "#/components/schemas/WorkPeriodPaymentCreatedError" "400": description: Bad request content: @@ -2266,6 +2209,12 @@ paths: application/json: schema: $ref: "#/components/schemas/Error" + "409": + description: Conflict + content: + application/json: + schema: + $ref: "#/components/schemas/Error" "500": description: Internal Server Error content: @@ -2334,7 +2283,8 @@ paths: required: false schema: type: string - enum: ["completed", "cancelled"] + enum: + ["completed", "scheduled", "in-progress", "failed", "cancelled"] description: The payment status. responses: "200": @@ -2398,38 +2348,28 @@ paths: application/json: schema: $ref: "#/components/schemas/Error" - /work-period-payments/{id}: - get: + /work-period-payments/query: + post: tags: - WorkPeriodPayments description: | - Get work period payment by id. + Create Multiple Work Period Payments for all the pages at once. - **Authorization** Topcoder token with read work period payment scope is allowed + **Authorization** Topcoder token with write Work period payment scope is allowed security: - bearerAuth: [] - parameters: - - in: path - name: id - description: The work period payment id. - required: true - schema: - type: string - format: uuid - - in: query - name: fromDb - description: get data from db or not. - required: false - schema: - type: boolean - default: false + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/WorkPeriodPaymentQueryCreateRequestBody" responses: "200": description: OK content: application/json: schema: - $ref: "#/components/schemas/WorkPeriodPayment" + $ref: "#/components/schemas/WorkPeriodPaymentQueryCreateResult" "400": description: Bad request content: @@ -2460,31 +2400,35 @@ paths: application/json: schema: $ref: "#/components/schemas/Error" - put: + + /work-period-payments/{id}: + get: tags: - WorkPeriodPayments description: | - Update the work period payment. + Get work period payment by id. - **Authorization** Topcoder token with update work period payment scope is allowed + **Authorization** Topcoder token with read work period payment scope is allowed security: - bearerAuth: [] parameters: - in: path name: id - description: The id of work period payment. + description: The work period payment id. required: true schema: type: string format: uuid - requestBody: - content: - application/json: - schema: - $ref: "#/components/schemas/WorkPeriodPaymentRequestBody" - responses: - "200": - description: OK + - in: query + name: fromDb + description: get data from db or not. + required: false + schema: + type: boolean + default: false + responses: + "200": + description: OK content: application/json: schema: @@ -3113,6 +3057,46 @@ paths: application/json: schema: $ref: "#/components/schemas/Error" + + /taas-teams/getSkillsByJobDescription: + post: + tags: + - Teams + description: | + Get skill list by Job Description + security: + - bearerAuth: [] + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/TeamJobDescriptionRequestBody" + responses: + "200": + description: OK + content: + application/json: + schema: + type: array + items: { $ref: "#/components/schemas/SkillItem" } + "400": + description: Bad request + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "401": + description: Not authenticated + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "500": + description: Internal Server Error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" /taas-teams/email: post: tags: @@ -3199,6 +3183,364 @@ paths: application/json: schema: $ref: "#/components/schemas/Error" + /taas-teams/sendRoleSearchRequest: + post: + tags: + - Teams + description: | + Perform a role search operaion + + **Authorization** Any Topcoder user with valid token is allowed. For not logged users Topcoder m2m token with create:taas-roleSearchRequests scope is allowed. + security: + - bearerAuth: [] + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/RoleSearchRequestBody" + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/RoleSearchResponse" + "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" + "500": + description: Internal Server Error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + /taas-teams/submitTeamRequest: + post: + tags: + - Teams + description: | + Creates new Team in persistence and new project that will source this team in Connect. + + **Authorization** Any Topcoder user with valid token is allowed. For not logged users Topcoder m2m token with create:taas-teams scope is allowed. + security: + - bearerAuth: [] + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/SubmitTeamRequestBody" + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/SubmitTeamResponse" + "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" + "409": + description: Conflict + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "500": + description: Internal Server Error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + /taas-roles: + post: + tags: + - Roles + description: | + Create Role. + + **Authorization** Topcoder m2m token with create scope is allowed. Topcoder user token with administrator or bookingmanager role is allowed. + security: + - bearerAuth: [] + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/RoleRequestBody" + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/Role" + "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" + "500": + description: Internal Server Error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + get: + tags: + - Roles + description: | + Search roles. + + **Authorization** Topcoder m2m token with read scope is allowed. Topcoder user token with any role is allowed. + security: + - bearerAuth: [] + parameters: + - in: query + name: skillsList + required: false + schema: + type: string + description: comma separated skill names. case-insensitive. + - in: query + name: keyword + required: false + schema: + type: string + description: role name. case-insensitive. partial match allowed + responses: + "200": + description: OK + content: + application/json: + schema: + type: array + items: + $ref: "#/components/schemas/Role" + "400": + description: Bad request + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "401": + description: Not authenticated + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "500": + description: Internal Server Error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + /taas-roles/{id}: + get: + tags: + - Roles + description: | + Get role by id. + + **Authorization** Topcoder m2m token with read scope is allowed. Topcoder user token with any role is allowed. + security: + - bearerAuth: [] + parameters: + - in: path + name: id + description: The role id. + required: true + schema: + type: string + format: uuid + - in: query + name: fromDb + description: get data from db or not. + required: false + schema: + type: boolean + default: false + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/Role" + "400": + description: Bad request + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "401": + description: Not authenticated + 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" + patch: + tags: + - Roles + description: | + Partial Update role. + + **Authorization** Topcoder m2m token with update scope is allowed. Topcoder user token with administrator or bookingmanager role is allowed. + security: + - bearerAuth: [] + parameters: + - in: path + name: id + description: The id of role. + required: true + schema: + type: string + format: uuid + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/RolePatchRequestBody" + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/Role" + "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" + delete: + tags: + - Roles + description: | + Delete the role. + + **Authorization** Topcoder m2m token with delete scope is allowed. Topcoder user token with administrator or bookingmanager role is allowed. + security: + - bearerAuth: [] + parameters: + - in: path + name: id + description: The id of role. + required: true + schema: + type: string + format: uuid + responses: + "204": + description: OK + "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" /health: get: tags: @@ -3225,6 +3567,18 @@ components: scheme: bearer bearerFormat: JWT schemas: + SkillItem: + properties: + tag: + type: string + example: "Java" + type: + type: string + example: "taas_skill" + source: + type: string + example: "taas-jd-parser" + Job: required: - id @@ -3233,6 +3587,12 @@ components: - numPositions - skills - status + - minSalary + - maxSalary + - hoursPerWeek + - jobLocation + - jobTimezone + - currency - createdAt - createdBy properties: @@ -3289,6 +3649,13 @@ components: type: string format: uuid description: "The skill id." + roleIds: + type: array + description: "The roles." + items: + type: string + format: uuid + description: "The role id." status: type: string enum: ["sourcing", "in-review", "assigned", "closed", "cancelled"] @@ -3301,6 +3668,30 @@ components: isApplicationPageActive: type: boolean default: false + minSalary: + type: integer + example: 1000 + description: "the amount of minimum salary" + maxSalary: + type: integer + example: 3000 + description: "the amount of maximum salary" + hoursPerWeek: + type: integer + example: 20 + description: "the amount working hours per week" + jobLocation: + type: string + example: "Any location" + description: "the location of job" + jobTimezone: + type: string + example: "GMT" + description: "the timezone of job" + currency: + type: string + example: "USD" + description: "the currency of job" createdAt: type: string format: date-time @@ -3317,12 +3708,27 @@ components: type: string example: "topcoder user" description: "The user who updated the job last time.(Will get the user info from the token)" + JobSearchBody: + properties: + jobIds: + type: array + items: + type: string + format: uuid + description: "The array of job ids" + JobRequestBody: required: - projectId - title - numPositions - skills + - minSalary + - maxSalary + - hoursPerWeek + - jobLocation + - jobTimezone + - currency properties: projectId: type: integer @@ -3378,9 +3784,40 @@ components: type: string format: uuid description: "The skill id." + roleIds: + type: array + description: "The roles." + items: + type: string + format: uuid + description: "The role id." isApplicationPageActive: type: boolean default: false + minSalary: + type: integer + example: 1000 + description: "the amount of minimum salary" + maxSalary: + type: integer + example: 3000 + description: "the amount of maximum salary" + hoursPerWeek: + type: integer + example: 20 + description: "the amount working hours per week" + jobLocation: + type: string + example: "Any location" + description: "the location of job" + jobTimezone: + type: string + example: "GMT" + description: "the timezone of job" + currency: + type: string + example: "USD" + description: "the currency of job" JobCandidate: required: - id @@ -3424,6 +3861,10 @@ components: type: string example: "http://example.com" description: "The resume link" + remark: + type: string + example: "excellent" + description: "The remark of candidate" createdAt: type: string format: date-time @@ -3480,6 +3921,10 @@ components: type: string example: "http://example.com" description: "The resume link" + remark: + type: string + example: "excellent" + description: "The remark of candidate" interviews: type: array description: "Interviews associated to this job candidate." @@ -3517,7 +3962,18 @@ components: description: "The user id." status: type: string - enum: ["open", "placed", "selected", "client rejected - screening", "client rejected - interview", "rejected - other", "cancelled", "interview", "topcoder-rejected"] + enum: + [ + "open", + "placed", + "selected", + "client rejected - screening", + "client rejected - interview", + "rejected - other", + "cancelled", + "interview", + "topcoder-rejected", + ] description: "The job candidate status." default: open externalId: @@ -3528,6 +3984,10 @@ components: type: string example: "http://example.com" description: "The resume link" + remark: + type: string + example: "excellent" + description: "The remark of candidate" JobCandidatePatchRequestBody: properties: status: @@ -3552,6 +4012,10 @@ components: type: string example: "http://example.com" description: "The resume link" + remark: + type: string + example: "excellent" + description: "The remark of candidate" Interview: required: - id @@ -3632,7 +4096,15 @@ components: description: "Interview end time." status: type: string - enum: ["Scheduling", "Scheduled", "Requested for reschedule", "Rescheduled", "Completed", "Cancelled"] + enum: + [ + "Scheduling", + "Scheduled", + "Requested for reschedule", + "Rescheduled", + "Completed", + "Cancelled", + ] description: "The interview status." rescheduleUrl: type: string @@ -3678,7 +4150,15 @@ components: format: email status: type: string - enum: ["Scheduling", "Scheduled", "Requested for reschedule", "Rescheduled", "Completed", "Cancelled"] + enum: + [ + "Scheduling", + "Scheduled", + "Requested for reschedule", + "Rescheduled", + "Completed", + "Cancelled", + ] default: "Scheduling" description: "The interview status." UpdateInterviewRequestBody: @@ -3737,7 +4217,15 @@ components: description: "Interview end time." status: type: string - enum: ["Scheduling", "Scheduled", "Requested for reschedule", "Rescheduled", "Completed", "Cancelled"] + enum: + [ + "Scheduling", + "Scheduled", + "Requested for reschedule", + "Rescheduled", + "Completed", + "Cancelled", + ] description: "The interview status." rescheduleUrl: type: string @@ -3784,9 +4272,40 @@ components: type: string format: uuid description: "The skill id." + roleIds: + type: array + description: "The roles." + items: + type: string + format: uuid + description: "The role id." isApplicationPageActive: type: boolean default: false + minSalary: + type: integer + example: 1000 + description: "the amount of minimum salary" + maxSalary: + type: integer + example: 3000 + description: "the amount of maximum salary" + hoursPerWeek: + type: integer + example: 20 + description: "the amount working hours per week" + jobLocation: + type: string + example: "Any location" + description: "the location of job" + jobTimezone: + type: string + example: "GMT" + description: "the timezone of job" + currency: + type: string + example: "USD" + description: "the currency of job" ResourceBooking: required: - id @@ -3845,7 +4364,12 @@ components: billingAccountId: type: integer example: 80000071 - description: 'the billing account id for payments' + description: "the billing account id for payments" + workPeriods: + type: array + description: "The work periods related with resource booking" + items: + $ref: "#/components/schemas/WorkPeriod" createdAt: type: string format: date-time @@ -3913,7 +4437,7 @@ components: billingAccountId: type: integer example: 80000071 - description: 'the billing account id for payments' + description: "the billing account id for payments" ResourceBookingPatchRequestBody: properties: status: @@ -3946,7 +4470,7 @@ components: billingAccountId: type: integer example: 80000071 - description: 'the billing account id for payments' + description: "the billing account id for payments" WorkPeriod: required: - id @@ -3955,6 +4479,9 @@ components: - projectId - startDate - endDate + - daysWorked + - daysPaid + - paymentTotal - paymentStatus - createdAt - createdBy @@ -3987,21 +4514,33 @@ components: description: "The end date of work period. Should be always Saturday." daysWorked: type: integer + minimum: 0 + maximum: 5 example: 2 description: "The count of the days worked for that work period." - memberRate: + daysPaid: type: integer - format: float - example: 13.13 - description: "The member rate." - customerRate: + minimum: 0 + maximum: 5 + format: integer + example: 1 + description: "The count of paid days for that work period" + paymentTotal: type: integer format: float example: 13.13 - description: "The customer rate." + description: "The total paid amount" paymentStatus: type: string - enum: ["pending", "partially-completed", "completed", "cancelled"] + enum: + [ + "pending", + "partially-completed", + "completed", + "in-progress", + "failed", + "no-days", + ] description: "The payment status." payments: type: array @@ -4024,86 +4563,21 @@ components: type: string format: uuid description: "The user Id who updated the work period last time.(Will get the user info from the token)" - WorkPeriodRequestBody: - required: - - resourceBookingId - - startDate - - endDate - - paymentStatus - properties: - resourceBookingId: - type: string - format: uuid - description: "The resource booking id." - startDate: - type: string - format: date - example: "2021-03-07" - description: "The start date of work period. Should be always Sunday." - endDate: - type: string - format: date - example: "2021-03-13" - description: "The end date of work period. Should be always Saturday." - daysWorked: - type: integer - example: 2 - description: "The count of the days worked for that work period." - memberRate: - type: integer - format: float - example: 13.13 - description: "The member rate." - customerRate: - type: integer - format: float - example: 13.13 - description: "The customer rate." - paymentStatus: - type: string - enum: ["pending", "partially-completed", "completed", "cancelled"] - description: "The payment status." WorkPeriodPatchRequestBody: properties: - resourceBookingId: - type: string - format: uuid - description: "The resource booking id." - startDate: - type: string - format: date - example: "2021-03-07" - description: "The start date of work period. Should be always Sunday." - endDate: - type: string - format: date - example: "2021-03-13" - description: "The end date of work period. Should be always Saturday." daysWorked: type: integer example: 2 description: "The count of the days worked for that work period." - memberRate: - type: integer - format: float - example: 13.13 - description: "The member rate." - customerRate: - type: integer - format: float - example: 13.13 - description: "The customer rate." - paymentStatus: - type: string - enum: ["pending", "partially-completed", "completed", "cancelled"] - description: "The payment status." WorkPeriodPayment: required: - id - workPeriodId - - challengeId + - memberRate + - days - amount - status + - billingAccountId - createdAt - createdBy properties: @@ -4119,18 +4593,48 @@ components: type: string format: uuid description: "The challenge id." + memberRate: + type: number + format: float + example: 20.5 + description: "The member rate" + customerRate: + type: number + format: float + example: 15.5 + description: "The customer rate" + days: + type: integer + minimum: 1 + maximum: 5 + example: 3 + description: "The workdays to pay" amount: type: integer example: 2 description: "The amount to be paid." status: type: string - enum: ["completed", "cancelled"] + enum: ["completed", "scheduled", "in-progress", "failed", "cancelled"] description: "The payment status." + statusDetails: + type: object + properties: + errorMessage: + type: string + errorCode: + type: integer + retry: + type: integer + step: + type: string + challengeId: + type: string + format: uuid billingAccountId: type: integer example: 80000071 - description: 'the billing account id for payments' + description: "the billing account id for payments" createdAt: type: string format: date-time @@ -4147,7 +4651,7 @@ components: type: string format: uuid description: "The user Id who updated the work period payment last time.(Will get the user info from the token)" - WorkPeriodPaymentRequestBody: + WorkPeriodPaymentCreatedError: required: - workPeriodId properties: @@ -4159,23 +4663,100 @@ components: type: integer example: 2 description: "The amount to be paid." - status: - type: string - enum: ["completed", "cancelled"] - description: "The payment status." - WorkPeriodPaymentPatchRequestBody: + error: + type: object + properties: + message: + type: string + description: "The error message" + code: + type: integer + example: 429 + description: "HTTP code of error" + WorkPeriodPaymentCreateRequestBody: + required: + - workPeriodId properties: workPeriodId: type: string format: uuid description: "The work period id." - amount: + days: type: integer + minimum: 1 + maximum: 5 example: 2 - description: "The amount to be paid." + description: "The workDays to be paid." + WorkPeriodPaymentQueryCreateRequestBody: + properties: + status: + type: string + enum: ["placed", "in-progress", "completed"] + description: The resource booking status. + startDate: + type: string + format: date + description: The resource booking start date. + endDate: + type: string + format: date + description: The resource booking end date. + rateType: + type: string + enum: ["hourly", "daily", "weekly", "monthly"] + description: The resource booking rate type. + jobId: + type: string + format: uuid + description: The job id. + userId: + type: string + format: uuid + description: The user id. + projectId: + type: integer + description: The project id. + projectIds: + oneOf: + - type: string + description: comma separated project ids. + - type: array + items: + type: integer + workPeriods.paymentStatus: + type: string + enum: ["pending", "partially-completed", "failed"] + workPeriods.startDate: + type: string + format: date + pattern: '^\d{4}-\d{2}-\d{2}$' + description: The work period start date. + workPeriods.endDate: + type: string + format: date + pattern: '^\d{4}-\d{2}-\d{2}$' + description: The work period end date. + workPeriods.userHandle: + type: string + description: The user handle. + WorkPeriodPaymentQueryCreateResult: + properties: + total: + type: integer + description: The total Work Periods found. + totalSuccess: + type: integer + description: The total payments scheduled successfully. + totalError: + type: integer + description: The total payments which failed to get scheduled. + query: + $ref: "#/components/schemas/WorkPeriodPaymentQueryCreateRequestBody" + WorkPeriodPaymentPatchRequestBody: + properties: status: type: string - enum: ["completed", "cancelled"] + enum: ["scheduled", "cancelled"] description: "The payment status." CheckRun: type: object @@ -4537,6 +5118,10 @@ components: type: string format: url description: "The link for the resume that can be downloaded" + remark: + type: string + example: "excellent" + description: "The remark of candidate" interviews: type: array items: @@ -4560,6 +5145,14 @@ components: type: array items: $ref: "#/components/schemas/Skill" + TeamJobDescriptionRequestBody: + type: object + properties: + description: + type: string + description: "job description" + example: "nodejs and java" + TeamEmailRequestBody: type: object properties: @@ -4624,6 +5217,289 @@ components: type: string description: "the email of a member" example: "xxx@xxx.com" + RoleSearchRequestBody: + anyOf: + - type: object + required: + - roleId + properties: + roleId: + type: string + format: uuid + description: "The role id." + - type: object + required: + - jobDescription + properties: + jobDescription: + type: string + description: "The description of the job." + - type: object + required: + - skills + properties: + skills: + type: array + description: "The array of skill ids." + items: + type: string + format: uuid + description: "The skill id" + + RoleSearchResponse: + allOf: + - $ref: "#/components/schemas/Role" + - type: object + required: + - roleSearchRequestId + - isExternalMember + properties: + roleSearchRequestId: + type: string + format: uuid + description: "The role search request id." + isExternalMember: + type: boolean + description: "Is the user external member" + SubmitTeamRequestBody: + properties: + teamName: + type: string + description: "The name of the team" + teamDescription: + type: string + description: "The description of the team" + positions: + type: array + description: "The array of positions" + items: + type: object + required: + - roleName + - roleSearchRequestId + - numberOfResources + properties: + roleName: + type: string + description: "The name of the role" + roleSearchRequestId: + type: string + format: uuid + description: "The id of roleSearchRequest" + numberOfResources: + type: integer + example: 10 + minimum: 1 + description: "The number of needed resources" + durationWeeks: + type: integer + example: 5 + minimum: 1 + description: "The amount of time in weeks" + startMonth: + type: string + format: date-time + description: "The start day of the job" + SubmitTeamResponse: + required: + - projectId + properties: + projectId: + type: string + format: uuid + description: "The id of created project" + Role: + required: + - id + - name + - rates + - createdAt + - createdBy + properties: + id: + type: string + format: uuid + description: "The role id." + name: + type: string + example: "Dev Ops Engineer" + description: "The role name." + description: + type: string + example: "A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates." + description: "The role description" + listOfSkills: + type: array + description: "The array of skill names." + items: + type: string + example: "HTML" + description: "The skill name" + rates: + type: array + description: "The rates object array." + items: + $ref: "#/components/schemas/RoleRates" + numberOfMembers: + type: number + example: 100 + description: "The number of members." + numberOfMembersAvailable: + type: integer + example: 100 + description: "The number of members available." + imageUrl: + type: string + format: url + example: "http://images.topcoder.com/images" + description: "The image url of the role." + timeToCandidate: + type: integer + example: 200 + description: "The time to candidate." + timeToInterview: + type: integer + example: 300 + description: "The time to interview." + createdAt: + type: string + format: date-time + description: "The role created date." + createdBy: + type: string + format: uuid + description: "The user Id who created the role.(Will get the user info from the token)" + updatedAt: + type: string + format: date-time + description: "The role last updated at." + updatedBy: + type: string + format: uuid + description: "The user Id who updated the role last time.(Will get the user info from the token)" + RoleRequestBody: + required: + - name + - rates + properties: + name: + type: string + example: "Dev Ops Engineer" + description: "The role name." + description: + type: string + example: "A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates." + description: "The role description" + listOfSkills: + type: array + description: "The array of skill names." + items: + type: string + example: "HTML" + description: "The skill name" + rates: + type: array + description: "The rates object array." + items: + $ref: "#/components/schemas/RoleRates" + numberOfMembers: + type: number + example: 100 + description: "The number of members." + numberOfMembersAvailable: + type: number + example: 100 + description: "The number of members available." + imageUrl: + type: string + format: url + example: "http://images.topcoder.com/images" + description: "The image url of the role." + timeToCandidate: + type: integer + example: 200 + description: "The time to candidate." + timeToInterview: + type: integer + example: 300 + description: "The time to interview." + RolePatchRequestBody: + properties: + name: + type: string + example: "Dev Ops Engineer" + description: "The role name." + description: + type: string + example: "A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates." + description: "The role description" + listOfSkills: + type: array + description: "The array of skill names." + items: + type: string + example: "HTML" + description: "The skill name" + rates: + type: array + description: "The rates object array." + items: + $ref: "#/components/schemas/RoleRates" + numberOfMembers: + type: number + example: 100 + description: "The number of members." + numberOfMembersAvailable: + type: number + example: 100 + description: "The number of members available." + imageUrl: + type: string + format: url + example: "http://images.topcoder.com/images" + description: "The image url of the role." + timeToCandidate: + type: integer + example: 200 + description: "The time to candidate." + timeToInterview: + type: integer + example: 300 + description: "The time to interview." + RoleRates: + required: + - global + - inCountry + - offShore + type: object + properties: + global: + type: integer + example: 10 + inCountry: + type: integer + example: 20 + offShore: + type: integer + example: 30 + rate30Global: + type: integer + example: 10 + rate30InCountry: + type: integer + example: 20 + rate30OffShore: + type: integer + example: 30 + rate20Global: + type: integer + example: 10 + rate20InCountry: + type: integer + example: 20 + rate20OffShore: + type: integer + example: 30 ProjectMember: type: object example: diff --git a/docs/topcoder-bookings.postman_environment.json b/docs/topcoder-bookings.postman_environment.json index 837b55db..461ac18c 100644 --- a/docs/topcoder-bookings.postman_environment.json +++ b/docs/topcoder-bookings.postman_environment.json @@ -1,5 +1,5 @@ { - "id": "228f4dcc-6914-462e-9b56-3285b643a2f8", + "id": "796b909b-aac8-4261-8bf5-ea9004c73353", "name": "topcoder-bookings", "values": [ { @@ -142,51 +142,6 @@ "value": "17234", "enabled": true }, - { - "key": "jobId", - "value": "", - "enabled": true - }, - { - "key": "jobIdCreatedByM2M", - "value": "", - "enabled": true - }, - { - "key": "jobIdCreatedByMember", - "value": "", - "enabled": true - }, - { - "key": "jobCandidateId", - "value": "", - "enabled": true - }, - { - "key": "jobCandidateIdCreatedByM2M", - "value": "", - "enabled": true - }, - { - "key": "resourceBookingId", - "value": "", - "enabled": true - }, - { - "key": "resourceBookingIdCreatedByM2M", - "value": "", - "enabled": true - }, - { - "key": "workPeriodId", - "value": "", - "enabled": true - }, - { - "key": "workPeriodIdCreatedByM2M", - "value": "", - "enabled": true - }, { "key": "token_m2m_create_work_period", "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL3RvcGNvZGVyLWRldi5hdXRoMC5jb20vIiwic3ViIjoiZW5qdzE4MTBlRHozWFR3U08yUm4yWTljUVRyc3BuM0JAY2xpZW50cyIsImF1ZCI6Imh0dHBzOi8vbTJtLnRvcGNvZGVyLWRldi5jb20vIiwiaWF0IjoxNTUwOTA2Mzg4LCJleHAiOjIxNDc0ODM2NDgsImF6cCI6ImVuancxODEwZUR6M1hUd1NPMlJuMlk5Y1FUcnNwbjNCIiwic2NvcGUiOiJjcmVhdGU6dGFhcy13b3JrUGVyaW9kcyIsImd0eSI6ImNsaWVudC1jcmVkZW50aWFscyJ9.tgKxTrlI8bu6CVFk4-kFB1gKHL-L6X8akKYYREjZiSE", @@ -312,11 +267,6 @@ "value": "", "enabled": true }, - { - "key": "job_id_created_for_member", - "value": "", - "enabled": true - }, { "key": "resource_bookings_id_created_for_member", "value": "", @@ -327,11 +277,6 @@ "value": "", "enabled": true }, - { - "key": "job_id_created_for_connect_manager", - "value": "", - "enabled": true - }, { "key": "resource_bookings_id_created_for_connect_manager", "value": "", @@ -352,46 +297,16 @@ "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", @@ -461,9 +376,154 @@ "key": "interview_id_created_for_connect_manager", "value": "", "enabled": true + }, + { + "key": "token_m2m_create_role", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL3RvcGNvZGVyLWRldi5hdXRoMC5jb20vIiwic3ViIjoiZW5qdzE4MTBlRHozWFR3U08yUm4yWTljUVRyc3BuM0JAY2xpZW50cyIsImF1ZCI6Imh0dHBzOi8vbTJtLnRvcGNvZGVyLWRldi5jb20vIiwiaWF0IjoxNTUwOTA2Mzg4LCJleHAiOjIxNDc0ODM2NDgsImF6cCI6ImVuancxODEwZUR6M1hUd1NPMlJuMlk5Y1FUcnNwbjNCIiwic2NvcGUiOiJjcmVhdGU6dGFhcy1yb2xlcyIsImd0eSI6ImNsaWVudC1jcmVkZW50aWFscyJ9.f1QP1QTacyDxy7dwzUhBIT8blXCjKn_mnu9Cg59vIc8", + "enabled": true + }, + { + "key": "token_m2m_read_role", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL3RvcGNvZGVyLWRldi5hdXRoMC5jb20vIiwic3ViIjoiZW5qdzE4MTBlRHozWFR3U08yUm4yWTljUVRyc3BuM0JAY2xpZW50cyIsImF1ZCI6Imh0dHBzOi8vbTJtLnRvcGNvZGVyLWRldi5jb20vIiwiaWF0IjoxNTUwOTA2Mzg4LCJleHAiOjIxNDc0ODM2NDgsImF6cCI6ImVuancxODEwZUR6M1hUd1NPMlJuMlk5Y1FUcnNwbjNCIiwic2NvcGUiOiJyZWFkOnRhYXMtcm9sZXMiLCJndHkiOiJjbGllbnQtY3JlZGVudGlhbHMifQ.ZeWS_W2o8YwlvIB_-z0CFFa9zhRjptCk7qNXsPPWxVY", + "enabled": true + }, + { + "key": "token_m2m_update_role", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL3RvcGNvZGVyLWRldi5hdXRoMC5jb20vIiwic3ViIjoiZW5qdzE4MTBlRHozWFR3U08yUm4yWTljUVRyc3BuM0JAY2xpZW50cyIsImF1ZCI6Imh0dHBzOi8vbTJtLnRvcGNvZGVyLWRldi5jb20vIiwiaWF0IjoxNTUwOTA2Mzg4LCJleHAiOjIxNDc0ODM2NDgsImF6cCI6ImVuancxODEwZUR6M1hUd1NPMlJuMlk5Y1FUcnNwbjNCIiwic2NvcGUiOiJ1cGRhdGU6dGFhcy1yb2xlcyIsImd0eSI6ImNsaWVudC1jcmVkZW50aWFscyJ9.0t4k0skZmxAUKuHQrG3ZrO2dgWcDMLD8W1rVluCy7XQ", + "enabled": true + }, + { + "key": "token_m2m_delete_role", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL3RvcGNvZGVyLWRldi5hdXRoMC5jb20vIiwic3ViIjoiZW5qdzE4MTBlRHozWFR3U08yUm4yWTljUVRyc3BuM0JAY2xpZW50cyIsImF1ZCI6Imh0dHBzOi8vbTJtLnRvcGNvZGVyLWRldi5jb20vIiwiaWF0IjoxNTUwOTA2Mzg4LCJleHAiOjIxNDc0ODM2NDgsImF6cCI6ImVuancxODEwZUR6M1hUd1NPMlJuMlk5Y1FUcnNwbjNCIiwic2NvcGUiOiJkZWxldGU6dGFhcy1yb2xlcyIsImd0eSI6ImNsaWVudC1jcmVkZW50aWFscyJ9.NSBbWOk5jCB8nIvLiZwJtR9px5wmUQaQjgpDlMDJ9hk", + "enabled": true + }, + { + "key": "token_m2m_all_role", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL3RvcGNvZGVyLWRldi5hdXRoMC5jb20vIiwic3ViIjoiZW5qdzE4MTBlRHozWFR3U08yUm4yWTljUVRyc3BuM0JAY2xpZW50cyIsImF1ZCI6Imh0dHBzOi8vbTJtLnRvcGNvZGVyLWRldi5jb20vIiwiaWF0IjoxNTUwOTA2Mzg4LCJleHAiOjIxNDc0ODM2NDgsImF6cCI6ImVuancxODEwZUR6M1hUd1NPMlJuMlk5Y1FUcnNwbjNCIiwic2NvcGUiOiJhbGw6dGFhcy1yb2xlcyIsImd0eSI6ImNsaWVudC1jcmVkZW50aWFscyJ9.cn0QVTOFnbHJckYqmGcpUBT8wQUxXWwtteWU7uhlDtI", + "enabled": true + }, + { + "key": "roleId-1", + "value": "", + "enabled": true + }, + { + "key": "roleId-2", + "value": "", + "enabled": true + }, + { + "key": "roleId-3", + "value": "", + "enabled": true + }, + { + "key": "token_member_test_2", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ik5VSkZORGd4UlRVME5EWTBOVVkzTlRkR05qTXlRamxETmpOQk5UYzVRVUV3UlRFeU56TTJRUSJ9.eyJodHRwczovL3RvcGNvZGVyLWRldi5jb20vcm9sZXMiOlsiVG9wY29kZXIgVXNlciJdLCJodHRwczovL3RvcGNvZGVyLWRldi5jb20vdXNlcklkIjoiODg3NzQ2MzQiLCJodHRwczovL3RvcGNvZGVyLWRldi5jb20vaGFuZGxlIjoiaXNiaWxpciIsImh0dHBzOi8vdG9wY29kZXItZGV2LmNvbS91c2VyX2lkIjoiYXV0aDB8ODg3NzQ2MzQiLCJodHRwczovL3RvcGNvZGVyLWRldi5jb20vdGNzc28iOiI0MDE1Mjg1Nnw4MTM0ZjQ4ZWJlMTFhODQ4YTM3NTllNWVmOWU5MmYyMTQ2OTJlMjExMzA0MGM4MmI1ZDhmNTgxYzZkZmNjYzg4IiwiaHR0cHM6Ly90b3Bjb2Rlci1kZXYuY29tL2FjdGl2ZSI6dHJ1ZSwibmlja25hbWUiOiJpc2JpbGlyIiwibmFtZSI6InZpa2FzLmFnYXJ3YWwrcHNoYWhfbWFuYWdlckB0b3Bjb2Rlci5jb20iLCJwaWN0dXJlIjoiaHR0cHM6Ly9zLmdyYXZhdGFyLmNvbS9hdmF0YXIvOTJhZmIyZjBlZDUyZmRmYWUxZjM3MTAyMWFlNjUwMTM_cz00ODAmcj1wZyZkPWh0dHBzJTNBJTJGJTJGY2RuLmF1dGgwLmNvbSUyRmF2YXRhcnMlMkZ2aS5wbmciLCJ1cGRhdGVkX2F0IjoiMjAyMC0xMC0yNFQwODoyODoyNC4xODRaIiwiZW1haWwiOiJ2aWthcy5hZ2Fyd2FsK3BzaGFoX21hbmFnZXJAdG9wY29kZXIuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlzcyI6Imh0dHBzOi8vYXV0aC50b3Bjb2Rlci1kZXYuY29tLyIsInN1YiI6ImF1dGgwfDQwMTUyODU2IiwiYXVkIjoiQlhXWFVXbmlsVlVQZE4wMXQyU2UyOVR3MlpZTkdadkgiLCJpYXQiOjE2MDM1NDMzMzgsImV4cCI6MzMxNjA0NTI3MzgsIm5vbmNlIjoiUjFBMmN6WXVWVFptYmpaSFJHOTJWbDlEU1VKNlVsbHZRWGMzUkhoNVMzWldkV1pEY0ROWE1FWjFYdz09In0.yM5SFG61TH9pSa1NhfL6Do2YwfbLrflaKnyAchdiq94", + "enabled": true + }, + { + "key": "token_m2m_create_roleSearchRequests", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL3RvcGNvZGVyLWRldi5hdXRoMC5jb20vIiwic3ViIjoiZW5qdzE4MTBlRHozWFR3U08yUm4yWTljUVRyc3BuM0JAY2xpZW50cyIsImF1ZCI6Imh0dHBzOi8vbTJtLnRvcGNvZGVyLWRldi5jb20vIiwiaWF0IjoxNTUwOTA2Mzg4LCJleHAiOjIxNDc0ODM2NDgsImF6cCI6ImVuancxODEwZUR6M1hUd1NPMlJuMlk5Y1FUcnNwbjNCIiwic2NvcGUiOiJjcmVhdGU6dGFhcy1yb2xlU2VhcmNoUmVxdWVzdHMiLCJndHkiOiJjbGllbnQtY3JlZGVudGlhbHMifQ.Gix3XnsXAJiJQOkHeFYUfjPCPY29MR4ZkwZG8LJTZ6E", + "enabled": true + }, + { + "key": "token_m2m_create_teams", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL3RvcGNvZGVyLWRldi5hdXRoMC5jb20vIiwic3ViIjoiZW5qdzE4MTBlRHozWFR3U08yUm4yWTljUVRyc3BuM0JAY2xpZW50cyIsImF1ZCI6Imh0dHBzOi8vbTJtLnRvcGNvZGVyLWRldi5jb20vIiwiaWF0IjoxNTUwOTA2Mzg4LCJleHAiOjIxNDc0ODM2NDgsImF6cCI6ImVuancxODEwZUR6M1hUd1NPMlJuMlk5Y1FUcnNwbjNCIiwic2NvcGUiOiJjcmVhdGU6dGFhcy10ZWFtcyIsImd0eSI6ImNsaWVudC1jcmVkZW50aWFscyJ9.7XNO80PSZAQF97P-WsGEWc49S9XAzAuS0fZPuMGnzeo", + "enabled": true + }, + { + "key": "roleIdForTeam-1", + "value": "", + "enabled": true + }, + { + "key": "roleIdForTeam-2", + "value": "", + "enabled": true + }, + { + "key": "roleIdForTeam-3", + "value": "", + "enabled": true + }, + { + "key": "roleSearchRequestId-1", + "value": "", + "enabled": true + }, + { + "key": "roleSearchRequestId-2", + "value": "", + "enabled": true + }, + { + "key": "roleSearchRequestId-3", + "value": "", + "enabled": true + }, + { + "key": "roleSearchRequestId1-1", + "value": "", + "enabled": true + }, + { + "key": "roleSearchRequestId1-2", + "value": "", + "enabled": true + }, + { + "key": "roleSearchRequestId1-3", + "value": "", + "enabled": true + }, + { + "key": "roleSearchRequestId2-1", + "value": "", + "enabled": true + }, + { + "key": "roleSearchRequestId2-2", + "value": "", + "enabled": true + }, + { + "key": "roleSearchRequestId2-3", + "value": "", + "enabled": true + }, + { + "key": "roleSearchRequestId3-1", + "value": "", + "enabled": true + }, + { + "key": "roleSearchRequestId3-2", + "value": "", + "enabled": true + }, + { + "key": "roleSearchRequestId3-3", + "value": "", + "enabled": true + }, + { + "key": "createTeamProjectId-1", + "value": "", + "enabled": true + }, + { + "key": "createTeamProjectId-2", + "value": "", + "enabled": true + }, + { + "key": "createTeamProjectId-3", + "value": "", + "enabled": true } ], "_postman_variable_scope": "environment", - "_postman_exported_at": "2021-05-10T05:06:38.661Z", - "_postman_exported_using": "Postman/8.3.1" + "_postman_exported_at": "2021-06-05T19:51:04.990Z", + "_postman_exported_using": "Postman/8.5.1" } \ No newline at end of file diff --git a/local/docker-compose.yml b/local/docker-compose.yml index 3894d100..34229bde 100644 --- a/local/docker-compose.yml +++ b/local/docker-compose.yml @@ -2,7 +2,7 @@ version: "3" services: postgres: container_name: tc-taas-postgres - image: postgres + image: postgres:11.8 environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres @@ -85,4 +85,4 @@ services: - AUTH0_AUDIENCE - AUTH0_CLIENT_ID - AUTH0_CLIENT_SECRET - - AUTH0_PROXY_SERVER_URL + - AUTH0_PROXY_SERVER_URL \ No newline at end of file diff --git a/local/kafka-client/create-topics.sh b/local/kafka-client/create-topics.sh index 88339fe9..f82c65e9 100755 --- a/local/kafka-client/create-topics.sh +++ b/local/kafka-client/create-topics.sh @@ -2,5 +2,5 @@ /opt/kafka/bin/kafka-topics.sh --list --zookeeper zookeeper:2181 > exists-topics.txt while read topic; do - /opt/kafka/bin/kafka-topics.sh --create --if-not-exists --zookeeper zookeeper:2181 --partitions 1 --replication-factor 1 --topic $topic + /opt/kafka/bin/kafka-topics.sh --create --if-not-exists --zookeeper zookeeper:2181 --partitions 10 --replication-factor 1 --topic $topic done < <(sort topics.txt exists-topics.txt exists-topics.txt | uniq -u) \ No newline at end of file diff --git a/local/kafka-client/topics.txt b/local/kafka-client/topics.txt index 8766a1b5..2611220b 100644 --- a/local/kafka-client/topics.txt +++ b/local/kafka-client/topics.txt @@ -3,17 +3,21 @@ taas.jobcandidate.create taas.resourcebooking.create taas.workperiod.create taas.workperiodpayment.create +taas.role.requested taas.job.update taas.jobcandidate.update taas.resourcebooking.update taas.workperiod.update taas.workperiodpayment.update +taas.role.update taas.job.delete taas.jobcandidate.delete taas.resourcebooking.delete taas.workperiod.delete taas.workperiodpayment.delete +taas.role.delete taas.interview.requested taas.interview.update taas.interview.bulkUpdate external.action.email +taas.action.retry diff --git a/migrations/2021-05-26-work-period-payment-table-migration.js b/migrations/2021-05-26-work-period-payment-table-migration.js new file mode 100644 index 00000000..5ee8ef70 --- /dev/null +++ b/migrations/2021-05-26-work-period-payment-table-migration.js @@ -0,0 +1,38 @@ +'use strict'; +const config = require('config') + +/** + * Migrate work_period_payments challenge_id - from not null to allow null. + * enum_work_period_payments_status from completed, cancelled to completed, canceled, scheduled. + */ +module.exports = { + up: async (queryInterface, Sequelize) => { + const table = { tableName: 'work_period_payments', schema: config.DB_SCHEMA_NAME } + await Promise.all([ + queryInterface.changeColumn(table, 'challenge_id', { type: Sequelize.UUID }), + queryInterface.sequelize.query(`ALTER TYPE ${config.DB_SCHEMA_NAME}.enum_work_period_payments_status ADD VALUE 'scheduled'`) + ]) + }, + + down: async (queryInterface, Sequelize) => { + const table = { tableName: 'work_period_payments', schema: config.DB_SCHEMA_NAME } + await Promise.all([ + queryInterface.changeColumn(table, 'challenge_id', { type: Sequelize.UUID, allowNull: false }), + queryInterface.sequelize.query(` + DELETE + FROM + pg_enum + WHERE + enumlabel = 'scheduled' AND + enumtypid = ( + SELECT + oid + FROM + pg_type + WHERE + typname = 'enum_work_period_payments_status' + ) + `) + ]) + } +}; diff --git a/migrations/2021-05-27-1-role-table-create.js b/migrations/2021-05-27-1-role-table-create.js new file mode 100644 index 00000000..bce2ae17 --- /dev/null +++ b/migrations/2021-05-27-1-role-table-create.js @@ -0,0 +1,146 @@ +const config = require('config') + +/* + * Create role table + */ + +module.exports = { + up: async (queryInterface, Sequelize) => { + const transaction = await queryInterface.sequelize.transaction() + try { + await queryInterface.createTable('roles', { + id: { + type: Sequelize.UUID, + primaryKey: true, + allowNull: false, + defaultValue: Sequelize.UUIDV4 + }, + name: { + type: Sequelize.STRING(50), + allowNull: false + }, + description: { + type: Sequelize.STRING(1000) + }, + listOfSkills: { + field: 'list_of_skills', + type: Sequelize.ARRAY({ + type: Sequelize.STRING(50) + }) + }, + rates: { + type: Sequelize.ARRAY({ + type: Sequelize.JSONB({ + global: { + type: Sequelize.SMALLINT, + allowNull: false + }, + inCountry: { + field: 'in_country', + type: Sequelize.SMALLINT, + allowNull: false + }, + offShore: { + field: 'off_shore', + type: Sequelize.SMALLINT, + allowNull: false + }, + rate30Global: { + field: 'rate30_global', + type: Sequelize.SMALLINT + }, + rate30InCountry: { + field: 'rate30_in_country', + type: Sequelize.SMALLINT + }, + rate30OffShore: { + field: 'rate30_off_shore', + type: Sequelize.SMALLINT + }, + rate20Global: { + field: 'rate20_global', + type: Sequelize.SMALLINT + }, + rate20InCountry: { + field: 'rate20_in_country', + type: Sequelize.SMALLINT + }, + rate20OffShore: { + field: 'rate20_off_shore', + type: Sequelize.SMALLINT + } + }), + allowNull: false + }), + allowNull: false + }, + numberOfMembers: { + field: 'number_of_members', + type: Sequelize.NUMERIC + }, + numberOfMembersAvailable: { + field: 'number_of_members_available', + type: Sequelize.SMALLINT + }, + imageUrl: { + field: 'image_url', + type: Sequelize.STRING(255) + }, + timeToCandidate: { + field: 'time_to_candidate', + type: Sequelize.SMALLINT + }, + timeToInterview: { + field: 'time_to_interview', + type: Sequelize.SMALLINT + }, + 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, + transaction + }) + await queryInterface.addIndex( + { + tableName: 'roles', + schema: config.DB_SCHEMA_NAME + }, + ['name'], + { + type: 'UNIQUE', + where: { deleted_at: null }, + transaction: transaction + } + ) + await transaction.commit() + } catch (err) { + await transaction.rollback() + throw err + } + }, + down: async (queryInterface, Sequelize) => { + await queryInterface.dropTable({ + tableName: 'roles', + schema: config.DB_SCHEMA_NAME + }) + } +} diff --git a/migrations/2021-05-27-2-job-add-roleIds-field.js b/migrations/2021-05-27-2-job-add-roleIds-field.js new file mode 100644 index 00000000..a5b9f4be --- /dev/null +++ b/migrations/2021-05-27-2-job-add-roleIds-field.js @@ -0,0 +1,19 @@ +const config = require('config') + +/* + * Add roleIds field to the Job model. + */ + +module.exports = { + up: async (queryInterface, Sequelize) => { + await queryInterface.addColumn({ tableName: 'jobs', schema: config.DB_SCHEMA_NAME }, 'role_ids', + { + type: Sequelize.ARRAY({ + type: Sequelize.UUID + }) + }) + }, + down: async (queryInterface, Sequelize) => { + await queryInterface.removeColumn({ tableName: 'jobs', schema: config.DB_SCHEMA_NAME }, 'role_ids') + } +} diff --git a/migrations/2021-05-28-add-fields-to-job-and-job-candidate.js b/migrations/2021-05-28-add-fields-to-job-and-job-candidate.js new file mode 100644 index 00000000..93b427b6 --- /dev/null +++ b/migrations/2021-05-28-add-fields-to-job-and-job-candidate.js @@ -0,0 +1,55 @@ +const config = require('config') + +/* + * Add min_salary, max_salary, hours_per_week, job_location, job_timezone and currency fields to the Job model. + * Add remark field to the JobCandidate model. + */ + +module.exports = { + up: async (queryInterface, Sequelize) => { + const transaction = await queryInterface.sequelize.transaction() + try { + await queryInterface.addColumn({ tableName: 'jobs', schema: config.DB_SCHEMA_NAME }, 'min_salary', + { type: Sequelize.INTEGER, allowNull: true }, + { transaction }) + await queryInterface.addColumn({ tableName: 'jobs', schema: config.DB_SCHEMA_NAME }, 'max_salary', + { type: Sequelize.INTEGER, allowNull: true }, + { transaction }) + await queryInterface.addColumn({ tableName: 'jobs', schema: config.DB_SCHEMA_NAME }, 'hours_per_week', + { type: Sequelize.INTEGER, allowNull: true }, + { transaction }) + await queryInterface.addColumn({ tableName: 'jobs', schema: config.DB_SCHEMA_NAME }, 'job_location', + { type: Sequelize.STRING(255), allowNull: true }, + { transaction }) + await queryInterface.addColumn({ tableName: 'jobs', schema: config.DB_SCHEMA_NAME }, 'job_timezone', + { type: Sequelize.STRING(128), allowNull: true }, + { transaction }) + await queryInterface.addColumn({ tableName: 'jobs', schema: config.DB_SCHEMA_NAME }, 'currency', + { type: Sequelize.STRING(30), allowNull: true }, + { transaction }) + await queryInterface.addColumn({ tableName: 'job_candidates', schema: config.DB_SCHEMA_NAME }, 'remark', + { type: Sequelize.STRING(255) }, + { transaction }) + await transaction.commit() + } catch (err) { + await transaction.rollback() + throw err + } + }, + down: async (queryInterface, Sequelize) => { + const transaction = await queryInterface.sequelize.transaction() + try { + await queryInterface.removeColumn({ tableName: 'jobs', schema: config.DB_SCHEMA_NAME }, 'min_salary', { transaction }) + await queryInterface.removeColumn({ tableName: 'jobs', schema: config.DB_SCHEMA_NAME }, 'max_salary', { transaction }) + await queryInterface.removeColumn({ tableName: 'jobs', schema: config.DB_SCHEMA_NAME }, 'hours_per_week', { transaction }) + await queryInterface.removeColumn({ tableName: 'jobs', schema: config.DB_SCHEMA_NAME }, 'job_location', { transaction }) + await queryInterface.removeColumn({ tableName: 'jobs', schema: config.DB_SCHEMA_NAME }, 'job_timezone', { transaction }) + await queryInterface.removeColumn({ tableName: 'jobs', schema: config.DB_SCHEMA_NAME }, 'currency', { transaction }) + await queryInterface.removeColumn({ tableName: 'job_candidates', schema: config.DB_SCHEMA_NAME }, 'remark', { transaction }) + await transaction.commit() + } catch (err) { + await transaction.rollback() + throw err + } + } +} diff --git a/migrations/2021-05-29-create-payment-scheduler-table-add-status-details-to-payment.js b/migrations/2021-05-29-create-payment-scheduler-table-add-status-details-to-payment.js new file mode 100644 index 00000000..3931f4bb --- /dev/null +++ b/migrations/2021-05-29-create-payment-scheduler-table-add-status-details-to-payment.js @@ -0,0 +1,111 @@ +'use strict'; + +const config = require('config') +const _ = require('lodash') +const { PaymentSchedulerStatus } = require('../app-constants') + +/** + * Create `payment_schedulers` table & relations. + */ +module.exports = { + up: async (queryInterface, Sequelize) => { + const transaction = await queryInterface.sequelize.transaction() + try { + await queryInterface.createTable('payment_schedulers', { + id: { + type: Sequelize.UUID, + primaryKey: true, + allowNull: false, + defaultValue: Sequelize.UUIDV4 + }, + challengeId: { + field: 'challenge_id', + type: Sequelize.UUID, + allowNull: false + }, + workPeriodPaymentId: { + field: 'work_period_payment_id', + type: Sequelize.UUID, + allowNull: false, + references: { + model: { + tableName: 'work_period_payments', + schema: config.DB_SCHEMA_NAME + }, + key: 'id' + } + }, + step: { + type: Sequelize.ENUM(_.values(PaymentSchedulerStatus)), + allowNull: false + }, + status: { + type: Sequelize.ENUM( + 'in-progress', + 'completed', + 'failed' + ), + allowNull: false + }, + userId: { + field: 'user_id', + type: Sequelize.BIGINT + }, + userHandle: { + field: 'user_handle', + type: Sequelize.STRING, + allowNull: false + }, + 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, transaction }) + await queryInterface.addColumn({ tableName: 'work_period_payments', schema: config.DB_SCHEMA_NAME }, 'status_details', + { type: Sequelize.JSONB }, + { transaction }) + await queryInterface.changeColumn({ tableName: 'work_period_payments', schema: config.DB_SCHEMA_NAME }, 'challenge_id', + { type: Sequelize.UUID }, + { transaction }) + await queryInterface.sequelize.query(`ALTER TYPE ${config.DB_SCHEMA_NAME}.enum_work_period_payments_status ADD VALUE 'in-progress'`) + await queryInterface.sequelize.query(`ALTER TYPE ${config.DB_SCHEMA_NAME}.enum_work_period_payments_status ADD VALUE 'failed'`) + await transaction.commit() + } catch (err) { + await transaction.rollback() + throw err + } + }, + + down: async (queryInterface, Sequelize) => { + const table = { schema: config.DB_SCHEMA_NAME, tableName: 'payment_schedulers' } + const statusTypeName = `${table.schema}.enum_${table.tableName}_status` + const stepTypeName = `${table.schema}.enum_${table.tableName}_step` + const transaction = await queryInterface.sequelize.transaction() + try { + await queryInterface.dropTable(table, { transaction }) + // drop enum type for status and step column + await queryInterface.sequelize.query(`DROP TYPE ${statusTypeName}`, { transaction }) + await queryInterface.sequelize.query(`DROP TYPE ${stepTypeName}`, { transaction }) + + await queryInterface.changeColumn({ tableName: 'work_period_payments', schema: config.DB_SCHEMA_NAME }, 'challenge_id', + { type: Sequelize.UUID, allowNull: false }, + { transaction }) + await queryInterface.removeColumn({ tableName: 'work_period_payments', schema: config.DB_SCHEMA_NAME }, 'status_details', + { transaction }) + await queryInterface.sequelize.query(`DELETE FROM pg_enum WHERE enumlabel in ('in-progress', 'failed') AND enumtypid = (SELECT oid FROM pg_type WHERE typname = 'enum_work_period_payments_status')`, + { transaction }) + await transaction.commit() + } catch (err) { + await transaction.rollback() + throw err + } + } +}; diff --git a/migrations/2021-06-04-role-search-request-table-create.js b/migrations/2021-06-04-role-search-request-table-create.js new file mode 100644 index 00000000..2e32ff1a --- /dev/null +++ b/migrations/2021-06-04-role-search-request-table-create.js @@ -0,0 +1,77 @@ +const config = require('config') + +/* + * Create role table + */ + +module.exports = { + up: async (queryInterface, Sequelize) => { + await queryInterface.createTable('role_search_requests', { + id: { + type: Sequelize.UUID, + primaryKey: true, + allowNull: false, + defaultValue: Sequelize.UUIDV4 + }, + memberId: { + field: 'member_id', + type: Sequelize.UUID + }, + previousRoleSearchRequestId: { + field: 'previous_role_search_request_id', + type: Sequelize.UUID + }, + roleId: { + field: 'role_id', + type: Sequelize.UUID, + references: { + model: { + tableName: 'roles', + schema: config.DB_SCHEMA_NAME + }, + key: 'id' + }, + onUpdate: 'CASCADE', + onDelete: 'SET NULL' + }, + jobDescription: { + field: 'job_description', + type: Sequelize.STRING() + }, + skills: { + type: Sequelize.ARRAY({ + type: Sequelize.UUID + }) + }, + 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) => { + await queryInterface.dropTable({ + tableName: 'role_search_requests', + schema: config.DB_SCHEMA_NAME + }) + } +} diff --git a/migrations/2021-06-14-recreate-and-repopulate-work-periods-for-resource-bookings.js b/migrations/2021-06-14-recreate-and-repopulate-work-periods-for-resource-bookings.js new file mode 100644 index 00000000..604a2072 --- /dev/null +++ b/migrations/2021-06-14-recreate-and-repopulate-work-periods-for-resource-bookings.js @@ -0,0 +1,146 @@ +const config = require('config') +const ResourceBooking = require('../src/models').ResourceBooking +const _ = require('lodash') +const helper = require('../src/common/helper') +const { v4: uuid } = require('uuid') +const { AggregatePaymentStatus } = require('../app-constants') + +// maximum start date of resource bookings when populating work periods from existing resource bookings in migration script +const MAX_START_DATE = process.env.MAX_START_DATE || '2100-12-31' +// maximum end date of resource bookings when populating work periods from existing resource bookings in migration script +const MAX_END_DATE = process.env.MAX_END_DATE || '2100-12-31' + +/* + * Populate WorkPeriods for ResourceBookings + */ + +module.exports = { + up: async (queryInterface, Sequelize) => { + const transaction = await queryInterface.sequelize.transaction() + const Op = Sequelize.Op + try { + await queryInterface.bulkDelete({ + tableName: 'payment_schedulers', + schema: config.DB_SCHEMA_NAME, + transaction + }) + await queryInterface.bulkDelete({ + tableName: 'work_period_payments', + schema: config.DB_SCHEMA_NAME, + transaction + }) + await queryInterface.bulkDelete({ + tableName: 'work_periods', + schema: config.DB_SCHEMA_NAME, + transaction + }) + await queryInterface.removeColumn({ tableName: 'work_periods', schema: config.DB_SCHEMA_NAME }, 'member_rate', { transaction }) + await queryInterface.removeColumn({ tableName: 'work_periods', schema: config.DB_SCHEMA_NAME }, 'customer_rate', { transaction }) + await queryInterface.addColumn({ tableName: 'work_periods', schema: config.DB_SCHEMA_NAME }, 'days_paid', + { type: Sequelize.INTEGER, allowNull: false }, + { transaction }) + await queryInterface.addColumn({ tableName: 'work_periods', schema: config.DB_SCHEMA_NAME }, 'payment_total', + { type: Sequelize.FLOAT, allowNull: false }, + { transaction }) + await queryInterface.changeColumn({ tableName: 'work_periods', schema: config.DB_SCHEMA_NAME }, 'days_worked', + { type: Sequelize.INTEGER, allowNull: false }, + { transaction }) + await queryInterface.addColumn({ tableName: 'work_period_payments', schema: config.DB_SCHEMA_NAME }, 'member_rate', + { type: Sequelize.FLOAT, allowNull: false }, + { transaction }) + await queryInterface.addColumn({ tableName: 'work_period_payments', schema: config.DB_SCHEMA_NAME }, 'customer_rate', + { type: Sequelize.FLOAT, allowNull: true }, + { transaction }) + await queryInterface.addColumn({ tableName: 'work_period_payments', schema: config.DB_SCHEMA_NAME }, 'days', + { type: Sequelize.INTEGER, allowNull: false }, + { transaction }) + await queryInterface.changeColumn({ tableName: 'work_period_payments', schema: config.DB_SCHEMA_NAME }, 'amount', + { type: Sequelize.DOUBLE, allowNull: false }, + { transaction }) + await queryInterface.changeColumn({ tableName: 'work_period_payments', schema: config.DB_SCHEMA_NAME }, 'billing_account_id', + { type: Sequelize.BIGINT, allowNull: false }, + { transaction }) + const resourceBookings = await ResourceBooking.findAll({ + where: { + start_date: { [Op.lt]: new Date(MAX_START_DATE) }, + end_date: { [Op.lt]: new Date(MAX_END_DATE) } + } + }) + if (resourceBookings.length === 0) { + return + } + const workPeriodData = [] + for (const rb of resourceBookings) { + if (!_.isNil(rb.startDate) && !_.isNil(rb.endDate)) { + const periods = helper.extractWorkPeriods(rb.startDate, rb.endDate) + const user = await helper.ensureUserById(rb.userId) + _.forEach(periods, period => { + workPeriodData.push({ + id: uuid(), + resource_booking_id: rb.id, + project_id: rb.projectId, + user_handle: user.handle, + start_date: period.startDate, + end_date: period.endDate, + days_worked: period.daysWorked, + days_paid: 0, + payment_total: 0, + payment_status: period.daysWorked === 0 ? AggregatePaymentStatus.NO_DAYS : AggregatePaymentStatus.PENDING, + created_by: config.m2m.M2M_AUDIT_USER_ID, + created_at: new Date() + }) + }) + } + } + await queryInterface.bulkInsert({ tableName: 'work_periods', schema: config.DB_SCHEMA_NAME }, workPeriodData, { transaction }) + await transaction.commit() + } catch (err) { + await transaction.rollback() + throw err + } + }, + down: async (queryInterface, Sequelize) => { + const transaction = await queryInterface.sequelize.transaction() + try { + await queryInterface.bulkDelete({ + tableName: 'payment_schedulers', + schema: config.DB_SCHEMA_NAME, + transaction + }) + await queryInterface.bulkDelete({ + tableName: 'work_period_payments', + schema: config.DB_SCHEMA_NAME, + transaction + }) + await queryInterface.bulkDelete({ + tableName: 'work_periods', + schema: config.DB_SCHEMA_NAME, + transaction + }) + await queryInterface.removeColumn({ tableName: 'work_periods', schema: config.DB_SCHEMA_NAME }, 'days_paid', { transaction }) + await queryInterface.removeColumn({ tableName: 'work_periods', schema: config.DB_SCHEMA_NAME }, 'payment_total', { transaction }) + await queryInterface.addColumn({ tableName: 'work_periods', schema: config.DB_SCHEMA_NAME }, 'member_rate', + { type: Sequelize.FLOAT, allowNull: true }, + { transaction }) + await queryInterface.addColumn({ tableName: 'work_periods', schema: config.DB_SCHEMA_NAME }, 'customer_rate', + { type: Sequelize.FLOAT, allowNull: true }, + { transaction }) + await queryInterface.changeColumn({ tableName: 'work_periods', schema: config.DB_SCHEMA_NAME }, 'days_worked', + { type: Sequelize.INTEGER, allowNull: true }, + { transaction }) + await queryInterface.removeColumn({ tableName: 'work_period_payments', schema: config.DB_SCHEMA_NAME }, 'member_rate', { transaction }) + await queryInterface.removeColumn({ tableName: 'work_period_payments', schema: config.DB_SCHEMA_NAME }, 'customer_rate', { transaction }) + await queryInterface.removeColumn({ tableName: 'work_period_payments', schema: config.DB_SCHEMA_NAME }, 'days', { transaction }) + await queryInterface.changeColumn({ tableName: 'work_period_payments', schema: config.DB_SCHEMA_NAME }, 'amount', + { type: Sequelize.DOUBLE, allowNull: true }, + { transaction }) + await queryInterface.changeColumn({ tableName: 'work_period_payments', schema: config.DB_SCHEMA_NAME }, 'billing_account_id', + { type: Sequelize.BIGINT, allowNull: true }, + { transaction }) + await transaction.commit() + } catch (err) { + await transaction.rollback() + throw err + } + } +} diff --git a/package.json b/package.json index 00d15b73..3e2e7b18 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "index:jobs": "node scripts/es/reIndexJobs.js", "index:job-candidates": "node scripts/es/reIndexJobCandidates.js", "index:resource-bookings": "node scripts/es/reIndexResourceBookings.js", - "index:work-periods": "node scripts/es/reIndexWorkPeriods.js", + "index:roles": "node scripts/es/reIndexRoles.js", "data:export": "node scripts/data/exportData.js", "data:import": "node scripts/data/importData.js", "migrate": "npx sequelize db:migrate", @@ -27,6 +27,7 @@ "local:init": "npm run local:reset && npm run data:import -- --force", "local:reset": "npm run delete-index -- --force || true && npm run create-index -- --force && npm run init-db force", "cov": "nyc --reporter=html --reporter=text npm run test", + "demo-payment-scheduler": "node scripts/demo-payment-scheduler/index.js && npm run index:all -- --force", "demo-payment": "node scripts/demo-payment" }, "keywords": [], @@ -86,4 +87,4 @@ "test/unit/**" ] } -} +} \ No newline at end of file diff --git a/scripts/data/exportData.js b/scripts/data/exportData.js index 356fcfc6..cb61e582 100644 --- a/scripts/data/exportData.js +++ b/scripts/data/exportData.js @@ -2,7 +2,7 @@ * Export data to a json file */ const config = require('config') -const { Interview, WorkPeriodPayment } = require('../../src/models') +const { Interview, WorkPeriod, WorkPeriodPayment } = require('../../src/models') const logger = require('../../src/common/logger') const helper = require('../../src/common/helper') @@ -14,17 +14,21 @@ const jobCandidateModelOpts = { }] } -const workPeriodModelOpts = { - modelName: 'WorkPeriod', +const resourceBookingModelOpts = { + modelName: 'ResourceBooking', include: [{ - model: WorkPeriodPayment, - as: 'payments' + model: WorkPeriod, + as: 'workPeriods', + include: [{ + model: WorkPeriodPayment, + as: 'payments' + }] }] } 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', jobCandidateModelOpts, 'ResourceBooking', workPeriodModelOpts] +const dataModels = ['Job', jobCandidateModelOpts, resourceBookingModelOpts, 'Role'] async function exportData () { await helper.promptUser(userPrompt, async () => { diff --git a/scripts/data/importData.js b/scripts/data/importData.js index 52b3feb8..a0aeeb64 100644 --- a/scripts/data/importData.js +++ b/scripts/data/importData.js @@ -2,7 +2,7 @@ * Import data from a json file into the db and index it in Elasticsearch */ const config = require('config') -const { Interview, WorkPeriodPayment } = require('../../src/models') +const { Interview, WorkPeriod, WorkPeriodPayment } = require('../../src/models') const logger = require('../../src/common/logger') const helper = require('../../src/common/helper') @@ -14,17 +14,21 @@ const jobCandidateModelOpts = { }] } -const workPeriodModelOpts = { - modelName: 'WorkPeriod', +const resourceBookingModelOpts = { + modelName: 'ResourceBooking', include: [{ - model: WorkPeriodPayment, - as: 'payments' + model: WorkPeriod, + as: 'workPeriods', + include: [{ + model: WorkPeriodPayment, + as: 'payments' + }] }] } 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', jobCandidateModelOpts, 'ResourceBooking', workPeriodModelOpts] +const dataModels = ['Job', jobCandidateModelOpts, resourceBookingModelOpts, 'Role'] async function importData () { await helper.promptUser(userPrompt, async () => { diff --git a/scripts/demo-payment-scheduler/data.json b/scripts/demo-payment-scheduler/data.json new file mode 100644 index 00000000..5023842c --- /dev/null +++ b/scripts/demo-payment-scheduler/data.json @@ -0,0 +1,103 @@ +{ + "Job":{ + "id":"43d695d4-e926-41d5-ad42-a899612b5246", + "projectId":17234, + "title":"Dummy title - at most 64 characters", + "numPositions":13, + "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-05-09T21:21:10.394Z", + "updatedAt":"2021-05-09T21:21:14.010Z" + }, + "ResourceBooking":{ + "id":"41671764-0ded-46fd-b7de-2af5d5e4f3fc", + "projectId":17234, + "userId":"05e988b7-7d54-4c10-ada1-1a04870a88a8", + "jobId":"43d695d4-e926-41d5-ad42-a899612b5246", + "status":"placed", + "startDate":"2020-09-27", + "endDate":"2020-10-27", + "memberRate":13.23, + "customerRate":13, + "rateType":"hourly", + "billingAccountId":80000069, + "createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy":null, + "createdAt":"2021-05-09T21:25:46.728Z", + "updatedAt":"2021-05-09T21:25:46.728Z" + }, + "WorkPeriods":[ + { + "id":"4baae2cf-fd70-4ab3-9959-e826257b7e0f", + "resourceBookingId":"41671764-0ded-46fd-b7de-2af5d5e4f3fc", + "userHandle":"pshah_manager", + "projectId":17234, + "startDate":"2020-09-27", + "endDate":"2020-10-03", + "daysWorked":4, + "memberRate":27.06, + "customerRate":13.13, + "paymentStatus":"partially-completed", + "createdBy":"00000000-0000-0000-0000-000000000000", + "updatedBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt":"2021-05-09T21:25:47.813Z", + "updatedAt":"2021-05-09T21:45:32.659Z" + }, + { + "id":"9918e1b7-acbc-41ae-baa6-fdcb2386681d", + "resourceBookingId":"41671764-0ded-46fd-b7de-2af5d5e4f3fc", + "userHandle":"Shuchikr", + "projectId":17234, + "startDate":"2020-10-18", + "endDate":"2020-10-24", + "daysWorked":4, + "memberRate":4.08, + "customerRate":3.89, + "paymentStatus":"cancelled", + "createdBy":"00000000-0000-0000-0000-000000000000", + "updatedBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt":"2021-05-09T21:25:47.834Z", + "updatedAt":"2021-05-09T21:45:37.647Z" + }, + { + "id":"42e990c9-b14c-4496-9977-c3024aa90024", + "resourceBookingId":"41671764-0ded-46fd-b7de-2af5d5e4f3fc", + "userHandle":"vkumars", + "projectId":17234, + "startDate":"2020-10-25", + "endDate":"2020-10-31", + "daysWorked":3, + "memberRate":15.61, + "customerRate":9.76, + "paymentStatus":"pending", + "createdBy":"00000000-0000-0000-0000-000000000000", + "updatedBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt":"2021-05-09T21:25:47.824Z", + "updatedAt":"2021-05-09T21:45:48.727Z" + }, + { + "id":"8bf64481-ae7b-4e51-b48c-000cd90c87d1", + "resourceBookingId":"41671764-0ded-46fd-b7de-2af5d5e4f3fc", + "userHandle":"chandanant", + "projectId":17234, + "startDate":"2020-10-11", + "endDate":"2020-10-17", + "daysWorked":4, + "memberRate":10.82, + "customerRate":30.71, + "paymentStatus":"pending", + "createdBy":"00000000-0000-0000-0000-000000000000", + "updatedBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt":"2021-05-09T21:25:47.815Z", + "updatedAt":"2021-05-09T21:45:41.810Z" + } + ] + } \ No newline at end of file diff --git a/scripts/demo-payment-scheduler/index.js b/scripts/demo-payment-scheduler/index.js new file mode 100644 index 00000000..8f76a814 --- /dev/null +++ b/scripts/demo-payment-scheduler/index.js @@ -0,0 +1,81 @@ +const { v4: uuid } = require('uuid') +const config = require('config') +const _ = require('lodash') +const data = require('./data.json') +const model = require('../../src/models') +const logger = require('../../src/common/logger') + +const payments = [] +for (let i = 0; i < 1000; i++) { + payments.push({ + id: uuid(), + workPeriodId: data.WorkPeriods[_.random(3)].id, + amount: _.round(_.random(1000, true), 2), + status: 'scheduled', + billingAccountId: data.ResourceBooking.billingAccountId, + createdBy: '57646ff9-1cd3-4d3c-88ba-eb09a395366c', + updatedBy: null, + createdAt: `2021-05-19T21:3${i % 10}:46.507Z`, + updatedAt: '2021-05-19T21:33:46.507Z' + }) +} + +/** + * Clear old demo data + */ +async function clearData () { + const workPeriodIds = _.join(_.map(data.WorkPeriods, w => `'${w.id}'`), ',') + await model.PaymentScheduler.destroy({ + where: { + workPeriodPaymentId: { + [model.Sequelize.Op.in]: [ + model.sequelize.literal(`select id from ${config.DB_SCHEMA_NAME}.work_period_payments where work_period_id in (${workPeriodIds})`) + ] + } + }, + force: true + }) + await model.WorkPeriodPayment.destroy({ + where: { + workPeriodId: _.map(data.WorkPeriods, 'id') + }, + force: true + }) + await model.WorkPeriod.destroy({ + where: { + id: _.map(data.WorkPeriods, 'id') + }, + force: true + }) + await model.ResourceBooking.destroy({ + where: { + id: data.ResourceBooking.id + }, + force: true + }) + await model.Job.destroy({ + where: { + id: data.Job.id + }, + force: true + }) +} + +/** + * Insert payment scheduler demo data + */ +async function insertPaymentSchedulerDemoData () { + logger.info({ component: 'payment-scheduler-demo-data', context: 'insertPaymentSchedulerDemoData', message: 'Starting to remove demo data if exists' }) + await clearData() + logger.info({ component: 'payment-scheduler-demo-data', context: 'insertPaymentSchedulerDemoData', message: 'Data cleared' }) + await model.Job.create(data.Job) + logger.info({ component: 'payment-scheduler-demo-data', context: 'insertPaymentSchedulerDemoData', message: `Job ${data.Job.id} created` }) + await model.ResourceBooking.create(data.ResourceBooking) + logger.info({ component: 'payment-scheduler-demo-data', context: 'insertPaymentSchedulerDemoData', message: `ResourceBooking: ${data.ResourceBooking.id} create` }) + await model.WorkPeriod.bulkCreate(data.WorkPeriods) + logger.info({ component: 'payment-scheduler-demo-data', context: 'insertPaymentSchedulerDemoData', message: `WorkPeriods: ${_.map(data.WorkPeriods, 'id')} created` }) + await model.WorkPeriodPayment.bulkCreate(payments) + logger.info({ component: 'payment-scheduler-demo-data', context: 'insertPaymentSchedulerDemoData', message: `${payments.length} of WorkPeriodPayments scheduled` }) +} + +insertPaymentSchedulerDemoData() diff --git a/scripts/es/createIndex.js b/scripts/es/createIndex.js index 4591214a..269cd5a4 100644 --- a/scripts/es/createIndex.js +++ b/scripts/es/createIndex.js @@ -9,7 +9,7 @@ const indices = [ config.get('esConfig.ES_INDEX_JOB'), config.get('esConfig.ES_INDEX_JOB_CANDIDATE'), config.get('esConfig.ES_INDEX_RESOURCE_BOOKING'), - config.get('esConfig.ES_INDEX_WORK_PERIOD') + config.get('esConfig.ES_INDEX_ROLE') ] const userPrompt = `WARNING: Are you sure want to create the following elasticsearch indices: ${indices}?` diff --git a/scripts/es/deleteIndex.js b/scripts/es/deleteIndex.js index 8acffe33..724d3556 100644 --- a/scripts/es/deleteIndex.js +++ b/scripts/es/deleteIndex.js @@ -9,7 +9,7 @@ const indices = [ config.get('esConfig.ES_INDEX_JOB'), config.get('esConfig.ES_INDEX_JOB_CANDIDATE'), config.get('esConfig.ES_INDEX_RESOURCE_BOOKING'), - config.get('esConfig.ES_INDEX_WORK_PERIOD') + config.get('esConfig.ES_INDEX_ROLE') ] const userPrompt = `WARNING: this would remove existent data! Are you sure want to delete the following eleasticsearch indices: ${indices}?` diff --git a/scripts/es/reIndexAll.js b/scripts/es/reIndexAll.js index 6a7bdf3f..0367be11 100644 --- a/scripts/es/reIndexAll.js +++ b/scripts/es/reIndexAll.js @@ -2,7 +2,7 @@ * Reindex all data in Elasticsearch using data from database */ const config = require('config') -const { Interview, WorkPeriodPayment } = require('../../src/models') +const { Interview, WorkPeriod, WorkPeriodPayment } = require('../../src/models') const logger = require('../../src/common/logger') const helper = require('../../src/common/helper') @@ -16,11 +16,15 @@ const jobCandidateModelOpts = { }] } -const workPeriodModelOpts = { - modelName: 'JobCandidate', +const resourceBookingModelOpts = { + modelName: 'ResourceBooking', include: [{ - model: WorkPeriodPayment, - as: 'payments' + model: WorkPeriod, + as: 'workPeriods', + include: [{ + model: WorkPeriodPayment, + as: 'payments' + }] }] } @@ -29,8 +33,8 @@ async function indexAll () { try { await helper.indexBulkDataToES('Job', config.get('esConfig.ES_INDEX_JOB'), 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(workPeriodModelOpts, config.get('esConfig.ES_INDEX_WORK_PERIOD'), logger) + await helper.indexBulkDataToES(resourceBookingModelOpts, config.get('esConfig.ES_INDEX_RESOURCE_BOOKING'), logger) + await helper.indexBulkDataToES('Role', config.get('esConfig.ES_INDEX_ROLE'), logger) process.exit(0) } catch (err) { logger.logFullError(err, { component: 'indexAll' }) diff --git a/scripts/es/reIndexResourceBookings.js b/scripts/es/reIndexResourceBookings.js index ef2bf940..b29e3600 100644 --- a/scripts/es/reIndexResourceBookings.js +++ b/scripts/es/reIndexResourceBookings.js @@ -2,6 +2,7 @@ * Reindex ResourceBookings data in Elasticsearch using data from database */ const config = require('config') +const { WorkPeriod, WorkPeriodPayment } = require('../../src/models') const logger = require('../../src/common/logger') const helper = require('../../src/common/helper') @@ -10,11 +11,23 @@ const index = config.get('esConfig.ES_INDEX_RESOURCE_BOOKING') const reIndexAllResourceBookingsPrompt = `WARNING: this would remove existent data! Are you sure you want to reindex the index ${index}` const reIndexResourceBookingPrompt = `WARNING: this would remove existent data! Are you sure you want to reindex the document with id ${resourceBookingId} in index ${index}?` +const resourceBookingModelOpts = { + modelName: 'ResourceBooking', + include: [{ + model: WorkPeriod, + as: 'workPeriods', + include: [{ + model: WorkPeriodPayment, + as: 'payments' + }] + }] +} + async function reIndexResourceBookings () { if (resourceBookingId === null) { await helper.promptUser(reIndexAllResourceBookingsPrompt, async () => { try { - await helper.indexBulkDataToES('ResourceBooking', index, logger) + await helper.indexBulkDataToES(resourceBookingModelOpts, index, logger) process.exit(0) } catch (err) { logger.logFullError(err, { component: 'reIndexResourceBookings' }) @@ -24,7 +37,7 @@ async function reIndexResourceBookings () { } else { await helper.promptUser(reIndexResourceBookingPrompt, async () => { try { - await helper.indexDataToEsById(resourceBookingId, 'ResourceBooking', index, logger) + await helper.indexDataToEsById(resourceBookingId, resourceBookingModelOpts, index, logger) process.exit(0) } catch (err) { logger.logFullError(err, { component: 'reIndexResourceBookings' }) diff --git a/scripts/es/reIndexRoles.js b/scripts/es/reIndexRoles.js new file mode 100644 index 00000000..a4507aa9 --- /dev/null +++ b/scripts/es/reIndexRoles.js @@ -0,0 +1,37 @@ +/** + * Reindex Roles data in Elasticsearch using data from database + */ +const config = require('config') +const logger = require('../../src/common/logger') +const helper = require('../../src/common/helper') + +const roleId = helper.getParamFromCliArgs() +const index = config.get('esConfig.ES_INDEX_ROLE') +const reIndexAllRolesPrompt = `WARNING: this would remove existent data! Are you sure you want to reindex the index ${index}?` +const reIndexRolePrompt = `WARNING: this would remove existent data! Are you sure you want to reindex the document with id ${roleId} in index ${index}?` + +async function reIndexRoles () { + if (roleId === null) { + await helper.promptUser(reIndexAllRolesPrompt, async () => { + try { + await helper.indexBulkDataToES('Role', index, logger) + process.exit(0) + } catch (err) { + logger.logFullError(err, { component: 'reIndexRoles' }) + process.exit(1) + } + }) + } else { + await helper.promptUser(reIndexRolePrompt, async () => { + try { + await helper.indexDataToEsById(roleId, 'Role', index, logger) + process.exit(0) + } catch (err) { + logger.logFullError(err, { component: 'reIndexRoles' }) + process.exit(1) + } + }) + } +} + +reIndexRoles() diff --git a/scripts/es/reIndexWorkPeriods.js b/scripts/es/reIndexWorkPeriods.js deleted file mode 100644 index a6f30737..00000000 --- a/scripts/es/reIndexWorkPeriods.js +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Reindex WorkPeriods data in Elasticsearch using data from database - */ -const config = require('config') -const { WorkPeriodPayment } = require('../../src/models') -const logger = require('../../src/common/logger') -const helper = require('../../src/common/helper') - -const workPeriodId = helper.getParamFromCliArgs() -const index = config.get('esConfig.ES_INDEX_WORK_PERIOD') -const reIndexAllWorkPeriodsPrompt = `WARNING: this would remove existent data! Are you sure you want to reindex the index ${index}` -const reIndexWorkPeriodPrompt = `WARNING: this would remove existent data! Are you sure you want to reindex the document with id ${workPeriodId} in index ${index}?` - -const workPeriodModelOpts = { - modelName: 'WorkPeriod', - include: [{ - model: WorkPeriodPayment, - as: 'payments' - }] -} - -async function reIndexWorkPeriods () { - if (workPeriodId === null) { - await helper.promptUser(reIndexAllWorkPeriodsPrompt, async () => { - try { - await helper.indexBulkDataToES(workPeriodModelOpts, index, logger) - process.exit(0) - } catch (err) { - logger.logFullError(err, { component: 'reIndexWorkPeriods' }) - process.exit(1) - } - }) - } else { - await helper.promptUser(reIndexWorkPeriodPrompt, async () => { - try { - await helper.indexDataToEsById(workPeriodId, workPeriodModelOpts, index, logger) - process.exit(0) - } catch (err) { - logger.logFullError(err, { component: 'reIndexWorkPeriods' }) - process.exit(1) - } - }) - } -} - -reIndexWorkPeriods() diff --git a/src/bootstrap.js b/src/bootstrap.js index 6a364e8a..6e088046 100644 --- a/src/bootstrap.js +++ b/src/bootstrap.js @@ -1,31 +1,32 @@ const fs = require('fs') const Joi = require('joi') +const config = require('config') const path = require('path') const _ = require('lodash') -const { Interviews } = require('../app-constants') +const { Interviews, AggregatePaymentStatus, WorkPeriodPaymentStatus, WorkPeriodPaymentUpdateStatus, PaymentProcessingSwitch } = require('../app-constants') const logger = require('./common/logger') -const constants = require('../app-constants') -const config = require('config') const allowedInterviewStatuses = _.values(Interviews.Status) 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.rateType = () => Joi.string().valid('hourly', 'daily', 'weekly', 'monthly', 'annual') Joi.jobStatus = () => Joi.string().valid('sourcing', 'in-review', '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', 'placed', 'selected', 'client rejected - screening', 'client rejected - interview', 'rejected - other', 'cancelled', 'interview', 'topcoder-rejected') +Joi.jobCandidateStatus = () => Joi.string().valid('open', 'placed', 'selected', 'client rejected - screening', 'client rejected - interview', 'rejected - other', 'cancelled', 'interview', 'topcoder-rejected', 'applied', 'rejected-pre-screen', 'skills-test', 'skills-test', 'phone-screen', 'job-closed', 'offered') Joi.title = () => Joi.string().max(128) -Joi.paymentStatus = () => Joi.string().valid('pending', 'partially-completed', 'completed', 'cancelled') +Joi.paymentStatus = () => Joi.string().valid(..._.values(AggregatePaymentStatus)) Joi.xaiTemplate = () => Joi.string().valid(...allowedXAITemplate) Joi.interviewStatus = () => Joi.string().valid(...allowedInterviewStatuses) -Joi.workPeriodPaymentStatus = () => Joi.string().valid('completed', 'cancelled') +Joi.workPeriodPaymentStatus = () => Joi.string().valid(..._.values(WorkPeriodPaymentStatus)) +Joi.workPeriodPaymentUpdateStatus = () => Joi.string().valid(..._.values(WorkPeriodPaymentUpdateStatus)) // 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. Joi.stringAllowEmpty = () => Joi.string().allow('') +Joi.smallint = () => Joi.number().min(-32768).max(32767) function buildServices (dir) { const files = fs.readdirSync(dir) @@ -48,10 +49,10 @@ buildServices(path.join(__dirname, 'services')) // validate some configurable parameters for the app const paymentProcessingSwitchSchema = Joi.string().label('PAYMENT_PROCESSING_SWITCH').valid( - ...Object.values(constants.PaymentProcessingSwitch) + ...Object.values(PaymentProcessingSwitch) ) try { - Joi.attempt(config.PAYMENT_PROCESSING_SWITCH, paymentProcessingSwitchSchema) + Joi.attempt(config.PAYMENT_PROCESSING.SWITCH, paymentProcessingSwitchSchema) } catch (err) { console.error(err.message) process.exit(1) diff --git a/src/common/helper.js b/src/common/helper.js index 43c1453e..773dde0f 100644 --- a/src/common/helper.js +++ b/src/common/helper.js @@ -12,31 +12,62 @@ 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 { + ResponseError: ESResponseError +} = require('@elastic/elasticsearch/lib/errors') const errors = require('../common/errors') const logger = require('./logger') const models = require('../models') const eventDispatcher = require('./eventDispatcher') const busApi = require('@topcoder-platform/topcoder-bus-api-wrapper') const moment = require('moment') +const { PaymentStatusRules } = require('../../app-constants') const localLogger = { - debug: (message) => logger.debug({ component: 'helper', context: message.context, message: message.message }), - error: (message) => logger.error({ component: 'helper', context: message.context, message: message.message }), - info: (message) => logger.info({ component: 'helper', context: message.context, message: message.message }) + debug: (message) => + logger.debug({ + component: 'helper', + context: message.context, + message: message.message + }), + error: (message) => + logger.error({ + component: 'helper', + context: message.context, + message: message.message + }), + info: (message) => + logger.info({ + component: 'helper', + context: message.context, + message: message.message + }) } AWS.config.region = config.esConfig.AWS_REGION const m2mAuth = require('tc-core-library-js').auth.m2m -const m2m = m2mAuth(_.pick(config, ['AUTH0_URL', 'AUTH0_AUDIENCE', 'AUTH0_CLIENT_ID', 'AUTH0_CLIENT_SECRET', 'AUTH0_PROXY_SERVER_URL'])) +const m2m = m2mAuth( + _.pick(config, [ + 'AUTH0_URL', + 'AUTH0_AUDIENCE', + 'AUTH0_CLIENT_ID', + 'AUTH0_CLIENT_SECRET', + 'AUTH0_PROXY_SERVER_URL' + ]) +) const m2mForUbahn = m2mAuth({ AUTH0_AUDIENCE: config.AUTH0_AUDIENCE_UBAHN, - ..._.pick(config, ['AUTH0_URL', 'TOKEN_CACHE_TIME', 'AUTH0_CLIENT_ID', 'AUTH0_CLIENT_SECRET', 'AUTH0_PROXY_SERVER_URL']) -} -) + ..._.pick(config, [ + 'AUTH0_URL', + 'TOKEN_CACHE_TIME', + 'AUTH0_CLIENT_ID', + 'AUTH0_CLIENT_SECRET', + 'AUTH0_PROXY_SERVER_URL' + ]) +}) let busApiClient @@ -49,7 +80,17 @@ function getBusApiClient () { if (busApiClient) { return busApiClient } - busApiClient = busApi(_.pick(config, ['AUTH0_URL', 'AUTH0_AUDIENCE', 'TOKEN_CACHE_TIME', 'AUTH0_CLIENT_ID', 'AUTH0_CLIENT_SECRET', 'BUSAPI_URL', 'KAFKA_ERROR_TOPIC', 'AUTH0_PROXY_SERVER_URL']) + busApiClient = busApi( + _.pick(config, [ + 'AUTH0_URL', + 'AUTH0_AUDIENCE', + 'TOKEN_CACHE_TIME', + 'AUTH0_CLIENT_ID', + 'AUTH0_CLIENT_SECRET', + 'BUSAPI_URL', + 'KAFKA_ERROR_TOPIC', + 'AUTH0_PROXY_SERVER_URL' + ]) ) return busApiClient } @@ -73,6 +114,13 @@ esIndexPropertyMapping[config.get('esConfig.ES_INDEX_JOB')] = { skills: { type: 'keyword' }, status: { type: 'keyword' }, isApplicationPageActive: { type: 'boolean' }, + minSalary: { type: 'integer' }, + maxSalary: { type: 'integer' }, + hoursPerWeek: { type: 'integer' }, + jobLocation: { type: 'keyword' }, + jobTimezone: { type: 'keyword' }, + currency: { type: 'keyword' }, + roleIds: { type: 'keyword' }, createdAt: { type: 'date' }, createdBy: { type: 'keyword' }, updatedAt: { type: 'date' }, @@ -84,6 +132,7 @@ esIndexPropertyMapping[config.get('esConfig.ES_INDEX_JOB_CANDIDATE')] = { status: { type: 'keyword' }, externalId: { type: 'keyword' }, resume: { type: 'text' }, + remark: { type: 'keyword' }, interviews: { type: 'nested', properties: { @@ -129,31 +178,51 @@ esIndexPropertyMapping[config.get('esConfig.ES_INDEX_RESOURCE_BOOKING')] = { customerRate: { type: 'float' }, rateType: { type: 'keyword' }, billingAccountId: { type: 'integer' }, - createdAt: { type: 'date' }, - createdBy: { type: 'keyword' }, - updatedAt: { type: 'date' }, - updatedBy: { type: 'keyword' } -} -esIndexPropertyMapping[config.get('esConfig.ES_INDEX_WORK_PERIOD')] = { - resourceBookingId: { type: 'keyword' }, - userHandle: { type: 'keyword' }, - projectId: { type: 'integer' }, - userId: { type: 'keyword' }, - startDate: { type: 'date', format: 'yyyy-MM-dd' }, - endDate: { type: 'date', format: 'yyyy-MM-dd' }, - daysWorked: { type: 'integer' }, - memberRate: { type: 'float' }, - customerRate: { type: 'float' }, - paymentStatus: { type: 'keyword' }, - payments: { + workPeriods: { type: 'nested', properties: { id: { type: 'keyword' }, - workPeriodId: { type: 'keyword' }, - challengeId: { type: 'keyword' }, - amount: { type: 'float' }, - status: { type: 'keyword' }, - billingAccountId: { type: 'integer' }, + resourceBookingId: { type: 'keyword' }, + userHandle: { + type: 'keyword', + normalizer: 'lowercaseNormalizer' + }, + projectId: { type: 'integer' }, + userId: { type: 'keyword' }, + startDate: { type: 'date', format: 'yyyy-MM-dd' }, + endDate: { type: 'date', format: 'yyyy-MM-dd' }, + daysWorked: { type: 'integer' }, + daysPaid: { type: 'integer' }, + paymentTotal: { type: 'float' }, + paymentStatus: { type: 'keyword' }, + payments: { + type: 'nested', + properties: { + id: { type: 'keyword' }, + workPeriodId: { type: 'keyword' }, + challengeId: { type: 'keyword' }, + memberRate: { type: 'float' }, + customerRate: { type: 'float' }, + days: { type: 'integer' }, + amount: { type: 'float' }, + status: { type: 'keyword' }, + statusDetails: { + type: 'nested', + properties: { + errorMessage: { type: 'text' }, + errorCode: { type: 'integer' }, + retry: { type: 'integer' }, + step: { type: 'keyword' }, + challengeId: { type: 'keyword' } + } + }, + billingAccountId: { type: 'integer' }, + createdAt: { type: 'date' }, + createdBy: { type: 'keyword' }, + updatedAt: { type: 'date' }, + updatedBy: { type: 'keyword' } + } + }, createdAt: { type: 'date' }, createdBy: { type: 'keyword' }, updatedAt: { type: 'date' }, @@ -165,12 +234,45 @@ esIndexPropertyMapping[config.get('esConfig.ES_INDEX_WORK_PERIOD')] = { updatedAt: { type: 'date' }, updatedBy: { type: 'keyword' } } +esIndexPropertyMapping[config.get('esConfig.ES_INDEX_ROLE')] = { + name: { + type: 'keyword', + normalizer: 'lowercaseNormalizer' + }, + description: { type: 'keyword' }, + listOfSkills: { + type: 'keyword', + normalizer: 'lowercaseNormalizer' + }, + rates: { + properties: { + global: { type: 'integer' }, + inCountry: { type: 'integer' }, + offShore: { type: 'integer' }, + rate30Global: { type: 'integer' }, + rate30InCountry: { type: 'integer' }, + rate30OffShore: { type: 'integer' }, + rate20Global: { type: 'integer' }, + rate20InCountry: { type: 'integer' }, + rate20OffShore: { type: 'integer' } + } + }, + numberOfMembers: { type: 'integer' }, + numberOfMembersAvailable: { type: 'integer' }, + imageUrl: { type: 'keyword' }, + timeToCandidate: { type: 'integer' }, + timeToInterview: { type: 'integer' }, + createdAt: { type: 'date' }, + createdBy: { type: 'keyword' }, + updatedAt: { type: 'date' }, + updatedBy: { type: 'keyword' } +} /** * Get the first parameter from cli arguments */ function getParamFromCliArgs () { - const filteredArgs = process.argv.filter(arg => !arg.includes('--')) + const filteredArgs = process.argv.filter((arg) => !arg.includes('--')) if (filteredArgs.length > 2) { return filteredArgs[2] @@ -198,6 +300,16 @@ async function promptUser (promptQuery, cb) { }) } +/** + * Sleep for a given number of milliseconds. + * + * @param {Number} milliseconds the sleep time + * @returns {undefined} + */ +async function sleep (milliseconds) { + return new Promise((resolve) => setTimeout(resolve, milliseconds)) +} + /** * Create index in elasticsearch * @param {Object} index the index name @@ -209,15 +321,33 @@ async function createIndex (index, logger, esClient = null) { esClient = getESClient() } - await esClient.indices.create({ - index, + await esClient.indices.create({ index }) + await esClient.indices.close({ index }) + await esClient.indices.putSettings({ + index: index, body: { - mappings: { - properties: esIndexPropertyMapping[index] + settings: { + analysis: { + normalizer: { + lowercaseNormalizer: { + filter: ['lowercase'] + } + } + } } } }) - logger.info({ component: 'createIndex', message: `ES Index ${index} creation succeeded!` }) + await esClient.indices.open({ index }) + await esClient.indices.putMapping({ + index, + body: { + properties: esIndexPropertyMapping[index] + } + }) + logger.info({ + component: 'createIndex', + message: `ES Index ${index} creation succeeded!` + }) } /** @@ -232,7 +362,10 @@ async function deleteIndex (index, logger, esClient = null) { } await esClient.indices.delete({ index }) - logger.info({ component: 'deleteIndex', message: `ES Index ${index} deletion succeeded!` }) + logger.info({ + component: 'deleteIndex', + message: `ES Index ${index} deletion succeeded!` + }) } /** @@ -254,13 +387,20 @@ function getBulksFromDocuments (data) { } // check if current document size is greater than the max bulk size, if so, throw error - const currentDocumentSize = Buffer.byteLength(JSON.stringify(data[documentIndex]), 'utf-8') + const currentDocumentSize = Buffer.byteLength( + JSON.stringify(data[documentIndex]), + 'utf-8' + ) if (maxBytes < currentDocumentSize) { - throw new Error(`Document with id ${data[documentIndex]} has size ${currentDocumentSize}, which is greater than the max bulk size, ${maxBytes}. Consider increasing the max bulk size.`) + throw new Error( + `Document with id ${data[documentIndex]} has size ${currentDocumentSize}, which is greater than the max bulk size, ${maxBytes}. Consider increasing the max bulk size.` + ) } - if (currentBulkSize + currentDocumentSize > maxBytes || - currentBulk.length >= config.get('esConfig.MAX_BULK_NUM_DOCUMENTS')) { + if ( + currentBulkSize + currentDocumentSize > maxBytes || + currentBulk.length >= config.get('esConfig.MAX_BULK_NUM_DOCUMENTS') + ) { // if adding the current document goes over the max bulk size OR goes over max number of docs // then push the current bulk to bulks array and reset the current bulk bulks.push(currentBulk) @@ -277,16 +417,19 @@ function getBulksFromDocuments (data) { } /** -* Index records in bulk -* @param {Object | String} modelOpts the model name in db, or model options -* @param {Object} indexName the index name -* @param {Object} logger the logger object -*/ + * Index records in bulk + * @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 (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!` }) + logger.info({ + component: 'indexBulkDataToES', + message: `Reindexing of ${modelName}s started!` + }) const esClient = getESClient() @@ -298,12 +441,18 @@ async function indexBulkDataToES (modelOpts, indexName, logger) { await createIndex(indexName, logger, esClient) // get data from db - logger.info({ component: 'indexBulkDataToES', message: 'Getting data from database' }) + logger.info({ + component: 'indexBulkDataToES', + message: 'Getting data from database' + }) const model = models[modelName] const data = await model.findAll({ include }) - const rawObjects = _.map(data, r => r.toJSON()) + const rawObjects = _.map(data, (r) => r.toJSON()) if (_.isEmpty(rawObjects)) { - logger.info({ component: 'indexBulkDataToES', message: `No data in database for ${modelName}` }) + logger.info({ + component: 'indexBulkDataToES', + message: `No data in database for ${modelName}` + }) return } const bulks = getBulksFromDocuments(rawObjects) @@ -312,18 +461,27 @@ async function indexBulkDataToES (modelOpts, indexName, logger) { let doneCount = 0 for (const bulk of bulks) { // send bulk to esclient - const body = bulk.flatMap(doc => [{ index: { _index: indexName, _id: doc.id } }, doc]) + const body = bulk.flatMap((doc) => [ + { index: { _index: indexName, _id: doc.id } }, + doc + ]) await esClient.bulk({ refresh: true, body }) doneCount += bulk.length // log metrics const timeSpent = Date.now() - startTime const avgTimePerDocument = timeSpent / doneCount - const estimatedLength = (avgTimePerDocument * data.length) - const timeLeft = (startTime + estimatedLength) - Date.now() + const estimatedLength = avgTimePerDocument * data.length + const timeLeft = startTime + estimatedLength - Date.now() logger.info({ component: 'indexBulkDataToES', - message: `Processed ${doneCount} of ${data.length} documents, average time per document ${formatTime(avgTimePerDocument)}, time spent: ${formatTime(timeSpent)}, time left: ${formatTime(timeLeft)}` + message: `Processed ${doneCount} of ${ + data.length + } documents, average time per document ${formatTime( + avgTimePerDocument + )}, time spent: ${formatTime(timeSpent)}, time left: ${formatTime( + timeLeft + )}` }) } } @@ -339,20 +497,32 @@ 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!` }) + logger.info({ + component: 'indexDataToEsById', + message: `Reindexing of ${modelName} with id ${id} started!` + }) const esClient = getESClient() - logger.info({ component: 'indexDataToEsById', message: 'Getting data from database' }) + logger.info({ + component: 'indexDataToEsById', + message: 'Getting data from database' + }) const model = models[modelName] const data = await model.findById(id, include) - logger.info({ component: 'indexDataToEsById', message: 'Indexing data into Elasticsearch' }) + logger.info({ + component: 'indexDataToEsById', + message: 'Indexing data into Elasticsearch' + }) await esClient.index({ index: indexName, id: id, body: data.dataValues }) - logger.info({ component: 'indexDataToEsById', message: 'Indexing complete!' }) + logger.info({ + component: 'indexDataToEsById', + message: 'Indexing complete!' + }) } /** @@ -388,22 +558,40 @@ async function importData (pathToFile, dataModels, logger) { const modelRecords = jsonData[modelName] if (modelRecords && modelRecords.length > 0) { - logger.info({ component: 'importData', message: `Importing data for model: ${modelName}` }) + logger.info({ + component: 'importData', + message: `Importing data for model: ${modelName}` + }) await model.bulkCreate(modelRecords, { include, transaction }) - logger.info({ component: 'importData', message: `Records imported for model: ${modelName} = ${modelRecords.length}` }) + 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}` }) + logger.info({ + component: 'importData', + message: `No records to import for model: ${modelName}` + }) } } // commit transaction only if all things went ok - logger.info({ component: 'importData', message: 'committing transaction to database...' }) + logger.info({ + component: 'importData', + message: 'committing transaction to database...' + }) await transaction.commit() } catch (error) { - logger.error({ component: 'importData', message: `Error while writing data of model: ${currentModelName}` }) + logger.error({ + component: 'importData', + message: `Error while writing data of model: ${currentModelName}` + }) // rollback all insert operations if (transaction) { - logger.info({ component: 'importData', message: 'rollback database transaction...' }) + logger.info({ + component: 'importData', + message: 'rollback database transaction...' + }) transaction.rollback() } if (error.name && error.errors && error.fields) { @@ -425,22 +613,40 @@ async function importData (pathToFile, dataModels, logger) { // after importing, index data const jobCandidateModelOpts = { modelName: 'JobCandidate', - include: [{ - model: models.Interview, - as: 'interviews' - }] - } - const workPeriodModelOpts = { - modelName: 'WorkPeriod', - include: [{ - model: models.WorkPeriodPayment, - as: 'payments' - }] + include: [ + { + model: models.Interview, + as: 'interviews' + } + ] + } + const resourceBookingModelOpts = { + modelName: 'ResourceBooking', + include: [ + { + model: models.WorkPeriod, + as: 'workPeriods', + include: [ + { + model: models.WorkPeriodPayment, + as: 'payments' + } + ] + } + ] } await indexBulkDataToES('Job', config.get('esConfig.ES_INDEX_JOB'), logger) - await indexBulkDataToES(jobCandidateModelOpts, config.get('esConfig.ES_INDEX_JOB_CANDIDATE'), logger) - await indexBulkDataToES('ResourceBooking', config.get('esConfig.ES_INDEX_RESOURCE_BOOKING'), logger) - await indexBulkDataToES(workPeriodModelOpts, config.get('esConfig.ES_INDEX_WORK_PERIOD'), logger) + await indexBulkDataToES( + jobCandidateModelOpts, + config.get('esConfig.ES_INDEX_JOB_CANDIDATE'), + logger + ) + await indexBulkDataToES( + resourceBookingModelOpts, + config.get('esConfig.ES_INDEX_RESOURCE_BOOKING'), + logger + ) + await indexBulkDataToES('Role', config.get('esConfig.ES_INDEX_ROLE'), logger) } /** @@ -450,7 +656,10 @@ async function importData (pathToFile, dataModels, logger) { * @param {Object} logger the logger object */ async function exportData (pathToFile, dataModels, logger) { - logger.info({ component: 'exportData', message: `Start Saving data to file with path ${pathToFile}....` }) + logger.info({ + component: 'exportData', + message: `Start Saving data to file with path ${pathToFile}....` + }) const allModelsRecords = {} for (let index = 0; index < dataModels.length; index += 1) { @@ -458,13 +667,19 @@ async function exportData (pathToFile, dataModels, logger) { 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()) + const rawRecords = _.map(modelRecords, (r) => r.toJSON()) allModelsRecords[modelName] = rawRecords - logger.info({ component: 'exportData', message: `Records loaded for model: ${modelName} = ${rawRecords.length}` }) + logger.info({ + component: 'exportData', + message: `Records loaded for model: ${modelName} = ${rawRecords.length}` + }) } fs.writeFileSync(pathToFile, JSON.stringify(allModelsRecords)) - logger.info({ component: 'exportData', message: 'End Saving data to file....' }) + logger.info({ + component: 'exportData', + message: 'End Saving data to file....' + }) } /** @@ -479,7 +694,7 @@ function formatTime (millisec) { const days = Math.floor((millisec / (1000 * 60 * 60 * 24)) % 7) const weeks = Math.floor((millisec / (1000 * 60 * 60 * 24 * 7)) % 4) const mnths = Math.floor((millisec / (1000 * 60 * 60 * 24 * 7 * 4)) % 12) - const yrs = Math.floor((millisec / (1000 * 60 * 60 * 24 * 7 * 4 * 12))) + const yrs = Math.floor(millisec / (1000 * 60 * 60 * 24 * 7 * 4 * 12)) let formattedTime = '0 milliseconds' if (ms > 0) { @@ -523,12 +738,12 @@ function checkIfExists (source, term) { throw new Error('Source argument should be an array') } - source = source.map(s => s.toLowerCase()) + source = source.map((s) => s.toLowerCase()) if (_.isString(term)) { terms = term.toLowerCase().split(' ') } else if (_.isArray(term)) { - terms = term.map(t => t.toLowerCase()) + terms = term.map((t) => t.toLowerCase()) } else { throw new Error('Term argument should be either a string or an array') } @@ -582,7 +797,9 @@ function autoWrapExpress (obj) { */ function getPageLink (req, page) { const q = _.assignIn({}, req.query, { page }) - return `${req.protocol}://${req.get('Host')}${req.baseUrl}${req.path}?${querystring.stringify(q)}` + return `${req.protocol}://${req.get('Host')}${req.baseUrl}${ + req.path + }?${querystring.stringify(q)}` } /** @@ -592,9 +809,6 @@ function getPageLink (req, page) { * @param {Object} result the operation result */ function setResHeaders (req, res, result) { - if (result.fromDb) { - return - } const totalPages = Math.ceil(result.total / result.perPage) if (result.page > 1) { res.set('X-Prev-Page', result.page - 1) @@ -606,9 +820,13 @@ function setResHeaders (req, res, result) { res.set('X-Per-Page', result.perPage) res.set('X-Total', result.total) res.set('X-Total-Pages', totalPages) + res.set('X-Data-Source', result.fromDb ? 'database' : 'elasticsearch') // set Link header if (totalPages > 0) { - let link = `<${getPageLink(req, 1)}>; rel="first", <${getPageLink(req, totalPages)}>; rel="last"` + let link = `<${getPageLink(req, 1)}>; rel="first", <${getPageLink( + req, + totalPages + )}>; rel="last"` if (result.page > 1) { link += `, <${getPageLink(req, result.page - 1)}>; rel="prev"` } @@ -654,7 +872,10 @@ function getESClient () { * @returns {Promise} */ const getM2MToken = async () => { - return await m2m.getMachineToken(config.AUTH0_CLIENT_ID, config.AUTH0_CLIENT_SECRET) + return await m2m.getMachineToken( + config.AUTH0_CLIENT_ID, + config.AUTH0_CLIENT_SECRET + ) } /* @@ -662,7 +883,10 @@ const getM2MToken = async () => { * @returns {Promise} */ const getM2MUbahnToken = async () => { - return await m2mForUbahn.getMachineToken(config.AUTH0_CLIENT_ID, config.AUTH0_CLIENT_SECRET) + return await m2mForUbahn.getMachineToken( + config.AUTH0_CLIENT_ID, + config.AUTH0_CLIENT_SECRET + ) } /** @@ -709,7 +933,10 @@ async function listUsersByExternalId (externalId) { .set('Authorization', `Bearer ${token}`) .set('Content-Type', 'application/json') .set('Accept', 'application/json') - localLogger.debug({ context: 'listUserByExternalId', message: `response body: ${JSON.stringify(res.body)}` }) + localLogger.debug({ + context: 'listUserByExternalId', + message: `response body: ${JSON.stringify(res.body)}` + }) return res.body } @@ -721,7 +948,9 @@ async function listUsersByExternalId (externalId) { async function getUserByExternalId (externalId) { const users = await listUsersByExternalId(externalId) if (_.isEmpty(users)) { - throw new errors.NotFoundError(`externalId: ${externalId} "user" not found`) + throw new errors.NotFoundError( + `externalId: ${externalId} "user" not found` + ) } return users[0] } @@ -733,7 +962,13 @@ async function getUserByExternalId (externalId) { * @params {Object} options the extra options to control the function */ async function postEvent (topic, payload, options = {}) { - logger.debug({ component: 'helper', context: 'postEvent', message: `Posting event to Kafka topic ${topic}, ${JSON.stringify(payload)}` }) + logger.debug({ + component: 'helper', + context: 'postEvent', + message: `Posting event to Kafka topic ${topic}, ${JSON.stringify( + payload + )}` + }) const client = getBusApiClient() const message = { topic, @@ -742,6 +977,9 @@ async function postEvent (topic, payload, options = {}) { 'mime-type': 'application/json', payload } + if (options.key) { + message.key = options.key + } await client.postEvent(message) await eventDispatcher.handleEvent(topic, { value: payload, options }) } @@ -780,8 +1018,11 @@ async function getProjects (currentUser, criteria = {}) { .set('Authorization', token) .set('Content-Type', 'application/json') .set('Accept', 'application/json') - localLogger.debug({ context: 'getProjects', message: `response body: ${JSON.stringify(res.body)}` }) - const result = _.map(res.body, item => { + localLogger.debug({ + context: 'getProjects', + message: `response body: ${JSON.stringify(res.body)}` + }) + const result = _.map(res.body, (item) => { return _.pick(item, ['id', 'name', 'invites', 'members']) }) return { @@ -805,10 +1046,15 @@ async function getTopcoderUserById (userId) { .query({ filter: `id=${userId}` }) .set('Authorization', `Bearer ${token}`) .set('Accept', 'application/json') - localLogger.debug({ context: 'getTopcoderUserById', message: `response body: ${JSON.stringify(res.body)}` }) + localLogger.debug({ + context: 'getTopcoderUserById', + message: `response body: ${JSON.stringify(res.body)}` + }) const user = _.get(res.body, 'result.content[0]') if (!user) { - throw new errors.NotFoundError(`userId: ${userId} "user" not found from ${config.TOPCODER_USERS_API}`) + throw new errors.NotFoundError( + `userId: ${userId} "user" not found from ${config.TOPCODER_USERS_API}` + ) } return user } @@ -825,14 +1071,21 @@ async function getUserById (userId, enrich) { .set('Authorization', `Bearer ${token}`) .set('Content-Type', 'application/json') .set('Accept', 'application/json') - localLogger.debug({ context: 'getUserById', message: `response body: ${JSON.stringify(res.body)}` }) + localLogger.debug({ + context: 'getUserById', + message: `response body: ${JSON.stringify(res.body)}` + }) const user = _.pick(res.body, ['id', 'handle', 'firstName', 'lastName']) if (enrich) { - user.skills = (res.body.skills || []).map((skillObj) => _.pick(skillObj.skill, ['id', 'name'])) + 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'])) + user.attributes = _.map(attributes, (attr) => + _.pick(attr, ['id', 'value', 'attribute.id', 'attribute.name']) + ) } return user @@ -851,7 +1104,10 @@ async function createUbahnUser ({ handle, firstName, lastName }) { .set('Content-Type', 'application/json') .set('Accept', 'application/json') .send({ handle, firstName, lastName }) - localLogger.debug({ context: 'createUbahnUser', message: `response body: ${JSON.stringify(res.body)}` }) + localLogger.debug({ + context: 'createUbahnUser', + message: `response body: ${JSON.stringify(res.body)}` + }) return _.pick(res.body, ['id']) } @@ -860,7 +1116,10 @@ async function createUbahnUser ({ handle, firstName, lastName }) { * @param {String} userId the user id(with uuid format) * @param {Object} data the profile data */ -async function createUserExternalProfile (userId, { organizationId, externalId }) { +async function createUserExternalProfile ( + userId, + { organizationId, externalId } +) { const token = await getM2MUbahnToken() const res = await request .post(`${config.TC_API}/users/${userId}/externalProfiles`) @@ -868,7 +1127,10 @@ async function createUserExternalProfile (userId, { organizationId, externalId } .set('Content-Type', 'application/json') .set('Accept', 'application/json') .send({ organizationId, externalId: String(externalId) }) - localLogger.debug({ context: 'createUserExternalProfile', message: `response body: ${JSON.stringify(res.body)}` }) + localLogger.debug({ + context: 'createUserExternalProfile', + message: `response body: ${JSON.stringify(res.body)}` + }) } /** @@ -878,7 +1140,7 @@ async function createUserExternalProfile (userId, { organizationId, externalId } */ async function getMembers (handles) { const token = await getM2MToken() - const handlesStr = _.map(handles, handle => { + const handlesStr = _.map(handles, (handle) => { return '%22' + handle.toLowerCase() + '%22' }).join(',') const url = `${config.TC_API}/members?fields=userId,handleLower,photoURL&handlesLower=[${handlesStr}]` @@ -888,7 +1150,10 @@ async function getMembers (handles) { .set('Authorization', `Bearer ${token}`) .set('Content-Type', 'application/json') .set('Accept', 'application/json') - localLogger.debug({ context: 'getMembers', message: `response body: ${JSON.stringify(res.body)}` }) + localLogger.debug({ + context: 'getMembers', + message: `response body: ${JSON.stringify(res.body)}` + }) return res.body } @@ -913,11 +1178,16 @@ async function getProjectById (currentUser, id) { .set('Authorization', token) .set('Content-Type', 'application/json') .set('Accept', 'application/json') - localLogger.debug({ context: 'getProjectById', message: `response body: ${JSON.stringify(res.body)}` }) + localLogger.debug({ + context: 'getProjectById', + message: `response body: ${JSON.stringify(res.body)}` + }) return _.pick(res.body, ['id', 'name', 'invites', 'members']) } catch (err) { if (err.status === HttpStatus.FORBIDDEN) { - throw new errors.ForbiddenError(`You are not allowed to access the project with id ${id}`) + throw new errors.ForbiddenError( + `You are not allowed to access the project with id ${id}` + ) } if (err.status === HttpStatus.NOT_FOUND) { throw new errors.NotFoundError(`id: ${id} project not found`) @@ -945,7 +1215,10 @@ async function getTopcoderSkills (criteria) { .set('Authorization', `Bearer ${token}`) .set('Content-Type', 'application/json') .set('Accept', 'application/json') - localLogger.debug({ context: 'getTopcoderSkills', message: `response body: ${JSON.stringify(res.body)}` }) + localLogger.debug({ + context: 'getTopcoderSkills', + message: `response body: ${JSON.stringify(res.body)}` + }) return { total: Number(_.get(res.headers, 'x-total')), page: Number(_.get(res.headers, 'x-page')), @@ -960,6 +1233,24 @@ async function getTopcoderSkills (criteria) { } } +/** + * Function to search and retrive all skills from v5/skills + * - only returns skills from Topcoder Skills Provider defined by `TOPCODER_SKILL_PROVIDER_ID` + * + * @param {Object} criteria the search criteria + * @returns the request result + */ +async function getAllTopcoderSkills (criteria) { + const skills = await getTopcoderSkills(_.assign(criteria, { page: 1, perPage: 100 })) + while (skills.page * skills.perPage <= skills.total) { + const newSkills = await getTopcoderSkills(_.assign(criteria, { page: skills.page + 1, perPage: 100 })) + skills.result = [...skills.result, ...newSkills.result] + skills.page = newSkills.page + skills.total = newSkills.total + } + return skills.result +} + /** * Function to get skill by id * @param {String} skillId the skill Id @@ -972,7 +1263,10 @@ async function getSkillById (skillId) { .set('Authorization', `Bearer ${token}`) .set('Content-Type', 'application/json') .set('Accept', 'application/json') - localLogger.debug({ context: 'getSkillById', message: `response body: ${JSON.stringify(res.body)}` }) + localLogger.debug({ + context: 'getSkillById', + message: `response body: ${JSON.stringify(res.body)}` + }) return _.pick(res.body, ['id', 'name']) } @@ -994,8 +1288,13 @@ async function ensureUbahnUserId (currentUser) { throw err } const topcoderUser = await getTopcoderUserById(currentUser.userId) - const user = await createUbahnUser(_.pick(topcoderUser, ['handle', 'firstName', 'lastName'])) - await createUserExternalProfile(user.id, { organizationId: config.ORG_ID, externalId: currentUser.userId }) + const user = await createUbahnUser( + _.pick(topcoderUser, ['handle', 'firstName', 'lastName']) + ) + await createUserExternalProfile(user.id, { + organizationId: config.ORG_ID, + externalId: currentUser.userId + }) return user.id } } @@ -1043,7 +1342,10 @@ async function ensureUserById (userId) { .set('Authorization', `Bearer ${token}`) .set('Content-Type', 'application/json') .set('Accept', 'application/json') - localLogger.debug({ context: 'ensureUserById', message: `response body: ${JSON.stringify(res.body)}` }) + localLogger.debug({ + context: 'ensureUserById', + message: `response body: ${JSON.stringify(res.body)}` + }) return res.body } catch (err) { if (err.status === HttpStatus.NOT_FOUND) { @@ -1059,7 +1361,11 @@ async function ensureUserById (userId) { * @returns {Object} the M2M auth user */ function getAuditM2Muser () { - return { isMachine: true, userId: config.m2m.M2M_AUDIT_USER_ID, handle: config.m2m.M2M_AUDIT_HANDLE } + return { + isMachine: true, + userId: config.m2m.M2M_AUDIT_USER_ID, + handle: config.m2m.M2M_AUDIT_HANDLE + } } /** @@ -1079,9 +1385,16 @@ async function checkIsMemberOfProject (userId, projectId) { .set('Content-Type', 'application/json') .set('Accept', 'application/json') const memberIdList = _.map(res.body.members, 'userId') - localLogger.debug({ context: 'checkIsMemberOfProject', message: `the members of project ${projectId}: ${JSON.stringify(memberIdList)}, authUserId: ${JSON.stringify(userId)}` }) + localLogger.debug({ + context: 'checkIsMemberOfProject', + message: `the members of project ${projectId}: ${JSON.stringify( + memberIdList + )}, authUserId: ${JSON.stringify(userId)}` + }) if (!memberIdList.includes(userId)) { - throw new errors.UnauthorizedError(`userId: ${userId} the user is not a member of project ${projectId}`) + throw new errors.UnauthorizedError( + `userId: ${userId} the user is not a member of project ${projectId}` + ) } } @@ -1097,15 +1410,18 @@ async function getMemberDetailsByHandles (handles) { } const token = await getM2MToken() const res = await request - .get(`${config.TOPCODER_MEMBERS_API}/_search`) + .get(`${config.TOPCODER_MEMBERS_API}/`) .query({ - query: _.map(handles, handle => `handleLower:${handle.toLowerCase()}`).join(' OR '), - fields: 'userId,handle,firstName,lastName,email' + 'handlesLower[]': handles.map(handle => handle.toLowerCase()), + fields: 'userId,handle,handleLower,firstName,lastName,email' }) .set('Authorization', `Bearer ${token}`) .set('Accept', 'application/json') - localLogger.debug({ context: 'getMemberDetailsByHandles', message: `response body: ${JSON.stringify(res.body)}` }) - return _.get(res.body, 'result.content') + localLogger.debug({ + context: 'getMemberDetailsByHandles', + message: `response body: ${JSON.stringify(res.body)}` + }) + return res.body } /** @@ -1114,14 +1430,14 @@ async function getMemberDetailsByHandles (handles) { * @param {String} handle the user handle * @returns {Object} the member details */ -async function getV3MemberDetailsByHandle (handle) { - const token = await getM2MToken() - const res = await request - .get(`${config.TOPCODER_MEMBERS_API}/${handle}`) - .set('Authorization', `Bearer ${token}`) - .set('Accept', 'application/json') - localLogger.debug({ context: 'getV3MemberDetailsByHandle', message: `response body: ${JSON.stringify(res.body)}` }) - return _.get(res.body, 'result.content') +async function getMemberDetailsByHandle (handle) { + const [memberDetails] = await getMemberDetailsByHandles([handle]) + + if (!memberDetails) { + throw new errors.NotFoundError(`Member details are not found by handle "${handle}".`) + } + + return memberDetails } /** @@ -1140,7 +1456,10 @@ async function _getMemberDetailsByEmail (token, email) { }) .set('Authorization', `Bearer ${token}`) .set('Accept', 'application/json') - localLogger.debug({ context: '_getMemberDetailsByEmail', message: `response body: ${JSON.stringify(res.body)}` }) + localLogger.debug({ + context: '_getMemberDetailsByEmail', + message: `response body: ${JSON.stringify(res.body)}` + }) return _.get(res.body, 'result.content') } @@ -1153,13 +1472,22 @@ async function _getMemberDetailsByEmail (token, email) { */ async function getMemberDetailsByEmails (emails) { const token = await getM2MToken() - const limiter = new Bottleneck({ maxConcurrent: config.MAX_PARALLEL_REQUEST_TOPCODER_USERS_API }) - const membersArray = await Promise.all(emails.map(email => limiter.schedule(() => _getMemberDetailsByEmail(token, email) - .catch((error) => { - localLogger.error({ context: 'getMemberDetailsByEmails', message: error.message }) - return [] - }) - ))) + const limiter = new Bottleneck({ + maxConcurrent: config.MAX_PARALLEL_REQUEST_TOPCODER_USERS_API + }) + const membersArray = await Promise.all( + emails.map((email) => + limiter.schedule(() => + _getMemberDetailsByEmail(token, email).catch((error) => { + localLogger.error({ + context: 'getMemberDetailsByEmails', + message: error.message + }) + return [] + }) + ) + ) + ) return _.flatten(membersArray) } @@ -1180,7 +1508,10 @@ async function createProjectMember (projectId, data, criteria) { .set('Accept', 'application/json') .query(criteria) .send(data) - localLogger.debug({ context: 'createProjectMember', message: `response body: ${JSON.stringify(member)}` }) + localLogger.debug({ + context: 'createProjectMember', + message: `response body: ${JSON.stringify(member)}` + }) return member } @@ -1192,15 +1523,19 @@ async function createProjectMember (projectId, data, criteria) { * @returns {Array} the project members */ async function listProjectMembers (currentUser, projectId, criteria = {}) { - const token = (currentUser.hasManagePermission || currentUser.isMachine) - ? `Bearer ${await getM2MToken()}` - : currentUser.jwtToken + const token = + currentUser.hasManagePermission || currentUser.isMachine + ? `Bearer ${await getM2MToken()}` + : currentUser.jwtToken const { body: members } = await request .get(`${config.TC_API}/projects/${projectId}/members`) .query(criteria) .set('Authorization', token) .set('Accept', 'application/json') - localLogger.debug({ context: 'listProjectMembers', message: `response body: ${JSON.stringify(members)}` }) + localLogger.debug({ + context: 'listProjectMembers', + message: `response body: ${JSON.stringify(members)}` + }) return members } @@ -1212,15 +1547,19 @@ async function listProjectMembers (currentUser, projectId, criteria = {}) { * @returns {Array} the member invites */ async function listProjectMemberInvites (currentUser, projectId, criteria = {}) { - const token = (currentUser.hasManagePermission || currentUser.isMachine) - ? `Bearer ${await getM2MToken()}` - : currentUser.jwtToken + const token = + currentUser.hasManagePermission || currentUser.isMachine + ? `Bearer ${await getM2MToken()}` + : currentUser.jwtToken const { body: invites } = await request .get(`${config.TC_API}/projects/${projectId}/invites`) .query(criteria) .set('Authorization', token) .set('Accept', 'application/json') - localLogger.debug({ context: 'listProjectMemberInvites', message: `response body: ${JSON.stringify(invites)}` }) + localLogger.debug({ + context: 'listProjectMemberInvites', + message: `response body: ${JSON.stringify(invites)}` + }) return invites } @@ -1232,16 +1571,21 @@ async function listProjectMemberInvites (currentUser, projectId, criteria = {}) * @returns {undefined} */ async function deleteProjectMember (currentUser, projectId, projectMemberId) { - const token = (currentUser.hasManagePermission || currentUser.isMachine) - ? `Bearer ${await getM2MToken()}` - : currentUser.jwtToken + const token = + currentUser.hasManagePermission || currentUser.isMachine + ? `Bearer ${await getM2MToken()}` + : currentUser.jwtToken try { await request - .delete(`${config.TC_API}/projects/${projectId}/members/${projectMemberId}`) + .delete( + `${config.TC_API}/projects/${projectId}/members/${projectMemberId}` + ) .set('Authorization', token) } catch (err) { if (err.status === HttpStatus.NOT_FOUND) { - throw new errors.NotFoundError(`projectMemberId: ${projectMemberId} "member" doesn't exist in project ${projectId}`) + throw new errors.NotFoundError( + `projectMemberId: ${projectMemberId} "member" doesn't exist in project ${projectId}` + ) } throw err } @@ -1255,7 +1599,10 @@ async function deleteProjectMember (currentUser, projectId, projectMemberId) { */ function getUserAttributeValue (user, attributeName) { const attributes = _.get(user, 'attributes', []) - const targetAttribute = _.find(attributes, a => a.attribute.name === attributeName) + const targetAttribute = _.find( + attributes, + (a) => a.attribute.name === attributeName + ) return _.get(targetAttribute, 'value') } @@ -1271,16 +1618,48 @@ async function createChallenge (data, token) { token = await getM2MToken() } const url = `${config.TC_API}/challenges` - localLogger.debug({ context: 'createChallenge', message: `EndPoint: POST ${url}` }) - localLogger.debug({ context: 'createChallenge', message: `Request Body: ${JSON.stringify(data)}` }) + localLogger.debug({ + context: 'createChallenge', + message: `EndPoint: POST ${url}` + }) + localLogger.debug({ + context: 'createChallenge', + message: `Request Body: ${JSON.stringify(data)}` + }) const { body: challenge, status: httpStatus } = await request .post(url) .set('Authorization', `Bearer ${token}`) .set('Content-Type', 'application/json') .set('Accept', 'application/json') .send(data) - localLogger.debug({ context: 'createChallenge', message: `Status Code: ${httpStatus}` }) - localLogger.debug({ context: 'createChallenge', message: `Response Body: ${JSON.stringify(challenge)}` }) + localLogger.debug({ + context: 'createChallenge', + message: `Status Code: ${httpStatus}` + }) + localLogger.debug({ + context: 'createChallenge', + message: `Response Body: ${JSON.stringify(challenge)}` + }) + return challenge +} + +/** + * Get a challenge + * + * @param {Object} data challenge data + * @returns {Object} the challenge + */ +async function getChallenge (challengeId) { + const token = await getM2MToken() + const url = `${config.TC_API}/challenges/${challengeId}` + localLogger.debug({ context: 'getChallenge', message: `EndPoint: GET ${url}` }) + const { body: challenge, status: httpStatus } = await request + .get(url) + .set('Authorization', `Bearer ${token}`) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json') + localLogger.debug({ context: 'getChallenge', message: `Status Code: ${httpStatus}` }) + localLogger.debug({ context: 'getChallenge', message: `Response Body: ${JSON.stringify(challenge)}` }) return challenge } @@ -1297,16 +1676,28 @@ async function updateChallenge (challengeId, data, token) { token = await getM2MToken() } const url = `${config.TC_API}/challenges/${challengeId}` - localLogger.debug({ context: 'updateChallenge', message: `EndPoint: PATCH ${url}` }) - localLogger.debug({ context: 'updateChallenge', message: `Request Body: ${JSON.stringify(data)}` }) + localLogger.debug({ + context: 'updateChallenge', + message: `EndPoint: PATCH ${url}` + }) + localLogger.debug({ + context: 'updateChallenge', + message: `Request Body: ${JSON.stringify(data)}` + }) const { body: challenge, status: httpStatus } = await request .patch(url) .set('Authorization', `Bearer ${token}`) .set('Content-Type', 'application/json') .set('Accept', 'application/json') .send(data) - localLogger.debug({ context: 'updateChallenge', message: `Status Code: ${httpStatus}` }) - localLogger.debug({ context: 'updateChallenge', message: `Response Body: ${JSON.stringify(challenge)}` }) + localLogger.debug({ + context: 'updateChallenge', + message: `Status Code: ${httpStatus}` + }) + localLogger.debug({ + context: 'updateChallenge', + message: `Response Body: ${JSON.stringify(challenge)}` + }) return challenge } @@ -1322,19 +1713,60 @@ async function createChallengeResource (data, token) { token = await getM2MToken() } const url = `${config.TC_API}/resources` - localLogger.debug({ context: 'createChallengeResource', message: `EndPoint: POST ${url}` }) - localLogger.debug({ context: 'createChallengeResource', message: `Request Body: ${JSON.stringify(data)}` }) + localLogger.debug({ + context: 'createChallengeResource', + message: `EndPoint: POST ${url}` + }) + localLogger.debug({ + context: 'createChallengeResource', + message: `Request Body: ${JSON.stringify(data)}` + }) const { body: resource, status: httpStatus } = await request .post(url) .set('Authorization', `Bearer ${token}`) .set('Content-Type', 'application/json') .set('Accept', 'application/json') .send(data) - localLogger.debug({ context: 'createChallengeResource', message: `Status Code: ${httpStatus}` }) - localLogger.debug({ context: 'createChallengeResource', message: `Response Body: ${JSON.stringify(resource)}` }) + localLogger.debug({ + context: 'createChallengeResource', + message: `Status Code: ${httpStatus}` + }) + localLogger.debug({ + context: 'createChallengeResource', + message: `Response Body: ${JSON.stringify(resource)}` + }) return resource } +/** + * + * @param {String} challengeId the challenge id + * @param {String} memberHandle the member handle + * @param {String} roleId the role id + * @returns {Object} the resource + */ +async function getChallengeResource (challengeId, memberHandle, roleId) { + const token = await getM2MToken() + const url = `${config.TC_API}/resources?challengeId=${challengeId}&memberHandle=${memberHandle}&roleId=${roleId}` + localLogger.debug({ context: 'createChallengeResource', message: `EndPoint: POST ${url}` }) + try { + const { body: resource, status: httpStatus } = await request + .get(url) + .set('Authorization', `Bearer ${token}`) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json') + localLogger.debug({ context: 'getChallengeResource', message: `Status Code: ${httpStatus}` }) + localLogger.debug({ context: 'getChallengeResource', message: `Response Body: ${JSON.stringify(resource)}` }) + return resource[0] + } catch (err) { + if (err.status === 404) { + localLogger.debug({ context: 'getChallengeResource', message: `Status Code: ${err.status}` }) + } else { + throw err + } + } +} + /** * Populates workPeriods from start and end date of resource booking * @param {Date} start start date of the resource booking @@ -1348,7 +1780,7 @@ function extractWorkPeriods (start, end) { return Math.min(endDay, 5) - Math.max(startDay, 1) + 1 } else if (week === 0) { return Math.min(6 - startDay, 5) - } else if (week === (weeks - 1)) { + } else if (week === weeks - 1) { return Math.min(endDay, 5) } else return 5 } @@ -1377,6 +1809,35 @@ function extractWorkPeriods (start, end) { return periods } +/** + * Calculate the payment status of given workPeriod + * @param {object} workPeriod workPeriod object with payments + * @returns {string} new workperiod payment status + * @throws {ConflictError} when no rule matches + */ +function calculateWorkPeriodPaymentStatus (workPeriod) { + function matchRule (rule) { + const actualState = { + daysWorked: workPeriod.daysWorked, + hasDueDays: workPeriod.daysWorked > workPeriod.daysPaid + } + return _.every(_.keys(rule.condition), condition => { + if (_.isArray(rule.condition[condition])) { + return checkIfExists(_.map(workPeriod.payments, 'status'), rule.condition[condition]) + } else { + return rule.condition[condition] === actualState[condition] + } + }) + } + // find the first rule which is matched by the Work Period + for (const rule of PaymentStatusRules) { + if (matchRule(rule)) { + return rule.paymentStatus + } + } + throw new errors.ConflictError('Cannot calculate payment status.') +} + /** * Returns the email address of specified (via handle) user. * @@ -1391,7 +1852,10 @@ async function getUserByHandle (userHandle) { .set('Authorization', `Bearer ${token}`) .set('Content-Type', 'application/json') .set('Accept', 'application/json') - localLogger.debug({ context: 'getUserByHandle', message: `response body: ${JSON.stringify(res.body)}` }) + localLogger.debug({ + context: 'getUserByHandle', + message: `response body: ${JSON.stringify(res.body)}` + }) return _.get(res, 'body') } @@ -1411,9 +1875,121 @@ async function substituteStringByObject (string, object) { return string } +/** + * Get tags from tagging service + * @param {String} description The challenge description + * @returns {Array} array of tags + */ +async function getTags (description) { + const data = { text: description, extract_confidence: false } + const type = 'emsi/internal_no_refresh' + const url = `${config.TC_API}/contest-tagging/${type}` + const res = await request + .post(url) + .set('Accept', 'application/json') + .send(querystring.stringify(data)) + + localLogger.debug({ + context: 'getTags', + message: `response body: ${JSON.stringify(res.body)}` + }) + return _.get(res, 'body') +} + +/** + * @param {Object} data title of project and any other info + * @returns {Object} the project created + */ +async function createProject (currentUser, data) { + const token = currentUser.jwtToken + const res = await request + .post(`${config.TC_API}/projects/`) + .set('Authorization', token) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json') + .send(data) + localLogger.debug({ + context: 'createProject', + message: `response body: ${JSON.stringify(res)}` + }) + return _.get(res, 'body') +} + +/** + * Returns the email address of specified (via handle) user. + * + * @param {String} userHandle user handle + * @returns {String} email address of the user + */ +async function getMemberGroups (userId) { + const token = await getM2MToken() + const url = `${config.TC_API}/groups/memberGroups/${userId}` + const res = await request + .get(url) + .set('Authorization', `Bearer ${token}`) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json') + localLogger.debug({ + context: 'getMemberGroups', + message: `response body: ${JSON.stringify(res.body)}` + }) + return _.get(res, 'body') +} + +/** + * Removes markdown and html formatting from given text + * + * @param {String} text formatted text + * @returns {String} cleaned words seperated by single space + */ +function removeTextFormatting (text) { + text = _.replace(text, /^(-\s*?|\*\s*?|_\s*?){3,}\s*$/gm, ' ') + text = _.replace(text, /^([\s\t]*)([*\-+]|\d+\.)\s+/gm, ' $1 ') + // Header + text = _.replace(text, /\n={2,}/g, '\n') + // Fenced codeblocks + text = _.replace(text, /~{3}.*\n/g, ' ') + // Strikethrough + text = _.replace(text, /~~/g, ' ') + // Fenced codeblocks + text = _.replace(text, /`{3}.*\n/g, ' ') + // Remove HTML tags + text = _.replace(text, /<[^>]*>/g, ' ') + // Remove setext-style headers + text = _.replace(text, /^[=-]{2,}\s*$/g, ' ') + // Remove footnotes + text = _.replace(text, /\[\^.+?\](: .*?$)?/g, ' ') + text = _.replace(text, /\s{0,2}\[.*?\]: .*?$/g, ' ') + // Remove images + text = _.replace(text, /!\[(.*?)\][[(].*?[\])]/g, ' $1 ') + // Remove inline links + text = _.replace(text, /\[(.*?)\][[(].*?[\])]/g, ' $1 ') + // Remove blockquotes + text = _.replace(text, /^\s{0,3}>\s?/g, ' ') + // Remove reference-style links + text = _.replace(text, /^\s{1,2}\[(.*?)\]: (\S+)( ".*?")?\s*$/g, ' ') + // Remove atx-style headers + text = _.replace(text, /^#{1,6}\s*([^#]*)\s*#{1,6}?$/gm, ' $1 ') + // Remove emphasis (repeat the line to remove double emphasis) + text = _.replace(text, /([*_]{1,3})(\S.*?\S{0,1})\1/g, ' $2 ') + text = _.replace(text, /([*_]{1,3})(\S.*?\S{0,1})\1/g, ' $2 ') + // Remove code blocks + text = _.replace(text, /(`{3,})(.*?)\1/gm, ' $2 ') + // Remove inline code + text = _.replace(text, /`(.+?)`/g, ' $1 ') + // Remove punctuation + text = _.replace(text, /[,"'?/\\]/g, ' ') + // Replace two or more newlines + text = _.replace(text, /\n/g, ' ') + // replace all whitespace characters with single space + text = _.replace(text, /\s\s+/g, ' ') + return text +} + module.exports = { getParamFromCliArgs, promptUser, + sleep, createIndex, deleteIndex, indexBulkDataToES, @@ -1442,6 +2018,7 @@ module.exports = { getMembers, getProjectById, getTopcoderSkills, + getAllTopcoderSkills, getSkillById, ensureJobById, ensureResourceBookingById, @@ -1450,17 +2027,24 @@ module.exports = { getAuditM2Muser, checkIsMemberOfProject, getMemberDetailsByHandles, - getV3MemberDetailsByHandle, + getMemberDetailsByHandle, getMemberDetailsByEmails, + getTags, createProjectMember, listProjectMembers, listProjectMemberInvites, deleteProjectMember, getUserAttributeValue, createChallenge, + getChallenge, updateChallenge, createChallengeResource, + getChallengeResource, extractWorkPeriods, + calculateWorkPeriodPaymentStatus, getUserByHandle, - substituteStringByObject + substituteStringByObject, + createProject, + getMemberGroups, + removeTextFormatting } diff --git a/src/controllers/JobController.js b/src/controllers/JobController.js index 14f5cfc5..606c690b 100644 --- a/src/controllers/JobController.js +++ b/src/controllers/JobController.js @@ -2,6 +2,7 @@ * Controller for Job endpoints */ const HttpStatus = require('http-status-codes') +const _ = require('lodash') const service = require('../services/JobService') const helper = require('../common/helper') @@ -57,7 +58,8 @@ async function deleteJob (req, res) { * @param res the response */ async function searchJobs (req, res) { - const result = await service.searchJobs(req.authUser, req.query) + const query = { ...req.query, jobIds: _.get(req, 'body.jobIds', []) } + const result = await service.searchJobs(req.authUser, query) helper.setResHeaders(req, res, result) res.send(result.result) } diff --git a/src/controllers/ResourceBookingController.js b/src/controllers/ResourceBookingController.js index 098fd8e5..f8d3d566 100644 --- a/src/controllers/ResourceBookingController.js +++ b/src/controllers/ResourceBookingController.js @@ -11,7 +11,7 @@ const helper = require('../common/helper') * @param res the response */ async function getResourceBooking (req, res) { - res.send(await service.getResourceBooking(req.authUser, req.params.id, req.query.fromDb)) + res.send(await service.getResourceBooking(req.authUser, req.params.id, req.query)) } /** diff --git a/src/controllers/RoleController.js b/src/controllers/RoleController.js new file mode 100644 index 00000000..747cbe4d --- /dev/null +++ b/src/controllers/RoleController.js @@ -0,0 +1,59 @@ +/** + * Controller for Role endpoints + */ +const HttpStatus = require('http-status-codes') +const service = require('../services/RoleService') + +/** + * Get role by id + * @param req the request + * @param res the response + */ +async function getRole (req, res) { + res.send(await service.getRole(req.authUser, req.params.id, req.query.fromDb)) +} + +/** + * Create role + * @param req the request + * @param res the response + */ +async function createRole (req, res) { + res.send(await service.createRole(req.authUser, req.body)) +} + +/** + * update role by id + * @param req the request + * @param res the response + */ +async function updateRole (req, res) { + res.send(await service.updateRole(req.authUser, req.params.id, req.body)) +} + +/** + * Delete role by id + * @param req the request + * @param res the response + */ +async function deleteRole (req, res) { + await service.deleteRole(req.authUser, req.params.id) + res.status(HttpStatus.NO_CONTENT).end() +} + +/** + * Search roles + * @param req the request + * @param res the response + */ +async function searchRoles (req, res) { + res.send(await service.searchRoles(req.authUser, req.query)) +} + +module.exports = { + getRole, + createRole, + updateRole, + deleteRole, + searchRoles +} diff --git a/src/controllers/SkillController.js b/src/controllers/SkillController.js deleted file mode 100644 index 0dd13ea7..00000000 --- a/src/controllers/SkillController.js +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Controller for skills endpoints - */ -const service = require('../services/SkillService') -const helper = require('../common/helper') - -/** - * Search skills - * @param req the request - * @param res the response - */ -async function searchSkills (req, res) { - const result = await service.searchSkills(req.query) - helper.setResHeaders(req, res, result) - res.send(result.result) -} - -module.exports = { - searchSkills -} diff --git a/src/controllers/TeamController.js b/src/controllers/TeamController.js index b8f7c149..d7992e14 100644 --- a/src/controllers/TeamController.js +++ b/src/controllers/TeamController.js @@ -31,7 +31,9 @@ async function getTeam (req, res) { * @param res the response */ async function getTeamJob (req, res) { - res.send(await service.getTeamJob(req.authUser, req.params.id, req.params.jobId)) + res.send( + await service.getTeamJob(req.authUser, req.params.id, req.params.jobId) + ) } /** @@ -50,7 +52,9 @@ async function sendEmail (req, res) { * @param res the response */ async function addMembers (req, res) { - res.send(await service.addMembers(req.authUser, req.params.id, req.query, req.body)) + res.send( + await service.addMembers(req.authUser, req.params.id, req.query, req.body) + ) } /** @@ -59,7 +63,11 @@ async function addMembers (req, res) { * @param res the response */ async function searchMembers (req, res) { - const result = await service.searchMembers(req.authUser, req.params.id, req.query) + const result = await service.searchMembers( + req.authUser, + req.params.id, + req.query + ) res.send(result.result) } @@ -69,7 +77,11 @@ async function searchMembers (req, res) { * @param res the response */ async function searchInvites (req, res) { - const result = await service.searchInvites(req.authUser, req.params.id, req.query) + const result = await service.searchInvites( + req.authUser, + req.params.id, + req.query + ) res.send(result.result) } @@ -79,7 +91,11 @@ async function searchInvites (req, res) { * @param res the response */ async function deleteMember (req, res) { - await service.deleteMember(req.authUser, req.params.id, req.params.projectMemberId) + await service.deleteMember( + req.authUser, + req.params.id, + req.params.projectMemberId + ) res.status(HttpStatus.NO_CONTENT).end() } @@ -92,6 +108,44 @@ async function getMe (req, res) { res.send(await service.getMe(req.authUser)) } +/** + * Return skills by job description. + * @param req the request + * @param res the response + */ +async function getSkillsByJobDescription (req, res) { + res.send(await service.getSkillsByJobDescription(req.authUser, req.body)) +} + +/** + * + * @param req the request + * @param res the response + */ +async function roleSearchRequest (req, res) { + res.send(await service.roleSearchRequest(req.authUser, req.body)) +} + +/** + * + * @param req the request + * @param res the response + */ +async function createTeam (req, res) { + res.send(await service.createTeam(req.authUser, req.body)) +} + +/** + * Search skills + * @param req the request + * @param res the response + */ +async function searchSkills (req, res) { + const result = await service.searchSkills(req.query) + helper.setResHeaders(req, res, result) + res.send(result.result) +} + module.exports = { searchTeams, getTeam, @@ -101,5 +155,9 @@ module.exports = { searchMembers, searchInvites, deleteMember, - getMe + getMe, + getSkillsByJobDescription, + roleSearchRequest, + createTeam, + searchSkills } diff --git a/src/controllers/WorkPeriodController.js b/src/controllers/WorkPeriodController.js index 8a54defa..0d0853de 100644 --- a/src/controllers/WorkPeriodController.js +++ b/src/controllers/WorkPeriodController.js @@ -1,7 +1,6 @@ /** * Controller for WorkPeriod endpoints */ -const HttpStatus = require('http-status-codes') const service = require('../services/WorkPeriodService') const helper = require('../common/helper') @@ -14,15 +13,6 @@ async function getWorkPeriod (req, res) { res.send(await service.getWorkPeriod(req.authUser, req.params.id, req.query.fromDb)) } -/** - * Create workPeriod - * @param req the request - * @param res the response - */ -async function createWorkPeriod (req, res) { - res.send(await service.createWorkPeriod(req.authUser, req.body)) -} - /** * Partially update workPeriod by id * @param req the request @@ -32,25 +22,6 @@ async function partiallyUpdateWorkPeriod (req, res) { res.send(await service.partiallyUpdateWorkPeriod(req.authUser, req.params.id, req.body)) } -/** - * Fully update workPeriod by id - * @param req the request - * @param res the response - */ -async function fullyUpdateWorkPeriod (req, res) { - res.send(await service.fullyUpdateWorkPeriod(req.authUser, req.params.id, req.body)) -} - -/** - * Delete workPeriod by id - * @param req the request - * @param res the response - */ -async function deleteWorkPeriod (req, res) { - await service.deleteWorkPeriod(req.authUser, req.params.id) - res.status(HttpStatus.NO_CONTENT).end() -} - /** * Search workPeriods * @param req the request @@ -64,9 +35,6 @@ async function searchWorkPeriods (req, res) { module.exports = { getWorkPeriod, - createWorkPeriod, partiallyUpdateWorkPeriod, - fullyUpdateWorkPeriod, - deleteWorkPeriod, searchWorkPeriods } diff --git a/src/controllers/WorkPeriodPaymentController.js b/src/controllers/WorkPeriodPaymentController.js index 93f5c046..3ac5c2fe 100644 --- a/src/controllers/WorkPeriodPaymentController.js +++ b/src/controllers/WorkPeriodPaymentController.js @@ -3,7 +3,6 @@ */ const service = require('../services/WorkPeriodPaymentService') const helper = require('../common/helper') -const config = require('config') /** * Get workPeriodPayment by id @@ -20,7 +19,7 @@ async function getWorkPeriodPayment (req, res) { * @param res the response */ async function createWorkPeriodPayment (req, res) { - res.send(await service.createWorkPeriodPayment(req.authUser, req.body, { paymentProcessingSwitch: config.PAYMENT_PROCESSING_SWITCH })) + res.send(await service.createWorkPeriodPayment(req.authUser, req.body)) } /** @@ -33,29 +32,29 @@ async function partiallyUpdateWorkPeriodPayment (req, res) { } /** - * Fully update workPeriodPayment by id + * Search workPeriodPayments * @param req the request * @param res the response */ -async function fullyUpdateWorkPeriodPayment (req, res) { - res.send(await service.fullyUpdateWorkPeriodPayment(req.authUser, req.params.id, req.body)) +async function searchWorkPeriodPayments (req, res) { + const result = await service.searchWorkPeriodPayments(req.authUser, req.query) + helper.setResHeaders(req, res, result) + res.send(result.result) } /** - * Search workPeriodPayments + * Create all query workPeriodPayments * @param req the request * @param res the response */ -async function searchWorkPeriodPayments (req, res) { - const result = await service.searchWorkPeriodPayments(req.authUser, req.query) - helper.setResHeaders(req, res, result) - res.send(result.result) +async function createQueryWorkPeriodPayments (req, res) { + res.send(await service.createQueryWorkPeriodPayments(req.authUser, req.body)) } module.exports = { getWorkPeriodPayment, createWorkPeriodPayment, + createQueryWorkPeriodPayments, partiallyUpdateWorkPeriodPayment, - fullyUpdateWorkPeriodPayment, searchWorkPeriodPayments } diff --git a/src/eventHandlers/JobCandidateEventHandler.js b/src/eventHandlers/JobCandidateEventHandler.js index c199cb7d..8780ab08 100644 --- a/src/eventHandlers/JobCandidateEventHandler.js +++ b/src/eventHandlers/JobCandidateEventHandler.js @@ -23,17 +23,25 @@ async function inReviewJob (payload) { }) return } - await JobService.partiallyUpdateJob( - helper.getAuditM2Muser(), - job.id, - { status: 'in-review' } - ).then(result => { - logger.info({ + if (payload.value.status === 'open') { + await JobService.partiallyUpdateJob( + helper.getAuditM2Muser(), + job.id, + { status: 'in-review' } + ).then(result => { + logger.info({ + component: 'JobCandidateEventHandler', + context: 'inReviewJob', + message: `id: ${result.id} job got in-review status.` + }) + }) + } else { + logger.debug({ component: 'JobCandidateEventHandler', context: 'inReviewJob', - message: `id: ${result.id} job got in-review status.` + message: `id: ${payload.value.id} candidate is not in open status` }) - }) + } } /** @@ -46,6 +54,17 @@ async function processCreate (payload) { await inReviewJob(payload) } +/** + * Process job candidate update event. + * + * @param {Object} payload the event payload + * @returns {undefined} + */ +async function processUpdate (payload) { + await inReviewJob(payload) +} + module.exports = { - processCreate + processCreate, + processUpdate } diff --git a/src/eventHandlers/ResourceBookingEventHandler.js b/src/eventHandlers/ResourceBookingEventHandler.js index 7a4a7c0a..1134674a 100644 --- a/src/eventHandlers/ResourceBookingEventHandler.js +++ b/src/eventHandlers/ResourceBookingEventHandler.js @@ -7,6 +7,7 @@ const _ = require('lodash') const models = require('../models') const logger = require('../common/logger') const helper = require('../common/helper') +const { AggregatePaymentStatus } = require('../../app-constants') const JobService = require('../services/JobService') const JobCandidateService = require('../services/JobCandidateService') const WorkPeriodService = require('../services/WorkPeriodService') @@ -155,7 +156,7 @@ async function createWorkPeriods (payload) { /** * When a ResourceBooking is updated, workPeriods related to * that ResourceBooking should be updated also. - * This function finds aout which workPeriods should be deleted, + * This function finds out which workPeriods should be deleted, * which ones should be created and which ones should be updated * @param {object} payload the event payload * @returns {undefined} @@ -169,20 +170,54 @@ async function updateWorkPeriods (payload) { raw: true }) // gather workPeriod dates - const newWorkPeriods = helper.extractWorkPeriods(payload.value.startDate || payload.options.oldValue.startDate, payload.value.endDate || payload.options.oldValue.endDate) + const newWorkPeriods = helper.extractWorkPeriods( + _.isUndefined(payload.value.startDate) ? payload.options.oldValue.startDate : payload.value.startDate, + _.isUndefined(payload.value.endDate) ? payload.options.oldValue.endDate : payload.value.endDate) // find which workPeriods should be removed const workPeriodsToRemove = _.differenceBy(workPeriods, newWorkPeriods, 'startDate') // find which workperiods should be created const workPeriodsToAdd = _.differenceBy(newWorkPeriods, workPeriods, 'startDate') - // find which workperiods' daysWorked propery should be updated - let workPeriodsToUpdate = _.intersectionBy(newWorkPeriods, workPeriods, 'startDate') - // find which workperiods' daysWorked property is preset and exceeds the possible maximum - workPeriodsToUpdate = _.differenceWith(workPeriodsToUpdate, workPeriods, (a, b) => b.startDate === a.startDate && _.defaultTo(b.daysWorked, a.daysWorked) <= a.daysWorked) - // include id - workPeriodsToUpdate = _.map(workPeriodsToUpdate, wpu => { - wpu.id = _.filter(workPeriods, ['startDate', wpu.startDate])[0].id - return wpu - }) + // find which workperiods' daysWorked property should be evaluated for changes + const intersectedWorkPeriods = _.intersectionBy(newWorkPeriods, workPeriods, 'startDate') + let workPeriodsToUpdate = [] + if (intersectedWorkPeriods.length > 0) { + // We only need check for first and last ones of intersected workPeriods + // The ones at the middle won't be updated and their daysWorked value will stay the same + if (payload.options.oldValue.startDate !== payload.value.startDate) { + const firstWeek = _.minBy(intersectedWorkPeriods, 'startDate') + const originalFirstWeek = _.find(workPeriods, ['startDate', firstWeek.startDate]) + const existentFirstWeek = _.minBy(workPeriods, 'startDate') + // recalculate daysWorked for the first week of existent workPeriods and daysWorked have changed + if (firstWeek.startDate === existentFirstWeek.startDate && firstWeek.daysWorked !== existentFirstWeek.daysWorked) { + workPeriodsToUpdate.push(_.assign(firstWeek, { id: originalFirstWeek.id })) + // if first of intersected workPeriods is not the first one of existent workPeriods + // we only check if it's daysWorked exceeds the possible maximum + } else if (originalFirstWeek.daysWorked > firstWeek.daysWorked) { + workPeriodsToUpdate.push(_.assign(firstWeek, { id: originalFirstWeek.id })) + } + } + if (payload.options.oldValue.endDate !== payload.value.endDate) { + const lastWeek = _.maxBy(intersectedWorkPeriods, 'startDate') + const originalLastWeek = _.find(workPeriods, ['startDate', lastWeek.startDate]) + const existentLastWeek = _.maxBy(workPeriods, 'startDate') + // recalculate daysWorked for the last week of existent workPeriods and daysWorked have changed + if (lastWeek.startDate === existentLastWeek.startDate && lastWeek.daysWorked !== existentLastWeek.daysWorked) { + workPeriodsToUpdate.push(_.assign(lastWeek, { id: originalLastWeek.id })) + // if last of intersected workPeriods is not the last one of existent workPeriods + // we only check if it's daysWorked exceeds the possible maximum + } else if (originalLastWeek.daysWorked > lastWeek.daysWorked) { + workPeriodsToUpdate.push(_.assign(lastWeek, { id: originalLastWeek.id })) + } + } + } + // if intersected WP count is 1, this can result to duplicated WorkPeriods. + // We should choose the one with higher daysWorked because, it's more likely + // the WP we applied "first/last one of existent WPs" logic above. + if (workPeriodsToUpdate.length === 2) { + if (workPeriodsToUpdate[0].startDate === workPeriodsToUpdate[1].startDate) { + workPeriodsToUpdate = [_.maxBy(workPeriodsToUpdate, 'daysWorked')] + } + } if (workPeriodsToRemove.length === 0 && workPeriodsToAdd.length === 0 && workPeriodsToUpdate.length === 0) { logger.debug({ component: 'ResourceBookingEventHandler', @@ -254,14 +289,16 @@ async function deleteWorkPeriods (payload) { * @returns {undefined} */ async function _createWorkPeriods (periods, resourceBookingId) { - await Promise.all(_.map(periods, async period => await WorkPeriodService.createWorkPeriod(helper.getAuditM2Muser(), - { - resourceBookingId: resourceBookingId, - startDate: period.startDate, - endDate: period.endDate, - daysWorked: null, - paymentStatus: 'pending' - }))) + for (const period of periods) { + await WorkPeriodService.createWorkPeriod( + { + resourceBookingId: resourceBookingId, + startDate: period.startDate, + endDate: period.endDate, + daysWorked: period.daysWorked, + paymentStatus: period.daysWorked === 0 ? AggregatePaymentStatus.NO_DAYS : AggregatePaymentStatus.PENDING + }) + } } /** @@ -270,11 +307,13 @@ async function _createWorkPeriods (periods, resourceBookingId) { * @returns {undefined} */ async function _updateWorkPeriods (periods) { - await Promise.all(_.map(periods, async period => await WorkPeriodService.partiallyUpdateWorkPeriod(helper.getAuditM2Muser(), - period.id, - { - daysWorked: period.daysWorked - }))) + for (const period of periods) { + await WorkPeriodService.partiallyUpdateWorkPeriod(helper.getAuditM2Muser(), + period.id, + { + daysWorked: period.daysWorked + }) + } } /** @@ -283,8 +322,9 @@ async function _updateWorkPeriods (periods) { * @returns {undefined} */ async function _deleteWorkPeriods (workPeriods) { - await Promise.all(_.map(workPeriods, - async workPeriod => await WorkPeriodService.deleteWorkPeriod(helper.getAuditM2Muser(), workPeriod.id))) + for (const period of workPeriods) { + await WorkPeriodService.deleteWorkPeriod(period.id) + } } /** diff --git a/src/eventHandlers/RoleEventHandler.js b/src/eventHandlers/RoleEventHandler.js new file mode 100644 index 00000000..38dbdb79 --- /dev/null +++ b/src/eventHandlers/RoleEventHandler.js @@ -0,0 +1,64 @@ +/* + * Handle events for ResourceBooking. + */ + +const { Op } = require('sequelize') +const _ = require('lodash') +const models = require('../models') +const logger = require('../common/logger') +const helper = require('../common/helper') +const JobService = require('../services/JobService') + +const Job = models.Job + +/** + * When a Role is deleted, jobs related to + * that role should be updated + * @param {object} payload the event payload + * @returns {undefined} + */ +async function updateJobs (payload) { + // find jobs have this role + const jobs = await Job.findAll({ + where: { + roleIds: { [Op.contains]: [payload.value.id] } + }, + raw: true + }) + if (jobs.length === 0) { + logger.debug({ + component: 'RoleEventHandler', + context: 'updateJobs', + message: `id: ${payload.value.id} role has no related job - ignored` + }) + return + } + const m2mUser = helper.getAuditM2Muser() + // remove role id from related jobs + await Promise.all(_.map(jobs, async job => { + let roleIds = _.filter(job.roleIds, roleId => roleId !== payload.value.id) + if (roleIds.length === 0) { + roleIds = null + } + await JobService.partiallyUpdateJob(m2mUser, job.id, { roleIds }) + })) + logger.debug({ + component: 'RoleEventHandler', + context: 'updateJobs', + message: `role id: ${payload.value.id} removed from jobs with id: ${_.map(jobs, 'id')}` + }) +} + +/** + * Process role delete event. + * + * @param {Object} payload the event payload + * @returns {undefined} + */ +async function processDelete (payload) { + await updateJobs(payload) +} + +module.exports = { + processDelete +} diff --git a/src/eventHandlers/WorkPeriodPaymentEventHandler.js b/src/eventHandlers/WorkPeriodPaymentEventHandler.js new file mode 100644 index 00000000..53ab7823 --- /dev/null +++ b/src/eventHandlers/WorkPeriodPaymentEventHandler.js @@ -0,0 +1,74 @@ +/* + * Handle events for WorkPeriodPayment. + */ + +const _ = require('lodash') +const config = require('config') +const models = require('../models') +const logger = require('../common/logger') +const helper = require('../common/helper') +const { ActiveWorkPeriodPaymentStatuses } = require('../../app-constants') +const WorkPeriod = models.WorkPeriod + +/** + * When a WorkPeriodPayment is updated or created, the workPeriod related to + * that WorkPeriodPayment should be updated also. + * @param {object} payload the event payload + * @returns {undefined} + */ +async function updateWorkPeriod (payload) { + const workPeriodPayment = payload.value + // find related workPeriod to evaluate the changes + const workPeriodModel = await WorkPeriod.findById(workPeriodPayment.workPeriodId, { withPayments: true }) + const workPeriod = workPeriodModel.toJSON() + const data = {} + data.daysPaid = 0 + data.paymentTotal = 0 + _.each(workPeriod.payments, payment => { + if (_.includes(ActiveWorkPeriodPaymentStatuses, payment.status)) { + data.daysPaid += payment.days + data.paymentTotal += payment.amount + } + }) + data.paymentStatus = helper.calculateWorkPeriodPaymentStatus(_.assign({}, workPeriod, data)) + if (workPeriod.daysPaid === data.daysPaid && workPeriod.paymentTotal === data.paymentTotal && workPeriod.paymentStatus === data.paymentStatus) { + logger.debug({ + component: 'WorkPeriodPaymentEventHandler', + context: 'updateWorkPeriod', + message: `id: ${workPeriod.id} WorkPeriod has no change - ignored` + }) + return + } + const updated = await workPeriodModel.update(data) + await helper.postEvent(config.TAAS_WORK_PERIOD_UPDATE_TOPIC, _.omit(updated.toJSON(), 'payments'), { oldValue: workPeriod, key: `resourceBooking.id:${workPeriod.resourceBookingId}` }) + logger.debug({ + component: 'WorkPeriodPaymentEventHandler', + context: 'updateWorkPeriod', + message: `id: ${workPeriod.id} WorkPeriod updated` + }) +} + +/** + * Process work period payment create event. + * + * @param {Object} payload the event payload + * @returns {undefined} + */ +async function processCreate (payload) { + await updateWorkPeriod(payload) +} + +/** + * Process work period payment update event. + * + * @param {Object} payload the event payload + * @returns {undefined} + */ +async function processUpdate (payload) { + await updateWorkPeriod(payload) +} + +module.exports = { + processCreate, + processUpdate +} diff --git a/src/eventHandlers/index.js b/src/eventHandlers/index.js index 17445994..3f308b18 100644 --- a/src/eventHandlers/index.js +++ b/src/eventHandlers/index.js @@ -8,15 +8,21 @@ const JobEventHandler = require('./JobEventHandler') const JobCandidateEventHandler = require('./JobCandidateEventHandler') const ResourceBookingEventHandler = require('./ResourceBookingEventHandler') const InterviewEventHandler = require('./InterviewEventHandler') +const RoleEventHandler = require('./RoleEventHandler') +const WorkPeriodPaymentEventHandler = require('./WorkPeriodPaymentEventHandler') const logger = require('../common/logger') const TopicOperationMapping = { [config.TAAS_JOB_UPDATE_TOPIC]: JobEventHandler.processUpdate, [config.TAAS_JOB_CANDIDATE_CREATE_TOPIC]: JobCandidateEventHandler.processCreate, + [config.TAAS_JOB_CANDIDATE_UPDATE_TOPIC]: JobCandidateEventHandler.processUpdate, [config.TAAS_RESOURCE_BOOKING_CREATE_TOPIC]: ResourceBookingEventHandler.processCreate, [config.TAAS_RESOURCE_BOOKING_UPDATE_TOPIC]: ResourceBookingEventHandler.processUpdate, [config.TAAS_RESOURCE_BOOKING_DELETE_TOPIC]: ResourceBookingEventHandler.processDelete, - [config.TAAS_INTERVIEW_REQUEST_TOPIC]: InterviewEventHandler.processRequest + [config.TAAS_WORK_PERIOD_PAYMENT_CREATE_TOPIC]: WorkPeriodPaymentEventHandler.processCreate, + [config.TAAS_WORK_PERIOD_PAYMENT_UPDATE_TOPIC]: WorkPeriodPaymentEventHandler.processUpdate, + [config.TAAS_INTERVIEW_REQUEST_TOPIC]: InterviewEventHandler.processRequest, + [config.TAAS_ROLE_DELETE_TOPIC]: RoleEventHandler.processDelete } /** diff --git a/src/models/Job.js b/src/models/Job.js index 49d34ff7..74b7eb3a 100644 --- a/src/models/Job.js +++ b/src/models/Job.js @@ -104,6 +104,42 @@ module.exports = (sequelize) => { defaultValue: false, allowNull: false }, + minSalary: { + field: 'min_salary', + type: Sequelize.INTEGER, + allowNull: true + }, + maxSalary: { + field: 'max_salary', + type: Sequelize.INTEGER, + allowNull: true + }, + hoursPerWeek: { + field: 'hours_per_week', + type: Sequelize.INTEGER, + allowNull: true + }, + jobLocation: { + field: 'job_location', + type: Sequelize.STRING(255), + allowNull: true + }, + jobTimezone: { + field: 'job_timezone', + type: Sequelize.STRING(128), + allowNull: true + }, + currency: { + field: 'currency', + type: Sequelize.STRING(30), + allowNull: true + }, + roleIds: { + field: 'role_ids', + type: Sequelize.ARRAY({ + type: Sequelize.UUID + }) + }, createdBy: { field: 'created_by', type: Sequelize.UUID, diff --git a/src/models/JobCandidate.js b/src/models/JobCandidate.js index 819b9177..fc54c0aa 100644 --- a/src/models/JobCandidate.js +++ b/src/models/JobCandidate.js @@ -62,6 +62,9 @@ module.exports = (sequelize) => { resume: { type: Sequelize.STRING(2048) }, + remark: { + type: Sequelize.STRING(255) + }, createdBy: { field: 'created_by', type: Sequelize.UUID, diff --git a/src/models/PaymentScheduler.js b/src/models/PaymentScheduler.js new file mode 100644 index 00000000..f8f64dfa --- /dev/null +++ b/src/models/PaymentScheduler.js @@ -0,0 +1,109 @@ +const { Sequelize, Model } = require('sequelize') +const config = require('config') +const _ = require('lodash') +const errors = require('../common/errors') +const { PaymentSchedulerStatus } = require('../../app-constants') + +module.exports = (sequelize) => { + class PaymentScheduler extends Model { + /** + * Create association between models + * @param {Object} models the database models + */ + static associate (models) { + PaymentScheduler.belongsTo(models.WorkPeriodPayment, { foreignKey: 'workPeriodPaymentId' }) + } + + /** + * Get payment scheduler by id + * @param {String} id the payment scheduler id + * @returns {PaymentScheduler} the payment scheduler instance + */ + static async findById (id) { + const paymentScheduler = await PaymentScheduler.findOne({ + where: { + id + } + }) + if (!paymentScheduler) { + throw new errors.NotFoundError(`id: ${id} "paymentScheduler" doesn't exists`) + } + return paymentScheduler + } + } + PaymentScheduler.init( + { + id: { + type: Sequelize.UUID, + primaryKey: true, + allowNull: false, + defaultValue: Sequelize.UUIDV4 + }, + challengeId: { + field: 'challenge_id', + type: Sequelize.UUID, + allowNull: false + }, + workPeriodPaymentId: { + field: 'work_period_payment_id', + type: Sequelize.UUID, + allowNull: false + }, + step: { + type: Sequelize.ENUM(_.values(PaymentSchedulerStatus)), + allowNull: false + }, + status: { + type: Sequelize.ENUM( + 'in-progress', + 'completed', + 'failed' + ), + allowNull: false + }, + userId: { + field: 'user_id', + type: Sequelize.BIGINT + }, + userHandle: { + field: 'user_handle', + type: Sequelize.STRING, + allowNull: false + }, + 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: 'payment_schedulers', + paranoid: true, + deletedAt: 'deletedAt', + createdAt: 'createdAt', + updatedAt: 'updatedAt', + timestamps: true, + defaultScope: { + attributes: { + exclude: ['deletedAt'] + } + }, + hooks: { + afterCreate: (paymentScheduler) => { + delete paymentScheduler.dataValues.deletedAt + } + } + } + ) + + return PaymentScheduler +} diff --git a/src/models/ResourceBooking.js b/src/models/ResourceBooking.js index 58dc5454..54a95b89 100644 --- a/src/models/ResourceBooking.js +++ b/src/models/ResourceBooking.js @@ -1,5 +1,6 @@ const { Sequelize, Model } = require('sequelize') const config = require('config') +const _ = require('lodash') const errors = require('../common/errors') module.exports = (sequelize) => { @@ -9,8 +10,9 @@ module.exports = (sequelize) => { * @param {Object} models the database models */ static associate (models) { + ResourceBooking._models = models ResourceBooking.belongsTo(models.Job, { foreignKey: 'jobId' }) - ResourceBooking.hasMany(models.WorkPeriod, { foreignKey: 'resourceBookingId' }) + ResourceBooking.hasMany(models.WorkPeriod, { as: 'workPeriods', foreignKey: 'resourceBookingId' }) } /** @@ -18,12 +20,36 @@ module.exports = (sequelize) => { * @param {String} id the resource booking id * @returns {ResourceBooking} the resource booking instance */ - static async findById (id) { - const resourceBooking = await ResourceBooking.findOne({ + static async findById (id, options) { + const criteria = { where: { id } - }) + } + if (!_.isUndefined(options)) { + // Select ResourceBooking fields + if (options.include && options.include.length > 0) { + criteria.attributes = options.fieldsRB + } else if (options.excludeRB && options.excludeRB.length > 0) { + criteria.attributes = { exclude: options.excludeRB } + } + // include WorkPeriod model + if (options.withWorkPeriods) { + criteria.include = [{ + model: ResourceBooking._models.WorkPeriod, + as: 'workPeriods', + required: false + }] + // Select WorkPeriod fields + if (!options.allWorkPeriods) { + criteria.include[0].attributes = _.map(options.fieldsWP, f => _.split(f, '.')[1]) + } else if (options.excludeWP && options.excludeWP.length > 0) { + criteria.include[0].attributes = { exclude: _.map(options.excludeWP, f => _.split(f, '.')[1]) } + } + } + } + + const resourceBooking = await ResourceBooking.findOne(criteria) if (!resourceBooking) { throw new errors.NotFoundError(`id: ${id} "ResourceBooking" doesn't exists.`) } diff --git a/src/models/Role.js b/src/models/Role.js new file mode 100644 index 00000000..ab8b4670 --- /dev/null +++ b/src/models/Role.js @@ -0,0 +1,174 @@ +const { Sequelize, Model } = require('sequelize') +const config = require('config') +const errors = require('../common/errors') + +module.exports = (sequelize) => { + class Role extends Model { + /** + * Create association between models + * @param {Object} models the database models + */ + static associate (models) { + Role._models = models + Role.hasMany(models.RoleSearchRequest, { foreignKey: 'roleId' }) + } + + /** + * Get role by id + * @param {String} id the role id + * @returns {Role} the role instance + */ + static async findById (id) { + const role = await Role.findOne({ + where: { + id + } + }) + if (!role) { + throw new errors.NotFoundError(`id: ${id} "Role" doesn't exists.`) + } + return role + } + } + Role.init( + { + id: { + type: Sequelize.UUID, + primaryKey: true, + allowNull: false, + defaultValue: Sequelize.UUIDV4 + }, + name: { + type: Sequelize.STRING(50), + allowNull: false + }, + description: { + type: Sequelize.STRING(1000) + }, + listOfSkills: { + field: 'list_of_skills', + type: Sequelize.ARRAY({ + type: Sequelize.STRING(50) + }) + }, + rates: { + type: Sequelize.ARRAY({ + type: Sequelize.JSONB({ + global: { + type: Sequelize.SMALLINT, + allowNull: false + }, + inCountry: { + field: 'in_country', + type: Sequelize.SMALLINT, + allowNull: false + }, + offShore: { + field: 'off_shore', + type: Sequelize.SMALLINT, + allowNull: false + }, + rate30Global: { + field: 'rate30_global', + type: Sequelize.SMALLINT + }, + rate30InCountry: { + field: 'rate30_in_country', + type: Sequelize.SMALLINT + }, + rate30OffShore: { + field: 'rate30_off_shore', + type: Sequelize.SMALLINT + }, + rate20Global: { + field: 'rate20_global', + type: Sequelize.SMALLINT + }, + rate20InCountry: { + field: 'rate20_in_country', + type: Sequelize.SMALLINT + }, + rate20OffShore: { + field: 'rate20_off_shore', + type: Sequelize.SMALLINT + } + }), + allowNull: false + }), + allowNull: false + }, + numberOfMembers: { + field: 'number_of_members', + type: Sequelize.NUMERIC + }, + numberOfMembersAvailable: { + field: 'number_of_members_available', + type: Sequelize.SMALLINT + }, + imageUrl: { + field: 'image_url', + type: Sequelize.STRING(255) + }, + timeToCandidate: { + field: 'time_to_candidate', + type: Sequelize.SMALLINT + }, + timeToInterview: { + field: 'time_to_interview', + type: Sequelize.SMALLINT + }, + 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: 'roles', + paranoid: true, + deletedAt: 'deletedAt', + createdAt: 'createdAt', + updatedAt: 'updatedAt', + timestamps: true, + defaultScope: { + attributes: { + exclude: ['deletedAt'] + } + }, + hooks: { + afterCreate: (role) => { + delete role.dataValues.deletedAt + } + }, + indexes: [ + { + unique: true, + fields: ['name'], + where: { + deleted_at: null + } + } + ] + } + ) + + return Role +} diff --git a/src/models/RoleSearchRequest.js b/src/models/RoleSearchRequest.js new file mode 100644 index 00000000..384b74d0 --- /dev/null +++ b/src/models/RoleSearchRequest.js @@ -0,0 +1,110 @@ +const { Sequelize, Model } = require('sequelize') +const config = require('config') +const errors = require('../common/errors') + +module.exports = (sequelize) => { + class RoleSearchRequest extends Model { + /** + * Create association between models + * @param {Object} models the database models + */ + static associate (models) { + RoleSearchRequest._models = models + RoleSearchRequest.belongsTo(models.Role, { + foreignKey: 'roleId' + }) + } + + /** + * Get RoleSearchRequest by id + * @param {String} id the RoleSearchRequest id + * @returns {RoleSearchRequest} the RoleSearchRequest instance + */ + static async findById (id) { + const roleSearchRequest = await RoleSearchRequest.findOne({ + where: { + id + } + }) + if (!roleSearchRequest) { + throw new errors.NotFoundError(`id: ${id} "RoleSearchRequest" doesn't exists.`) + } + return roleSearchRequest + } + } + RoleSearchRequest.init( + { + id: { + type: Sequelize.UUID, + primaryKey: true, + allowNull: false, + defaultValue: Sequelize.UUIDV4 + }, + memberId: { + field: 'member_id', + type: Sequelize.UUID + }, + previousRoleSearchRequestId: { + field: 'previous_role_search_request_id', + type: Sequelize.UUID + }, + roleId: { + field: 'role_id', + type: Sequelize.UUID, + allowNull: true + }, + jobDescription: { + field: 'job_description', + type: Sequelize.STRING() + }, + skills: { + type: Sequelize.ARRAY({ + type: Sequelize.UUID + }) + }, + 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: 'role_search_requests', + paranoid: true, + deletedAt: 'deletedAt', + createdAt: 'createdAt', + updatedAt: 'updatedAt', + timestamps: true, + defaultScope: { + attributes: { + exclude: ['deletedAt'] + } + }, + hooks: { + afterCreate: (role) => { + delete role.dataValues.deletedAt + } + } + } + ) + + return RoleSearchRequest +} diff --git a/src/models/WorkPeriod.js b/src/models/WorkPeriod.js index 455818b5..720e4870 100644 --- a/src/models/WorkPeriod.js +++ b/src/models/WorkPeriod.js @@ -20,12 +20,15 @@ module.exports = (sequelize) => { * @param {Object} options { withPayments: true/false } whether contains payments * @returns {WorkPeriod} the work period instance */ - static async findById (id, options = { withPayments: false }) { + static async findById (id, options = { withPayments: false, exclude: [] }) { const criteria = { where: { id } } + if (options.exclude && options.exclude.length > 0) { + criteria.attributes = { exclude: options.exclude } + } if (options.withPayments) { criteria.include = [{ model: WorkPeriod._models.WorkPeriodPayment, @@ -75,15 +78,18 @@ module.exports = (sequelize) => { }, daysWorked: { field: 'days_worked', - type: Sequelize.INTEGER + type: Sequelize.INTEGER, + allowNull: false }, - memberRate: { - field: 'member_rate', - type: Sequelize.FLOAT + daysPaid: { + field: 'days_paid', + type: Sequelize.INTEGER, + allowNull: false }, - customerRate: { - field: 'customer_rate', - type: Sequelize.FLOAT + paymentTotal: { + field: 'payment_total', + type: Sequelize.FLOAT, + allowNull: false }, paymentStatus: { field: 'payment_status', diff --git a/src/models/WorkPeriodPayment.js b/src/models/WorkPeriodPayment.js index 3683faf0..bac461d0 100644 --- a/src/models/WorkPeriodPayment.js +++ b/src/models/WorkPeriodPayment.js @@ -1,6 +1,8 @@ const { Sequelize, Model } = require('sequelize') +const _ = require('lodash') const config = require('config') const errors = require('../common/errors') +const { WorkPeriodPaymentStatus } = require('../../app-constants') module.exports = (sequelize) => { class WorkPeriodPayment extends Model { @@ -44,22 +46,37 @@ module.exports = (sequelize) => { }, challengeId: { field: 'challenge_id', - type: Sequelize.UUID, + type: Sequelize.UUID + }, + memberRate: { + field: 'member_rate', + type: Sequelize.FLOAT, + allowNull: false + }, + customerRate: { + field: 'customer_rate', + type: Sequelize.FLOAT + }, + days: { + type: Sequelize.INTEGER, allowNull: false }, amount: { - type: Sequelize.DOUBLE + type: Sequelize.DOUBLE, + allowNull: false }, status: { - type: Sequelize.ENUM( - 'completed', - 'cancelled' - ), + type: Sequelize.ENUM(_.values(WorkPeriodPaymentStatus)), allowNull: false }, + statusDetails: { + field: 'status_details', + type: Sequelize.JSONB + }, billingAccountId: { field: 'billing_account_id', - type: Sequelize.BIGINT + type: Sequelize.BIGINT, + allowNull: false }, createdBy: { field: 'created_by', diff --git a/src/routes/RoleRoutes.js b/src/routes/RoleRoutes.js new file mode 100644 index 00000000..7230b593 --- /dev/null +++ b/src/routes/RoleRoutes.js @@ -0,0 +1,41 @@ +/** + * Contains role routes + */ +const constants = require('../../app-constants') + +module.exports = { + '/taas-roles': { + post: { + controller: 'RoleController', + method: 'createRole', + auth: 'jwt', + scopes: [constants.Scopes.CREATE_ROLE, constants.Scopes.ALL_ROLE] + }, + get: { + controller: 'RoleController', + method: 'searchRoles', + auth: 'jwt', + scopes: [constants.Scopes.READ_ROLE, constants.Scopes.ALL_ROLE] + } + }, + '/taas-roles/:id': { + get: { + controller: 'RoleController', + method: 'getRole', + auth: 'jwt', + scopes: [constants.Scopes.READ_ROLE, constants.Scopes.ALL_ROLE] + }, + patch: { + controller: 'RoleController', + method: 'updateRole', + auth: 'jwt', + scopes: [constants.Scopes.UPDATE_ROLE, constants.Scopes.ALL_ROLE] + }, + delete: { + controller: 'RoleController', + method: 'deleteRole', + auth: 'jwt', + scopes: [constants.Scopes.DELETE_ROLE, constants.Scopes.ALL_ROLE] + } + } +} diff --git a/src/routes/TeamRoutes.js b/src/routes/TeamRoutes.js index f5d062c6..b82f4f02 100644 --- a/src/routes/TeamRoutes.js +++ b/src/routes/TeamRoutes.js @@ -22,7 +22,7 @@ module.exports = { }, '/taas-teams/skills': { get: { - controller: 'SkillController', + controller: 'TeamController', method: 'searchSkills', auth: 'jwt', scopes: [constants.Scopes.READ_TAAS_TEAM] @@ -36,6 +36,14 @@ module.exports = { scopes: [constants.Scopes.READ_TAAS_TEAM] } }, + '/taas-teams/getSkillsByJobDescription': { + post: { + controller: 'TeamController', + method: 'getSkillsByJobDescription', + auth: 'jwt', + scopes: [constants.Scopes.READ_TAAS_TEAM] + } + }, '/taas-teams/:id': { get: { controller: 'TeamController', @@ -81,5 +89,21 @@ module.exports = { auth: 'jwt', scopes: [constants.Scopes.READ_TAAS_TEAM] } + }, + '/taas-teams/sendRoleSearchRequest': { + post: { + controller: 'TeamController', + method: 'roleSearchRequest', + auth: 'jwt', + scopes: [constants.Scopes.CREATE_ROLE_SEARCH_REQUEST] + } + }, + '/taas-teams/submitTeamRequest': { + post: { + controller: 'TeamController', + method: 'createTeam', + auth: 'jwt', + scopes: [constants.Scopes.CREATE_TAAS_TEAM] + } } } diff --git a/src/routes/WorkPeriodPaymentRoutes.js b/src/routes/WorkPeriodPaymentRoutes.js index dcc284eb..7ddd2bc5 100644 --- a/src/routes/WorkPeriodPaymentRoutes.js +++ b/src/routes/WorkPeriodPaymentRoutes.js @@ -18,6 +18,14 @@ module.exports = { scopes: [constants.Scopes.READ_WORK_PERIOD_PAYMENT, constants.Scopes.ALL_WORK_PERIOD_PAYMENT] } }, + '/work-period-payments/query': { + post: { + controller: 'WorkPeriodPaymentController', + method: 'createQueryWorkPeriodPayments', + auth: 'jwt', + scopes: [constants.Scopes.CREATE_WORK_PERIOD_PAYMENT, constants.Scopes.ALL_WORK_PERIOD_PAYMENT] + } + }, '/work-period-payments/:id': { get: { controller: 'WorkPeriodPaymentController', @@ -25,12 +33,6 @@ module.exports = { auth: 'jwt', scopes: [constants.Scopes.READ_WORK_PERIOD_PAYMENT, constants.Scopes.ALL_WORK_PERIOD_PAYMENT] }, - put: { - controller: 'WorkPeriodPaymentController', - method: 'fullyUpdateWorkPeriodPayment', - auth: 'jwt', - scopes: [constants.Scopes.UPDATE_WORK_PERIOD_PAYMENT, constants.Scopes.ALL_WORK_PERIOD_PAYMENT] - }, patch: { controller: 'WorkPeriodPaymentController', method: 'partiallyUpdateWorkPeriodPayment', diff --git a/src/routes/WorkPeriodRoutes.js b/src/routes/WorkPeriodRoutes.js index 7f84b5b0..659e4d58 100644 --- a/src/routes/WorkPeriodRoutes.js +++ b/src/routes/WorkPeriodRoutes.js @@ -5,12 +5,6 @@ const constants = require('../../app-constants') module.exports = { '/work-periods': { - post: { - controller: 'WorkPeriodController', - method: 'createWorkPeriod', - auth: 'jwt', - scopes: [constants.Scopes.CREATE_WORK_PERIOD, constants.Scopes.ALL_WORK_PERIOD] - }, get: { controller: 'WorkPeriodController', method: 'searchWorkPeriods', @@ -25,23 +19,11 @@ module.exports = { auth: 'jwt', scopes: [constants.Scopes.READ_WORK_PERIOD, constants.Scopes.ALL_WORK_PERIOD] }, - put: { - controller: 'WorkPeriodController', - method: 'fullyUpdateWorkPeriod', - auth: 'jwt', - scopes: [constants.Scopes.UPDATE_WORK_PERIOD, constants.Scopes.ALL_WORK_PERIOD] - }, patch: { controller: 'WorkPeriodController', method: 'partiallyUpdateWorkPeriod', auth: 'jwt', scopes: [constants.Scopes.UPDATE_WORK_PERIOD, constants.Scopes.ALL_WORK_PERIOD] - }, - delete: { - controller: 'WorkPeriodController', - method: 'deleteWorkPeriod', - auth: 'jwt', - scopes: [constants.Scopes.DELETE_WORK_PERIOD, constants.Scopes.ALL_WORK_PERIOD] } } } diff --git a/src/services/InterviewService.js b/src/services/InterviewService.js index 10a065f4..3ddb1a3d 100644 --- a/src/services/InterviewService.js +++ b/src/services/InterviewService.js @@ -241,8 +241,8 @@ async function requestInterview (currentUser, jobCandidateId, interview) { const guestMembers = await helper.getMemberDetailsByEmails(interview.guestEmails) interview.hostName = `${hostMembers[0].firstName} ${hostMembers[0].lastName}` interview.guestNames = _.map(interview.guestEmails, (guestEmail) => { - var foundGuestMember = _.find(guestMembers, function(guestMember) { return guestEmail == guestMember.email }); - return (foundGuestMember != undefined) ? `${foundGuestMember.firstName} ${foundGuestMember.lastName}` : guestEmail.split("@")[0] + var foundGuestMember = _.find(guestMembers, function (guestMember) { return guestEmail === guestMember.email }) + return (foundGuestMember !== undefined) ? `${foundGuestMember.firstName} ${foundGuestMember.lastName}` : guestEmail.split('@')[0] }) try { @@ -539,9 +539,10 @@ async function searchInterviews (currentUser, jobCandidateId, criteria) { limit: perPage, order: [[criteria.sortBy, criteria.sortOrder]] }) + const total = await Interview.count({ where: filter }) return { fromDb: true, - total: interviews.length, + total, page, perPage, result: _.map(interviews, interview => interview.dataValues) diff --git a/src/services/JobCandidateService.js b/src/services/JobCandidateService.js index 392d0af6..1f283512 100644 --- a/src/services/JobCandidateService.js +++ b/src/services/JobCandidateService.js @@ -130,7 +130,8 @@ createJobCandidate.schema = Joi.object().keys({ jobId: Joi.string().uuid().required(), userId: Joi.string().uuid().required(), externalId: Joi.string().allow(null), - resume: Joi.string().uri().allow(null) + resume: Joi.string().uri().allow(null), + remark: Joi.string().allow(null) }).required() }).required() @@ -176,7 +177,8 @@ partiallyUpdateJobCandidate.schema = Joi.object().keys({ data: Joi.object().keys({ status: Joi.jobCandidateStatus(), externalId: Joi.string().allow(null), - resume: Joi.string().uri().allow(null) + resume: Joi.string().uri().allow(null), + remark: Joi.string().allow(null) }).required() }).required() @@ -201,7 +203,8 @@ fullyUpdateJobCandidate.schema = Joi.object().keys({ userId: Joi.string().uuid().required(), status: Joi.jobCandidateStatus().default('open'), externalId: Joi.string().allow(null).default(null), - resume: Joi.string().uri().allow(null).default(null) + resume: Joi.string().uri().allow('').allow(null).default(null), + remark: Joi.string().allow('').allow(null).default(null) }).required() }).required() @@ -313,9 +316,10 @@ async function searchJobCandidates (currentUser, criteria) { limit: perPage, order: [[criteria.sortBy, criteria.sortOrder]] }) + const total = await JobCandidate.count({ where: filter }) return { fromDb: true, - total: jobCandidates.length, + total, page, perPage, result: _.map(jobCandidates, jobCandidate => _.omit(jobCandidate.dataValues, omitList)) diff --git a/src/services/JobService.js b/src/services/JobService.js index 7d855bd0..06e3b67c 100644 --- a/src/services/JobService.js +++ b/src/services/JobService.js @@ -74,6 +74,27 @@ async function _validateSkills (skills) { } } +/** + * Validate if all roles exist. + * + * @param {Array} roles the list of roles + * @returns {undefined} + */ +async function _validateRoles (roles) { + const foundRolesObj = await models.Role.findAll({ + where: { + id: roles + }, + attributes: ['id'], + raw: true + }) + const foundRoles = _.map(foundRolesObj, 'id') + const nonexistentRoles = _.difference(roles, foundRoles) + if (nonexistentRoles.length > 0) { + throw new errors.BadRequestError(`Invalid roles: [${nonexistentRoles}]`) + } +} + /** * Check user permission for getting job. * @@ -154,6 +175,10 @@ async function createJob (currentUser, job) { } await _validateSkills(job.skills) + if (job.roleIds) { + job.roleIds = _.uniq(job.roleIds) + await _validateRoles(job.roleIds) + } job.id = uuid() job.createdBy = await helper.getUserId(currentUser.userId) @@ -162,24 +187,35 @@ async function createJob (currentUser, job) { return created.toJSON() } -createJob.schema = Joi.object().keys({ - currentUser: Joi.object().required(), - job: Joi.object().keys({ - status: Joi.jobStatus().default('sourcing'), - projectId: Joi.number().integer().required(), - externalId: Joi.string().allow(null), - description: Joi.stringAllowEmpty().allow(null), - title: Joi.title().required(), - startDate: Joi.date().allow(null), - duration: Joi.number().integer().min(1).allow(null), - numPositions: Joi.number().integer().min(1).required(), - resourceType: Joi.stringAllowEmpty().allow(null), - rateType: Joi.rateType().allow(null), - workload: Joi.workload().allow(null), - skills: Joi.array().items(Joi.string().uuid()).required(), - isApplicationPageActive: Joi.boolean() - }).required() -}).required() +createJob.schema = Joi.object() + .keys({ + currentUser: Joi.object().required(), + job: Joi.object() + .keys({ + status: Joi.jobStatus().default('sourcing'), + projectId: Joi.number().integer().required(), + externalId: Joi.string().allow(null), + description: Joi.stringAllowEmpty().allow(null), + title: Joi.title().required(), + startDate: Joi.date().allow(null), + duration: Joi.number().integer().min(1).allow(null), + numPositions: Joi.number().integer().min(1).required(), + resourceType: Joi.stringAllowEmpty().allow(null), + rateType: Joi.rateType().allow(null), + workload: Joi.workload().allow(null), + skills: Joi.array().items(Joi.string().uuid()).required(), + isApplicationPageActive: Joi.boolean(), + minSalary: Joi.number().integer().allow(null), + maxSalary: Joi.number().integer().allow(null), + hoursPerWeek: Joi.number().integer().allow(null), + jobLocation: Joi.string().allow(null).allow(''), + jobTimezone: Joi.string().allow(null).allow(''), + currency: Joi.string().allow(null).allow(''), + roleIds: Joi.array().items(Joi.string().uuid().required()) + }) + .required() + }) + .required() /** * Update job. Normal user can only update the job he/she created. @@ -192,6 +228,10 @@ async function updateJob (currentUser, id, data) { if (data.skills) { await _validateSkills(data.skills) } + if (data.roleIds) { + data.roleIds = _.uniq(data.roleIds) + await _validateRoles(data.roleIds) + } let job = await Job.findById(id) const oldValue = job.toJSON() @@ -245,7 +285,14 @@ partiallyUpdateJob.schema = Joi.object().keys({ rateType: Joi.rateType().allow(null), workload: Joi.workload().allow(null), skills: Joi.array().items(Joi.string().uuid()), - isApplicationPageActive: Joi.boolean() + isApplicationPageActive: Joi.boolean(), + minSalary: Joi.number().integer(), + maxSalary: Joi.number().integer(), + hoursPerWeek: Joi.number().integer(), + jobLocation: Joi.string(), + jobTimezone: Joi.string(), + currency: Joi.string(), + roleIds: Joi.array().items(Joi.string().uuid().required()).allow(null) }).required() }).required() @@ -276,7 +323,14 @@ fullyUpdateJob.schema = Joi.object().keys({ workload: Joi.workload().allow(null).default(null), skills: Joi.array().items(Joi.string().uuid()).required(), status: Joi.jobStatus().default('sourcing'), - isApplicationPageActive: Joi.boolean() + isApplicationPageActive: Joi.boolean(), + minSalary: Joi.number().integer().allow(null), + maxSalary: Joi.number().integer().allow(null), + hoursPerWeek: Joi.number().integer().allow(null), + jobLocation: Joi.string().allow(null), + jobTimezone: Joi.string().allow(null), + currency: Joi.string().allow(null), + roleIds: Joi.array().items(Joi.string().uuid().required()).default(null) }).required() }).required() @@ -344,7 +398,8 @@ async function searchJobs (currentUser, criteria, options = { returnAll: false } body: { query: { bool: { - must: [] + must: [], + filter: [] } }, from: (page - 1) * perPage, @@ -360,6 +415,7 @@ async function searchJobs (currentUser, criteria, options = { returnAll: false } 'startDate', 'resourceType', 'skill', + 'role', 'rateType', 'workload', 'title', @@ -374,10 +430,10 @@ async function searchJobs (currentUser, criteria, options = { returnAll: false } } } } - } else if (key === 'skill') { + } else if (key === 'skill' || key === 'role') { must = { terms: { - skills: [value] + [`${key}s`]: [value] } } } else { @@ -393,11 +449,19 @@ async function searchJobs (currentUser, criteria, options = { returnAll: false } }) // If criteria contains projectIds, filter projectId with this value if (criteria.projectIds) { - esQuery.body.query.bool.filter = [{ + esQuery.body.query.bool.filter.push({ terms: { projectId: criteria.projectIds } - }] + }) + } + // if criteria contains jobIds, filter jobIds with this value + if (criteria.jobIds && criteria.jobIds.length > 0) { + esQuery.body.query.bool.filter.push({ + terms: { + _id: criteria.jobIds + } + }) } logger.debug({ component: 'JobService', context: 'searchJobs', message: `Query: ${JSON.stringify(esQuery)}` }) @@ -422,7 +486,7 @@ async function searchJobs (currentUser, criteria, options = { returnAll: false } logger.logFullError(err, { component: 'JobService', context: 'searchJobs' }) } logger.info({ component: 'JobService', context: 'searchJobs', message: 'fallback to DB query' }) - const filter = {} + const filter = { [Op.and]: [] } _.each(_.pick(criteria, [ 'projectId', 'externalId', @@ -444,11 +508,19 @@ async function searchJobs (currentUser, criteria, options = { returnAll: false } [Op.like]: `%${criteria.title}%` } } - if (criteria.skills) { + if (criteria.skill) { filter.skills = { - [Op.contains]: [criteria.skills] + [Op.contains]: [criteria.skill] + } + } + if (criteria.role) { + filter.roles = { + [Op.contains]: [criteria.role] } } + if (criteria.jobIds && criteria.jobIds.length > 0) { + filter[Op.and].push({ id: criteria.jobIds }) + } const jobs = await Job.findAll({ where: filter, offset: ((page - 1) * perPage), @@ -460,9 +532,10 @@ async function searchJobs (currentUser, criteria, options = { returnAll: false } required: false }] }) + const total = await Job.count({ where: filter }) return { fromDb: true, - total: jobs.length, + total, page, perPage, result: _.map(jobs, job => job.dataValues) @@ -483,10 +556,12 @@ searchJobs.schema = Joi.object().keys({ startDate: Joi.date(), resourceType: Joi.string(), skill: Joi.string().uuid(), + role: Joi.string().uuid(), rateType: Joi.rateType(), workload: Joi.workload(), status: Joi.jobStatus(), - projectIds: Joi.array().items(Joi.number().integer()).single() + projectIds: Joi.array().items(Joi.number().integer()).single(), + jobIds: Joi.array().items(Joi.string().uuid()) }).required(), options: Joi.object() }).required() diff --git a/src/services/PaymentSchedulerService.js b/src/services/PaymentSchedulerService.js new file mode 100644 index 00000000..666c66bb --- /dev/null +++ b/src/services/PaymentSchedulerService.js @@ -0,0 +1,337 @@ +const _ = require('lodash') +const config = require('config') +const moment = require('moment') +const models = require('../models') +const { getMemberDetailsByHandle, getChallenge, getChallengeResource, sleep, postEvent } = require('../common/helper') +const logger = require('../common/logger') +const { createChallenge, addResourceToChallenge, activateChallenge, closeChallenge } = require('./PaymentService') +const { ChallengeStatus, PaymentSchedulerStatus, PaymentProcessingSwitch } = require('../../app-constants') + +const WorkPeriodPayment = models.WorkPeriodPayment +const WorkPeriod = models.WorkPeriod +const PaymentScheduler = models.PaymentScheduler +const { + SWITCH, BATCH_SIZE, IN_PROGRESS_EXPIRED, MAX_RETRY_COUNT, RETRY_BASE_DELAY, RETRY_MAX_DELAY, PER_REQUEST_MAX_TIME, PER_PAYMENT_MAX_TIME, + PER_MINUTE_PAYMENT_MAX_COUNT, PER_MINUTE_CHALLENGE_REQUEST_MAX_COUNT, PER_MINUTE_RESOURCE_REQUEST_MAX_COUNT, + FIX_DELAY_STEP_CREATE_CHALLENGE, FIX_DELAY_STEP_ASSIGN_MEMBER, FIX_DELAY_STEP_ACTIVATE_CHALLENGE +} = config.PAYMENT_PROCESSING +const processStatus = { + perMin: { + minute: '0:0', + paymentsProcessed: 0, + challengeRequested: 0, + resourceRequested: 0 + }, + perMinThreshold: { + paymentsProcessed: PER_MINUTE_PAYMENT_MAX_COUNT, + challengeRequested: PER_MINUTE_CHALLENGE_REQUEST_MAX_COUNT, + resourceRequested: PER_MINUTE_RESOURCE_REQUEST_MAX_COUNT + }, + paymentStartTime: 0, + requestStartTime: 0 +} +const processResult = { + SUCCESS: 'success', + FAIL: 'fail', + SKIP: 'skip' +} + +const localLogger = { + debug: (message, context) => logger.debug({ component: 'PaymentSchedulerService', context, message }), + error: (message, context) => logger.error({ component: 'PaymentSchedulerService', context, message }), + info: (message, context) => logger.info({ component: 'PaymentSchedulerService', context, message }) +} + +/** + * Scheduler process entrance + */ +async function processScheduler () { + // Get the oldest Work Periods Payment records in status "scheduled" and "in-progress", + // the in progress state may be caused by an abnormal shutdown, + // or it may be a normal record that is still being processed + const workPeriodPaymentList = await WorkPeriodPayment.findAll({ where: { status: ['in-progress', 'scheduled'] }, order: [['status', 'desc'], ['createdAt']], limit: BATCH_SIZE }) + localLogger.info(`start processing ${workPeriodPaymentList.length} of payments`, 'processScheduler') + const failIds = [] + const skipIds = [] + for (const workPeriodPayment of workPeriodPaymentList) { + const result = await processPayment(workPeriodPayment) + if (result === processResult.FAIL) { + failIds.push(workPeriodPayment.id) + } else if (result === processResult.SKIP) { + skipIds.push(workPeriodPayment.id) + } + } + localLogger.info(`process end. ${workPeriodPaymentList.length - failIds.length - skipIds.length} of payments processed successfully`, 'processScheduler') + if (!_.isEmpty(skipIds)) { + localLogger.info(`payments: ${_.join(skipIds, ',')} are processing by other processor`, 'processScheduler') + } + if (!_.isEmpty(failIds)) { + localLogger.error(`payments: ${_.join(failIds, ',')} are processed failed`, 'processScheduler') + } +} + +/** + * Process a record of payment + * @param {Object} workPeriodPayment the work period payment + * @returns {String} process result + */ +async function processPayment (workPeriodPayment) { + processStatus.paymentStartTime = Date.now() + let paymentScheduler + if (workPeriodPayment.status === 'in-progress') { + paymentScheduler = await PaymentScheduler.findOne({ where: { workPeriodPaymentId: workPeriodPayment.id, status: 'in-progress' } }) + + // If the in-progress record has not expired, it is considered to be being processed by other processes + if (paymentScheduler && moment(paymentScheduler.updatedAt).add(moment.duration(IN_PROGRESS_EXPIRED)).isAfter(moment())) { + localLogger.info(`workPeriodPayment: ${workPeriodPayment.id} is being processed by other processor`, 'processPayment') + return processResult.SKIP + } + } else { + const oldValue = workPeriodPayment.toJSON() + const updated = await workPeriodPayment.update({ status: 'in-progress' }) + // Update the modified status to es + await postEvent(config.TAAS_WORK_PERIOD_PAYMENT_UPDATE_TOPIC, updated.toJSON(), { oldValue }) + } + // Check whether the number of processed records per minute exceeds the specified number, if it exceeds, wait for the next minute before processing + await checkWait(PaymentSchedulerStatus.START_PROCESS) + localLogger.info(`Processing workPeriodPayment ${workPeriodPayment.id}`, 'processPayment') + + const workPeriod = await WorkPeriod.findById(workPeriodPayment.workPeriodId) + try { + if (!paymentScheduler) { + // 1. create challenge + const challengeId = await withRetry(createChallenge, [getCreateChallengeParam(workPeriod, workPeriodPayment)], validateError, PaymentSchedulerStatus.CREATE_CHALLENGE) + paymentScheduler = await PaymentScheduler.create({ challengeId, step: PaymentSchedulerStatus.CREATE_CHALLENGE, workPeriodPaymentId: workPeriodPayment.id, userHandle: workPeriod.userHandle, status: 'in-progress' }) + } else { + // If the paymentScheduler already exists, it means that this is a record caused by an abnormal shutdown + await setPaymentSchedulerStep(paymentScheduler) + } + // Start from unprocessed step, perform the process step by step + while (paymentScheduler.step !== PaymentSchedulerStatus.CLOSE_CHALLENGE) { + await processStep(paymentScheduler) + } + + const oldValue = workPeriodPayment.toJSON() + // 5. update wp and save it should only update already existent Work Period Payment record with created "challengeId" and "status=completed". + const updated = await workPeriodPayment.update({ challengeId: paymentScheduler.challengeId, status: 'completed' }) + // Update the modified status to es + await postEvent(config.TAAS_WORK_PERIOD_PAYMENT_UPDATE_TOPIC, updated.toJSON(), { oldValue }) + + await paymentScheduler.update({ step: PaymentSchedulerStatus.CLOSE_CHALLENGE, userId: paymentScheduler.userId, status: 'completed' }) + + localLogger.info(`Processed workPeriodPayment ${workPeriodPayment.id} successfully`, 'processPayment') + return processResult.SUCCESS + } catch (err) { + logger.logFullError(err, { component: 'PaymentSchedulerService', context: 'processPayment' }) + const statusDetails = { errorMessage: err.message, errorCode: _.get(err, 'status', -1), retry: _.get(err, 'retry', -1), step: _.get(err, 'step'), challengeId: paymentScheduler ? paymentScheduler.challengeId : null } + const oldValue = workPeriodPayment.toJSON() + // If payment processing failed Work Periods Payment "status" should be changed to "failed" and populate "statusDetails" field with error details in JSON format. + const updated = await workPeriodPayment.update({ statusDetails, status: 'failed' }) + // Update the modified status to es + await postEvent(config.TAAS_WORK_PERIOD_PAYMENT_UPDATE_TOPIC, updated.toJSON(), { oldValue }) + + if (paymentScheduler) { + await paymentScheduler.update({ step: PaymentSchedulerStatus.CLOSE_CHALLENGE, userId: paymentScheduler.userId, status: 'failed' }) + } + localLogger.error(`Processed workPeriodPayment ${workPeriodPayment.id} failed`, 'processPayment') + return processResult.FAIL + } +} + +/** + * Perform a specific step in the process + * @param {Object} paymentScheduler the payment scheduler + */ +async function processStep (paymentScheduler) { + if (paymentScheduler.step === PaymentSchedulerStatus.CREATE_CHALLENGE) { + // 2. assign member to the challenge + await withRetry(addResourceToChallenge, [paymentScheduler.challengeId, paymentScheduler.userHandle], validateError, PaymentSchedulerStatus.ASSIGN_MEMBER) + paymentScheduler.step = PaymentSchedulerStatus.ASSIGN_MEMBER + } else if (paymentScheduler.step === PaymentSchedulerStatus.ASSIGN_MEMBER) { + // 3. active the challenge + await withRetry(activateChallenge, [paymentScheduler.challengeId], validateError, PaymentSchedulerStatus.ACTIVATE_CHALLENGE) + paymentScheduler.step = PaymentSchedulerStatus.ACTIVATE_CHALLENGE + } else if (paymentScheduler.step === PaymentSchedulerStatus.ACTIVATE_CHALLENGE) { + // 4.1. get user id + const { userId } = await withRetry(getMemberDetailsByHandle, [paymentScheduler.userHandle], validateError, PaymentSchedulerStatus.GET_USER_ID) + paymentScheduler.userId = userId + paymentScheduler.step = PaymentSchedulerStatus.GET_USER_ID + } else if (paymentScheduler.step === PaymentSchedulerStatus.GET_USER_ID) { + // 4.2. close the challenge + await withRetry(closeChallenge, [paymentScheduler.challengeId, paymentScheduler.userId, paymentScheduler.userHandle], validateError, PaymentSchedulerStatus.CLOSE_CHALLENGE) + paymentScheduler.step = PaymentSchedulerStatus.CLOSE_CHALLENGE + } +} + +/** + * Set the scheduler actual step + * @param {Object} paymentScheduler the scheduler object + */ +async function setPaymentSchedulerStep (paymentScheduler) { + const challenge = await getChallenge(paymentScheduler.challengeId) + if (SWITCH === PaymentProcessingSwitch.OFF) { + paymentScheduler.step = PaymentSchedulerStatus.CLOSE_CHALLENGE + } else if (challenge.status === ChallengeStatus.COMPLETED) { + paymentScheduler.step = PaymentSchedulerStatus.CLOSE_CHALLENGE + } else if (challenge.status === ChallengeStatus.ACTIVE) { + paymentScheduler.step = PaymentSchedulerStatus.ACTIVATE_CHALLENGE + } else { + const resource = await getChallengeResource(paymentScheduler.challengeId, paymentScheduler.userHandle, config.ROLE_ID_SUBMITTER) + if (resource) { + paymentScheduler.step = PaymentSchedulerStatus.ASSIGN_MEMBER + } else { + paymentScheduler.step = PaymentSchedulerStatus.CREATE_CHALLENGE + } + } + // The main purpose is updating the updatedAt of payment scheduler to avoid simultaneous processing + await paymentScheduler.update({ step: paymentScheduler.step }) +} + +/** + * Generate the create challenge parameter + * @param {Object} workPeriod the work period + * @param {Object} workPeriodPayment the work period payment + * @returns {Object} the create challenge parameter + */ +function getCreateChallengeParam (workPeriod, workPeriodPayment) { + return { + projectId: workPeriod.projectId, + userHandle: workPeriod.userHandle, + amount: workPeriodPayment.amount, + name: `TaaS Payment - ${workPeriod.userHandle} - Week Ending ${moment(workPeriod.endDate).format('D/M/YYYY')}`, + description: `TaaS Payment - ${workPeriod.userHandle} - Week Ending ${moment(workPeriod.endDate).format('D/M/YYYY')}`, + billingAccountId: workPeriodPayment.billingAccountId + } +} + +/** + * Before each step is processed, wait for the corresponding time + * @param {String} step the step name + * @param {Number} tryCount the try count + */ +async function checkWait (step, tryCount) { + // When calculating the retry time later, we need to subtract the time that has been waited before + let lapse = 0 + if (step === PaymentSchedulerStatus.START_PROCESS) { + lapse += await checkPerMinThreshold('paymentsProcessed') + } else if (step === PaymentSchedulerStatus.CREATE_CHALLENGE) { + await checkPerMinThreshold('challengeRequested') + } else if (step === PaymentSchedulerStatus.ASSIGN_MEMBER) { + // Only when tryCount = 0, it comes from the previous step, and it is necessary to wait for a fixed time + if (FIX_DELAY_STEP_CREATE_CHALLENGE > 0 && tryCount === 0) { + await sleep(FIX_DELAY_STEP_CREATE_CHALLENGE) + } + lapse += await checkPerMinThreshold('resourceRequested') + } else if (step === PaymentSchedulerStatus.ACTIVATE_CHALLENGE) { + // Only when tryCount = 0, it comes from the previous step, and it is necessary to wait for a fixed time + if (FIX_DELAY_STEP_ASSIGN_MEMBER > 0 && tryCount === 0) { + await sleep(FIX_DELAY_STEP_ASSIGN_MEMBER) + } + lapse += await checkPerMinThreshold('challengeRequested') + } else if (step === PaymentSchedulerStatus.CLOSE_CHALLENGE) { + // Only when tryCount = 0, it comes from the previous step, and it is necessary to wait for a fixed time + if (FIX_DELAY_STEP_ACTIVATE_CHALLENGE > 0 && tryCount === 0) { + await sleep(FIX_DELAY_STEP_ACTIVATE_CHALLENGE) + } + lapse += await checkPerMinThreshold('challengeRequested') + } + + if (tryCount > 0) { + // exponential backoff and do not exceed the maximum retry delay + const retryDelay = Math.min(RETRY_BASE_DELAY * Math.pow(2, tryCount), RETRY_MAX_DELAY) + await sleep(retryDelay - lapse) + } +} + +/** + * Determine whether the number of records processed every minute exceeds the specified number, if it exceeds, wait for the next minute + * @param {String} key the min threshold key + * @returns {Number} wait time + */ +async function checkPerMinThreshold (key) { + const mt = moment() + const min = mt.format('h:m') + let waitMs = 0 + if (processStatus.perMin.minute === min) { + if (processStatus.perMin[key] >= processStatus.perMinThreshold[key]) { + waitMs = (60 - mt.seconds()) * 1000 + localLogger.info(`The number of records of ${key} processed per minute reaches ${processStatus.perMinThreshold[key]}, and it need to wait for ${60 - mt.seconds()} seconds until the next minute`) + await sleep(waitMs) + processStatus.perMin = { + minute: moment().format('h:m'), + paymentsProcessed: 0, + challengeRequested: 0, + resourceRequested: 0 + } + } + } else { + processStatus.perMin = { + minute: min, + paymentsProcessed: 0, + challengeRequested: 0, + resourceRequested: 0 + } + } + processStatus.perMin[key]++ + return waitMs +} + +/** + * Determine whether it can try again + * @param {Object} err the process error + * @returns {Boolean} + */ +function validateError (err) { + return err.status >= 500 && err.status < 600 +} + +/** + * Execute the function, if an exception occurs, retry according to the conditions + * @param {Function} func the main function + * @param {Array} argArr the args of main function + * @param {Function} predictFunc the determine error function + * @param {String} step the step name + * @returns the result of main function + */ +async function withRetry (func, argArr, predictFunc, step) { + let tryCount = 0 + processStatus.requestStartTime = Date.now() + while (true) { + await checkWait(step, tryCount) + tryCount++ + try { + // mock code + if (SWITCH === PaymentProcessingSwitch.OFF) { + // without actual API calls by adding delay (for example 1 second for each step), to simulate the act + sleep(1000) + if (step === PaymentSchedulerStatus.CREATE_CHALLENGE) { + return '00000000-0000-0000-0000-000000000000' + } else if (step === PaymentSchedulerStatus.GET_USER_ID) { + return { userId: 100001 } + } + return + } else { + // Execute the main function + const result = await func(...argArr) + return result + } + } catch (err) { + const now = Date.now() + // The following is the case of not retrying: + // 1. The number of retries exceeds the configured number + // 2. The thrown error does not match the retry conditions + // 3. The request execution time exceeds the configured time + // 4. The processing time of the payment record exceeds the configured time + if (tryCount > MAX_RETRY_COUNT || !predictFunc(err) || now - processStatus.requestStartTime > PER_REQUEST_MAX_TIME || now - processStatus.paymentStartTime > PER_PAYMENT_MAX_TIME) { + err.retry = tryCount + err.step = step + throw err + } + localLogger.info(`execute ${step} with error: ${err.message}, retry...`, 'withRetry') + } + } +} + +module.exports = { + processScheduler +} diff --git a/src/services/PaymentService.js b/src/services/PaymentService.js index 3143b936..93d04e41 100644 --- a/src/services/PaymentService.js +++ b/src/services/PaymentService.js @@ -39,7 +39,8 @@ async function createPayment (options) { const challengeId = await createChallenge(options, token) await addResourceToChallenge(challengeId, options.userHandle, token) await activateChallenge(challengeId, token) - const completedChallenge = await closeChallenge(challengeId, options.userHandle, token) + const { userId } = await helper.getV3MemberDetailsByHandle(options.userHandle) + const completedChallenge = await closeChallenge(challengeId, userId, options.userHandle, token) return completedChallenge } @@ -84,8 +85,8 @@ async function createChallenge (challenge, token) { if (challenge.billingAccountId) { body.billing = { - billingAccountId: challenge.billingAccountId, - markup: 0 // for TaaS payments we always use 0 markup + billingAccountId: _.toString(challenge.billingAccountId), + markup: 0 // for TaaS payments we always use 0 markup } } try { @@ -117,6 +118,13 @@ async function addResourceToChallenge (id, handle, token) { await helper.createChallengeResource(body, token) localLogger.info({ context: 'addResourceToChallenge', message: `${handle} added to challenge ${id}` }) } catch (err) { + if (err.status === 409) { + const resource = await helper.getChallengeResource(id, handle, config.ROLE_ID_SUBMITTER) + if (resource) { + localLogger.info({ context: 'addResourceToChallenge', message: `${handle} exists in challenge ${id}` }) + return + } + } localLogger.error({ context: 'addResourceToChallenge', message: `Status Code: ${err.status}` }) localLogger.error({ context: 'addResourceToChallenge', message: err.response.text }) throw err @@ -137,6 +145,13 @@ async function activateChallenge (id, token) { await helper.updateChallenge(id, body, token) localLogger.info({ context: 'activateChallenge', message: `Challenge ${id} is activated successfully.` }) } catch (err) { + if (err.status >= 500) { + const challenge = await helper.getChallenge(id) + if (_.includes([constants.ChallengeStatus.ACTIVE, constants.ChallengeStatus.COMPLETED], challenge.status)) { + localLogger.info({ context: 'activateChallenge', message: `the status of Challenge ${id} had been ${challenge.status}.` }) + return + } + } localLogger.error({ context: 'activateChallenge', message: `Status Code: ${err.status}` }) localLogger.error({ context: 'activateChallenge', message: err.response.text }) throw err @@ -146,14 +161,14 @@ async function activateChallenge (id, token) { /** * closes the topcoder challenge * @param {String} id the challenge id + * @param {String} userId the user id * @param {String} userHandle the user handle * @param {String} token m2m token * @returns {Object} the closed challenge */ -async function closeChallenge (id, userHandle, token) { +async function closeChallenge (id, userId, userHandle, token) { localLogger.info({ context: 'closeChallenge', message: `Closing challenge ${id}` }) try { - const { userId } = await helper.getV3MemberDetailsByHandle(userHandle) const body = { status: constants.ChallengeStatus.COMPLETED, winners: [{ @@ -166,6 +181,13 @@ async function closeChallenge (id, userHandle, token) { localLogger.info({ context: 'closeChallenge', message: `Challenge ${id} is closed successfully.` }) return response } catch (err) { + if (err.status >= 500) { + const challenge = await helper.getChallenge(id) + if (constants.ChallengeStatus.COMPLETED === challenge.status) { + localLogger.info({ context: 'activateChallenge', message: `the status of Challenge ${id} had been ${challenge.status}.` }) + return challenge + } + } localLogger.error({ context: 'closeChallenge', message: `Status Code: ${err.status}` }) localLogger.error({ context: 'closeChallenge', message: err.response.text }) throw err @@ -173,5 +195,9 @@ async function closeChallenge (id, userHandle, token) { } module.exports = { - createPayment + createPayment, + createChallenge, + addResourceToChallenge, + activateChallenge, + closeChallenge } diff --git a/src/services/ResourceBookingService.js b/src/services/ResourceBookingService.js index 3693f22c..9204eed5 100644 --- a/src/services/ResourceBookingService.js +++ b/src/services/ResourceBookingService.js @@ -1,3 +1,4 @@ +/* eslint-disable no-unreachable */ /** * This service provides operations of ResourceBooking. */ @@ -12,23 +13,139 @@ const helper = require('../common/helper') const logger = require('../common/logger') const errors = require('../common/errors') const models = require('../models') +const constants = require('../../app-constants') const moment = require('moment') const ResourceBooking = models.ResourceBooking const WorkPeriod = models.WorkPeriod +const WorkPeriodPayment = models.WorkPeriodPayment const esClient = helper.getESClient() +const cachedModelFields = _cacheModelFields() /** - * filter fields of resource booking by user role. + * Get the fields of the ResourceBooking model and the nested WorkPeriod model + * @returns {Array} array of field names + */ +function _cacheModelFields () { + const resourceBookingFields = _.keys(ResourceBooking.rawAttributes) + const workPeriodFields = _.map(_.keys(WorkPeriod.rawAttributes), key => `workPeriods.${key}`) + return [...resourceBookingFields, 'workPeriods', ...workPeriodFields] +} + +/** + * Check user scopes for getting workPeriods * @param {Object} currentUser the user who perform this operation. - * @param {Object} resourceBooking the resourceBooking with all fields - * @returns {Object} the resourceBooking + * @returns {Boolean} true if user is machine and has read/all workPeriod scopes + */ +function _checkUserScopesForGetWorkPeriods (currentUser) { + const getWorkPeriodsScopes = [constants.Scopes.READ_WORK_PERIOD, constants.Scopes.ALL_WORK_PERIOD] + return currentUser.isMachine && helper.checkIfExists(getWorkPeriodsScopes, currentUser.scopes) +} + +/** + * Evaluates the criterias and returns the fields + * to be returned as a result of GET endpoints + * @param {Object} currentUser the user who perform this operation. + * @param {Object} criteria the query criterias + * @returns {Object} result + * @returns {Array} result.include field names to include + * @returns {Array} result.fieldsRB ResourceBooking field names to include + * @returns {Array} result.fieldsWP WorkPeriod field names to include + * @returns {Array} result.excludeRB ResourceBooking field names to exclude + * @returns {Array} result.excludeWP WorkPeriod field names to exclude + * @returns {Boolean} result.regularUser is current user a regular user? + * @returns {Boolean} result.allWorkPeriods will all WorkPeriod fields be returned? + * @returns {Boolean} result.withWorkPeriods does fields include any WorkPeriod field? + * @returns {Boolean} result.sortByWP will the sorting be done by WorkPeriod field? */ -async function _getResourceBookingFilteringFields (currentUser, resourceBooking) { - if (currentUser.hasManagePermission || currentUser.isMachine) { - return resourceBooking +function _checkCriteriaAndGetFields (currentUser, criteria) { + const result = { + include: [], + fieldsRB: [], + fieldsWP: [], + excludeRB: [], + excludeWP: [] + } + const fields = criteria.fields + const sort = criteria.sortBy + const onlyResourceBooking = _.isUndefined(fields) + const query = onlyResourceBooking ? [] : _.split(fields, ',') + const notAllowedFields = _.difference(query, cachedModelFields) + // Check if fields criteria has a field name that RB or WP models don't have + if (notAllowedFields.length > 0) { + throw new errors.BadRequestError(`${notAllowedFields} are not allowed`) + } + // Check if user is a regular user. Regular users can't get ResourceBookings for which they are not a member + result.regularUser = !currentUser.hasManagePermission && !currentUser.isMachine && !currentUser.isConnectManager + // Check if all WorkPeriod fields will be returned + result.allWorkPeriods = _.some(query, q => q === 'workPeriods') + // Split the fields criteria into ResourceBooking and WorkPeriod fields + _.forEach(query, q => { + if (_.includes(q, '.')) { result.fieldsWP.push(q) } else if (q !== 'workPeriods') { result.fieldsRB.push(q) } + }) + // Check if any WorkPeriod field will be returned + result.withWorkPeriods = result.allWorkPeriods || result.fieldsWP.length > 0 + // Extract the filters from criteria parameter + let filters = _.filter(Object.keys(criteria), key => _.indexOf(['fromDb', 'fields', 'page', 'perPage', 'sortBy', 'sortOrder'], key) === -1) + filters = _.map(filters, f => { + if (f === 'projectIds') { + return 'projectId' + } return f + }) + const filterRB = [] + const filterWP = [] + // Split the filters criteria into ResourceBooking and WorkPeriod filters + _.forEach(filters, q => { if (_.includes(q, '.')) { filterWP.push(q) } else { filterRB.push(q) } }) + // Check if filter criteria has any WorkPeriod filter + const filterHasWorkPeriods = filterWP.length > 0 + // Check if sorting will be done by WorkPeriod field + result.sortByWP = _.split(sort, '.')[0] === 'workPeriods' + // Check if the current user has the right to see the memberRate + const canSeeMemberRate = currentUser.hasManagePermission || currentUser.isMachine + // If current user has no right to see the memberRate then it's excluded + // "currentUser.isMachine" to be true is not enough to return "workPeriods.memberRate" + // but returning "workPeriod" will be evaluated later + if (!canSeeMemberRate) { + result.excludeRB.push('paymentTotal') + result.excludeWP.push('workPeriods.paymentTotal') + } + // if "fields" is not included in cretia, then only ResourceBooking model will be returned + // No further evaluation is required as long as the criteria does not include a WorkPeriod filter or a WorkPeriod sorting condition + if (onlyResourceBooking) { + if (filterHasWorkPeriods || result.sortByWP) { + throw new errors.BadRequestError('Can not filter or sort by some field which is not included in fields') + } + result.excludeWP.push('workPeriods') + return result + } + // Include sorting condition in filters + if (result.sortByWP) { + // It is required to filter by "workPeriods.startDate" or "workPeriods.endDate" if sorting will be done by WorkPeriod field + if (!_.some(filterWP, f => _.includes(['workPeriods.startDate', 'workPeriods.endDate'], f))) { + throw new errors.BadRequestError('Can not sort by workPeriod field without filtering by workPeriods.startDate or workPeriods.endDate') + } + filterWP.push(sort) + } else if (!_.isUndefined(sort) && sort !== 'id') { + filterRB.push(sort) } - return _.omit(resourceBooking, 'memberRate') + // Check If it's tried to filter or sort by some field which should not be included as per rules of fields param + if (_.difference(filterRB, result.fieldsRB).length > 0) { + throw new errors.BadRequestError('Can not filter or sort by some field which is not included in fields') + } + // Check If it's tried to filter or sort by some field which should not be included as per rules of fields param + if (!result.allWorkPeriods && _.difference(filterWP, result.fieldsWP).length > 0) { + throw new errors.BadRequestError('Can not filter or sort by some field which is not included in fields') + } + // Check if the current user has no right to see the memberRate and memberRate is included in fields parameter + if (!canSeeMemberRate && _.some(query, q => _.includes(['memberRate', 'workPeriods.paymentTotal'], q))) { + throw new errors.ForbiddenError('You don\'t have access to view memberRate and paymentTotal') + } + // Check if the current user has no right to see the workPeriods and workPeriods is included in fields parameter + if (currentUser.isMachine && result.withWorkPeriods && !_checkUserScopesForGetWorkPeriods(currentUser)) { + throw new errors.ForbiddenError('You don\'t have access to view workPeriods') + } + result.include.push(...query) + return result } /** @@ -39,9 +156,7 @@ async function _getResourceBookingFilteringFields (currentUser, resourceBooking) * @returns {undefined} */ async function _checkUserPermissionForGetResourceBooking (currentUser, projectId) { - if (!currentUser.hasManagePermission && !currentUser.isMachine && !currentUser.isConnectManager) { - await helper.checkIsMemberOfProject(currentUser.userId, projectId) - } + await helper.checkIsMemberOfProject(currentUser.userId, projectId) } /** @@ -54,81 +169,117 @@ async function _checkUserPermissionForGetResourceBooking (currentUser, projectId */ async function _ensurePaidWorkPeriodsNotDeleted (resourceBookingId, oldValue, newValue) { function _checkForPaidWorkPeriods (workPeriods) { - const paidWorkPeriods = _.filter(workPeriods - , workPeriod => _.includes(['completed', 'partially-completed'], workPeriod.paymentStatus)) + const paidWorkPeriods = _.filter(workPeriods, workPeriod => { + // filter by WP and WPP status + return _.some(workPeriod.payments, payment => constants.ActiveWorkPeriodPaymentStatuses.indexOf(payment.status) !== -1) + }) if (paidWorkPeriods.length > 0) { - throw new errors.BadRequestError(`WorkPeriods with id of ${_.map(paidWorkPeriods, workPeriod => workPeriod.id)} - has completed or partially-completed payment status.`) + throw new errors.BadRequestError(`Can't delete associated WorkPeriods ${_.map(paidWorkPeriods, workPeriod => workPeriod.id)} + as they have associated WorkPeriodsPayment with one of statuses ${constants.ActiveWorkPeriodPaymentStatuses.join(', ')}.`) } } // find related workPeriods to evaluate the changes - const workPeriods = await WorkPeriod.findAll({ + // We don't need to include WPP because WPP's status changes should + // update WP's status. In case of any bug or slow processing, it's better to check both WP + // and WPP status for now. + let workPeriods = await WorkPeriod.findAll({ where: { resourceBookingId: resourceBookingId }, - raw: true + attributes: ['id', 'paymentStatus', 'startDate', 'endDate', 'daysPaid'], + include: [{ + model: WorkPeriodPayment, + as: 'payments', + required: false, + attributes: ['status'] + }] }) + workPeriods = _.map(workPeriods, wp => wp.toJSON()) // oldValue and newValue are not provided at deleteResourceBooking process if (_.isUndefined(oldValue) || _.isUndefined(newValue)) { _checkForPaidWorkPeriods(workPeriods) return } // We should not be able to change status of ResourceBooking to 'cancelled' - // if there is at least one associated Work Period with paymentStatus 'partially-completed' or 'completed'. + // if there is at least one associated Work Period with paymentStatus 'partially-completed', 'completed' or 'in-progress', + // or any of it's WorkPeriodsPayment has status 'completed' or 'in-progress'. if (oldValue.status !== 'cancelled' && newValue.status === 'cancelled') { _checkForPaidWorkPeriods(workPeriods) // we have already checked all existing workPeriods return } // gather workPeriod dates from provided dates - const newWorkPeriods = helper.extractWorkPeriods(newValue.startDate || oldValue.startDate, newValue.endDate || oldValue.endDate) + const newWorkPeriods = helper.extractWorkPeriods( + _.isUndefined(newValue.startDate) ? oldValue.startDate : newValue.startDate, + _.isUndefined(newValue.endDate) ? oldValue.endDate : newValue.endDate) // find which workPeriods should be removed const workPeriodsToRemove = _.differenceBy(workPeriods, newWorkPeriods, 'startDate') - // we can't delete workperiods with paymentStatus 'partially-completed' or 'completed'. + // we can't delete workperiods with paymentStatus 'partially-completed', 'completed' or 'in-progress', + // or any of it's WorkPeriodsPayment has status 'completed' or 'in-progress'. _checkForPaidWorkPeriods(workPeriodsToRemove) + // check if this update makes maximum possible daysWorked value less than daysPaid + _.each(newWorkPeriods, newWP => { + const wp = _.find(workPeriods, ['startDate', newWP.startDate]) + if (!wp) { + return + } + if (wp.daysPaid > newWP.daysWorked) { + throw new errors.ConflictError(`Cannot make maximum daysWorked (${newWP.daysWorked}) to the value less than daysPaid (${wp.daysPaid}) for WorkPeriod: ${wp.id}`) + } + }) } /** * Get resourceBooking by id * @param {Object} currentUser the user who perform this operation. * @param {String} id the resourceBooking id - * @param {Boolean} fromDb flag if query db for data or not + * @param {Object} criteria object including fields and fromDb criteria * @returns {Object} the resourceBooking */ -async function getResourceBooking (currentUser, id, fromDb = false) { - if (!fromDb) { +async function getResourceBooking (currentUser, id, criteria) { + // Evaluate criteria and extract the fields to be included or excluded + const queryOpt = _checkCriteriaAndGetFields(currentUser, criteria) + // We don't allow regular user to exclude projectId from result + if (queryOpt.regularUser && queryOpt.include.length > 0 && !_.includes(queryOpt.include, 'projectId')) { + throw new errors.ForbiddenError('Not allowed without including "projectId"') + } + if (!criteria.fromDb) { try { const resourceBooking = await esClient.get({ index: config.esConfig.ES_INDEX_RESOURCE_BOOKING, - id + id, + _source_includes: [...queryOpt.include], + _source_excludes: ['workPeriods.payments', ...queryOpt.excludeRB, ...queryOpt.excludeWP] }) - - await _checkUserPermissionForGetResourceBooking(currentUser, resourceBooking.body._source.projectId) // check user permission - - const resourceBookingRecord = { id: resourceBooking.body._id, ...resourceBooking.body._source } - return _getResourceBookingFilteringFields(currentUser, resourceBookingRecord) + if (queryOpt.regularUser) { + await _checkUserPermissionForGetResourceBooking(currentUser, resourceBooking.body._source.projectId) // check user permission + } + return resourceBooking.body._source } catch (err) { if (helper.isDocumentMissingException(err)) { throw new errors.NotFoundError(`id: ${id} "ResourceBooking" not found`) } - if (err.httpStatus === HttpStatus.FORBIDDEN) { + if (err.httpStatus === HttpStatus.UNAUTHORIZED) { throw err } logger.logFullError(err, { component: 'ResourceBookingService', context: 'getResourceBooking' }) } } logger.info({ component: 'ResourceBookingService', context: 'getResourceBooking', message: 'try to query db for data' }) - const resourceBooking = await ResourceBooking.findById(id) - - await _checkUserPermissionForGetResourceBooking(currentUser, resourceBooking.projectId) // check user permission - - return _getResourceBookingFilteringFields(currentUser, resourceBooking.dataValues) + const resourceBooking = await ResourceBooking.findById(id, queryOpt) + if (queryOpt.regularUser) { + await _checkUserPermissionForGetResourceBooking(currentUser, resourceBooking.projectId) // check user permission + } + return resourceBooking.dataValues } getResourceBooking.schema = Joi.object().keys({ currentUser: Joi.object().required(), id: Joi.string().guid().required(), - fromDb: Joi.boolean() + criteria: Joi.object().keys({ + fromDb: Joi.boolean().default(false), + fields: Joi.string() + }) }).required() /** @@ -194,6 +345,10 @@ async function updateResourceBooking (currentUser, id, data) { const resourceBooking = await ResourceBooking.findById(id) const oldValue = resourceBooking.toJSON() + // We can't remove dates of Resource Booking once they are both set + if (!_.isNil(oldValue.startDate) && !_.isNil(oldValue.endDate) && (_.isNull(data.startDate) || _.isNull(data.endDate))) { + throw new errors.BadRequestError('You cannot remove start or end date if both are already set for Resource Booking.') + } // before updating the record, we need to check if any paid work periods tried to be deleted await _ensurePaidWorkPeriodsNotDeleted(id, oldValue, data) @@ -306,12 +461,14 @@ deleteResourceBooking.schema = Joi.object().keys({ * @returns {Object} the search result, contain total/page/perPage and result array */ async function searchResourceBookings (currentUser, criteria, options = { returnAll: false }) { + // Evaluate criteria and extract the fields to be included or excluded + const queryOpt = _checkCriteriaAndGetFields(currentUser, criteria) // check user permission - if (!currentUser.hasManagePermission && !currentUser.isMachine && !currentUser.isConnectManager && !options.returnAll) { + if (queryOpt.regularUser && !options.returnAll) { if (!criteria.projectId) { // regular user can only search with filtering by "projectId" throw new errors.ForbiddenError('Not allowed without filtering by "projectId"') } - await helper.checkIsMemberOfProject(currentUser.userId, criteria.projectId) + await _checkUserPermissionForGetResourceBooking(currentUser, criteria.projectId) } // `criteria`.projectIds` could be array of ids, or comma separated string of ids @@ -326,7 +483,12 @@ async function searchResourceBookings (currentUser, criteria, options = { return return projectId }) } - const page = criteria.page > 0 ? criteria.page : 1 + // `criteria[workPeriods.paymentStatus]` could be array of paymentStatus, or comma separated string of paymentStatus + // in case it's comma separated string of paymentStatus we have to convert it to an array of paymentStatus + if ((typeof criteria['workPeriods.paymentStatus']) === 'string') { + criteria['workPeriods.paymentStatus'] = criteria['workPeriods.paymentStatus'].trim().split(',').map(ps => Joi.attempt({ paymentStatus: ps.trim() }, Joi.object().keys({ paymentStatus: Joi.paymentStatus() })).paymentStatus) + } + const page = criteria.page let perPage if (options.returnAll) { // To simplify the logic we are use a very large number for perPage @@ -335,7 +497,7 @@ async function searchResourceBookings (currentUser, criteria, options = { return // https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules.html#index-max-result-window perPage = 10000 } else { - perPage = criteria.perPage > 0 ? criteria.perPage : 20 + perPage = criteria.perPage } if (!criteria.sortBy) { @@ -345,10 +507,10 @@ async function searchResourceBookings (currentUser, criteria, options = { return criteria.sortOrder = 'desc' } try { - const sort = [{ [criteria.sortBy === 'id' ? '_id' : criteria.sortBy]: { order: criteria.sortOrder } }] - const esQuery = { index: config.get('esConfig.ES_INDEX_RESOURCE_BOOKING'), + _source_includes: queryOpt.include, + _source_excludes: ['workPeriods.payments', ...queryOpt.excludeRB, ...queryOpt.excludeWP], body: { query: { bool: { @@ -357,7 +519,7 @@ async function searchResourceBookings (currentUser, criteria, options = { return }, from: (page - 1) * perPage, size: perPage, - sort + sort: [] } } // change the date format to match with index schema @@ -367,6 +529,24 @@ async function searchResourceBookings (currentUser, criteria, options = { return if (criteria.endDate) { criteria.endDate = moment(criteria.endDate).format('YYYY-MM-DD') } + if (criteria['workPeriods.startDate']) { + criteria['workPeriods.startDate'] = moment(criteria['workPeriods.startDate']).format('YYYY-MM-DD') + } + if (criteria['workPeriods.endDate']) { + criteria['workPeriods.endDate'] = moment(criteria['workPeriods.endDate']).format('YYYY-MM-DD') + } + const sort = { [criteria.sortBy === 'id' ? '_id' : criteria.sortBy]: { order: criteria.sortOrder } } + if (queryOpt.sortByWP) { + const nestedSortFilter = {} + if (criteria['workPeriods.startDate']) { + nestedSortFilter.term = { 'workPeriods.startDate': criteria['workPeriods.startDate'] } + } else if (criteria['workPeriods.endDate']) { + nestedSortFilter.term = { 'workPeriods.endDate': criteria['workPeriods.endDate'] } + } + sort[criteria.sortBy].nested = { path: 'workPeriods', filter: nestedSortFilter } + } + esQuery.body.sort.push(sort) + // Apply ResourceBooking filters _.each(_.pick(criteria, ['status', 'startDate', 'endDate', 'rateType', 'projectId', 'jobId', 'userId']), (value, key) => { esQuery.body.query.bool.must.push({ term: { @@ -384,52 +564,155 @@ async function searchResourceBookings (currentUser, criteria, options = { return } }] } + // Apply WorkPeriod filters + const workPeriodFilters = _.pick(criteria, ['workPeriods.paymentStatus', 'workPeriods.startDate', 'workPeriods.endDate', 'workPeriods.userHandle']) + if (!_.isEmpty(workPeriodFilters)) { + const workPeriodsMust = [] + _.each(workPeriodFilters, (value, key) => { + if (key === 'workPeriods.paymentStatus') { + workPeriodsMust.push({ + terms: { + [key]: value + } + }) + } else { + workPeriodsMust.push({ + term: { + [key]: { + value + } + } + }) + } + }) + + esQuery.body.query.bool.must.push({ + nested: { + path: 'workPeriods', + query: { bool: { must: workPeriodsMust } } + } + }) + } logger.debug({ component: 'ResourceBookingService', context: 'searchResourceBookings', message: `Query: ${JSON.stringify(esQuery)}` }) const { body } = await esClient.search(esQuery) + const resourceBookings = _.map(body.hits.hits, '_source') + // ESClient will return ResourceBookings with it's all nested WorkPeriods + // We re-apply WorkPeriod filters except userHandle because all WPs share same userHandle + _.each(_.omit(workPeriodFilters, 'workPeriods.userHandle'), (value, key) => { + key = key.split('.')[1] + _.each(resourceBookings, r => { + r.workPeriods = _.filter(r.workPeriods, wp => { + if (key === 'paymentStatus') { + return _.includes(value, wp[key]) + } else { + return wp[key] === value + } + }) + }) + }) + + // sort Work Periods inside Resource Bookings by startDate just for comfort output + _.each(resourceBookings, r => { + if (_.isArray(r.workPeriods)) { + r.workPeriods = _.sortBy(r.workPeriods, ['startDate']) + } + }) return { total: body.hits.total.value, page, perPage, - result: _.map(body.hits.hits, (hit) => { - const obj = _.cloneDeep(hit._source) - obj.id = hit._id - return obj - }) + result: resourceBookings } } catch (err) { logger.logFullError(err, { component: 'ResourceBookingService', context: 'searchResourceBookings' }) } logger.info({ component: 'ResourceBookingService', context: 'searchResourceBookings', message: 'fallback to DB query' }) const filter = { [Op.and]: [] } + // Apply ResourceBooking filters _.each(_.pick(criteria, ['status', 'startDate', 'endDate', 'rateType', 'projectId', 'jobId', 'userId']), (value, key) => { filter[Op.and].push({ [key]: value }) }) if (criteria.projectIds) { filter[Op.and].push({ projectId: criteria.projectIds }) } - const resourceBookings = await ResourceBooking.findAll({ + const queryCriteria = { where: filter, offset: ((page - 1) * perPage), - limit: perPage, - order: [[criteria.sortBy, criteria.sortOrder]] + limit: perPage + } + // Select ResourceBooking fields + if (queryOpt.include.length > 0) { + queryCriteria.attributes = queryOpt.fieldsRB + } else if (queryOpt.excludeRB && queryOpt.excludeRB.length > 0) { + queryCriteria.attributes = { exclude: queryOpt.excludeRB } + } + // Include WorkPeriod Model + if (queryOpt.withWorkPeriods) { + queryCriteria.include = [{ + model: WorkPeriod, + as: 'workPeriods', + required: false, + where: { [Op.and]: [] } + }] + // Select WorkPeriod fields + if (!queryOpt.allWorkPeriods) { + queryCriteria.include[0].attributes = _.map(queryOpt.fieldsWP, f => _.split(f, '.')[1]) + } else if (queryOpt.excludeWP && queryOpt.excludeWP.length > 0) { + queryCriteria.include[0].attributes = { exclude: _.map(queryOpt.excludeWP, f => _.split(f, '.')[1]) } + } + // Apply WorkPeriod filters + _.each(_.pick(criteria, ['workPeriods.startDate', 'workPeriods.endDate', 'workPeriods.paymentStatus']), (value, key) => { + key = key.split('.')[1] + queryCriteria.include[0].where[Op.and].push({ [key]: value }) + }) + if (criteria['workPeriods.userHandle']) { + queryCriteria.include[0].where[Op.and].push({ userHandle: { [Op.iLike]: criteria['workPeriods.userHandle'] } }) + } + if (queryCriteria.include[0].where[Op.and].length > 0) { + queryCriteria.include[0].required = true + } + } + // Apply sorting criteria + if (!queryOpt.sortByWP) { + queryCriteria.order = [[criteria.sortBy, `${criteria.sortOrder} NULLS LAST`]] + } else { + queryCriteria.subQuery = false + queryCriteria.order = [[{ model: WorkPeriod, as: 'workPeriods' }, _.split(criteria.sortBy, '.')[1], `${criteria.sortOrder} NULLS LAST`]] + } + const result = await ResourceBooking.findAll(queryCriteria) + // sort Work Periods inside Resource Bookings by startDate just for comfort output + _.each(result, r => { + if (_.isArray(r.workPeriods)) { + r.workPeriods = _.sortBy(r.workPeriods, ['startDate']) + } }) + let countQuery + countQuery = _.omit(queryCriteria, ['limit', 'offset', 'attributes', 'order']) + if (queryOpt.withWorkPeriods && !queryCriteria.include[0].required) { + countQuery = _.omit(countQuery, ['include']) + } + countQuery.subQuery = false + countQuery.group = ['ResourceBooking.id'] + const total = await ResourceBooking.count(countQuery) return { fromDb: true, - total: resourceBookings.length, + total: total.length, page, perPage, - result: _.map(resourceBookings, resourceBooking => resourceBooking.dataValues) + result } } searchResourceBookings.schema = Joi.object().keys({ currentUser: Joi.object().required(), criteria: Joi.object().keys({ - page: Joi.number().integer(), - perPage: Joi.number().integer(), - sortBy: Joi.string().valid('id', 'rateType', 'startDate', 'endDate', 'customerRate', 'memberRate', 'status'), + fields: Joi.string(), + page: Joi.page(), + perPage: Joi.perPage(), + sortBy: Joi.string().valid('id', 'rateType', 'startDate', 'endDate', 'customerRate', 'memberRate', 'status', + 'workPeriods.userHandle', 'workPeriods.daysWorked', 'workPeriods.daysPaid', 'workPeriods.paymentTotal', 'workPeriods.paymentStatus'), sortOrder: Joi.string().valid('desc', 'asc'), status: Joi.resourceBookingStatus(), startDate: Joi.date().format('YYYY-MM-DD'), @@ -441,7 +724,14 @@ searchResourceBookings.schema = Joi.object().keys({ projectIds: Joi.alternatives( Joi.string(), Joi.array().items(Joi.number().integer()) - ) + ), + 'workPeriods.paymentStatus': Joi.alternatives( + Joi.string(), + Joi.array().items(Joi.paymentStatus()) + ), + 'workPeriods.startDate': Joi.date().format('YYYY-MM-DD'), + 'workPeriods.endDate': Joi.date().format('YYYY-MM-DD'), + 'workPeriods.userHandle': Joi.string() }).required(), options: Joi.object() }).required() diff --git a/src/services/RoleService.js b/src/services/RoleService.js new file mode 100644 index 00000000..bbd2c141 --- /dev/null +++ b/src/services/RoleService.js @@ -0,0 +1,307 @@ +/** + * This service provides operations of Roles. + */ + +const _ = require('lodash') +const config = require('config') +const Joi = require('joi') +const { Op } = require('sequelize') +const uuid = require('uuid') +const helper = require('../common/helper') +const logger = require('../common/logger') +const errors = require('../common/errors') +const models = require('../models') + +const Role = models.Role +const esClient = helper.getESClient() + +/** + * Check user permission for deleting, creating or updating role. + * @param {Object} currentUser the user who perform this operation. + * @returns {undefined} + */ +async function _checkUserPermissionForWriteDeleteRole (currentUser) { + if (!currentUser.hasManagePermission && !currentUser.isMachine) { + throw new errors.ForbiddenError('You are not allowed to perform this action!') + } +} + +/** + * Cleans and validates skill names using skills service + * @param {Array} skills array of skill names to validate + * @returns {undefined} + */ +async function _cleanAndValidateSkillNames (skills) { + // remove duplicates, leading and trailing whitespaces, empties. + const cleanedSkills = _.uniq(_.filter(_.map(skills, skill => _.trim(skill)), skill => !_.isEmpty(skill))) + if (cleanedSkills.length > 0) { + // search skills if they are exists + const result = await helper.getAllTopcoderSkills({ name: _.join(cleanedSkills, ',') }) + const skillNames = _.map(result, 'name') + // find skills that not valid + const unValidSkills = _.differenceBy(cleanedSkills, skillNames, _.toLower) + if (unValidSkills.length > 0) { + throw new errors.BadRequestError(`skills: "${unValidSkills}" are not valid`) + } + return _.intersectionBy(skillNames, cleanedSkills, _.toLower) + } else { + return null + } +} + +/** + * Check user permission for deleting, creating or updating role. + * @param {Object} currentUser the user who perform this operation. + * @returns {undefined} + */ +async function _checkIfSameNamedRoleExists (roleName) { + // We can't create another Role with the same name + const role = await Role.findOne({ + where: { + name: { [Op.iLike]: roleName } + }, + raw: true + }) + if (role) { + throw new errors.BadRequestError(`Role: "${role.name}" is already exists.`) + } +} + +/** + * Get role by id + * @param {Object} currentUser the user who perform this operation. + * @param {String} id the role id + * @param {Boolean} fromDb flag if query db for data or not + * @returns {Object} the role + */ +async function getRole (currentUser, id, fromDb = false) { + if (!fromDb) { + try { + const role = await esClient.get({ + index: config.esConfig.ES_INDEX_ROLE, + id + }) + return { id: role.body._id, ...role.body._source } + } catch (err) { + if (helper.isDocumentMissingException(err)) { + throw new errors.NotFoundError(`id: ${id} "Role" not found`) + } + } + } + logger.info({ component: 'RoleService', context: 'getRole', message: 'try to query db for data' }) + const role = await Role.findById(id) + + return role.toJSON() +} + +getRole.schema = Joi.object().keys({ + currentUser: Joi.object().required(), + id: Joi.string().uuid().required(), + fromDb: Joi.boolean() +}).required() + +/** + * Create role + * @param {Object} currentUser the user who perform this operation + * @param {Object} role the role to be created + * @returns {Object} the created role + */ +async function createRole (currentUser, role) { + // check permission + await _checkUserPermissionForWriteDeleteRole(currentUser) + // check if another Role with the same name exists. + await _checkIfSameNamedRoleExists(role.name) + // clean and validate skill names + if (role.listOfSkills) { + role.listOfSkills = await _cleanAndValidateSkillNames(role.listOfSkills) + } + + role.id = uuid.v4() + role.createdBy = await helper.getUserId(currentUser.userId) + + const created = await Role.create(role) + + await helper.postEvent(config.TAAS_ROLE_CREATE_TOPIC, created.toJSON()) + return created.toJSON() +} + +createRole.schema = Joi.object().keys({ + currentUser: Joi.object().required(), + role: Joi.object().keys({ + name: Joi.string().max(50).required(), + description: Joi.string().max(1000), + listOfSkills: Joi.array().items(Joi.string().max(50).required()), + rates: Joi.array().items(Joi.object().keys({ + global: Joi.smallint().required(), + inCountry: Joi.smallint().required(), + offShore: Joi.smallint().required(), + rate30Global: Joi.smallint(), + rate30InCountry: Joi.smallint(), + rate30OffShore: Joi.smallint(), + rate20Global: Joi.smallint(), + rate20InCountry: Joi.smallint(), + rate20OffShore: Joi.smallint() + }).required()).required(), + numberOfMembers: Joi.number(), + numberOfMembersAvailable: Joi.smallint(), + imageUrl: Joi.string().uri().max(255), + timeToCandidate: Joi.smallint(), + timeToInterview: Joi.smallint() + }).required() +}).required() + +/** + * Partially Update role + * @param {Object} currentUser the user who perform this operation + * @param {String} id the role id + * @param {Object} data the data to be updated + * @returns {Object} the updated role + */ +async function updateRole (currentUser, id, data) { + // check permission + await _checkUserPermissionForWriteDeleteRole(currentUser) + + const role = await Role.findById(id) + const oldValue = role.toJSON() + // if name is changed, check if another Role with the same name exists. + if (data.name && data.name.toLowerCase() !== role.dataValues.name.toLowerCase()) { + await _checkIfSameNamedRoleExists(data.name) + } + // clean and validate skill names + if (data.listOfSkills) { + data.listOfSkills = await _cleanAndValidateSkillNames(data.listOfSkills) + } + + data.updatedBy = await helper.getUserId(currentUser.userId) + const updated = await role.update(data) + + await helper.postEvent(config.TAAS_ROLE_UPDATE_TOPIC, updated.toJSON(), { oldValue: oldValue }) + return updated.toJSON() +} + +updateRole.schema = Joi.object().keys({ + currentUser: Joi.object().required(), + id: Joi.string().uuid().required(), + data: Joi.object().keys({ + name: Joi.string().max(50), + description: Joi.string().max(1000).allow(null), + listOfSkills: Joi.array().items(Joi.string().max(50).required()).allow(null), + rates: Joi.array().items(Joi.object().keys({ + global: Joi.smallint().required(), + inCountry: Joi.smallint().required(), + offShore: Joi.smallint().required(), + rate30Global: Joi.smallint(), + rate30InCountry: Joi.smallint(), + rate30OffShore: Joi.smallint(), + rate20Global: Joi.smallint(), + rate20InCountry: Joi.smallint(), + rate20OffShore: Joi.smallint() + }).required()), + numberOfMembers: Joi.number().allow(null), + numberOfMembersAvailable: Joi.smallint().allow(null), + imageUrl: Joi.string().uri().max(255).allow(null), + timeToCandidate: Joi.smallint().allow(null), + timeToInterview: Joi.smallint().allow(null) + }).required() +}).required() + +/** + * Delete role by id + * @param {Object} currentUser the user who perform this operation + * @param {String} id the role id + */ +async function deleteRole (currentUser, id) { + // check permission + await _checkUserPermissionForWriteDeleteRole(currentUser) + + const role = await Role.findById(id) + await role.destroy() + await helper.postEvent(config.TAAS_ROLE_DELETE_TOPIC, { id }) +} + +deleteRole.schema = Joi.object().keys({ + currentUser: Joi.object().required(), + id: Joi.string().uuid().required() +}).required() + +/** + * List roles + * @param {Object} currentUser the user who perform this operation. + * @param {Object} criteria the search criteria + * @returns {Object} the search result + */ +async function searchRoles (currentUser, criteria) { + // clean skill names and convert into an array + criteria.skillsList = _.filter(_.map(_.split(criteria.skillsList, ','), skill => _.trim(skill)), skill => !_.isEmpty(skill)) + try { + const esQuery = { + index: config.get('esConfig.ES_INDEX_ROLE'), + body: { + query: { + bool: { + must: [] + } + }, + size: 10000, + sort: [{ name: { order: 'asc' } }] + } + } + // Apply skill name filters. listOfSkills array should include all skills provided in criteria. + _.each(criteria.skillsList, skill => { + esQuery.body.query.bool.must.push({ + term: { + listOfSkills: skill + } + }) + }) + // Apply name filter, allow partial match + if (criteria.keyword) { + esQuery.body.query.bool.must.push({ + wildcard: { + name: `*${criteria.keyword}*` + + } + }) + } + logger.debug({ component: 'RoleService', context: 'searchRoles', message: `Query: ${JSON.stringify(esQuery)}` }) + + const { body } = await esClient.search(esQuery) + return _.map(body.hits.hits, (hit) => _.assign(hit._source, { id: hit._id })) + } catch (err) { + logger.logFullError(err, { component: 'RoleService', context: 'searchRoles' }) + } + logger.info({ component: 'RoleService', context: 'searchRoles', message: 'fallback to DB query' }) + const filter = { [Op.and]: [] } + // Apply skill name filters. listOfSkills array should include all skills provided in criteria. + if (criteria.skillsList) { + _.each(criteria.skillsList, skill => { + filter[Op.and].push(models.Sequelize.literal(`LOWER('${skill}') in (SELECT lower(x) FROM unnest("list_of_skills"::text[]) x)`)) + }) + } + // Apply name filter, allow partial match and ignore case + if (criteria.keyword) { + filter[Op.and].push({ name: { [Op.iLike]: `%${criteria.keyword}%` } }) + } + const queryCriteria = { + where: filter, + order: [['name', 'asc']] + } + const roles = await Role.findAll(queryCriteria) + return roles +} + +searchRoles.schema = Joi.object().keys({ + currentUser: Joi.object().required(), + criteria: Joi.object().keys({ + skillsList: Joi.string(), + keyword: Joi.string() + }).required() +}).required() + +module.exports = { + getRole, + createRole, + updateRole, + deleteRole, + searchRoles +} diff --git a/src/services/SkillService.js b/src/services/SkillService.js deleted file mode 100644 index b3d33025..00000000 --- a/src/services/SkillService.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - * This service provides operations of Skill. - */ -const Joi = require('joi') -const helper = require('../common/helper') - -/** - * Search skills - * @param {Object} criteria the search criteria - * @returns {Object} the search result, contain total/page/perPage and result array - */ -async function searchSkills (criteria) { - return helper.getTopcoderSkills(criteria) -} - -searchSkills.schema = Joi.object().keys({ - criteria: Joi.object().keys({ - page: Joi.page(), - perPage: Joi.perPage(), - orderBy: Joi.string() - }).required() -}).required() - -module.exports = { - searchSkills -} diff --git a/src/services/TeamService.js b/src/services/TeamService.js index a1432fd1..36797330 100644 --- a/src/services/TeamService.js +++ b/src/services/TeamService.js @@ -12,6 +12,13 @@ const logger = require('../common/logger') const errors = require('../common/errors') const JobService = require('./JobService') const ResourceBookingService = require('./ResourceBookingService') +const HttpStatus = require('http-status-codes') +const { Op } = require('sequelize') +const models = require('../models') +const stopWords = require('../../data/stopWords.json') +const Role = models.Role +const RoleSearchRequest = models.RoleSearchRequest +const topcoderSkills = {} const emailTemplates = _.mapValues(emailTemplateConfig, (template) => { return { @@ -32,7 +39,11 @@ const emailTemplates = _.mapValues(emailTemplateConfig, (template) => { */ async function _getPlacedResourceBookingsByProjectIds (currentUser, projectIds) { const criteria = { status: 'placed', projectIds } - const { result } = await ResourceBookingService.searchResourceBookings(currentUser, criteria, { returnAll: true }) + const { result } = await ResourceBookingService.searchResourceBookings( + currentUser, + criteria, + { returnAll: true } + ) return result } @@ -43,10 +54,81 @@ async function _getPlacedResourceBookingsByProjectIds (currentUser, projectIds) * @returns the request result */ async function _getJobsByProjectIds (currentUser, projectIds) { - const { result } = await JobService.searchJobs(currentUser, { projectIds }, { returnAll: true }) + const { result } = await JobService.searchJobs( + currentUser, + { projectIds }, + { returnAll: true } + ) return result } +/** + * Gets topcoder skills and stores their name and compiled + * regex patters according to Levenshtein distance <=1 + */ +async function _reloadCachedTopcoderSkills () { + // do not reload if cache time is not expired + if (!_.isUndefined(topcoderSkills.time)) { + const cacheTime = config.TOPCODER_SKILLS_CACHE_TIME * 60 * 1000 + if (new Date().getTime() - topcoderSkills.time < cacheTime) { + return + } + } + // collect all skills + const skills = await helper.getAllTopcoderSkills() + // set the last cached time + topcoderSkills.time = new Date().getTime() + topcoderSkills.skills = [] + // store skill names and compiled regex paterns + _.each(skills, skill => { + topcoderSkills.skills.push({ + name: skill.name, + pattern: _compileRegexPatternForSkillName(skill.name) + }) + }) +} + +/** + * Prepares the regex pattern for the given word + * according to Levenshtein distance of 1 (insertions, deletions or substitutions) + * @param {String} skillName the name of the skill + * @returns {RegExp} the compiled regex pattern + */ +function _compileRegexPatternForSkillName (skillName) { + // split the name into its chars + let chars = _.split(skillName, '') + // escape characters reserved to regex + chars = _.map(chars, _.escapeRegExp) + // Its not a good idea to apply tolerance according to + // Levenshtein distance for the words have less than 3 letters + // We expect the skill names have 1 or 2 letters to take place + // in job description as how they are exactly spelled + if (chars.length < 3) { + return new RegExp(`^(?:${_.join(chars, '')})$`, 'i') + } + + const res = [] + // include the skill name itself + res.push(_.join(chars, '')) + // include every transposition combination + // E.g. java => ajva, jvaa, jaav + for (let i = 0; i < chars.length - 1; i++) { + res.push(_.join(_.slice(chars, 0, i), '') + chars[i + 1] + chars[i] + _.join(_.slice(chars, i + 2), '')) + } + // include every insertion combination + // E.g. java => .java, j.ava, ja.va, jav.a, java. + for (let i = 0; i <= chars.length; i++) { + res.push(_.join(_.slice(chars, 0, i), '') + '.' + _.join(_.slice(chars, i), '')) + } + // include every deletion/substitution combination + // E.g. java => .?ava, j.?va, ja.?a, jav.? + for (let i = 0; i < chars.length; i++) { + res.push(_.join(_.slice(chars, 0, i), '') + '.?' + _.join(_.slice(chars, i + 1), '')) + } + // return the regex pattern + return new RegExp(`^(?:${_.join(res, '|')})$`, 'i') +} + /** * List teams * @param {Object} currentUser the user who perform this operation @@ -56,15 +138,17 @@ async function _getJobsByProjectIds (currentUser, projectIds) { async function searchTeams (currentUser, criteria) { const sort = `${criteria.sortBy} ${criteria.sortOrder}` // Get projects from /v5/projects with searching criteria - const { total, page, perPage, result: projects } = await helper.getProjects( - currentUser, - { - page: criteria.page, - perPage: criteria.perPage, - name: criteria.name, - sort - } - ) + const { + total, + page, + perPage, + result: projects + } = await helper.getProjects(currentUser, { + page: criteria.page, + perPage: criteria.perPage, + name: criteria.name, + sort + }) return { total, page, @@ -73,20 +157,37 @@ async function searchTeams (currentUser, criteria) { } } -searchTeams.schema = Joi.object().keys({ - currentUser: Joi.object().required(), - criteria: Joi.object().keys({ - page: Joi.page(), - perPage: Joi.perPage(), - sortBy: Joi.string().valid('createdAt', 'updatedAt', 'lastActivityAt', 'id', 'status', 'name', 'type', 'best match').default('lastActivityAt'), - sortOrder: Joi.when('sortBy', { - is: 'best match', - then: Joi.forbidden().label('sortOrder(with sortBy being `best match`)'), - otherwise: Joi.string().valid('asc', 'desc').default('desc') - }), - name: Joi.string() - }).required() -}).required() +searchTeams.schema = Joi.object() + .keys({ + currentUser: Joi.object().required(), + criteria: Joi.object() + .keys({ + page: Joi.page(), + perPage: Joi.perPage(), + sortBy: Joi.string() + .valid( + 'createdAt', + 'updatedAt', + 'lastActivityAt', + 'id', + 'status', + 'name', + 'type', + 'best match' + ) + .default('lastActivityAt'), + sortOrder: Joi.when('sortBy', { + is: 'best match', + then: Joi.forbidden().label( + 'sortOrder(with sortBy being `best match`)' + ), + otherwise: Joi.string().valid('asc', 'desc').default('desc') + }), + name: Joi.string() + }) + .required() + }) + .required() /** * Get team details @@ -98,7 +199,10 @@ searchTeams.schema = Joi.object().keys({ async function getTeamDetail (currentUser, projects, isSearch = true) { const projectIds = _.map(projects, 'id') // Get all placed resourceBookings filtered by projectIds - const resourceBookings = await _getPlacedResourceBookingsByProjectIds(currentUser, projectIds) + const resourceBookings = await _getPlacedResourceBookingsByProjectIds( + currentUser, + projectIds + ) // Get all jobs filtered by projectIds const jobs = await _getJobsByProjectIds(currentUser, projectIds) @@ -107,7 +211,11 @@ async function getTeamDetail (currentUser, projects, isSearch = true) { const firstDay = dateFNS.startOfWeek(curr) const lastDay = dateFNS.endOfWeek(curr) - logger.debug({ component: 'TeamService', context: 'getTeamDetail', message: `week started: ${firstDay}, week ended: ${lastDay}` }) + logger.debug({ + component: 'TeamService', + context: 'getTeamDetail', + message: `week started: ${firstDay}, week ended: ${lastDay}` + }) const result = [] for (const project of projects) { @@ -146,31 +254,33 @@ async function getTeamDetail (currentUser, projects, isSearch = true) { const endDate = new Date(item.endDate) // normally startDate is smaller than endDate for a resourceBooking so not check if startDate < endDate - if ((!item.startDate || startDate < lastDay) && - (!item.endDate || endDate > firstDay)) { + if ( + (!item.startDate || startDate < lastDay) && + (!item.endDate || endDate > firstDay) + ) { res.weeklyCost += item.customerRate } } const resourceInfos = await Promise.all( _.map(rbs, (rb) => { - return helper.getUserById(rb.userId, true) - .then(user => { - const resource = { - id: rb.id, - userId: user.id, - ..._.pick(user, ['handle', 'firstName', 'lastName', 'skills']) - } - // If call function is not search, add jobId field - if (!isSearch) { - resource.jobId = rb.jobId - resource.customerRate = rb.customerRate - resource.startDate = rb.startDate - resource.endDate = rb.endDate - } - return resource - }) - })) + return helper.getUserById(rb.userId, true).then((user) => { + const resource = { + id: rb.id, + userId: user.id, + ..._.pick(user, ['handle', 'firstName', 'lastName', 'skills']) + } + // If call function is not search, add jobId field + if (!isSearch) { + resource.jobId = rb.jobId + resource.customerRate = rb.customerRate + resource.startDate = rb.startDate + resource.endDate = rb.endDate + } + return resource + }) + }) + ) if (resourceInfos && resourceInfos.length > 0) { res.resources = resourceInfos @@ -179,7 +289,9 @@ async function getTeamDetail (currentUser, projects, isSearch = true) { const members = await helper.getMembers(userHandles) for (const item of res.resources) { - const findMember = _.find(members, { handleLower: item.handle.toLowerCase() }) + const findMember = _.find(members, { + handleLower: item.handle.toLowerCase() + }) if (findMember && findMember.photoURL) { item.photo_url = findMember.photoURL } @@ -200,8 +312,19 @@ async function getTeamDetail (currentUser, projects, isSearch = true) { res.totalPositions += item.numPositions } } else { - res.jobs = _.map(jobsTmp, job => { - return _.pick(job, ['id', 'description', 'startDate', 'duration', 'numPositions', 'rateType', 'skills', 'customerRate', 'status', 'title']) + res.jobs = _.map(jobsTmp, (job) => { + return _.pick(job, [ + 'id', + 'description', + 'startDate', + 'duration', + 'numPositions', + 'rateType', + 'skills', + 'customerRate', + 'status', + 'title' + ]) }) } } @@ -228,7 +351,9 @@ async function getTeam (currentUser, id) { for (const job of teamDetail.jobs) { if (job.skills) { const usersPromises = [] - _.map(job.skills, (skillId) => { usersPromises.push(helper.getSkillById(skillId)) }) + _.map(job.skills, (skillId) => { + usersPromises.push(helper.getSkillById(skillId)) + }) jobSkills = await Promise.all(usersPromises) job.skills = jobSkills } @@ -238,10 +363,12 @@ async function getTeam (currentUser, id) { return teamDetail } -getTeam.schema = Joi.object().keys({ - currentUser: Joi.object().required(), - id: Joi.number().integer().required() -}).required() +getTeam.schema = Joi.object() + .keys({ + currentUser: Joi.object().required(), + id: Joi.number().integer().required() + }) + .required() /** * Get team job with id @@ -256,7 +383,9 @@ async function getTeamJob (currentUser, id, jobId) { const job = _.find(jobs, { id: jobId }) if (!job) { - throw new errors.NotFoundError(`id: ${jobId} "Job" with Team id ${id} doesn't exist`) + throw new errors.NotFoundError( + `id: ${jobId} "Job" with Team id ${id} doesn't exist` + ) } const result = { id: job.id, @@ -278,7 +407,9 @@ async function getTeamJob (currentUser, id, jobId) { if (job && job.candidates && job.candidates.length > 0) { // find user data for candidates const users = await Promise.all( - _.map(_.uniq(_.map(job.candidates, 'userId')), userId => helper.getUserById(userId, true)) + _.map(_.uniq(_.map(job.candidates, 'userId')), (userId) => + helper.getUserById(userId, true) + ) ) const userMap = _.groupBy(users, 'id') @@ -286,11 +417,20 @@ async function getTeamJob (currentUser, id, jobId) { const members = await helper.getMembers(_.map(users, 'handle')) const photoURLMap = _.groupBy(members, 'handleLower') - result.candidates = _.map(job.candidates, candidate => { - const candidateData = _.pick(candidate, ['status', 'resume', 'userId', 'interviews', 'id']) + result.candidates = _.map(job.candidates, (candidate) => { + 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'])) + Object.assign( + candidateData, + _.pick(userData, ['handle', 'firstName', 'lastName', 'skills']) + ) // attach photo URL to the candidate const handleLower = userData.handle.toLowerCase() if (photoURLMap[handleLower]) { @@ -303,11 +443,13 @@ async function getTeamJob (currentUser, id, jobId) { return result } -getTeamJob.schema = Joi.object().keys({ - currentUser: Joi.object().required(), - id: Joi.number().integer().required(), - jobId: Joi.string().guid().required() -}).required() +getTeamJob.schema = Joi.object() + .keys({ + currentUser: Joi.object().required(), + id: Joi.number().integer().required(), + jobId: Joi.string().guid().required() + }) + .required() /** * Send email through a particular template @@ -326,7 +468,10 @@ async function sendEmail (currentUser, data) { body: data.body || template.body } for (const key in subjectBody) { - subjectBody[key] = await helper.substituteStringByObject(subjectBody[key], data.data) + subjectBody[key] = await helper.substituteStringByObject( + subjectBody[key], + data.data + ) } const emailData = { // override template if coming data already have the 'from' address @@ -341,16 +486,22 @@ async function sendEmail (currentUser, data) { await helper.postEvent(config.EMAIL_TOPIC, emailData) } -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(), - from: Joi.string().email(), - recipients: Joi.array().items(Joi.string().email()).allow(null), - cc: Joi.array().items(Joi.string().email()).allow(null) - }).required() -}).required() +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(), + from: Joi.string().email(), + recipients: Joi.array().items(Joi.string().email()).allow(null), + cc: Joi.array().items(Joi.string().email()).allow(null) + }) + .required() + }) + .required() /** * Add a member to a team as customer. @@ -401,70 +552,101 @@ async function addMembers (currentUser, id, criteria, data) { const handles = data.handles || [] const emails = data.emails || [] - const handleMembers = await helper.getMemberDetailsByHandles(handles) - .then((members) => _.map(members, (member) => ({ - ...member, - // populate members with lower-cased handle for case insensitive search - handleLowerCase: member.handle.toLowerCase() - }))) + const handleMembers = await helper + .getMemberDetailsByHandles(handles) + .then((members) => + _.map(members, (member) => ({ + ...member, + // populate members with lower-cased handle for case insensitive search + handleLowerCase: member.handle.toLowerCase() + })) + ) - const emailMembers = await helper.getMemberDetailsByEmails(emails) - .then((members) => _.map(members, (member) => ({ - ...member, - // populate members with lower-cased email for case insensitive search - emailLowerCase: member.email.toLowerCase() - }))) + const emailMembers = await helper + .getMemberDetailsByEmails(emails) + .then((members) => + _.map(members, (member) => ({ + ...member, + // populate members with lower-cased email for case insensitive search + emailLowerCase: member.email.toLowerCase() + })) + ) await Promise.all([ - Promise.all(handles.map(handle => { - const memberDetails = _.find(handleMembers, { handleLowerCase: handle.toLowerCase() }) - - if (!memberDetails) { - result.failed.push({ error: 'User doesn\'t exist', handle }) - return - } - - return _addMemberToProjectAsCustomer(id, memberDetails.userId, criteria.fields) - .then(member => { - // note, that we return `handle` in the same case it was in request - result.success.push(({ ...member, handle })) - }).catch(err => { - result.failed.push({ error: err.message, handle }) + Promise.all( + handles.map((handle) => { + const memberDetails = _.find(handleMembers, { + handleLowerCase: handle.toLowerCase() }) - })), - Promise.all(emails.map(email => { - const memberDetails = _.find(emailMembers, { emailLowerCase: email.toLowerCase() }) + if (!memberDetails) { + result.failed.push({ error: "User doesn't exist", handle }) + return + } - if (!memberDetails) { - result.failed.push({ error: 'User doesn\'t exist', email }) - return - } + return _addMemberToProjectAsCustomer( + id, + memberDetails.userId, + criteria.fields + ) + .then((member) => { + // note, that we return `handle` in the same case it was in request + result.success.push({ ...member, handle }) + }) + .catch((err) => { + result.failed.push({ error: err.message, handle }) + }) + }) + ), - return _addMemberToProjectAsCustomer(id, memberDetails.id, criteria.fields) - .then(member => { - // note, that we return `email` in the same case it was in request - result.success.push(({ ...member, email })) - }).catch(err => { - result.failed.push({ error: err.message, email }) + Promise.all( + emails.map((email) => { + const memberDetails = _.find(emailMembers, { + emailLowerCase: email.toLowerCase() }) - })) + + if (!memberDetails) { + result.failed.push({ error: "User doesn't exist", email }) + return + } + + return _addMemberToProjectAsCustomer( + id, + memberDetails.id, + criteria.fields + ) + .then((member) => { + // note, that we return `email` in the same case it was in request + result.success.push({ ...member, email }) + }) + .catch((err) => { + result.failed.push({ error: err.message, email }) + }) + }) + ) ]) return result } -addMembers.schema = Joi.object().keys({ - currentUser: Joi.object().required(), - id: Joi.number().integer().required(), - criteria: Joi.object().keys({ - fields: Joi.string() - }).required(), - data: Joi.object().keys({ - handles: Joi.array().items(Joi.string()), - emails: Joi.array().items(Joi.string().email()) - }).or('handles', 'emails').required() -}).required() +addMembers.schema = Joi.object() + .keys({ + currentUser: Joi.object().required(), + id: Joi.number().integer().required(), + criteria: Joi.object() + .keys({ + fields: Joi.string() + }) + .required(), + data: Joi.object() + .keys({ + handles: Joi.array().items(Joi.string()), + emails: Joi.array().items(Joi.string().email()) + }) + .or('handles', 'emails') + .required() + }) + .required() /** * Search members in a team. @@ -480,14 +662,18 @@ async function searchMembers (currentUser, id, criteria) { return { result } } -searchMembers.schema = Joi.object().keys({ - currentUser: Joi.object().required(), - id: Joi.number().integer().required(), - criteria: Joi.object().keys({ - role: Joi.string(), - fields: Joi.string() - }).required() -}).required() +searchMembers.schema = Joi.object() + .keys({ + currentUser: Joi.object().required(), + id: Joi.number().integer().required(), + criteria: Joi.object() + .keys({ + role: Joi.string(), + fields: Joi.string() + }) + .required() + }) + .required() /** * Search member invites for a team. @@ -499,17 +685,25 @@ searchMembers.schema = Joi.object().keys({ * @returns {Object} the search result */ async function searchInvites (currentUser, id, criteria) { - const result = await helper.listProjectMemberInvites(currentUser, id, criteria) + const result = await helper.listProjectMemberInvites( + currentUser, + id, + criteria + ) return { result } } -searchInvites.schema = Joi.object().keys({ - currentUser: Joi.object().required(), - id: Joi.number().integer().required(), - criteria: Joi.object().keys({ - fields: Joi.string() - }).required() -}).required() +searchInvites.schema = Joi.object() + .keys({ + currentUser: Joi.object().required(), + id: Joi.number().integer().required(), + criteria: Joi.object() + .keys({ + fields: Joi.string() + }) + .required() + }) + .required() /** * Remove a member from a team. @@ -524,11 +718,13 @@ async function deleteMember (currentUser, id, projectMemberId) { await helper.deleteProjectMember(currentUser, id, projectMemberId) } -deleteMember.schema = Joi.object().keys({ - currentUser: Joi.object().required(), - id: Joi.number().integer().required(), - projectMemberId: Joi.number().integer().required() -}).required() +deleteMember.schema = Joi.object() + .keys({ + currentUser: Joi.object().required(), + id: Joi.number().integer().required(), + projectMemberId: Joi.number().integer().required() + }) + .required() /** * Return details about the current user. @@ -541,8 +737,387 @@ async function getMe (currentUser) { return helper.getUserByExternalId(currentUser.userId) } -getMe.schema = Joi.object().keys({ - currentUser: Joi.object().required() +getMe.schema = Joi.object() + .keys({ + currentUser: Joi.object().required() + }) + .required() + +/** + * Searches roles either by roleId or jobDescription or skills + * @param {Object} currentUser the user performing the operation. + * @param {Object} data search request data + * @returns {Object} the created project + */ +async function roleSearchRequest (currentUser, data) { + let role + // if roleId is provided then find role with given id. + if (!_.isUndefined(data.roleId)) { + role = await Role.findById(data.roleId) + role = role.toJSON() + // if skills is provided then use skills to find role + } else if (!_.isUndefined(data.skills)) { + // validate given skillIds and convert them into skill names + const skills = await getSkillNamesByIds(data.skills) + // find the best matching role + role = await getRoleBySkills(skills) + } else { + // if only job description is provided, collect skill names from description + const tags = await getSkillsByJobDescription(currentUser, { description: data.jobDescription }) + const skills = _.map(tags, 'tag') + // find the best matching role + role = await getRoleBySkills(skills) + } + data.roleId = role.id + // create roleSearchRequest entity with found roleId + const { id: roleSearchRequestId } = await createRoleSearchRequest(currentUser, data) + // clean Role + role = await _cleanRoleDTO(currentUser, role) + // return Role + return _.assign(role, { roleSearchRequestId }) +} + +roleSearchRequest.schema = Joi.object() + .keys({ + currentUser: Joi.object().required(), + data: Joi.object().keys({ + roleId: Joi.string().uuid(), + jobDescription: Joi.string().max(255), + skills: Joi.array().items(Joi.string().uuid().required()) + }).required().min(1) + }).required() + +/** + * Returns 1 role most relevant to the specified skills + * @param {Array} skills the array of skill names + * @returns {Role} the best matching Role + */ +async function getRoleBySkills (skills) { + // find all roles which includes any of the given skills + const queryCriteria = { + where: { listOfSkills: { [Op.overlap]: skills } }, + raw: true + } + const roles = await Role.findAll(queryCriteria) + if (roles.length > 0) { + let result = _.each(roles, role => { + // calculate each found roles matching rate + role.matchingRate = _.intersection(role.listOfSkills, skills).length / skills.length + // each role can have multiple rates, get the maximum of global rates + role.maxGlobal = _.maxBy(role.rates, 'global').global + }) + // sort roles by matchingRate, global rate and name + result = _.orderBy(result, ['matchingRate', 'maxGlobal', 'name'], ['desc', 'desc', 'asc']) + if (result[0].matchingRate >= config.ROLE_MATCHING_RATE) { + // return the 1st role + return _.omit(result[0], ['matchingRate', 'maxGlobal']) + } + } + // if no matching role found then return Niche role or empty object + return await Role.findOne({ where: { name: { [Op.iLike]: 'Niche' } } }) || {} +} + +getRoleBySkills.schema = Joi.object() + .keys({ + skills: Joi.array().items(Joi.string().required()).required() + }).required() + +/** + * Return skills by job description. + * + * @param {Object} currentUser the user who perform this operation. + * @param {Object} data the search criteria + * @returns {Object} the result + */ +async function getSkillsByJobDescription (currentUser, data) { + // load topcoder skills if needed. Using cached skills helps to avoid + // unnecessary api calls which is extremely time comsuming. + await _reloadCachedTopcoderSkills() + // replace markdown tags with spaces + const description = helper.removeTextFormatting(data.description) + // extract words from description + let words = _.split(description, ' ') + // remove stopwords from description + words = _.filter(words, word => stopWords.indexOf(word.toLowerCase()) === -1) + // include consecutive two word combinations + const twoWords = [] + for (let i = 0; i < words.length - 1; i++) { + twoWords.push(`${words[i]} ${words[i + 1]}`) + } + words = _.concat(words, twoWords) + let foundSkills = [] + const result = [] + // try to match each word with skill names + // using pre-compiled regex pattern + _.each(words, word => { + _.each(topcoderSkills.skills, skill => { + // do not stop searching after a match in order to detect more lookalikes + if (skill.pattern.test(word)) { + foundSkills.push(skill.name) + } + }) + }) + foundSkills = _.uniq(foundSkills) + // apply desired template + _.each(foundSkills, skill => { + result.push({ + tag: skill, + type: 'taas_skill', + source: 'taas-jd-parser' + }) + }) + + return result +} + +getSkillsByJobDescription.schema = Joi.object() + .keys({ + currentUser: Joi.object().required(), + data: Joi.object().keys({ + description: Joi.string().required() + }).required() + }).required() + +/** + * Validate given skillIds and return their names + * + * @param {Array} skills the array of skill ids + * @returns {Array} the array of skill names + */ +async function getSkillNamesByIds (skills) { + const responses = await Promise.all( + skills.map( + skill => helper.getSkillById(skill) + .then((skill) => { + return _.assign(skill, { found: true }) + }) + .catch(err => { + if (err.status !== HttpStatus.NOT_FOUND) { + throw err + } + return { found: false, skill } + }) + ) + ) + const errResponses = responses.filter(res => !res.found) + if (errResponses.length) { + throw new errors.BadRequestError(`Invalid skills: [${errResponses.map(res => res.skill)}]`) + } + return _.map(responses, 'name') +} + +getSkillNamesByIds.schema = Joi.object() + .keys({ + skills: Joi.array().items(Joi.string().uuid().required()).required() + }).required() + +/** + * Finds and returns the ids of given skill names + * + * @param {Array} skills the array of skill names + * @returns {Array} the array of skill ids + */ +async function getSkillIdsByNames (skills) { + const result = await helper.getAllTopcoderSkills({ name: _.join(skills, ',') }) + // endpoint returns the partial matched skills + // we need to filter by exact match case insensitive + const filteredSkills = _.filter(result, tcSkill => _.some(skills, skill => _.toLower(skill) === _.toLower(tcSkill.name))) + const skillIds = _.map(filteredSkills, 'id') + return skillIds +} + +getSkillIdsByNames.schema = Joi.object() + .keys({ + skills: Joi.array().items(Joi.string().required()).required() + }).required() + +/** + * Creates the role search request + * + * @param {Object} currentUser the user who perform this operation. + * @param {Object} roleSearchRequest the role search request + * @returns {RoleSearchRequest} the role search request entity + */ + +async function createRoleSearchRequest (currentUser, roleSearchRequest) { + roleSearchRequest.createdBy = await helper.getUserId(currentUser.userId) + // if current user is not machine then it must be logged user + if (!currentUser.isMachine) { + roleSearchRequest.memberId = roleSearchRequest.createdBy + // find the previous search done by this user + const previous = await RoleSearchRequest.findOne({ + where: { + memberId: roleSearchRequest.memberId + }, + order: [['createdAt', 'DESC']] + }) + if (previous) { + roleSearchRequest.previousRoleSearchRequestId = previous.id + } + } + const created = await RoleSearchRequest.create(roleSearchRequest) + return created.toJSON() +} +createRoleSearchRequest.schema = Joi.object() + .keys({ + currentUser: Joi.object().required(), + roleSearchRequest: Joi.object().keys({ + roleId: Joi.string().uuid(), + jobDescription: Joi.string().max(255), + skills: Joi.array().items(Joi.string().uuid().required()) + }).required().min(1) + }).required() + +/** + * Exclude some fields from role if the user is external member + * + * @param {Object} currentUser the user who perform this operation. + * @param {Object} role the role object to be cleaned + * @returns {Object} the cleaned role + */ +async function _cleanRoleDTO (currentUser, role) { + // if current user is machine, it means user is not logged in + if (currentUser.isMachine || await isExternalMember(currentUser.userId)) { + role.isExternalMember = true + if (role.rates) { + role.rates = _.map(role.rates, rate => + _.omit(rate, ['inCountry', 'offShore', 'rate30InCountry', 'rate30OffShore', 'rate20InCountry', 'rate20OffShore'])) + } + return role + } + role.isExternalMember = false + return role +} + +/** + * Finds out if member is external member + * + * @param {number} memberId the external id of member + * @returns {boolean} + */ +async function isExternalMember (memberId) { + const groups = await helper.getMemberGroups(memberId) + return _.intersection(config.INTERNAL_MEMBER_GROUPS, groups).length === 0 +} + +isExternalMember.schema = Joi.object() + .keys({ + memberId: Joi.number().required() + }).required() + +/** + * @param {Object} currentUser the user performing the operation. + * @param {Object} data the team data + * @returns {Object} the created project id + */ +async function createTeam (currentUser, data) { + // before creating a project, we should validate the given roleSearchRequestIds + // because if some data is missing it would fail to create jobs. + const roleSearchRequests = await _validateRoleSearchRequests(_.map(data.positions, 'roleSearchRequestId')) + const projectRequestBody = { + name: data.teamName, + description: data.teamDescription, + type: 'talent-as-a-service', + details: { + positions: data.positions + } + } + // create project with given data + const project = await helper.createProject(currentUser, projectRequestBody) + // create jobs for the given positions. + await Promise.all(_.map(data.positions, async position => { + const roleSearchRequest = roleSearchRequests[position.roleSearchRequestId] + const job = { + projectId: project.id, + title: position.roleName, + numPositions: position.numberOfResources, + rateType: position.rateType, + workload: position.workload, + skills: roleSearchRequest.skills, + description: roleSearchRequest.jobDescription, + roleIds: [roleSearchRequest.roleId], + resourceType: roleSearchRequest.resourceType + } + if (position.startMonth) { + job.startDate = position.startMonth + } + if (position.durationWeeks) { + job.duration = position.durationWeeks + } + await JobService.createJob(currentUser, job) + })) + return { projectId: project.id } +} + +createTeam.schema = Joi.object() + .keys({ + currentUser: Joi.object().required(), + data: Joi.object().keys({ + teamName: Joi.string().required(), + teamDescription: Joi.string(), + positions: Joi.array().items( + Joi.object().keys({ + roleName: Joi.string().required(), + roleSearchRequestId: Joi.string().uuid().required(), + numberOfResources: Joi.number().integer().min(1).required(), + durationWeeks: Joi.number().integer().min(1), + startMonth: Joi.date(), + rateType: Joi.rateType().default('weekly'), + workload: Joi.workload().default('full-time'), + resourceType: Joi.string() + }).required() + ).required() + }).required() + }) + .required() + +/** + * @param {Array} roleSearchRequestIds the roleSearchRequestIds + * @returns {Object} the roleSearchRequests + */ +async function _validateRoleSearchRequests (roleSearchRequestIds) { + const roleSearchRequests = {} + await Promise.all(_.map(roleSearchRequestIds, async roleSearchRequestId => { + // check if roleSearchRequest exists + const roleSearchRequest = await RoleSearchRequest.findById(roleSearchRequestId) + // store the found roleSearchRequest to avoid unnecessary DB calls + roleSearchRequests[roleSearchRequestId] = roleSearchRequest.toJSON() + // we can't create a job without a role + if (!roleSearchRequest.roleId) { + throw new errors.ConflictError(`roleSearchRequestId: ${roleSearchRequestId} must have roleId`) + } + const role = await Role.findById(roleSearchRequest.roleId) + // if roleSearchRequest doesn't have skills, we have to get skills through role + if (!roleSearchRequest.skills) { + if (!role.listOfSkills) { + throw new errors.ConflictError(`role: ${role.id} must have skills`) + } + // store role's skills + roleSearchRequests[roleSearchRequestId].skills = await getSkillIdsByNames(role.listOfSkills) + } + if (!roleSearchRequest.jobDescription) { + roleSearchRequests[roleSearchRequestId].jobDescription = role.description + } + roleSearchRequests[roleSearchRequestId].resourceType = role.name + })) + return roleSearchRequests +} + +/** + * Search skills + * @param {Object} criteria the search criteria + * @returns {Object} the search result, contain total/page/perPage and result array + */ +async function searchSkills (criteria) { + return helper.getTopcoderSkills(criteria) +} + +searchSkills.schema = Joi.object().keys({ + criteria: Joi.object().keys({ + page: Joi.page(), + perPage: Joi.perPage(), + orderBy: Joi.string() + }).required() }).required() module.exports = { @@ -554,5 +1129,14 @@ module.exports = { searchMembers, searchInvites, deleteMember, - getMe + getMe, + roleSearchRequest, + getRoleBySkills, + getSkillsByJobDescription, + getSkillNamesByIds, + getSkillIdsByNames, + createRoleSearchRequest, + isExternalMember, + createTeam, + searchSkills } diff --git a/src/services/WorkPeriodPaymentService.js b/src/services/WorkPeriodPaymentService.js index e8694c76..576d934d 100644 --- a/src/services/WorkPeriodPaymentService.js +++ b/src/services/WorkPeriodPaymentService.js @@ -3,20 +3,20 @@ */ const _ = require('lodash') -const Joi = require('joi') +const Joi = require('joi').extend(require('@joi/date')) const config = require('config') const HttpStatus = require('http-status-codes') const { Op } = require('sequelize') const uuid = require('uuid') -const moment = require('moment') const helper = require('../common/helper') const logger = require('../common/logger') const errors = require('../common/errors') -const constants = require('../../app-constants') const models = require('../models') -const PaymentService = require('./PaymentService') +const { WorkPeriodPaymentStatus } = require('../../app-constants') +const { searchResourceBookings } = require('./ResourceBookingService') const WorkPeriodPayment = models.WorkPeriodPayment +const WorkPeriod = models.WorkPeriod const esClient = helper.getESClient() /** @@ -26,12 +26,66 @@ const esClient = helper.getESClient() * @param {Object} currentUser the user who perform this operation. * @returns {undefined} */ -async function _checkUserPermissionForCRUWorkPeriodPayment (currentUser) { +function _checkUserPermissionForCRUWorkPeriodPayment (currentUser) { if (!currentUser.hasManagePermission && !currentUser.isMachine) { throw new errors.ForbiddenError('You are not allowed to perform this action!') } } +/** + * Create single workPeriodPayment + * @param {Object} workPeriodPayment the workPeriodPayment to be created + * @param {String} createdBy the authUser id + * @returns {Object} the created workPeriodPayment + */ +async function _createSingleWorkPeriodPayment (workPeriodPayment, createdBy) { + const correspondingWorkPeriod = await helper.ensureWorkPeriodById(workPeriodPayment.workPeriodId) // ensure work period exists + + // get billingAccountId from corresponding resource booking + const correspondingResourceBooking = await helper.ensureResourceBookingById(correspondingWorkPeriod.resourceBookingId) + + return _createSingleWorkPeriodPaymentWithWorkPeriodAndResourceBooking(workPeriodPayment, createdBy, correspondingWorkPeriod.toJSON(), correspondingResourceBooking.toJSON()) +} + +/** + * Create single workPeriodPayment + * @param {Object} workPeriodPayment the workPeriodPayment to be created + * @param {String} createdBy the authUser id + * @param {Object} correspondingWorkPeriod the workPeriod + * @param {Object} correspondingResourceBooking the resourceBooking + * @returns {Object} the created workPeriodPayment + */ +async function _createSingleWorkPeriodPaymentWithWorkPeriodAndResourceBooking (workPeriodPayment, createdBy, correspondingWorkPeriod, correspondingResourceBooking) { + if (_.isNil(correspondingResourceBooking.billingAccountId)) { + throw new errors.ConflictError(`id: ${correspondingResourceBooking.id} "ResourceBooking" Billing account is not assigned to the resource booking`) + } + workPeriodPayment.billingAccountId = correspondingResourceBooking.billingAccountId + if (_.isNil(correspondingResourceBooking.memberRate)) { + throw new errors.ConflictError(`Can't find a member rate in ResourceBooking: ${correspondingResourceBooking.id} to calculate the amount`) + } + if (correspondingResourceBooking.memberRate <= 0) { + throw new errors.ConflictError(`Can't process payment with member rate: ${correspondingResourceBooking.memberRate}. It must be higher than 0`) + } + workPeriodPayment.memberRate = correspondingResourceBooking.memberRate + const maxPossibleDays = correspondingWorkPeriod.daysWorked - correspondingWorkPeriod.daysPaid + if (workPeriodPayment.days > maxPossibleDays) { + throw new errors.BadRequestError(`Days cannot be more than not paid days which is ${maxPossibleDays}`) + } + if (maxPossibleDays <= 0) { + throw new errors.ConflictError(`There are no days to pay for WorkPeriod: ${correspondingWorkPeriod.id}`) + } + workPeriodPayment.days = _.defaultTo(workPeriodPayment.days, maxPossibleDays) + workPeriodPayment.amount = _.round(workPeriodPayment.memberRate * workPeriodPayment.days / 5, 2) + workPeriodPayment.customerRate = _.defaultTo(correspondingResourceBooking.customerRate, null) + workPeriodPayment.id = uuid.v4() + workPeriodPayment.status = WorkPeriodPaymentStatus.SCHEDULED + workPeriodPayment.createdBy = createdBy + + const created = await WorkPeriodPayment.create(workPeriodPayment) + await helper.postEvent(config.TAAS_WORK_PERIOD_PAYMENT_CREATE_TOPIC, created.toJSON(), { key: `workPeriodPayment.billingAccountId:${workPeriodPayment.billingAccountId}` }) + return created.dataValues +} + /** * Get workPeriodPayment by id * @param {Object} currentUser the user who perform this operation. @@ -41,28 +95,39 @@ async function _checkUserPermissionForCRUWorkPeriodPayment (currentUser) { */ async function getWorkPeriodPayment (currentUser, id, fromDb = false) { // check user permission - await _checkUserPermissionForCRUWorkPeriodPayment(currentUser) + _checkUserPermissionForCRUWorkPeriodPayment(currentUser) if (!fromDb) { try { - const workPeriod = await esClient.search({ - index: config.esConfig.ES_INDEX_WORK_PERIOD, - _source: 'payments', + const resourceBooking = await esClient.search({ + index: config.esConfig.ES_INDEX_RESOURCE_BOOKING, + _source: 'workPeriods.payments', body: { query: { nested: { - path: 'payments', + path: 'workPeriods.payments', query: { - match: { 'payments.id': id } + match: { 'workPeriods.payments.id': id } } } } } }) - if (!workPeriod.body.hits.total.value) { + if (!resourceBooking.body.hits.total.value) { throw new errors.NotFoundError() } - const workPeriodPaymentRecord = _.find(workPeriod.body.hits.hits[0]._source.payments, { id }) + let workPeriodPaymentRecord = null + _.forEach(resourceBooking.body.hits.hits[0]._source.workPeriods, wp => { + _.forEach(wp.payments, p => { + if (p.id === id) { + workPeriodPaymentRecord = p + return false + } + }) + if (workPeriodPaymentRecord) { + return false + } + }) return workPeriodPaymentRecord } catch (err) { if (err.httpStatus === HttpStatus.NOT_FOUND) { @@ -90,58 +155,39 @@ getWorkPeriodPayment.schema = Joi.object().keys({ * Create workPeriodPayment * @param {Object} currentUser the user who perform this operation * @param {Object} workPeriodPayment the workPeriodPayment to be created - * @param {Object} options the extra options to control the function * @returns {Object} the created workPeriodPayment */ -async function createWorkPeriodPayment (currentUser, workPeriodPayment, options = { paymentProcessingSwitch: 'OFF' }) { +async function createWorkPeriodPayment (currentUser, workPeriodPayment) { // check permission - await _checkUserPermissionForCRUWorkPeriodPayment(currentUser) - - const { projectId, userHandle, endDate, resourceBookingId } = await helper.ensureWorkPeriodById(workPeriodPayment.workPeriodId) // ensure work period exists - - // get billingAccountId from corresponding resource booking - const correspondingResourceBooking = await helper.ensureResourceBookingById(resourceBookingId) - if (!correspondingResourceBooking.billingAccountId) { - throw new errors.ConflictError(`id: ${resourceBookingId} "ResourceBooking" Billing account is not assigned to the resource booking`) - } - workPeriodPayment.billingAccountId = correspondingResourceBooking.billingAccountId - - const paymentChallenge = options.paymentProcessingSwitch === constants.PaymentProcessingSwitch.ON ? (await PaymentService.createPayment({ - projectId, - userHandle, - amount: workPeriodPayment.amount, - name: `TaaS Payment - ${userHandle} - Week Ending ${moment(endDate).format('D/M/YYYY')}`, - description: `TaaS Payment - ${userHandle} - Week Ending ${moment(endDate).format('D/M/YYYY')}`, - billingAccountId: correspondingResourceBooking.billingAccountId - })) : ({ id: '00000000-0000-0000-0000-000000000000' }) + _checkUserPermissionForCRUWorkPeriodPayment(currentUser) + const createdBy = await helper.getUserId(currentUser.userId) - workPeriodPayment.id = uuid.v4() - workPeriodPayment.challengeId = paymentChallenge.id - workPeriodPayment.createdBy = await helper.getUserId(currentUser.userId) - - let created = null - try { - created = await WorkPeriodPayment.create(workPeriodPayment) - } catch (err) { - if (!_.isUndefined(err.original)) { - throw new errors.BadRequestError(err.original.detail) - } else { - throw err + if (_.isArray(workPeriodPayment)) { + const result = [] + for (const wp of workPeriodPayment) { + try { + const successResult = await _createSingleWorkPeriodPayment(wp, createdBy) + result.push(successResult) + } catch (e) { + result.push(_.extend(_.pick(wp, 'workPeriodId'), { error: { message: e.message, code: e.httpStatus } })) + } } + return result + } else { + return await _createSingleWorkPeriodPayment(workPeriodPayment, createdBy) } - - await helper.postEvent(config.TAAS_WORK_PERIOD_PAYMENT_CREATE_TOPIC, created.toJSON()) - return created.dataValues } +const singleCreateWorkPeriodPaymentSchema = Joi.object().keys({ + workPeriodId: Joi.string().uuid().required(), + days: Joi.number().integer().min(1).max(5) +}) createWorkPeriodPayment.schema = Joi.object().keys({ currentUser: Joi.object().required(), - workPeriodPayment: Joi.object().keys({ - workPeriodId: Joi.string().uuid().required(), - amount: Joi.number().greater(0).allow(null), - status: Joi.workPeriodPaymentStatus().default('completed') - }).required(), - options: Joi.object() + workPeriodPayment: Joi.alternatives().try( + singleCreateWorkPeriodPaymentSchema.required(), + Joi.array().min(1).items(singleCreateWorkPeriodPaymentSchema).required() + ).required() }).required() /** @@ -153,28 +199,27 @@ createWorkPeriodPayment.schema = Joi.object().keys({ */ async function updateWorkPeriodPayment (currentUser, id, data) { // check permission - await _checkUserPermissionForCRUWorkPeriodPayment(currentUser) + _checkUserPermissionForCRUWorkPeriodPayment(currentUser) - if (data.workPeriodId) { - // ensure work period exists - await helper.ensureWorkPeriodById(data.workPeriodId) - } const workPeriodPayment = await WorkPeriodPayment.findById(id) const oldValue = workPeriodPayment.toJSON() - - data.updatedBy = await helper.getUserId(currentUser.userId) - let updated = null - try { - updated = await workPeriodPayment.update(data) - } catch (err) { - if (!_.isUndefined(err.original)) { - throw new errors.BadRequestError(err.original.detail) - } else { - throw err + if (data.status === 'cancelled' && oldValue.status === 'in-progress') { + throw new errors.BadRequestError('You cannot cancel a WorkPeriodPayment which is in-progress') + } + if (data.status === 'scheduled') { + if (oldValue.status !== 'failed') { + throw new errors.BadRequestError(`You cannot schedule a WorkPeriodPayment which is ${oldValue.status}`) + } + const workPeriod = WorkPeriod.findById(workPeriodPayment.workPeriodId) + // we con't check if paymentStatus is 'completed' + // because paymentStatus can be in-progress when daysWorked = daysPaid + if (workPeriod.daysWorked === workPeriod.daysPaid) { + throw new errors.BadRequestError('There is no available daysWorked to schedule a payment') } } - - await helper.postEvent(config.TAAS_WORK_PERIOD_PAYMENT_UPDATE_TOPIC, updated.toJSON(), { oldValue: oldValue }) + data.updatedBy = await helper.getUserId(currentUser.userId) + const updated = await workPeriodPayment.update(data) + await helper.postEvent(config.TAAS_WORK_PERIOD_PAYMENT_UPDATE_TOPIC, updated.toJSON(), { oldValue: oldValue, key: `workPeriodPayment.billingAccountId:${updated.billingAccountId}` }) return updated.dataValues } @@ -193,31 +238,8 @@ partiallyUpdateWorkPeriodPayment.schema = Joi.object().keys({ currentUser: Joi.object().required(), id: Joi.string().uuid().required(), data: Joi.object().keys({ - workPeriodId: Joi.string().uuid(), - amount: Joi.number().greater(0).allow(null), - status: Joi.workPeriodPaymentStatus() - }).required() -}).required() - -/** - * Fully update workPeriodPayment by id - * @param {Object} currentUser the user who perform this operation - * @param {String} id the workPeriodPayment id - * @param {Object} data the data to be updated - * @returns {Object} the updated workPeriodPayment - */ -async function fullyUpdateWorkPeriodPayment (currentUser, id, data) { - return updateWorkPeriodPayment(currentUser, id, data) -} - -fullyUpdateWorkPeriodPayment.schema = Joi.object().keys({ - currentUser: Joi.object().required(), - id: Joi.string().uuid().required(), - data: Joi.object().keys({ - workPeriodId: Joi.string().uuid().required(), - amount: Joi.number().greater(0).allow(null), - status: Joi.workPeriodPaymentStatus() - }).required() + status: Joi.workPeriodPaymentUpdateStatus() + }).min(1).required() }).required() /** @@ -229,7 +251,7 @@ fullyUpdateWorkPeriodPayment.schema = Joi.object().keys({ */ async function searchWorkPeriodPayments (currentUser, criteria, options = { returnAll: false }) { // check user permission - await _checkUserPermissionForCRUWorkPeriodPayment(currentUser) + _checkUserPermissionForCRUWorkPeriodPayment(currentUser) if ((typeof criteria.workPeriodIds) === 'string') { criteria.workPeriodIds = criteria.workPeriodIds.trim().split(',').map(workPeriodIdRaw => { @@ -244,12 +266,12 @@ async function searchWorkPeriodPayments (currentUser, criteria, options = { retu const perPage = criteria.perPage try { const esQuery = { - index: config.get('esConfig.ES_INDEX_WORK_PERIOD'), - _source: 'payments', + index: config.get('esConfig.ES_INDEX_RESOURCE_BOOKING'), + _source: 'workPeriods.payments', body: { query: { nested: { - path: 'payments', + path: 'workPeriods.payments', query: { bool: { must: [] } } } }, @@ -263,7 +285,7 @@ async function searchWorkPeriodPayments (currentUser, criteria, options = { retu _.each(_.pick(criteria, ['status', 'workPeriodId']), (value, key) => { esQuery.body.query.nested.query.bool.must.push({ term: { - [`payments.${key}`]: { + [`workPeriods.payments.${key}`]: { value } } @@ -272,14 +294,20 @@ async function searchWorkPeriodPayments (currentUser, criteria, options = { retu if (criteria.workPeriodIds) { esQuery.body.query.nested.query.bool.filter = [{ terms: { - 'payments.workPeriodId': criteria.workPeriodIds + 'workPeriods.payments.workPeriodId': criteria.workPeriodIds } }] } logger.debug({ component: 'WorkPeriodPaymentService', context: 'searchWorkPeriodPayment', message: `Query: ${JSON.stringify(esQuery)}` }) const { body } = await esClient.search(esQuery) - let payments = _.reduce(body.hits.hits, (acc, workPeriod) => _.concat(acc, workPeriod._source.payments), []) + const workPeriods = _.reduce(body.hits.hits, (acc, resourceBooking) => _.concat(acc, resourceBooking._source.workPeriods), []) + let payments = _.reduce(workPeriods, (acc, workPeriod) => _.concat(acc, workPeriod.payments), []) + if (criteria.workPeriodId) { + payments = _.filter(payments, { workPeriodId: criteria.workPeriodId }) + } else if (criteria.workPeriodIds) { + payments = _.filter(payments, p => _.includes(criteria.workPeriodIds, p.workPeriodId)) + } if (criteria.status) { payments = _.filter(payments, { status: criteria.status }) } @@ -315,14 +343,13 @@ async function searchWorkPeriodPayments (currentUser, criteria, options = { retu limit: perPage, order: [[criteria.sortBy, criteria.sortOrder]] }) + const total = await WorkPeriodPayment.count({ where: filter }) return { fromDb: true, - total: workPeriodPayments.length, + total, page, perPage, - result: _.map(workPeriodPayments, workPeriodPayment => { - return workPeriodPayment.dataValues - }) + result: workPeriodPayments } } @@ -343,10 +370,72 @@ searchWorkPeriodPayments.schema = Joi.object().keys({ options: Joi.object() }).required() +/** + * Create all query workPeriodPayments + * @param {Object} currentUser the user who perform this operation. + * @param {Object} criteria the query criteria + * @returns {Object} the process result + */ +async function createQueryWorkPeriodPayments (currentUser, criteria) { + // check permission + _checkUserPermissionForCRUWorkPeriodPayment(currentUser) + const createdBy = await helper.getUserId(currentUser.userId) + const query = criteria.query + if ((typeof query['workPeriods.paymentStatus']) === 'string') { + query['workPeriods.paymentStatus'] = query['workPeriods.paymentStatus'].trim().split(',').map(ps => Joi.attempt({ paymentStatus: ps.trim() }, Joi.object().keys({ paymentStatus: Joi.paymentStatus() })).paymentStatus) + } + const fields = _.join(_.uniq(_.concat( + ['id', 'billingAccountId', 'memberRate', 'customerRate', 'workPeriods.id', 'workPeriods.resourceBookingId', 'workPeriods.daysWorked', 'workPeriods.daysPaid'], + _.map(_.keys(query), k => k === 'projectIds' ? 'projectId' : k)) + ), ',') + const searchResult = await searchResourceBookings(currentUser, _.extend({ fields, page: 1 }, query), { returnAll: true }) + + const wpArray = _.flatMap(searchResult.result, 'workPeriods') + const resourceBookingMap = _.fromPairs(_.map(searchResult.result, rb => [rb.id, rb])) + const result = { total: wpArray.length, query, totalSuccess: 0, totalError: 0 } + + for (const wp of wpArray) { + try { + await _createSingleWorkPeriodPaymentWithWorkPeriodAndResourceBooking({ workPeriodId: wp.id }, createdBy, wp, resourceBookingMap[wp.resourceBookingId]) + result.totalSuccess++ + } catch (err) { + logger.logFullError(err, { component: 'WorkPeriodPaymentService', context: 'createQueryWorkPeriodPayments' }) + result.totalError++ + } + } + return result +} + +createQueryWorkPeriodPayments.schema = Joi.object().keys({ + currentUser: Joi.object().required(), + criteria: Joi.object().keys({ + query: Joi.object().keys({ + status: Joi.resourceBookingStatus(), + startDate: Joi.date().format('YYYY-MM-DD'), + endDate: Joi.date().format('YYYY-MM-DD'), + rateType: Joi.rateType(), + jobId: Joi.string().uuid(), + userId: Joi.string().uuid(), + projectId: Joi.number().integer(), + projectIds: Joi.alternatives( + Joi.string(), + Joi.array().items(Joi.number().integer()) + ), + 'workPeriods.paymentStatus': Joi.alternatives( + Joi.string(), + Joi.array().items(Joi.string().valid(Joi.paymentStatus())) + ), + 'workPeriods.startDate': Joi.date().format('YYYY-MM-DD'), + 'workPeriods.endDate': Joi.date().format('YYYY-MM-DD'), + 'workPeriods.userHandle': Joi.string() + }).required() + }).required() +}).required() + module.exports = { getWorkPeriodPayment, createWorkPeriodPayment, + createQueryWorkPeriodPayments, partiallyUpdateWorkPeriodPayment, - fullyUpdateWorkPeriodPayment, searchWorkPeriodPayments } diff --git a/src/services/WorkPeriodService.js b/src/services/WorkPeriodService.js index 92e1deb0..8d018fb0 100644 --- a/src/services/WorkPeriodService.js +++ b/src/services/WorkPeriodService.js @@ -83,16 +83,27 @@ function _checkUserScopesForGetPayments (currentUser) { } /** - * filter fields of work period by user role. + * Get which fields to be excluded from result * @param {Object} currentUser the user who perform this operation. - * @param {Object} workPeriod the workPeriod with all fields - * @returns {Object} the workPeriod + * @returns {Object} queryOpt + * @returns {Object} queryOpt.excludeES excluded fields for ES query + * @returns {Object} queryOpt.excludeDB excluded fields for DB query + * @returns {Object} queryOpt.withPayments is payments field included? */ -async function _getWorkPeriodFilteringFields (currentUser, workPeriod) { - if (currentUser.hasManagePermission || _checkUserScopesForGetPayments(currentUser)) { - return workPeriod +function _getWorkPeriodFilteringFields (currentUser) { + const queryOpt = { + excludeES: [], + excludeDB: [], + withPayments: false + } + if (!currentUser.hasManagePermission && !currentUser.isMachine) { + queryOpt.excludeES.push('workPeriods.paymentTotal') + queryOpt.excludeDB.push('paymentTotal') } - return _.omit(workPeriod, ['memberRate', 'payments']) + if (currentUser.hasManagePermission || _checkUserScopesForGetPayments(currentUser)) { + queryOpt.withPayments = true + } else { queryOpt.excludeES.push('workPeriods.payments') } + return queryOpt } /** @@ -144,33 +155,46 @@ function _autoCalculateDates (data) { * @returns {Object} the workPeriod */ async function getWorkPeriod (currentUser, id, fromDb = false) { + // get query options according to currentUser + const queryOpt = _getWorkPeriodFilteringFields(currentUser) if (!fromDb) { try { - const workPeriod = await esClient.get({ - index: config.esConfig.ES_INDEX_WORK_PERIOD, - id + const resourceBooking = await esClient.search({ + index: config.esConfig.ES_INDEX_RESOURCE_BOOKING, + _source_includes: 'workPeriods', + _source_excludes: queryOpt.excludeES, + body: { + query: { + nested: { + path: 'workPeriods', + query: { + match: { 'workPeriods.id': id } + } + } + } + } }) - - await _checkUserPermissionForGetWorkPeriod(currentUser, workPeriod.body._source.projectId) // check user permission - - const workPeriodRecord = { id: workPeriod.body._id, ...workPeriod.body._source } - return _getWorkPeriodFilteringFields(currentUser, workPeriodRecord) + if (!resourceBooking.body.hits.total.value) { + throw new errors.NotFoundError() + } + const workPeriod = _.find(resourceBooking.body.hits.hits[0]._source.workPeriods, { id }) + await _checkUserPermissionForGetWorkPeriod(currentUser, workPeriod.projectId) // check user permission + return workPeriod } catch (err) { if (helper.isDocumentMissingException(err)) { throw new errors.NotFoundError(`id: ${id} "WorkPeriod" not found`) } - if (err.httpStatus === HttpStatus.FORBIDDEN) { + if (err.httpStatus === HttpStatus.UNAUTHORIZED) { throw err } logger.logFullError(err, { component: 'WorkPeriodService', context: 'getWorkPeriod' }) } } logger.info({ component: 'WorkPeriodService', context: 'getWorkPeriod', message: 'try to query db for data' }) - const workPeriod = await WorkPeriod.findById(id, { withPayments: true }) + const workPeriod = await WorkPeriod.findById(id, { withPayments: queryOpt.withPayments, exclude: queryOpt.excludeDB }) await _checkUserPermissionForGetWorkPeriod(currentUser, workPeriod.projectId) // check user permission - // We should only return "memberRate" to Booking Manager, Administrator or M2M - return _getWorkPeriodFilteringFields(currentUser, workPeriod.dataValues) + return workPeriod.dataValues } getWorkPeriod.schema = Joi.object().keys({ @@ -181,13 +205,10 @@ getWorkPeriod.schema = Joi.object().keys({ /** * Create workPeriod - * @param {Object} currentUser the user who perform this operation * @param {Object} workPeriod the workPeriod to be created * @returns {Object} the created workPeriod */ -async function createWorkPeriod (currentUser, workPeriod) { - // check permission - await _checkUserPermissionForWriteWorkPeriod(currentUser) +async function createWorkPeriod (workPeriod) { // If one of the dates are missing then auto-calculate it _autoCalculateDates(workPeriod) @@ -198,7 +219,7 @@ async function createWorkPeriod (currentUser, workPeriod) { workPeriod.userHandle = user.handle workPeriod.id = uuid.v4() - workPeriod.createdBy = await helper.getUserId(currentUser.userId) + workPeriod.createdBy = config.m2m.M2M_AUDIT_USER_ID let created = null try { @@ -211,19 +232,18 @@ async function createWorkPeriod (currentUser, workPeriod) { } } - await helper.postEvent(config.TAAS_WORK_PERIOD_CREATE_TOPIC, created.toJSON()) + await helper.postEvent(config.TAAS_WORK_PERIOD_CREATE_TOPIC, created.toJSON(), { key: `resourceBooking.id:${workPeriod.resourceBookingId}` }) return created.dataValues } createWorkPeriod.schema = Joi.object().keys({ - currentUser: Joi.object().required(), workPeriod: Joi.object().keys({ resourceBookingId: Joi.string().uuid().required(), startDate: Joi.workPeriodStartDate(), endDate: Joi.workPeriodEndDate(), - daysWorked: Joi.number().integer().min(0).allow(null), - memberRate: Joi.number().allow(null), - customerRate: Joi.number().allow(null), + daysWorked: Joi.number().integer().min(0).max(5).required(), + daysPaid: Joi.number().default(0).forbidden(), + paymentTotal: Joi.number().default(0).forbidden(), paymentStatus: Joi.paymentStatus().required() }).required() }).required() @@ -239,34 +259,30 @@ async function updateWorkPeriod (currentUser, id, data) { // check permission await _checkUserPermissionForWriteWorkPeriod(currentUser) - const workPeriod = await WorkPeriod.findById(id) + const workPeriod = await WorkPeriod.findById(id, { withPayments: true }) const oldValue = workPeriod.toJSON() - - // if resourceBookingId is provided then update projectId and userHandle - if (data.resourceBookingId) { - const resourceBooking = await helper.ensureResourceBookingById(data.resourceBookingId) // ensure resource booking exists - data.projectId = resourceBooking.projectId - - const user = await helper.ensureUserById(resourceBooking.userId) // ensure user exists - data.userHandle = user.handle + if (data.daysWorked < oldValue.daysPaid) { + throw new errors.BadRequestError(`Cannot update daysWorked (${data.daysWorked}) to the value less than daysPaid (${oldValue.daysPaid})`) } - // If one of the dates are missing then auto-calculate it - _autoCalculateDates(data) - - data.updatedBy = await helper.getUserId(currentUser.userId) - let updated = null - try { - updated = await workPeriod.update(data) - } catch (err) { - if (!_.isUndefined(err.original)) { - throw new errors.BadRequestError(err.original.detail) - } else { - throw err - } + const resourceBooking = await helper.ensureResourceBookingById(oldValue.resourceBookingId) + const weeks = helper.extractWorkPeriods(resourceBooking.startDate, resourceBooking.endDate) + if (_.isEmpty(weeks)) { + throw new errors.ConflictError('Resource booking has missing dates') } - - await helper.postEvent(config.TAAS_WORK_PERIOD_UPDATE_TOPIC, updated.toJSON(), { oldValue: oldValue }) - return updated.dataValues + const thisWeek = _.find(weeks, ['startDate', oldValue.startDate]) + if (_.isNil(thisWeek)) { + throw new errors.ConflictError('Work Period dates are not compatible with Resource Booking dates') + } + if (thisWeek.daysWorked < data.daysWorked) { + throw new errors.BadRequestError(`Maximum allowed daysWorked is (${thisWeek.daysWorked})`) + } + data.paymentStatus = helper.calculateWorkPeriodPaymentStatus(_.assign({}, oldValue, data)) + data.updatedBy = await helper.getUserId(currentUser.userId) + const updated = await workPeriod.update(data) + const updatedDataWithoutPayments = _.omit(updated.toJSON(), ['payments']) + const oldValueWithoutPayments = _.omit(oldValue, ['payments']) + await helper.postEvent(config.TAAS_WORK_PERIOD_UPDATE_TOPIC, updatedDataWithoutPayments, { oldValue: oldValueWithoutPayments, key: `resourceBooking.id:${updated.resourceBookingId}` }) + return updatedDataWithoutPayments } /** @@ -284,68 +300,29 @@ partiallyUpdateWorkPeriod.schema = Joi.object().keys({ currentUser: Joi.object().required(), id: Joi.string().uuid().required(), data: Joi.object().keys({ - resourceBookingId: Joi.string().uuid(), - startDate: Joi.workPeriodStartDate(), - endDate: Joi.workPeriodEndDateOptional(), - daysWorked: Joi.number().integer().min(0).allow(null), - memberRate: Joi.number().allow(null), - customerRate: Joi.number().allow(null), - paymentStatus: Joi.paymentStatus() - }).required() -}).required() - -/** - * Fully update workPeriod by id - * @param {Object} currentUser the user who perform this operation - * @param {String} id the workPeriod id - * @param {Object} data the data to be updated - * @returns {Object} the updated workPeriod - */ -async function fullyUpdateWorkPeriod (currentUser, id, data) { - return updateWorkPeriod(currentUser, id, data) -} - -fullyUpdateWorkPeriod.schema = Joi.object().keys({ - currentUser: Joi.object().required(), - id: Joi.string().uuid().required(), - data: Joi.object().keys({ - resourceBookingId: Joi.string().uuid().required(), - startDate: Joi.workPeriodStartDate(), - endDate: Joi.workPeriodEndDate(), - daysWorked: Joi.number().integer().min(0).allow(null).default(null), - memberRate: Joi.number().allow(null).default(null), - customerRate: Joi.number().allow(null).default(null), - paymentStatus: Joi.paymentStatus().required() - }).required() + daysWorked: Joi.number().integer().min(0).max(5) + }).required().min(1) }).required() /** * Delete workPeriod by id - * @params {Object} currentUser the user who perform this operation - * @params {String} id the workPeriod id + * @param {String} id the workPeriod id */ -async function deleteWorkPeriod (currentUser, id) { - // check permission - if (!currentUser.hasManagePermission && !currentUser.isMachine) { - throw new errors.ForbiddenError('You are not allowed to perform this action!') - } - +async function deleteWorkPeriod (id) { const workPeriod = await WorkPeriod.findById(id, { withPayments: true }) - if (_.includes(['completed', 'partially-completed'], workPeriod.paymentStatus)) { - throw new errors.BadRequestError("Can't delete WorkPeriod with paymentStatus completed or partially-completed") + if (_.some(workPeriod.payments, payment => constants.ActiveWorkPeriodPaymentStatuses.indexOf(payment.status) !== -1)) { + throw new errors.BadRequestError(`Can't delete WorkPeriod as it has associated WorkPeriodsPayment with one of statuses ${constants.ActiveWorkPeriodPaymentStatuses.join(', ')}`) } await models.WorkPeriodPayment.destroy({ where: { workPeriodId: id } }) - await Promise.all(workPeriod.payments.map(({ id }) => helper.postEvent(config.TAAS_WORK_PERIOD_PAYMENT_DELETE_TOPIC, { id }))) await workPeriod.destroy() - await helper.postEvent(config.TAAS_WORK_PERIOD_DELETE_TOPIC, { id }) + await helper.postEvent(config.TAAS_WORK_PERIOD_DELETE_TOPIC, { id }, { key: `resourceBooking.id:${workPeriod.resourceBookingId}` }) } deleteWorkPeriod.schema = Joi.object().keys({ - currentUser: Joi.object().required(), id: Joi.string().uuid().required() }).required() @@ -364,7 +341,7 @@ async function searchWorkPeriods (currentUser, criteria, options = { returnAll: } await helper.checkIsMemberOfProject(currentUser.userId, criteria.projectId) } - + const queryOpt = _getWorkPeriodFilteringFields(currentUser) // `criteria.resourceBookingIds` could be array of ids, or comma separated string of ids // in case it's comma separated string of ids we have to convert it to an array of ids if ((typeof criteria.resourceBookingIds) === 'string') { @@ -376,18 +353,13 @@ async function searchWorkPeriods (currentUser, criteria, options = { returnAll: return resourceBookingId }) } - const page = criteria.page - let perPage - if (options.returnAll) { - // To simplify the logic we are use a very large number for perPage - // because in practice there could hardly be so many records to be returned.(also consider we are using filters in the meantime) - // the number is limited by `index.max_result_window`, its default value is 10000, see - // https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules.html#index-max-result-window - perPage = 10000 - } else { - perPage = criteria.perPage + // `criteria.paymentStatus` could be array of paymentStatus, or comma separated string of paymentStatus + // in case it's comma separated string of paymentStatus we have to convert it to an array of paymentStatus + if ((typeof criteria.paymentStatus) === 'string') { + criteria.paymentStatus = criteria.paymentStatus.trim().split(',').map(ps => Joi.attempt({ paymentStatus: ps.trim() }, Joi.object().keys({ paymentStatus: Joi.paymentStatus() })).paymentStatus) } - + const page = criteria.page + const perPage = criteria.perPage if (!criteria.sortBy) { criteria.sortBy = 'id' } @@ -395,19 +367,22 @@ async function searchWorkPeriods (currentUser, criteria, options = { returnAll: criteria.sortOrder = 'desc' } try { - const sort = [{ [criteria.sortBy === 'id' ? '_id' : criteria.sortBy]: { order: criteria.sortOrder } }] - const esQuery = { - index: config.get('esConfig.ES_INDEX_WORK_PERIOD'), + index: config.get('esConfig.ES_INDEX_RESOURCE_BOOKING'), + _source_includes: 'workPeriods', + _source_excludes: queryOpt.excludeES, body: { query: { - bool: { - must: [] + nested: { + path: 'workPeriods', + query: { bool: { must: [] } } } }, - from: (page - 1) * perPage, - size: perPage, - sort + size: 10000 + // We use a very large number for size, because we can't paginate nested documents + // and in practice there could hardly be so many records to be returned.(also consider we are using filters in the meantime) + // the number is limited by `index.max_result_window`, its default value is 10000, see + // https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules.html#index-max-result-window } } // change the date format to match with database model @@ -417,41 +392,56 @@ async function searchWorkPeriods (currentUser, criteria, options = { returnAll: if (criteria.endDate) { criteria.endDate = moment(criteria.endDate).format('YYYY-MM-DD') } - _.each(_.pick(criteria, ['resourceBookingId', 'userHandle', 'projectId', 'startDate', 'endDate', 'paymentStatus']), (value, key) => { - esQuery.body.query.bool.must.push({ + // Apply filters + _.each(_.pick(criteria, ['resourceBookingId', 'userHandle', 'projectId', 'startDate', 'endDate']), (value, key) => { + esQuery.body.query.nested.query.bool.must.push({ term: { - [key]: { + [`workPeriods.${key}`]: { value } } }) }) + if (criteria.paymentStatus) { + esQuery.body.query.nested.query.bool.must.push({ + terms: { + 'workPeriods.paymentStatus': criteria.paymentStatus + } + }) + } // if criteria contains resourceBookingIds, filter resourceBookingId with this value if (criteria.resourceBookingIds) { - esQuery.body.query.bool.filter = [{ + esQuery.body.query.nested.query.bool.filter = [{ terms: { - resourceBookingId: criteria.resourceBookingIds + 'workPeriods.resourceBookingId': criteria.resourceBookingIds } }] } logger.debug({ component: 'WorkPeriodService', context: 'searchWorkPeriods', message: `Query: ${JSON.stringify(esQuery)}` }) const { body } = await esClient.search(esQuery) - + let workPeriods = _.reduce(body.hits.hits, (acc, resourceBooking) => _.concat(acc, resourceBooking._source.workPeriods), []) + // ESClient will return ResourceBookings with it's all nested WorkPeriods + // We re-apply WorkPeriod filters + _.each(_.pick(criteria, ['startDate', 'endDate']), (value, key) => { + workPeriods = _.filter(workPeriods, { [key]: value }) + }) + if (criteria.paymentStatus) { + workPeriods = _.filter(workPeriods, wp => _.includes(criteria.paymentStatus, wp.paymentStatus)) + } + workPeriods = _.sortBy(workPeriods, [criteria.sortBy]) + if (criteria.sortOrder === 'desc') { + workPeriods = _.reverse(workPeriods) + } + const total = workPeriods.length + if (!options.returnAll) { + workPeriods = _.slice(workPeriods, (page - 1) * perPage, page * perPage) + } return { - total: body.hits.total.value, + total, page, perPage, - result: _.map(body.hits.hits, (hit) => { - const obj = _.cloneDeep(hit._source) - obj.id = hit._id - // We should only return "memberRate" to Booking Manager, Administrator or M2M - if (!currentUser.hasManagePermission && !_checkUserScopesForGetPayments(currentUser)) { - delete obj.memberRate - delete obj.payments - } - return obj - }) + result: workPeriods } } catch (err) { logger.logFullError(err, { component: 'WorkPeriodService', context: 'searchWorkPeriods' }) @@ -464,30 +454,32 @@ async function searchWorkPeriods (currentUser, criteria, options = { returnAll: if (criteria.resourceBookingIds) { filter[Op.and].push({ resourceBookingId: criteria.resourceBookingIds }) } - const workPeriods = await WorkPeriod.findAll({ + const queryCriteria = { where: filter, - include: [{ - model: models.WorkPeriodPayment, - as: 'payments', - required: false - }], offset: ((page - 1) * perPage), limit: perPage, order: [[criteria.sortBy, criteria.sortOrder]] - }) + } + // add excluded fields criteria + if (queryOpt.excludeDB.length > 0) { + queryCriteria.attributes = { exclude: queryOpt.excludeDB } + } + // include WorkPeriodPayment model + if (queryOpt.withPayments) { + queryCriteria.include = [{ + model: models.WorkPeriodPayment, + as: 'payments', + required: false + }] + } + const workPeriods = await WorkPeriod.findAll(queryCriteria) + const total = await WorkPeriod.count({ where: filter }) return { fromDb: true, - total: workPeriods.length, + total, page, perPage, - result: _.map(workPeriods, workPeriod => { - // We should only return "memberRate" to Booking Manager, Administrator or M2M - if (!currentUser.hasManagePermission && !_checkUserScopesForGetPayments(currentUser)) { - delete workPeriod.dataValues.memberRate - delete workPeriod.dataValues.payments - } - return workPeriod.dataValues - }) + result: workPeriods } } @@ -498,7 +490,10 @@ searchWorkPeriods.schema = Joi.object().keys({ perPage: Joi.number().integer().min(1).max(10000).default(20), sortBy: Joi.string().valid('id', 'resourceBookingId', 'userHandle', 'projectId', 'startDate', 'endDate', 'daysWorked', 'customerRate', 'memberRate', 'paymentStatus'), sortOrder: Joi.string().valid('desc', 'asc'), - paymentStatus: Joi.paymentStatus(), + paymentStatus: Joi.alternatives( + Joi.string(), + Joi.array().items(Joi.paymentStatus()) + ), startDate: Joi.date().format('YYYY-MM-DD'), endDate: Joi.date().format('YYYY-MM-DD'), userHandle: Joi.string(), @@ -516,7 +511,6 @@ module.exports = { getWorkPeriod, createWorkPeriod, partiallyUpdateWorkPeriod, - fullyUpdateWorkPeriod, deleteWorkPeriod, searchWorkPeriods } diff --git a/test/prepare.js b/test/prepare.js index 42277c70..c7e16a81 100644 --- a/test/prepare.js +++ b/test/prepare.js @@ -1,7 +1,10 @@ /* * Prepare for tests. */ - +const sinon = require('sinon') +const helper = require('../src/common/helper') +const commonData = require('./unit/common/CommonData') process.env.NODE_ENV = 'test' +sinon.stub(helper, 'getESClient').callsFake(() => commonData.ESClient) require('../src/bootstrap') require('../src/eventHandlers').init() diff --git a/test/unit/ResourceBookingService.test.js b/test/unit/ResourceBookingService.test.js index f557466e..97335d86 100644 --- a/test/unit/ResourceBookingService.test.js +++ b/test/unit/ResourceBookingService.test.js @@ -8,6 +8,8 @@ const workPeriodService = require('../../src/services/WorkPeriodService') const commonData = require('./common/CommonData') const testData = require('./common/ResourceBookingData') const helper = require('../../src/common/helper') +const errors = require('../../src/common/errors') +const _ = require('lodash') const busApiClient = helper.getBusApiClient() const ResourceBooking = models.ResourceBooking const WorkPeriod = models.WorkPeriod @@ -48,11 +50,11 @@ describe('resourceBooking service test', () => { expect(stubCreateWorkPeriodService.callCount).to.eq(6) expect(stubUpdateWorkPeriodService.callCount).to.eq(0) expect(stubDeleteWorkPeriodService.callCount).to.eq(0) - expect(stubCreateWorkPeriodService.getCall(0).args[1]).to.deep.eq(data.workPeriod.request[0]) - expect(stubCreateWorkPeriodService.getCall(1).args[1]).to.deep.eq(data.workPeriod.request[1]) - expect(stubCreateWorkPeriodService.getCall(2).args[1]).to.deep.eq(data.workPeriod.request[2]) - expect(stubCreateWorkPeriodService.getCall(3).args[1]).to.deep.eq(data.workPeriod.request[3]) - expect(stubCreateWorkPeriodService.getCall(4).args[1]).to.deep.eq(data.workPeriod.request[4]) + expect(stubCreateWorkPeriodService.getCall(0).args[0]).to.deep.eq(data.workPeriod.request[0]) + expect(stubCreateWorkPeriodService.getCall(1).args[0]).to.deep.eq(data.workPeriod.request[1]) + expect(stubCreateWorkPeriodService.getCall(2).args[0]).to.deep.eq(data.workPeriod.request[2]) + expect(stubCreateWorkPeriodService.getCall(3).args[0]).to.deep.eq(data.workPeriod.request[3]) + expect(stubCreateWorkPeriodService.getCall(4).args[0]).to.deep.eq(data.workPeriod.request[4]) }) it('T02:Create resource booking start Sunday end Saturday', async () => { const data = testData.T02 @@ -68,7 +70,7 @@ describe('resourceBooking service test', () => { expect(stubCreateWorkPeriodService.callCount).to.eq(1) expect(stubUpdateWorkPeriodService.callCount).to.eq(0) expect(stubDeleteWorkPeriodService.callCount).to.eq(0) - expect(stubCreateWorkPeriodService.getCall(0).args[1]).to.deep.eq(data.workPeriod.request[0]) + expect(stubCreateWorkPeriodService.getCall(0).args[0]).to.deep.eq(data.workPeriod.request[0]) }) it('T03:Create resource booking without startDate', async () => { const data = testData.T03 @@ -130,12 +132,15 @@ describe('resourceBooking service test', () => { }) }) describe('Update resource booking successfully', () => { - it('T06:Update resource booking dates and do not cause work period change', async () => { + it('T06:Update resource booking dates and do not cause work period create/delete', async () => { const data = testData.T06 const stubResourceBookingFindById = sinon.stub(ResourceBooking, 'findById').callsFake(async () => { return data.resourceBooking.value }) - const stubWorkPeriodFindAll = sinon.stub(WorkPeriod, 'findAll').callsFake(async () => { + const stubWorkPeriodFindAll = sinon.stub(WorkPeriod, 'findAll').callsFake(async (criteria) => { + if (criteria.raw) { + return _.map(data.workPeriod.response, wp => wp.toJSON()) + } return data.workPeriod.response }) const entity = await service.partiallyUpdateResourceBooking(commonData.currentUser, data.resourceBooking.value.dataValues.id, data.resourceBooking.request) @@ -144,15 +149,20 @@ describe('resourceBooking service test', () => { expect(stubPostEvent.calledOnce).to.be.true expect(stubWorkPeriodFindAll.called).to.be.true expect(stubCreateWorkPeriodService.callCount).to.eq(0) - expect(stubUpdateWorkPeriodService.callCount).to.eq(0) + expect(stubUpdateWorkPeriodService.callCount).to.eq(1) expect(stubDeleteWorkPeriodService.callCount).to.eq(0) + expect(stubUpdateWorkPeriodService.getCall(0).args[1]).to.deep.eq(data.workPeriod.request[0].id) + expect(stubUpdateWorkPeriodService.getCall(0).args[2]).to.deep.eq(data.workPeriod.request[0].data) }) it('T07:Update resource booking dates and cause work period creation - 1', async () => { const data = testData.T07 const stubResourceBookingFindById = sinon.stub(ResourceBooking, 'findById').callsFake(async () => { return data.resourceBooking.value }) - const stubWorkPeriodFindAll = sinon.stub(WorkPeriod, 'findAll').callsFake(async () => { + const stubWorkPeriodFindAll = sinon.stub(WorkPeriod, 'findAll').callsFake(async (criteria) => { + if (criteria.raw) { + return _.map(data.workPeriod.response, wp => wp.toJSON()) + } return data.workPeriod.response }) const entity = await service.partiallyUpdateResourceBooking(commonData.currentUser, data.resourceBooking.value.dataValues.id, data.resourceBooking.request) @@ -161,16 +171,21 @@ describe('resourceBooking service test', () => { expect(stubPostEvent.calledOnce).to.be.true expect(stubWorkPeriodFindAll.called).to.be.true expect(stubCreateWorkPeriodService.callCount).to.eq(1) - expect(stubUpdateWorkPeriodService.callCount).to.eq(0) + expect(stubUpdateWorkPeriodService.callCount).to.eq(1) expect(stubDeleteWorkPeriodService.callCount).to.eq(0) - expect(stubCreateWorkPeriodService.getCall(0).args[1]).to.deep.eq(data.workPeriod.request[0]) + expect(stubCreateWorkPeriodService.getCall(0).args[0]).to.deep.eq(data.workPeriod.request[0].data) + expect(stubUpdateWorkPeriodService.getCall(0).args[1]).to.deep.eq(data.workPeriod.request[1].id) + expect(stubUpdateWorkPeriodService.getCall(0).args[2]).to.deep.eq(data.workPeriod.request[1].data) }) it('T08:Update resource booking dates and cause work period creation - 2', async () => { const data = testData.T08 const stubResourceBookingFindById = sinon.stub(ResourceBooking, 'findById').callsFake(async () => { return data.resourceBooking.value }) - const stubWorkPeriodFindAll = sinon.stub(WorkPeriod, 'findAll').callsFake(async () => { + const stubWorkPeriodFindAll = sinon.stub(WorkPeriod, 'findAll').callsFake(async (criteria) => { + if (criteria.raw) { + return _.map(data.workPeriod.response, wp => wp.toJSON()) + } return data.workPeriod.response }) const entity = await service.partiallyUpdateResourceBooking(commonData.currentUser, data.resourceBooking.value.dataValues.id, data.resourceBooking.request) @@ -181,14 +196,17 @@ describe('resourceBooking service test', () => { expect(stubCreateWorkPeriodService.callCount).to.eq(1) expect(stubUpdateWorkPeriodService.callCount).to.eq(0) expect(stubDeleteWorkPeriodService.callCount).to.eq(0) - expect(stubCreateWorkPeriodService.getCall(0).args[1]).to.deep.eq(data.workPeriod.request[0]) + expect(stubCreateWorkPeriodService.getCall(0).args[0]).to.deep.eq(data.workPeriod.request[0].data) }) it('T09:Update resource booking startDate and cause work period to be deleted', async () => { const data = testData.T09 const stubResourceBookingFindById = sinon.stub(ResourceBooking, 'findById').callsFake(async () => { return data.resourceBooking.value }) - const stubWorkPeriodFindAll = sinon.stub(WorkPeriod, 'findAll').callsFake(async () => { + const stubWorkPeriodFindAll = sinon.stub(WorkPeriod, 'findAll').callsFake(async (criteria) => { + if (criteria.raw) { + return _.map(data.workPeriod.response, wp => wp.toJSON()) + } return data.workPeriod.response }) const entity = await service.partiallyUpdateResourceBooking(commonData.currentUser, data.resourceBooking.value.dataValues.id, data.resourceBooking.request) @@ -197,16 +215,21 @@ describe('resourceBooking service test', () => { expect(stubPostEvent.calledOnce).to.be.true expect(stubWorkPeriodFindAll.called).to.be.true expect(stubCreateWorkPeriodService.callCount).to.eq(0) - expect(stubUpdateWorkPeriodService.callCount).to.eq(0) + expect(stubUpdateWorkPeriodService.callCount).to.eq(1) expect(stubDeleteWorkPeriodService.callCount).to.eq(1) - expect(stubDeleteWorkPeriodService.getCall(0).args[1]).to.deep.eq(data.workPeriod.request[0]) + expect(stubDeleteWorkPeriodService.getCall(0).args[0]).to.deep.eq(data.workPeriod.request[0].id) + expect(stubUpdateWorkPeriodService.getCall(0).args[1]).to.deep.eq(data.workPeriod.request[1].id) + expect(stubUpdateWorkPeriodService.getCall(0).args[2]).to.deep.eq(data.workPeriod.request[1].data) }) it('T10:Update resource booking endDate and cause work period to be deleted', async () => { const data = testData.T10 const stubResourceBookingFindById = sinon.stub(ResourceBooking, 'findById').callsFake(async () => { return data.resourceBooking.value }) - const stubWorkPeriodFindAll = sinon.stub(WorkPeriod, 'findAll').callsFake(async () => { + const stubWorkPeriodFindAll = sinon.stub(WorkPeriod, 'findAll').callsFake(async (criteria) => { + if (criteria.raw) { + return _.map(data.workPeriod.response, wp => wp.toJSON()) + } return data.workPeriod.response }) const entity = await service.partiallyUpdateResourceBooking(commonData.currentUser, data.resourceBooking.value.dataValues.id, data.resourceBooking.request) @@ -215,16 +238,21 @@ describe('resourceBooking service test', () => { expect(stubPostEvent.calledOnce).to.be.true expect(stubWorkPeriodFindAll.called).to.be.true expect(stubCreateWorkPeriodService.callCount).to.eq(0) - expect(stubUpdateWorkPeriodService.callCount).to.eq(0) + expect(stubUpdateWorkPeriodService.callCount).to.eq(1) expect(stubDeleteWorkPeriodService.callCount).to.eq(1) - expect(stubDeleteWorkPeriodService.getCall(0).args[1]).to.deep.eq(data.workPeriod.request[0]) + expect(stubDeleteWorkPeriodService.getCall(0).args[0]).to.deep.eq(data.workPeriod.request[0].id) + expect(stubUpdateWorkPeriodService.getCall(0).args[1]).to.deep.eq(data.workPeriod.request[1].id) + expect(stubUpdateWorkPeriodService.getCall(0).args[2]).to.deep.eq(data.workPeriod.request[1].data) }) it('T11:Update resource booking dates and cause work period daysWorked to change', async () => { const data = testData.T11 const stubResourceBookingFindById = sinon.stub(ResourceBooking, 'findById').callsFake(async () => { return data.resourceBooking.value }) - const stubWorkPeriodFindAll = sinon.stub(WorkPeriod, 'findAll').callsFake(async () => { + const stubWorkPeriodFindAll = sinon.stub(WorkPeriod, 'findAll').callsFake(async (criteria) => { + if (criteria.raw) { + return _.map(data.workPeriod.response, wp => wp.toJSON()) + } return data.workPeriod.response }) const entity = await service.partiallyUpdateResourceBooking(commonData.currentUser, data.resourceBooking.value.dataValues.id, data.resourceBooking.request) @@ -233,17 +261,22 @@ describe('resourceBooking service test', () => { expect(stubPostEvent.calledOnce).to.be.true expect(stubWorkPeriodFindAll.called).to.be.true expect(stubCreateWorkPeriodService.callCount).to.eq(0) - expect(stubUpdateWorkPeriodService.callCount).to.eq(1) + expect(stubUpdateWorkPeriodService.callCount).to.eq(2) expect(stubDeleteWorkPeriodService.callCount).to.eq(0) - expect(stubUpdateWorkPeriodService.getCall(0).args[1]).to.deep.eq(data.workPeriod.request[0]) - expect(stubUpdateWorkPeriodService.getCall(0).args[2]).to.deep.eq(data.workPeriod.request[1]) + expect(stubUpdateWorkPeriodService.getCall(0).args[1]).to.deep.eq(data.workPeriod.request[0].id) + expect(stubUpdateWorkPeriodService.getCall(0).args[2]).to.deep.eq(data.workPeriod.request[0].data) + expect(stubUpdateWorkPeriodService.getCall(1).args[1]).to.deep.eq(data.workPeriod.request[1].id) + expect(stubUpdateWorkPeriodService.getCall(1).args[2]).to.deep.eq(data.workPeriod.request[1].data) }) it('T12:Update resource booking dates and cause delete, update, create work period operations', async () => { const data = testData.T12 const stubResourceBookingFindById = sinon.stub(ResourceBooking, 'findById').callsFake(async () => { return data.resourceBooking.value }) - const stubWorkPeriodFindAll = sinon.stub(WorkPeriod, 'findAll').callsFake(async () => { + const stubWorkPeriodFindAll = sinon.stub(WorkPeriod, 'findAll').callsFake(async (criteria) => { + if (criteria.raw) { + return _.map(data.workPeriod.response, wp => wp.toJSON()) + } return data.workPeriod.response }) const entity = await service.partiallyUpdateResourceBooking(commonData.currentUser, data.resourceBooking.value.dataValues.id, data.resourceBooking.request) @@ -254,10 +287,10 @@ describe('resourceBooking service test', () => { expect(stubCreateWorkPeriodService.callCount).to.eq(1) expect(stubUpdateWorkPeriodService.callCount).to.eq(1) expect(stubDeleteWorkPeriodService.callCount).to.eq(1) - expect(stubDeleteWorkPeriodService.getCall(0).args[1]).to.deep.eq(data.workPeriod.request[0]) - expect(stubUpdateWorkPeriodService.getCall(0).args[1]).to.deep.eq(data.workPeriod.request[1]) - expect(stubUpdateWorkPeriodService.getCall(0).args[2]).to.deep.eq(data.workPeriod.request[2]) - expect(stubCreateWorkPeriodService.getCall(0).args[1]).to.deep.eq(data.workPeriod.request[3]) + expect(stubDeleteWorkPeriodService.getCall(0).args[0]).to.deep.eq(data.workPeriod.request[0].id) + expect(stubUpdateWorkPeriodService.getCall(0).args[1]).to.deep.eq(data.workPeriod.request[1].id) + expect(stubUpdateWorkPeriodService.getCall(0).args[2]).to.deep.eq(data.workPeriod.request[1].data) + expect(stubCreateWorkPeriodService.getCall(0).args[0]).to.deep.eq(data.workPeriod.request[2].data) }) }) describe('Update resource booking unsuccessfully', () => { @@ -266,7 +299,10 @@ describe('resourceBooking service test', () => { const stubResourceBookingFindById = sinon.stub(ResourceBooking, 'findById').callsFake(async () => { return data.resourceBooking.value }) - const stubWorkPeriodFindAll = sinon.stub(WorkPeriod, 'findAll').callsFake(async () => { + const stubWorkPeriodFindAll = sinon.stub(WorkPeriod, 'findAll').callsFake(async (criteria) => { + if (criteria.raw) { + return _.map(data.workPeriod.response, wp => wp.toJSON()) + } return data.workPeriod.response }) let error @@ -289,7 +325,10 @@ describe('resourceBooking service test', () => { const stubResourceBookingFindById = sinon.stub(ResourceBooking, 'findById').callsFake(async () => { return data.resourceBooking.value }) - const stubWorkPeriodFindAll = sinon.stub(WorkPeriod, 'findAll').callsFake(async () => { + const stubWorkPeriodFindAll = sinon.stub(WorkPeriod, 'findAll').callsFake(async (criteria) => { + if (criteria.raw) { + return _.map(data.workPeriod.response, wp => wp.toJSON()) + } return data.workPeriod.response }) let error @@ -314,7 +353,10 @@ describe('resourceBooking service test', () => { const stubResourceBookingFindById = sinon.stub(ResourceBooking, 'findById').callsFake(async () => { return data.resourceBooking.value }) - const stubWorkPeriodFindAll = sinon.stub(WorkPeriod, 'findAll').callsFake(async () => { + const stubWorkPeriodFindAll = sinon.stub(WorkPeriod, 'findAll').callsFake(async (criteria) => { + if (criteria.raw) { + return _.map(data.workPeriod.response, wp => wp.toJSON()) + } return data.workPeriod.response }) await service.deleteResourceBooking(commonData.currentUser, data.resourceBooking.value.dataValues.id) @@ -324,8 +366,8 @@ describe('resourceBooking service test', () => { expect(stubCreateWorkPeriodService.callCount).to.eq(0) expect(stubUpdateWorkPeriodService.callCount).to.eq(0) expect(stubDeleteWorkPeriodService.callCount).to.eq(2) - expect(stubDeleteWorkPeriodService.getCall(0).args[1]).to.deep.eq(data.workPeriod.request[0]) - expect(stubDeleteWorkPeriodService.getCall(1).args[1]).to.deep.eq(data.workPeriod.request[1]) + expect(stubDeleteWorkPeriodService.getCall(0).args[0]).to.deep.eq(data.workPeriod.request[0].id) + expect(stubDeleteWorkPeriodService.getCall(1).args[0]).to.deep.eq(data.workPeriod.request[1].id) }) }) describe('Delete resource booking unsuccessfully', () => { @@ -334,7 +376,10 @@ describe('resourceBooking service test', () => { const stubResourceBookingFindById = sinon.stub(ResourceBooking, 'findById').callsFake(async () => { return data.resourceBooking.value }) - const stubWorkPeriodFindAll = sinon.stub(WorkPeriod, 'findAll').callsFake(async () => { + const stubWorkPeriodFindAll = sinon.stub(WorkPeriod, 'findAll').callsFake(async (criteria) => { + if (criteria.raw) { + return _.map(data.workPeriod.response, wp => wp.toJSON()) + } return data.workPeriod.response }) let error @@ -353,4 +398,284 @@ describe('resourceBooking service test', () => { expect(stubDeleteWorkPeriodService.callCount).to.eq(0) }) }) + describe('Get resource booking with/without nested fields', () => { + it('T17:Get resource booking from ES', async () => { + const data = testData.T17 + const ESClient = commonData.ESClient + ESClient.get = () => {} + const esClientGet = sinon.stub(ESClient, 'get').callsFake(() => data.esClientGet) + const result = await service.getResourceBooking(commonData.userWithManagePermission, data.esClientGet.body._source.id, data.criteria) + expect(esClientGet.calledOnce).to.be.true + expect(result).to.deep.eq(data.esClientGet.body._source) + }) + it('T18:Get resource booking from DB', async () => { + const data = testData.T18 + const stubResourceBookingFindById = sinon.stub(ResourceBooking, 'findById').callsFake(async () => { + return data.resourceBooking.value + }) + const result = await service.getResourceBooking(commonData.userWithManagePermission, data.resourceBooking.value.dataValues.id, data.criteria) + expect(stubResourceBookingFindById.calledOnce).to.be.true + expect(result).to.deep.eq(data.resourceBooking.value.dataValues) + }) + it('T19:Fail to get resource booking with not allowed fields', async () => { + const data = testData.T19 + let error + try { + await service.getResourceBooking(commonData.userWithManagePermission, data.id, data.criteria) + } catch (err) { + error = err + } + expect(error.httpStatus).to.eq(data.error.httpStatus) + expect(error.message).to.eq(data.error.message) + }) + it('T20:Fail to get resource booking with memberRate', async () => { + const data = testData.T20 + let error + try { + await service.getResourceBooking(commonData.regularUser, data.id, data.criteria) + } catch (err) { + error = err + } + expect(error.httpStatus).to.eq(data.error.httpStatus) + expect(error.message).to.eq(data.error.message) + }) + it('T21:Fail to get resource booking with nested workPeriods', async () => { + const data = testData.T21 + let error + try { + await service.getResourceBooking(commonData.currentUser, data.id, data.criteria) + } catch (err) { + error = err + } + expect(error.httpStatus).to.eq(data.error.httpStatus) + expect(error.message).to.eq(data.error.message) + }) + it('T22:Fail to get resource booking without including projectId as a regularUser', async () => { + const data = testData.T22 + let error + try { + await service.getResourceBooking(commonData.regularUser, data.id, data.criteria) + } catch (err) { + error = err + } + expect(error.httpStatus).to.eq(data.error.httpStatus) + expect(error.message).to.eq(data.error.message) + }) + it('T23:Fail to get resource booking as a regularUser who is not member of project', async () => { + const data = testData.T23 + const ESClient = commonData.ESClient + ESClient.get = () => {} + const esClientGet = sinon.stub(ESClient, 'get').callsFake(() => data.esClientGet) + const checkIsMemberOfProject = sinon.stub(helper, 'checkIsMemberOfProject').callsFake(() => { + throw new errors.UnauthorizedError(data.error.message) + }) + let error + try { + await service.getResourceBooking(commonData.regularUser, data.id, data.criteria) + } catch (err) { + error = err + } + expect(esClientGet.calledOnce).to.be.true + expect(checkIsMemberOfProject.calledOnce).to.be.true + expect(error.httpStatus).to.eq(data.error.httpStatus) + expect(error.message).to.eq(data.error.message) + }) + }) + describe('Search resource booking with/without nested fields', () => { + it('T24:Search resource booking from ES', async () => { + const data = testData.T24 + const ESClient = commonData.ESClient + ESClient.search = () => {} + const esClientSearch = sinon.stub(ESClient, 'search').callsFake(() => data.esClientSearch) + const result = await service.searchResourceBookings(commonData.userWithManagePermission, data.criteria) + expect(esClientSearch.calledOnce).to.be.true + expect(result).to.deep.eq(data.result) + }) + it('T25:Search resource booking from DB', async () => { + const data = testData.T25 + const ESClient = commonData.ESClient + ESClient.search = () => {} + const esClientSearch = sinon.stub(ESClient, 'search').callsFake(() => { throw new Error() }) + const stubResourceBookingFindAll = sinon.stub(ResourceBooking, 'findAll').callsFake(async () => { + return data.resourceBookingFindAll + }) + const stubResourceBookingCount = sinon.stub(ResourceBooking, 'count').callsFake(async () => { + return data.resourceBookingCount + }) + const result = await service.searchResourceBookings(commonData.userWithManagePermission, data.criteria) + expect(esClientSearch.calledOnce).to.be.true + expect(stubResourceBookingFindAll.calledOnce).to.be.true + expect(stubResourceBookingCount.calledOnce).to.be.true + expect(result).to.deep.eq(data.result) + }) + it('T26:Fail to search resource booking with not allowed fields', async () => { + const data = testData.T26 + let error + try { + await service.searchResourceBookings(commonData.userWithManagePermission, data.criteria) + } catch (err) { + error = err + } + expect(error.httpStatus).to.eq(data.error.httpStatus) + expect(error.message).to.eq(data.error.message) + }) + it('T27:Fail to search resource booking with memberRate', async () => { + const data = testData.T27 + let error + try { + await service.searchResourceBookings(commonData.regularUser, data.criteria) + } catch (err) { + error = err + } + expect(error.httpStatus).to.eq(data.error.httpStatus) + expect(error.message).to.eq(data.error.message) + }) + it('T28:Fail to search resource booking with nested workPeriods', async () => { + const data = testData.T28 + let error + try { + await service.searchResourceBookings(commonData.currentUser, data.criteria) + } catch (err) { + error = err + } + expect(error.httpStatus).to.eq(data.error.httpStatus) + expect(error.message).to.eq(data.error.message) + }) + it('T29:Fail to search resource booking without filtering by projectId as a regularUser', async () => { + const data = testData.T29 + let error + try { + await service.searchResourceBookings(commonData.regularUser, data.criteria) + } catch (err) { + error = err + } + expect(error.httpStatus).to.eq(data.error.httpStatus) + expect(error.message).to.eq(data.error.message) + }) + it('T30:Fail to search resource booking as a regularUser who is not member of project', async () => { + const data = testData.T30 + const checkIsMemberOfProject = sinon.stub(helper, 'checkIsMemberOfProject').callsFake(() => { + throw new errors.UnauthorizedError(data.error.message) + }) + let error + try { + await service.searchResourceBookings(commonData.regularUser, data.criteria) + } catch (err) { + error = err + } + expect(checkIsMemberOfProject.calledOnce).to.be.true + expect(error.httpStatus).to.eq(data.error.httpStatus) + expect(error.message).to.eq(data.error.message) + }) + it('T31:Fail to search resource booking with filtering by nested field', async () => { + const data = testData.T31 + let error + try { + await service.searchResourceBookings(commonData.userWithManagePermission, data.criteria) + } catch (err) { + error = err + } + expect(error.httpStatus).to.eq(data.error.httpStatus) + expect(error.message).to.eq(data.error.message) + }) + it('T32:Fail to search resource booking with sorting by not included field', async () => { + const data = testData.T32 + let error + try { + await service.searchResourceBookings(commonData.userWithManagePermission, data.criteria) + } catch (err) { + error = err + } + expect(error.httpStatus).to.eq(data.error.httpStatus) + expect(error.message).to.eq(data.error.message) + }) + it('T33:Fail to search resource booking with sorting by nested field', async () => { + const data = testData.T33 + let error + try { + await service.searchResourceBookings(commonData.userWithManagePermission, data.criteria) + } catch (err) { + error = err + } + expect(error.httpStatus).to.eq(data.error.httpStatus) + expect(error.message).to.eq(data.error.message) + }) + it('T34:Fail to search resource booking with filtering by not included field', async () => { + const data = testData.T34 + let error + try { + await service.searchResourceBookings(commonData.userWithManagePermission, data.criteria) + } catch (err) { + error = err + } + expect(error.httpStatus).to.eq(data.error.httpStatus) + expect(error.message).to.eq(data.error.message) + }) + it('T35:Fail to search resource booking with filtering by not included nested field', async () => { + const data = testData.T35 + let error + try { + await service.searchResourceBookings(commonData.userWithManagePermission, data.criteria) + } catch (err) { + error = err + } + expect(error.httpStatus).to.eq(data.error.httpStatus) + expect(error.message).to.eq(data.error.message) + }) + }) + describe('Update resource booking dates to null', () => { + it('T36:Should not allow setting dates to null if both dates are not null', async () => { + const data = testData.T36 + const stubResourceBookingFindById = sinon.stub(ResourceBooking, 'findById').callsFake(async () => { + return data.resourceBooking.value + }) + let error + try { + await service.partiallyUpdateResourceBooking(commonData.currentUser, data.resourceBooking.value.dataValues.id, data.resourceBooking.request) + } catch (err) { + error = err + } + expect(error.httpStatus).to.eq(data.error.httpStatus) + expect(error.message).to.eq(data.error.message) + expect(stubResourceBookingFindById.calledOnce).to.be.true + expect(stubPostEvent.notCalled).to.be.true + expect(stubCreateWorkPeriodService.callCount).to.eq(0) + expect(stubUpdateWorkPeriodService.callCount).to.eq(0) + expect(stubDeleteWorkPeriodService.callCount).to.eq(0) + }) + it('T37:Should allow setting dates to null if one of the dates is null', async () => { + const data = testData.T37 + const stubResourceBookingFindById = sinon.stub(ResourceBooking, 'findById').callsFake(async () => { + return data.resourceBooking.value + }) + const stubWorkPeriodFindAll = sinon.stub(WorkPeriod, 'findAll').callsFake(async () => { + return data.workPeriod.response + }) + const entity = await service.partiallyUpdateResourceBooking(commonData.currentUser, data.resourceBooking.value.dataValues.id, data.resourceBooking.request) + expect(entity).to.deep.eql(data.resourceBooking.response.toJSON()) + expect(stubResourceBookingFindById.calledOnce).to.be.true + expect(stubPostEvent.calledOnce).to.be.true + expect(stubWorkPeriodFindAll.called).to.be.true + expect(stubCreateWorkPeriodService.callCount).to.eq(0) + expect(stubUpdateWorkPeriodService.callCount).to.eq(0) + expect(stubDeleteWorkPeriodService.callCount).to.eq(0) + }) + it('T38:Should allow setting dates to null if both dates are null', async () => { + const data = testData.T38 + const stubResourceBookingFindById = sinon.stub(ResourceBooking, 'findById').callsFake(async () => { + return data.resourceBooking.value + }) + const stubWorkPeriodFindAll = sinon.stub(WorkPeriod, 'findAll').callsFake(async () => { + return data.workPeriod.response + }) + const entity = await service.partiallyUpdateResourceBooking(commonData.currentUser, data.resourceBooking.value.dataValues.id, data.resourceBooking.request) + expect(entity).to.deep.eql(data.resourceBooking.response.toJSON()) + expect(stubResourceBookingFindById.calledOnce).to.be.true + expect(stubPostEvent.calledOnce).to.be.true + expect(stubWorkPeriodFindAll.called).to.be.true + expect(stubCreateWorkPeriodService.callCount).to.eq(0) + expect(stubUpdateWorkPeriodService.callCount).to.eq(0) + expect(stubDeleteWorkPeriodService.callCount).to.eq(0) + }) + }) }) diff --git a/test/unit/WorkPeriodPaymentService.test.js b/test/unit/WorkPeriodPaymentService.test.js index 5e90b072..0b5a8aca 100644 --- a/test/unit/WorkPeriodPaymentService.test.js +++ b/test/unit/WorkPeriodPaymentService.test.js @@ -1,15 +1,11 @@ /* eslint-disable no-unused-expressions */ - -// const _ = require('lodash') const expect = require('chai').expect const sinon = require('sinon') const models = require('../../src/models') const service = require('../../src/services/WorkPeriodPaymentService') -const paymentService = require('../../src/services/PaymentService') const commonData = require('./common/CommonData') const testData = require('./common/WorkPeriodPaymentData') const helper = require('../../src/common/helper') -// const esClient = helper.getESClient() const busApiClient = helper.getBusApiClient() describe('workPeriod service test', () => { beforeEach(() => { @@ -20,43 +16,35 @@ describe('workPeriod service test', () => { sinon.restore() }) - describe('create work period test', () => { + describe('create work period payment test', () => { let stubGetUserId let stubEnsureWorkPeriodById let stubEnsureResourceBookingById let stubCreateWorkPeriodPayment - let stubCreatePayment beforeEach(async () => { stubGetUserId = sinon.stub(helper, 'getUserId').callsFake(async () => testData.workPeriodPayment01.getUserIdResponse) stubEnsureWorkPeriodById = sinon.stub(helper, 'ensureWorkPeriodById').callsFake(async () => testData.workPeriodPayment01.ensureWorkPeriodByIdResponse) stubEnsureResourceBookingById = sinon.stub(helper, 'ensureResourceBookingById').callsFake(async () => testData.workPeriodPayment01.ensureResourceBookingByIdResponse) stubCreateWorkPeriodPayment = sinon.stub(models.WorkPeriodPayment, 'create').callsFake(() => testData.workPeriodPayment01.response) - stubCreatePayment = sinon.stub(paymentService, 'createPayment').callsFake(async () => testData.workPeriodPayment01.createPaymentResponse) }) it('create work period success', async () => { - const response = await service.createWorkPeriodPayment(commonData.currentUser, testData.workPeriodPayment01.request, { paymentProcessingSwitch: 'ON' }) + const stubWorkPeriodFindById = sinon.stub(models.WorkPeriod, 'findOne').callsFake(async () => testData.workPeriodPayment01.workPeriodWithPayments) + const stubUpdateWorkPeriod = sinon.stub(testData.workPeriodPayment01.workPeriodWithPayments, 'update').callsFake(async () => testData.workPeriodPayment01.workPeriodUpdateResponse) + const response = await service.createWorkPeriodPayment(commonData.currentUser, testData.workPeriodPayment01.request) expect(stubGetUserId.calledOnce).to.be.true expect(stubEnsureWorkPeriodById.calledOnce).to.be.true expect(stubEnsureResourceBookingById.calledOnce).to.be.true - expect(stubCreatePayment.calledOnce).to.be.true expect(stubCreateWorkPeriodPayment.calledOnce).to.be.true + expect(stubWorkPeriodFindById.calledOnce).to.be.true + expect(stubUpdateWorkPeriod.calledOnce).to.be.true expect(response).to.eql(testData.workPeriodPayment01.response.dataValues) - }) - - it('create work period success - billingAccountId is set', async () => { - await service.createWorkPeriodPayment(commonData.currentUser, testData.workPeriodPayment01.request, { paymentProcessingSwitch: 'ON' }) - expect(stubCreatePayment.calledOnce).to.be.true - expect(stubCreatePayment.args[0][0]).to.include({ - billingAccountId: testData.workPeriodPayment01.ensureResourceBookingByIdResponse.billingAccountId - }) - expect(stubCreateWorkPeriodPayment.calledOnce).to.be.true + expect(stubUpdateWorkPeriod.getCall(0).args[0]).to.deep.eq(testData.workPeriodPayment01.workPeriodUpdateRequest) expect(stubCreateWorkPeriodPayment.args[0][0]).to.include({ billingAccountId: testData.workPeriodPayment01.ensureResourceBookingByIdResponse.billingAccountId }) }) - it('fail to create work period if corresponding resource booking does not have bill account', async () => { stubEnsureResourceBookingById.restore() sinon.stub(helper, 'ensureResourceBookingById').callsFake(async () => testData.workPeriodPayment01.ensureResourceBookingByIdResponse02) @@ -67,16 +55,5 @@ describe('workPeriod service test', () => { expect(err.message).to.include('"ResourceBooking" Billing account is not assigned to the resource booking') } }) - - describe('when PAYMENT_PROCESSING_SWITCH is ON/OFF', async () => { - it('do not create payment if PAYMENT_PROCESSING_SWITCH is OFF', async () => { - await service.createWorkPeriodPayment(commonData.currentUser, testData.workPeriodPayment01.request, { paymentProcessingSwitch: 'OFF' }) - expect(stubCreatePayment.calledOnce).to.be.false - }) - it('create payment if PAYMENT_PROCESSING_SWITCH is ON', async () => { - await service.createWorkPeriodPayment(commonData.currentUser, testData.workPeriodPayment01.request, { paymentProcessingSwitch: 'ON' }) - expect(stubCreatePayment.calledOnce).to.be.true - }) - }) }) }) diff --git a/test/unit/common/CommonData.js b/test/unit/common/CommonData.js index 08f8aa66..2653e732 100644 --- a/test/unit/common/CommonData.js +++ b/test/unit/common/CommonData.js @@ -1,12 +1,23 @@ const currentUser = { userId: '00000000-0000-0000-0000-000000000000', - isMachine: true + isMachine: true, + scopes: [] } const UserTCConnCopilot = { userId: '4709473d-f060-4102-87f8-4d51ff0b34c1', handle: 'TCConnCopilot' } +const userWithManagePermission = { + hasManagePermission: true +} +const regularUser = { + userId: '222' +} +const ESClient = {} module.exports = { currentUser, - UserTCConnCopilot + UserTCConnCopilot, + userWithManagePermission, + regularUser, + ESClient } diff --git a/test/unit/common/ResourceBookingData.js b/test/unit/common/ResourceBookingData.js index 4679a835..0970c73e 100644 --- a/test/unit/common/ResourceBookingData.js +++ b/test/unit/common/ResourceBookingData.js @@ -34,43 +34,43 @@ const T01 = { resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', startDate: '2021-03-28', endDate: '2021-04-03', - daysWorked: null, - paymentStatus: 'pending' + daysWorked: 0, + paymentStatus: 'no-days' }, { resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', startDate: '2021-04-04', endDate: '2021-04-10', - daysWorked: null, + daysWorked: 5, paymentStatus: 'pending' }, { resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', startDate: '2021-04-11', endDate: '2021-04-17', - daysWorked: null, + daysWorked: 5, paymentStatus: 'pending' }, { resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', startDate: '2021-04-18', endDate: '2021-04-24', - daysWorked: null, + daysWorked: 5, paymentStatus: 'pending' }, { resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', startDate: '2021-04-25', endDate: '2021-05-01', - daysWorked: null, + daysWorked: 5, paymentStatus: 'pending' }, { resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', startDate: '2021-05-02', endDate: '2021-05-08', - daysWorked: null, - paymentStatus: 'pending' + daysWorked: 0, + paymentStatus: 'no-days' }] } } @@ -111,7 +111,7 @@ const T02 = { resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', startDate: '2021-04-11', endDate: '2021-04-17', - daysWorked: null, + daysWorked: 5, paymentStatus: 'pending' }] } @@ -242,21 +242,30 @@ const T06 = { }, workPeriod: { response: [{ - id: '10faf505-d0e3-4d13-a817-7f1319625e91', - resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', - userHandle: 'pshah_manager', - projectId: 21, - startDate: '2021-04-11', - endDate: '2021-04-17', - daysWorked: null, - memberRate: null, - customerRate: null, - paymentStatus: 'pending', - createdBy: '00000000-0000-0000-0000-000000000000', - updatedBy: null, - createdAt: '2021-04-10T22:25:08.289Z', - updatedAt: '2021-04-10T22:25:08.289Z' - }] + dataValues: { + id: '10faf505-d0e3-4d13-a817-7f1319625e91', + resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', + userHandle: 'pshah_manager', + projectId: 21, + startDate: '2021-04-11', + endDate: '2021-04-17', + daysWorked: 5, + daysPaid: 0, + paymentTotal: 0, + paymentStatus: 'pending', + createdBy: '00000000-0000-0000-0000-000000000000', + updatedBy: null, + createdAt: '2021-04-10T22:25:08.289Z', + updatedAt: '2021-04-10T22:25:08.289Z' + }, + toJSON: () => T06.workPeriod.response[0].dataValues + }], + request: [ + { + id: '10faf505-d0e3-4d13-a817-7f1319625e91', + data: { daysWorked: 3 } + } + ] } } T06.resourceBooking.value.toJSON = () => T06.resourceBooking.value.dataValues @@ -305,28 +314,39 @@ const T07 = { }, workPeriod: { response: [{ - id: '10faf505-d0e3-4d13-a817-7f1319625e91', - resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', - userHandle: 'pshah_manager', - projectId: 21, - startDate: '2021-04-11', - endDate: '2021-04-17', - daysWorked: null, - memberRate: null, - customerRate: null, - paymentStatus: 'pending', - createdBy: '00000000-0000-0000-0000-000000000000', - updatedBy: null, - createdAt: '2021-04-10T22:25:08.289Z', - updatedAt: '2021-04-10T22:25:08.289Z' + dataValues: { + id: '10faf505-d0e3-4d13-a817-7f1319625e91', + resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', + userHandle: 'pshah_manager', + projectId: 21, + startDate: '2021-04-11', + endDate: '2021-04-17', + daysWorked: 5, + daysPaid: 0, + paymentTotal: 0, + paymentStatus: 'pending', + createdBy: '00000000-0000-0000-0000-000000000000', + updatedBy: null, + createdAt: '2021-04-10T22:25:08.289Z', + updatedAt: '2021-04-10T22:25:08.289Z' + }, + toJSON: () => T07.workPeriod.response[0].dataValues }], request: [ { - resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', - startDate: '2021-04-04', - endDate: '2021-04-10', - daysWorked: null, - paymentStatus: 'pending' + data: { + resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', + startDate: '2021-04-04', + endDate: '2021-04-10', + daysWorked: 0, + paymentStatus: 'no-days' + } + }, + { + id: '10faf505-d0e3-4d13-a817-7f1319625e91', + data: { + daysWorked: 4 + } } ] } @@ -377,28 +397,33 @@ const T08 = { }, workPeriod: { response: [{ - id: '10faf505-d0e3-4d13-a817-7f1319625e91', - resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', - userHandle: 'pshah_manager', - projectId: 21, - startDate: '2021-04-11', - endDate: '2021-04-17', - daysWorked: null, - memberRate: null, - customerRate: null, - paymentStatus: 'pending', - createdBy: '00000000-0000-0000-0000-000000000000', - updatedBy: null, - createdAt: '2021-04-10T22:25:08.289Z', - updatedAt: '2021-04-10T22:25:08.289Z' + dataValues: { + id: '10faf505-d0e3-4d13-a817-7f1319625e91', + resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', + userHandle: 'pshah_manager', + projectId: 21, + startDate: '2021-04-11', + endDate: '2021-04-17', + daysWorked: 5, + daysPaid: 0, + paymentTotal: 0, + paymentStatus: 'pending', + createdBy: '00000000-0000-0000-0000-000000000000', + updatedBy: null, + createdAt: '2021-04-10T22:25:08.289Z', + updatedAt: '2021-04-10T22:25:08.289Z' + }, + toJSON: () => T08.workPeriod.response[0].dataValues }], request: [ { - resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', - startDate: '2021-04-18', - endDate: '2021-04-24', - daysWorked: null, - paymentStatus: 'pending' + data: { + resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', + startDate: '2021-04-18', + endDate: '2021-04-24', + daysWorked: 0, + paymentStatus: 'no-days' + } } ] } @@ -449,38 +474,52 @@ const T09 = { }, workPeriod: { response: [{ - id: '10faf505-d0e3-4d13-a817-7f1319625e90', - resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', - userHandle: 'pshah_manager', - projectId: 21, - startDate: '2021-04-04', - endDate: '2021-04-10', - daysWorked: null, - memberRate: null, - customerRate: null, - paymentStatus: 'pending', - createdBy: '00000000-0000-0000-0000-000000000000', - updatedBy: null, - createdAt: '2021-04-10T22:25:08.289Z', - updatedAt: '2021-04-10T22:25:08.289Z' + dataValues: { + id: '10faf505-d0e3-4d13-a817-7f1319625e90', + resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', + userHandle: 'pshah_manager', + projectId: 21, + startDate: '2021-04-04', + endDate: '2021-04-10', + daysWorked: 0, + daysPaid: 0, + paymentTotal: 0, + paymentStatus: 'no-days', + createdBy: '00000000-0000-0000-0000-000000000000', + updatedBy: null, + createdAt: '2021-04-10T22:25:08.289Z', + updatedAt: '2021-04-10T22:25:08.289Z' + }, + toJSON: () => T09.workPeriod.response[0].dataValues }, { - id: '10faf505-d0e3-4d13-a817-7f1319625e91', - resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', - userHandle: 'pshah_manager', - projectId: 21, - startDate: '2021-04-11', - endDate: '2021-04-17', - daysWorked: null, - memberRate: null, - customerRate: null, - paymentStatus: 'pending', - createdBy: '00000000-0000-0000-0000-000000000000', - updatedBy: null, - createdAt: '2021-04-10T22:25:08.289Z', - updatedAt: '2021-04-10T22:25:08.289Z' + dataValues: { + id: '10faf505-d0e3-4d13-a817-7f1319625e91', + resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', + userHandle: 'pshah_manager', + projectId: 21, + startDate: '2021-04-11', + endDate: '2021-04-17', + daysWorked: 5, + daysPaid: 0, + paymentTotal: 0, + paymentStatus: 'pending', + createdBy: '00000000-0000-0000-0000-000000000000', + updatedBy: null, + createdAt: '2021-04-10T22:25:08.289Z', + updatedAt: '2021-04-10T22:25:08.289Z' + }, + toJSON: () => T09.workPeriod.response[1].dataValues }], request: [ - '10faf505-d0e3-4d13-a817-7f1319625e90' + { + id: '10faf505-d0e3-4d13-a817-7f1319625e90' + }, + { + id: '10faf505-d0e3-4d13-a817-7f1319625e91', + data: { + daysWorked: 4 + } + } ] } } @@ -530,38 +569,52 @@ const T10 = { }, workPeriod: { response: [{ - id: '10faf505-d0e3-4d13-a817-7f1319625e90', - resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', - userHandle: 'pshah_manager', - projectId: 21, - startDate: '2021-04-04', - endDate: '2021-04-10', - daysWorked: null, - memberRate: null, - customerRate: null, - paymentStatus: 'pending', - createdBy: '00000000-0000-0000-0000-000000000000', - updatedBy: null, - createdAt: '2021-04-10T22:25:08.289Z', - updatedAt: '2021-04-10T22:25:08.289Z' + dataValues: { + id: '10faf505-d0e3-4d13-a817-7f1319625e90', + resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', + userHandle: 'pshah_manager', + projectId: 21, + startDate: '2021-04-04', + endDate: '2021-04-10', + daysWorked: 0, + daysPaid: 0, + paymentTotal: 0, + paymentStatus: 'no-days', + createdBy: '00000000-0000-0000-0000-000000000000', + updatedBy: null, + createdAt: '2021-04-10T22:25:08.289Z', + updatedAt: '2021-04-10T22:25:08.289Z' + }, + toJSON: () => T10.workPeriod.response[0].dataValues }, { - id: '10faf505-d0e3-4d13-a817-7f1319625e91', - resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', - userHandle: 'pshah_manager', - projectId: 21, - startDate: '2021-04-11', - endDate: '2021-04-17', - daysWorked: null, - memberRate: null, - customerRate: null, - paymentStatus: 'pending', - createdBy: '00000000-0000-0000-0000-000000000000', - updatedBy: null, - createdAt: '2021-04-10T22:25:08.289Z', - updatedAt: '2021-04-10T22:25:08.289Z' + dataValues: { + id: '10faf505-d0e3-4d13-a817-7f1319625e91', + resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', + userHandle: 'pshah_manager', + projectId: 21, + startDate: '2021-04-11', + endDate: '2021-04-17', + daysWorked: 5, + daysPaid: 0, + paymentTotal: 0, + paymentStatus: 'pending', + createdBy: '00000000-0000-0000-0000-000000000000', + updatedBy: null, + createdAt: '2021-04-10T22:25:08.289Z', + updatedAt: '2021-04-10T22:25:08.289Z' + }, + toJSON: () => T10.workPeriod.response[1].dataValues }], request: [ - '10faf505-d0e3-4d13-a817-7f1319625e91' + { + id: '10faf505-d0e3-4d13-a817-7f1319625e91' + }, + { + id: '10faf505-d0e3-4d13-a817-7f1319625e90', + data: { + daysWorked: 2 + } + } ] } } @@ -611,39 +664,51 @@ const T11 = { }, workPeriod: { response: [{ - id: '10faf505-d0e3-4d13-a817-7f1319625e90', - resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', - userHandle: 'pshah_manager', - projectId: 21, - startDate: '2021-04-04', - endDate: '2021-04-10', - daysWorked: 0, - memberRate: null, - customerRate: null, - paymentStatus: 'pending', - createdBy: '00000000-0000-0000-0000-000000000000', - updatedBy: null, - createdAt: '2021-04-10T22:25:08.289Z', - updatedAt: '2021-04-10T22:25:08.289Z' + dataValues: { + id: '10faf505-d0e3-4d13-a817-7f1319625e90', + resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', + userHandle: 'pshah_manager', + projectId: 21, + startDate: '2021-04-04', + endDate: '2021-04-10', + daysWorked: 0, + daysPaid: 0, + paymentTotal: 0, + paymentStatus: 'no-days', + createdBy: '00000000-0000-0000-0000-000000000000', + updatedBy: null, + createdAt: '2021-04-10T22:25:08.289Z', + updatedAt: '2021-04-10T22:25:08.289Z' + }, + toJSON: () => T11.workPeriod.response[0].dataValues }, { - id: '10faf505-d0e3-4d13-a817-7f1319625e91', - resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', - userHandle: 'pshah_manager', - projectId: 21, - startDate: '2021-04-11', - endDate: '2021-04-17', - daysWorked: 3, - memberRate: null, - customerRate: null, - paymentStatus: 'pending', - createdBy: '00000000-0000-0000-0000-000000000000', - updatedBy: null, - createdAt: '2021-04-10T22:25:08.289Z', - updatedAt: '2021-04-10T22:25:08.289Z' + dataValues: { + id: '10faf505-d0e3-4d13-a817-7f1319625e91', + resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', + userHandle: 'pshah_manager', + projectId: 21, + startDate: '2021-04-11', + endDate: '2021-04-17', + daysWorked: 3, + daysPaid: 0, + paymentTotal: 0, + paymentStatus: 'pending', + createdBy: '00000000-0000-0000-0000-000000000000', + updatedBy: null, + createdAt: '2021-04-10T22:25:08.289Z', + updatedAt: '2021-04-10T22:25:08.289Z' + }, + toJSON: () => T11.workPeriod.response[1].dataValues }], request: [ - '10faf505-d0e3-4d13-a817-7f1319625e91', - { daysWorked: 2 } + { + id: '10faf505-d0e3-4d13-a817-7f1319625e90', + data: { daysWorked: 2 } + }, + { + id: '10faf505-d0e3-4d13-a817-7f1319625e91', + data: { daysWorked: 2 } + } ] } } @@ -693,46 +758,58 @@ const T12 = { }, workPeriod: { response: [{ - id: '10faf505-d0e3-4d13-a817-7f1319625e90', - resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', - userHandle: 'pshah_manager', - projectId: 21, - startDate: '2021-04-04', - endDate: '2021-04-10', - daysWorked: 4, - memberRate: null, - customerRate: null, - paymentStatus: 'pending', - createdBy: '00000000-0000-0000-0000-000000000000', - updatedBy: null, - createdAt: '2021-04-10T22:25:08.289Z', - updatedAt: '2021-04-10T22:25:08.289Z' + dataValues: { + id: '10faf505-d0e3-4d13-a817-7f1319625e90', + resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', + userHandle: 'pshah_manager', + projectId: 21, + startDate: '2021-04-04', + endDate: '2021-04-10', + daysWorked: 4, + daysPaid: 0, + paymentTotal: 0, + paymentStatus: 'pending', + createdBy: '00000000-0000-0000-0000-000000000000', + updatedBy: null, + createdAt: '2021-04-10T22:25:08.289Z', + updatedAt: '2021-04-10T22:25:08.289Z' + }, + toJSON: () => T12.workPeriod.response[0].dataValues }, { - id: '10faf505-d0e3-4d13-a817-7f1319625e91', - resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', - userHandle: 'pshah_manager', - projectId: 21, - startDate: '2021-04-11', - endDate: '2021-04-17', - daysWorked: 4, - memberRate: null, - customerRate: null, - paymentStatus: 'partially-completed', - createdBy: '00000000-0000-0000-0000-000000000000', - updatedBy: null, - createdAt: '2021-04-10T22:25:08.289Z', - updatedAt: '2021-04-10T22:25:08.289Z' + dataValues: { + id: '10faf505-d0e3-4d13-a817-7f1319625e91', + resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', + userHandle: 'pshah_manager', + projectId: 21, + startDate: '2021-04-11', + endDate: '2021-04-17', + daysWorked: 4, + daysPaid: 1, + paymentTotal: 2.65, + paymentStatus: 'partially-completed', + createdBy: '00000000-0000-0000-0000-000000000000', + updatedBy: null, + createdAt: '2021-04-10T22:25:08.289Z', + updatedAt: '2021-04-10T22:25:08.289Z' + }, + toJSON: () => T12.workPeriod.response[1].dataValues }], request: [ - '10faf505-d0e3-4d13-a817-7f1319625e90', - '10faf505-d0e3-4d13-a817-7f1319625e91', - { daysWorked: 3 }, { - resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', - startDate: '2021-04-18', - endDate: '2021-04-24', - daysWorked: null, - paymentStatus: 'pending' + id: '10faf505-d0e3-4d13-a817-7f1319625e90' + }, + { + id: '10faf505-d0e3-4d13-a817-7f1319625e91', + data: { daysWorked: 3 } + }, + { + data: { + resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', + startDate: '2021-04-18', + endDate: '2021-04-24', + daysWorked: 5, + paymentStatus: 'pending' + } } ] } @@ -765,40 +842,63 @@ const T13 = { }, error: { httpStatus: 400, - message: `WorkPeriods with id of 10faf505-d0e3-4d13-a817-7f1319625e91 - has completed or partially-completed payment status.` + message: `Can't delete associated WorkPeriods 10faf505-d0e3-4d13-a817-7f1319625e91 + as they have associated WorkPeriodsPayment with one of statuses scheduled, in-progress, completed.` }, workPeriod: { response: [{ - id: '10faf505-d0e3-4d13-a817-7f1319625e90', - resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', - userHandle: 'pshah_manager', - projectId: 21, - startDate: '2021-04-04', - endDate: '2021-04-10', - daysWorked: 4, - memberRate: null, - customerRate: null, - paymentStatus: 'pending', - createdBy: '00000000-0000-0000-0000-000000000000', - updatedBy: null, - createdAt: '2021-04-10T22:25:08.289Z', - updatedAt: '2021-04-10T22:25:08.289Z' + dataValues: { + id: '10faf505-d0e3-4d13-a817-7f1319625e90', + resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', + userHandle: 'pshah_manager', + projectId: 21, + startDate: '2021-04-04', + endDate: '2021-04-10', + daysWorked: 4, + daysPaid: 0, + paymentTotal: 0, + paymentStatus: 'pending', + createdBy: '00000000-0000-0000-0000-000000000000', + updatedBy: null, + createdAt: '2021-04-10T22:25:08.289Z', + updatedAt: '2021-04-10T22:25:08.289Z', + payments: [] + }, + toJSON: () => T13.workPeriod.response[0].dataValues }, { - id: '10faf505-d0e3-4d13-a817-7f1319625e91', - resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', - userHandle: 'pshah_manager', - projectId: 21, - startDate: '2021-04-11', - endDate: '2021-04-17', - daysWorked: 4, - memberRate: null, - customerRate: null, - paymentStatus: 'completed', - createdBy: '00000000-0000-0000-0000-000000000000', - updatedBy: null, - createdAt: '2021-04-10T22:25:08.289Z', - updatedAt: '2021-04-10T22:25:08.289Z' + dataValues: { + id: '10faf505-d0e3-4d13-a817-7f1319625e91', + resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', + userHandle: 'pshah_manager', + projectId: 21, + startDate: '2021-04-11', + endDate: '2021-04-17', + daysWorked: 4, + daysPaid: 4, + paymentTotal: 10.59, + paymentStatus: 'completed', + createdBy: '00000000-0000-0000-0000-000000000000', + updatedBy: null, + createdAt: '2021-04-10T22:25:08.289Z', + updatedAt: '2021-04-10T22:25:08.289Z', + payments: [{ + amount: 400, + updatedBy: '57646ff9-1cd3-4d3c-88ba-eb09a395366c', + billingAccountId: 80000071, + workPeriodId: '193a029e-0d3d-48fa-a249-0a4b6b21c32a', + createdAt: '2021-06-16T08:51:30.374Z', + challengeId: '3c849caf-6c60-40f7-8f0e-ee72c41ede6e', + memberRate: 2000, + createdBy: '57646ff9-1cd3-4d3c-88ba-eb09a395366c', + customerRate: 2600, + days: 1, + statusDetails: null, + id: 'c3ba01c5-56db-462f-811f-65cd256096c3', + status: 'in-progress', + updatedAt: '2021-06-16T08:57:21.483Z' + }] + }, + toJSON: () => T13.workPeriod.response[1].dataValues }] } } @@ -829,40 +929,63 @@ const T14 = { }, error: { httpStatus: 400, - message: `WorkPeriods with id of 10faf505-d0e3-4d13-a817-7f1319625e91 - has completed or partially-completed payment status.` + message: `Can't delete associated WorkPeriods 10faf505-d0e3-4d13-a817-7f1319625e91 + as they have associated WorkPeriodsPayment with one of statuses scheduled, in-progress, completed.` }, workPeriod: { response: [{ - id: '10faf505-d0e3-4d13-a817-7f1319625e90', - resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', - userHandle: 'pshah_manager', - projectId: 21, - startDate: '2021-04-04', - endDate: '2021-04-10', - daysWorked: 4, - memberRate: null, - customerRate: null, - paymentStatus: 'pending', - createdBy: '00000000-0000-0000-0000-000000000000', - updatedBy: null, - createdAt: '2021-04-10T22:25:08.289Z', - updatedAt: '2021-04-10T22:25:08.289Z' + dataValues: { + id: '10faf505-d0e3-4d13-a817-7f1319625e90', + resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', + userHandle: 'pshah_manager', + projectId: 21, + startDate: '2021-04-04', + endDate: '2021-04-10', + daysWorked: 4, + daysPaid: 0, + paymentTotal: 0, + paymentStatus: 'pending', + createdBy: '00000000-0000-0000-0000-000000000000', + updatedBy: null, + createdAt: '2021-04-10T22:25:08.289Z', + updatedAt: '2021-04-10T22:25:08.289Z', + payments: [] + }, + toJSON: () => T14.workPeriod.response[0].dataValues }, { - id: '10faf505-d0e3-4d13-a817-7f1319625e91', - resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', - userHandle: 'pshah_manager', - projectId: 21, - startDate: '2021-04-11', - endDate: '2021-04-17', - daysWorked: 4, - memberRate: null, - customerRate: null, - paymentStatus: 'completed', - createdBy: '00000000-0000-0000-0000-000000000000', - updatedBy: null, - createdAt: '2021-04-10T22:25:08.289Z', - updatedAt: '2021-04-10T22:25:08.289Z' + dataValues: { + id: '10faf505-d0e3-4d13-a817-7f1319625e91', + resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', + userHandle: 'pshah_manager', + projectId: 21, + startDate: '2021-04-11', + endDate: '2021-04-17', + daysWorked: 4, + daysPaid: 4, + paymentTotal: 10.59, + paymentStatus: 'completed', + createdBy: '00000000-0000-0000-0000-000000000000', + updatedBy: null, + createdAt: '2021-04-10T22:25:08.289Z', + updatedAt: '2021-04-10T22:25:08.289Z', + payments: [{ + amount: 400, + updatedBy: '57646ff9-1cd3-4d3c-88ba-eb09a395366c', + billingAccountId: 80000071, + workPeriodId: '193a029e-0d3d-48fa-a249-0a4b6b21c32a', + createdAt: '2021-06-16T08:51:30.374Z', + challengeId: '3c849caf-6c60-40f7-8f0e-ee72c41ede6e', + memberRate: 2000, + createdBy: '57646ff9-1cd3-4d3c-88ba-eb09a395366c', + customerRate: 2600, + days: 1, + statusDetails: null, + id: 'c3ba01c5-56db-462f-811f-65cd256096c3', + status: 'scheduled', + updatedAt: '2021-06-16T08:57:21.483Z' + }] + }, + toJSON: () => T14.workPeriod.response[1].dataValues }] } } @@ -889,37 +1012,67 @@ const T15 = { }, workPeriod: { response: [{ - id: '10faf505-d0e3-4d13-a817-7f1319625e90', - resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', - userHandle: 'pshah_manager', - projectId: 21, - startDate: '2021-04-04', - endDate: '2021-04-10', - daysWorked: 4, - memberRate: null, - customerRate: null, - paymentStatus: 'pending', - createdBy: '00000000-0000-0000-0000-000000000000', - updatedBy: null, - createdAt: '2021-04-10T22:25:08.289Z', - updatedAt: '2021-04-10T22:25:08.289Z' + dataValues: { + id: '10faf505-d0e3-4d13-a817-7f1319625e90', + resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', + userHandle: 'pshah_manager', + projectId: 21, + startDate: '2021-04-04', + endDate: '2021-04-10', + daysWorked: 4, + daysPaid: 0, + paymentTotal: 0, + paymentStatus: 'pending', + createdBy: '00000000-0000-0000-0000-000000000000', + updatedBy: null, + createdAt: '2021-04-10T22:25:08.289Z', + updatedAt: '2021-04-10T22:25:08.289Z', + payments: [] + }, + toJSON: () => T15.workPeriod.response[0].dataValues }, { - id: '10faf505-d0e3-4d13-a817-7f1319625e91', - resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', - userHandle: 'pshah_manager', - projectId: 21, - startDate: '2021-04-11', - endDate: '2021-04-17', - daysWorked: 4, - memberRate: null, - customerRate: null, - paymentStatus: 'pending', - createdBy: '00000000-0000-0000-0000-000000000000', - updatedBy: null, - createdAt: '2021-04-10T22:25:08.289Z', - updatedAt: '2021-04-10T22:25:08.289Z' + dataValues: { + id: '10faf505-d0e3-4d13-a817-7f1319625e91', + resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', + userHandle: 'pshah_manager', + projectId: 21, + startDate: '2021-04-11', + endDate: '2021-04-17', + daysWorked: 4, + daysPaid: 0, + paymentTotal: 0, + paymentStatus: 'pending', + createdBy: '00000000-0000-0000-0000-000000000000', + updatedBy: null, + createdAt: '2021-04-10T22:25:08.289Z', + updatedAt: '2021-04-10T22:25:08.289Z', + payments: [{ + amount: 400, + updatedBy: '57646ff9-1cd3-4d3c-88ba-eb09a395366c', + billingAccountId: 80000071, + workPeriodId: '193a029e-0d3d-48fa-a249-0a4b6b21c32a', + createdAt: '2021-06-16T08:51:30.374Z', + challengeId: '3c849caf-6c60-40f7-8f0e-ee72c41ede6e', + memberRate: 2000, + createdBy: '57646ff9-1cd3-4d3c-88ba-eb09a395366c', + customerRate: 2600, + days: 1, + statusDetails: null, + id: 'c3ba01c5-56db-462f-811f-65cd256096c3', + status: 'failed', + updatedAt: '2021-06-16T08:57:21.483Z' + }] + }, + toJSON: () => T15.workPeriod.response[1].dataValues }], - request: ['10faf505-d0e3-4d13-a817-7f1319625e90', '10faf505-d0e3-4d13-a817-7f1319625e91'] + request: [ + { + id: '10faf505-d0e3-4d13-a817-7f1319625e90' + }, + { + id: '10faf505-d0e3-4d13-a817-7f1319625e91' + } + ] } } T15.resourceBooking.value.toJSON = () => T15.resourceBooking.value.dataValues @@ -946,44 +1099,560 @@ const T16 = { }, error: { httpStatus: 400, - message: `WorkPeriods with id of 10faf505-d0e3-4d13-a817-7f1319625e91 - has completed or partially-completed payment status.` + message: `Can't delete associated WorkPeriods 10faf505-d0e3-4d13-a817-7f1319625e91 + as they have associated WorkPeriodsPayment with one of statuses scheduled, in-progress, completed.` }, workPeriod: { response: [{ - id: '10faf505-d0e3-4d13-a817-7f1319625e90', - resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', - userHandle: 'pshah_manager', - projectId: 21, - startDate: '2021-04-04', - endDate: '2021-04-10', - daysWorked: 4, - memberRate: null, - customerRate: null, - paymentStatus: 'pending', - createdBy: '00000000-0000-0000-0000-000000000000', - updatedBy: null, - createdAt: '2021-04-10T22:25:08.289Z', - updatedAt: '2021-04-10T22:25:08.289Z' + dataValues: { + id: '10faf505-d0e3-4d13-a817-7f1319625e90', + resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', + userHandle: 'pshah_manager', + projectId: 21, + startDate: '2021-04-04', + endDate: '2021-04-10', + daysWorked: 4, + daysPaid: 0, + paymentTotal: 0, + paymentStatus: 'pending', + createdBy: '00000000-0000-0000-0000-000000000000', + updatedBy: null, + createdAt: '2021-04-10T22:25:08.289Z', + updatedAt: '2021-04-10T22:25:08.289Z', + payments: [] + }, + toJSON: () => T16.workPeriod.response[0].dataValues }, { - id: '10faf505-d0e3-4d13-a817-7f1319625e91', - resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', - userHandle: 'pshah_manager', - projectId: 21, - startDate: '2021-04-11', - endDate: '2021-04-17', - daysWorked: 4, - memberRate: null, - customerRate: null, - paymentStatus: 'completed', - createdBy: '00000000-0000-0000-0000-000000000000', - updatedBy: null, - createdAt: '2021-04-10T22:25:08.289Z', - updatedAt: '2021-04-10T22:25:08.289Z' + dataValues: { + id: '10faf505-d0e3-4d13-a817-7f1319625e91', + resourceBookingId: '520bb632-a02a-415e-9857-93b2ecbf7d60', + userHandle: 'pshah_manager', + projectId: 21, + startDate: '2021-04-11', + endDate: '2021-04-17', + daysWorked: 4, + daysPaid: 4, + paymentTotal: 400, + paymentStatus: 'completed', + createdBy: '00000000-0000-0000-0000-000000000000', + updatedBy: null, + createdAt: '2021-04-10T22:25:08.289Z', + updatedAt: '2021-04-10T22:25:08.289Z', + payments: [{ + amount: 400, + updatedBy: '57646ff9-1cd3-4d3c-88ba-eb09a395366c', + billingAccountId: 80000071, + workPeriodId: '193a029e-0d3d-48fa-a249-0a4b6b21c32a', + createdAt: '2021-06-16T08:51:30.374Z', + challengeId: '3c849caf-6c60-40f7-8f0e-ee72c41ede6e', + memberRate: 2000, + createdBy: '57646ff9-1cd3-4d3c-88ba-eb09a395366c', + customerRate: 2600, + days: 4, + statusDetails: null, + id: 'c3ba01c5-56db-462f-811f-65cd256096c3', + status: 'completed', + updatedAt: '2021-06-16T08:57:21.483Z' + }] + }, + toJSON: () => T16.workPeriod.response[1].dataValues }] } } T16.resourceBooking.value.toJSON = () => T16.resourceBooking.value.dataValues +const T17 = { + esClientGet: { + body: { + _source: { + updatedBy: null, + endDate: '2020-10-27', + billingAccountId: 80000071, + userId: 'a55fe1bc-1754-45fa-9adc-cf3d6d7c377a', + jobId: '05232809-3693-44c1-a0cc-9a79f2672385', + rateType: 'hourly', + createdAt: '2021-05-08T18:47:37.268Z', + memberRate: 13.23, + createdBy: '57646ff9-1cd3-4d3c-88ba-eb09a395366c', + customerRate: 13, + id: '60e99790-8da0-4596-badc-29a06feb78a0', + projectId: 17234, + startDate: '2020-09-27', + status: 'placed', + updatedAt: '2021-05-08T18:47:37.268Z' + } + } + }, + criteria: {} +} +const T18 = { + resourceBooking: { + value: { + dataValues: { + id: '520bb632-a02a-415e-9857-93b2ecbf7d60', + projectId: 21, + userId: 'a55fe1bc-1754-45fa-9adc-cf3d6d7c377a', + jobId: '6093e58c-683d-4022-8482-5515e8345016', + startDate: '2021-04-05', + endDate: '2021-04-17', + memberRate: 13.23, + customerRate: 13, + rateType: 'hourly', + createdAt: '2020-10-09T04:24:01.048Z', + createdBy: '57646ff9-1cd3-4d3c-88ba-eb09a395366c', + status: 'sourcing', + billingAccountId: 68800079 + } + } + }, + criteria: { fromDb: true } +} +const T19 = { + id: '520bb632-a02a-415e-9857-93b2ecbf7d60', + criteria: { + fields: 'other' + }, + error: { + httpStatus: 400, + message: 'other are not allowed' + } +} +const T20 = { + id: '520bb632-a02a-415e-9857-93b2ecbf7d60', + criteria: { + fields: 'memberRate' + }, + error: { + httpStatus: 403, + message: 'You don\'t have access to view memberRate and paymentTotal' + } +} +const T21 = { + id: '520bb632-a02a-415e-9857-93b2ecbf7d60', + criteria: { + fields: 'workPeriods' + }, + error: { + httpStatus: 403, + message: 'You don\'t have access to view workPeriods' + } +} +const T22 = { + id: '520bb632-a02a-415e-9857-93b2ecbf7d60', + criteria: { + fields: 'id' + }, + error: { + httpStatus: 403, + message: 'Not allowed without including "projectId"' + } +} +const T23 = { + id: '520bb632-a02a-415e-9857-93b2ecbf7d60', + criteria: {}, + esClientGet: { + body: { + _source: { + updatedBy: null, + endDate: '2020-10-27', + billingAccountId: 80000071, + userId: 'a55fe1bc-1754-45fa-9adc-cf3d6d7c377a', + jobId: '05232809-3693-44c1-a0cc-9a79f2672385', + rateType: 'hourly', + createdAt: '2021-05-08T18:47:37.268Z', + memberRate: 13.23, + createdBy: '57646ff9-1cd3-4d3c-88ba-eb09a395366c', + customerRate: 13, + id: '520bb632-a02a-415e-9857-93b2ecbf7d60', + projectId: 111, + startDate: '2020-09-27', + status: 'placed', + updatedAt: '2021-05-08T18:47:37.268Z' + } + } + }, + error: { + httpStatus: 401, + message: 'userId: 222 the user is not a member of project 111' + } +} +const T24 = { + esClientSearch: { + body: { + hits: { + total: { + value: 2 + }, + hits: [ + { + _source: { + updatedBy: null, + endDate: '2020-10-27', + billingAccountId: 80000071, + userId: 'a55fe1bc-1754-45fa-9adc-cf3d6d7c377a', + jobId: '05232809-3693-44c1-a0cc-9a79f2672385', + rateType: 'hourly', + createdAt: '2021-05-08T18:35:16.368Z', + memberRate: 13.23, + createdBy: '57646ff9-1cd3-4d3c-88ba-eb09a395366c', + customerRate: 13, + id: 'fbe133dd-0e36-4d0c-8197-49307b13ce75', + projectId: 17234, + startDate: '2020-09-27', + status: 'placed', + updatedAt: '2021-05-08T18:35:16.368Z' + } + }, + { + _source: { + updatedBy: null, + endDate: '2020-10-27', + billingAccountId: 80000071, + userId: 'a55fe1bc-1754-45fa-9adc-cf3d6d7c377a', + jobId: '05232809-3693-44c1-a0cc-9a79f2672385', + rateType: 'hourly', + createdAt: '2021-05-08T18:47:37.268Z', + memberRate: 13.23, + createdBy: '57646ff9-1cd3-4d3c-88ba-eb09a395366c', + customerRate: 13, + id: '60e99790-8da0-4596-badc-29a06feb78a0', + projectId: 17234, + startDate: '2020-09-27', + status: 'placed', + updatedAt: '2021-05-08T18:47:37.268Z' + } + } + ] + } + } + }, + criteria: {}, + result: { + total: 2, + page: 1, + perPage: 20, + result: [ + { + updatedBy: null, + endDate: '2020-10-27', + billingAccountId: 80000071, + userId: 'a55fe1bc-1754-45fa-9adc-cf3d6d7c377a', + jobId: '05232809-3693-44c1-a0cc-9a79f2672385', + rateType: 'hourly', + createdAt: '2021-05-08T18:35:16.368Z', + memberRate: 13.23, + createdBy: '57646ff9-1cd3-4d3c-88ba-eb09a395366c', + customerRate: 13, + id: 'fbe133dd-0e36-4d0c-8197-49307b13ce75', + projectId: 17234, + startDate: '2020-09-27', + status: 'placed', + updatedAt: '2021-05-08T18:35:16.368Z' + }, + { + updatedBy: null, + endDate: '2020-10-27', + billingAccountId: 80000071, + userId: 'a55fe1bc-1754-45fa-9adc-cf3d6d7c377a', + jobId: '05232809-3693-44c1-a0cc-9a79f2672385', + rateType: 'hourly', + createdAt: '2021-05-08T18:47:37.268Z', + memberRate: 13.23, + createdBy: '57646ff9-1cd3-4d3c-88ba-eb09a395366c', + customerRate: 13, + id: '60e99790-8da0-4596-badc-29a06feb78a0', + projectId: 17234, + startDate: '2020-09-27', + status: 'placed', + updatedAt: '2021-05-08T18:47:37.268Z' + } + ] + } +} +const T25 = { + resourceBookingFindAll: [ + { + updatedBy: null, + endDate: '2020-10-27', + billingAccountId: 80000071, + userId: 'a55fe1bc-1754-45fa-9adc-cf3d6d7c377a', + jobId: '05232809-3693-44c1-a0cc-9a79f2672385', + rateType: 'hourly', + createdAt: '2021-05-08T18:35:16.368Z', + memberRate: 13.23, + createdBy: '57646ff9-1cd3-4d3c-88ba-eb09a395366c', + customerRate: 13, + id: 'fbe133dd-0e36-4d0c-8197-49307b13ce75', + projectId: 17234, + startDate: '2020-09-27', + status: 'placed', + updatedAt: '2021-05-08T18:35:16.368Z' + }, + { + updatedBy: null, + endDate: '2020-10-27', + billingAccountId: 80000071, + userId: 'a55fe1bc-1754-45fa-9adc-cf3d6d7c377a', + jobId: '05232809-3693-44c1-a0cc-9a79f2672385', + rateType: 'hourly', + createdAt: '2021-05-08T18:47:37.268Z', + memberRate: 13.23, + createdBy: '57646ff9-1cd3-4d3c-88ba-eb09a395366c', + customerRate: 13, + id: '60e99790-8da0-4596-badc-29a06feb78a0', + projectId: 17234, + startDate: '2020-09-27', + status: 'placed', + updatedAt: '2021-05-08T18:47:37.268Z' + } + ], + resourceBookingCount: [{ id: 'fbe133dd-0e36-4d0c-8197-49307b13ce75', count: 1 }, + { id: '60e99790-8da0-4596-badc-29a06feb78a0', count: 1 }], + criteria: {}, + result: { + fromDb: true, + total: 2, + page: 1, + perPage: 20, + result: [ + { + updatedBy: null, + endDate: '2020-10-27', + billingAccountId: 80000071, + userId: 'a55fe1bc-1754-45fa-9adc-cf3d6d7c377a', + jobId: '05232809-3693-44c1-a0cc-9a79f2672385', + rateType: 'hourly', + createdAt: '2021-05-08T18:35:16.368Z', + memberRate: 13.23, + createdBy: '57646ff9-1cd3-4d3c-88ba-eb09a395366c', + customerRate: 13, + id: 'fbe133dd-0e36-4d0c-8197-49307b13ce75', + projectId: 17234, + startDate: '2020-09-27', + status: 'placed', + updatedAt: '2021-05-08T18:35:16.368Z' + }, + { + updatedBy: null, + endDate: '2020-10-27', + billingAccountId: 80000071, + userId: 'a55fe1bc-1754-45fa-9adc-cf3d6d7c377a', + jobId: '05232809-3693-44c1-a0cc-9a79f2672385', + rateType: 'hourly', + createdAt: '2021-05-08T18:47:37.268Z', + memberRate: 13.23, + createdBy: '57646ff9-1cd3-4d3c-88ba-eb09a395366c', + customerRate: 13, + id: '60e99790-8da0-4596-badc-29a06feb78a0', + projectId: 17234, + startDate: '2020-09-27', + status: 'placed', + updatedAt: '2021-05-08T18:47:37.268Z' + } + ] + } +} +const T26 = { + criteria: { + fields: 'other' + }, + error: { + httpStatus: 400, + message: 'other are not allowed' + } +} +const T27 = { + criteria: { + fields: 'memberRate' + }, + error: { + httpStatus: 403, + message: 'You don\'t have access to view memberRate and paymentTotal' + } +} +const T28 = { + criteria: { + fields: 'workPeriods' + }, + error: { + httpStatus: 403, + message: 'You don\'t have access to view workPeriods' + } +} +const T29 = { + criteria: {}, + error: { + httpStatus: 403, + message: 'Not allowed without filtering by "projectId"' + } +} +const T30 = { + criteria: { projectId: 111 }, + error: { + httpStatus: 401, + message: 'userId: 222 the user is not a member of project 111' + } +} +const T31 = { + criteria: { 'workPeriods.startDate': '2021-05-10' }, + error: { + httpStatus: 400, + message: 'Can not filter or sort by some field which is not included in fields' + } +} +const T32 = { + criteria: { sortBy: 'workPeriods.daysWorked' }, + error: { + httpStatus: 400, + message: 'Can not filter or sort by some field which is not included in fields' + } +} +const T33 = { + criteria: { fields: 'workPeriods', sortBy: 'workPeriods.daysWorked' }, + error: { + httpStatus: 400, + message: 'Can not sort by workPeriod field without filtering by workPeriods.startDate or workPeriods.endDate' + } +} +const T34 = { + criteria: { fields: 'id,startDate,endDate,workPeriods', status: 'closed' }, + error: { + httpStatus: 400, + message: 'Can not filter or sort by some field which is not included in fields' + } +} +const T35 = { + criteria: { fields: 'id,startDate,endDate', 'workPeriods.paymentStatus': 'completed' }, + error: { + httpStatus: 400, + message: 'Can not filter or sort by some field which is not included in fields' + } +} +const T36 = { + resourceBooking: { + value: { + dataValues: { + id: '520bb632-a02a-415e-9857-93b2ecbf7d60', + projectId: 21, + userId: 'a55fe1bc-1754-45fa-9adc-cf3d6d7c377a', + jobId: '6093e58c-683d-4022-8482-5515e8345016', + startDate: '2021-04-05', + endDate: '2021-04-17', + memberRate: 13.23, + customerRate: 13, + rateType: 'hourly', + createdAt: '2020-10-09T04:24:01.048Z', + createdBy: '57646ff9-1cd3-4d3c-88ba-eb09a395366c', + status: 'sourcing', + billingAccountId: 68800079 + } + }, + request: { + startDate: '2021-04-05', + endDate: null + } + }, + error: { + httpStatus: 400, + message: 'You cannot remove start or end date if both are already set for Resource Booking.' + } +} +T36.resourceBooking.value.toJSON = () => T36.resourceBooking.value.dataValues +const T37 = { + resourceBooking: { + value: { + dataValues: { + id: '520bb632-a02a-415e-9857-93b2ecbf7d60', + projectId: 21, + userId: 'a55fe1bc-1754-45fa-9adc-cf3d6d7c377a', + jobId: '6093e58c-683d-4022-8482-5515e8345016', + startDate: null, + endDate: '2021-04-17', + memberRate: 13.23, + customerRate: 13, + rateType: 'hourly', + createdAt: '2020-10-09T04:24:01.048Z', + createdBy: '57646ff9-1cd3-4d3c-88ba-eb09a395366c', + status: 'sourcing', + billingAccountId: 68800079 + } + }, + request: { + startDate: null, + endDate: null + }, + response: { + dataValues: { + id: '520bb632-a02a-415e-9857-93b2ecbf7d60', + projectId: 21, + userId: 'a55fe1bc-1754-45fa-9adc-cf3d6d7c377a', + jobId: '6093e58c-683d-4022-8482-5515e8345016', + startDate: null, + endDate: null, + memberRate: 13.23, + customerRate: 13, + rateType: 'hourly', + createdAt: '2020-10-09T04:24:01.048Z', + createdBy: '57646ff9-1cd3-4d3c-88ba-eb09a395366c', + status: 'sourcing', + billingAccountId: 68800079 + } + } + }, + workPeriod: { + response: [] + } +} +T37.resourceBooking.value.toJSON = () => T37.resourceBooking.value.dataValues +T37.resourceBooking.value.update = () => T37.resourceBooking.response +T37.resourceBooking.response.toJSON = () => T37.resourceBooking.response.dataValues +const T38 = { + resourceBooking: { + value: { + dataValues: { + id: '520bb632-a02a-415e-9857-93b2ecbf7d60', + projectId: 21, + userId: 'a55fe1bc-1754-45fa-9adc-cf3d6d7c377a', + jobId: '6093e58c-683d-4022-8482-5515e8345016', + startDate: null, + endDate: null, + memberRate: 13.23, + customerRate: 13, + rateType: 'hourly', + createdAt: '2020-10-09T04:24:01.048Z', + createdBy: '57646ff9-1cd3-4d3c-88ba-eb09a395366c', + status: 'sourcing', + billingAccountId: 68800079 + } + }, + request: { + startDate: null, + endDate: null + }, + response: { + dataValues: { + id: '520bb632-a02a-415e-9857-93b2ecbf7d60', + projectId: 21, + userId: 'a55fe1bc-1754-45fa-9adc-cf3d6d7c377a', + jobId: '6093e58c-683d-4022-8482-5515e8345016', + startDate: null, + endDate: null, + memberRate: 13.23, + customerRate: 13, + rateType: 'hourly', + createdAt: '2020-10-09T04:24:01.048Z', + createdBy: '57646ff9-1cd3-4d3c-88ba-eb09a395366c', + status: 'sourcing', + billingAccountId: 68800079 + } + } + }, + workPeriod: { + response: [] + } +} +T38.resourceBooking.value.toJSON = () => T38.resourceBooking.value.dataValues +T38.resourceBooking.value.update = () => T38.resourceBooking.response +T38.resourceBooking.response.toJSON = () => T38.resourceBooking.response.dataValues module.exports = { T01, T02, @@ -1000,5 +1669,27 @@ module.exports = { T13, T14, T15, - T16 + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25, + T26, + T27, + T28, + T29, + T30, + T31, + T32, + T33, + T34, + T35, + T36, + T37, + T38 } diff --git a/test/unit/common/WorkPeriodPaymentData.js b/test/unit/common/WorkPeriodPaymentData.js index d94d9280..67322137 100644 --- a/test/unit/common/WorkPeriodPaymentData.js +++ b/test/unit/common/WorkPeriodPaymentData.js @@ -1,17 +1,18 @@ const workPeriodPayment01 = { request: { - workPeriodId: '467b4df7-ced4-41b9-9710-b83808cddaf4', - amount: 600, - status: 'completed' + workPeriodId: '467b4df7-ced4-41b9-9710-b83808cddaf4' }, response: { dataValues: { workPeriodId: '467b4df7-ced4-41b9-9710-b83808cddaf4', amount: 600, - status: 'completed', + status: 'scheduled', + days: 3, + memberRate: 13.23, + customerRate: 13, id: '01971e6f-0f09-4a2a-bc2e-2adac0f00622', challengeId: '00000000-0000-0000-0000-000000000000', - createdBy: '57646ff9-1cd3-4d3c-88ba-eb09a395366c', + createdBy: '79a39efd-91af-494a-b0f6-62310495effd', updatedAt: '2021-04-21T12:58:07.535Z', createdAt: '2021-04-21T12:58:07.535Z', updatedBy: null @@ -19,23 +20,150 @@ const workPeriodPayment01 = { }, getUserIdResponse: '79a39efd-91af-494a-b0f6-62310495effd', ensureWorkPeriodByIdResponse: { - projectId: 111, userHandle: 'pshah_manager', - endDate: '2021-03-13' + updatedBy: null, + endDate: '2020-10-31', + daysPaid: 2, + resourceBookingId: '8694a939-45fe-482e-bee2-3b530acf4139', + daysWorked: 5, + createdAt: '2021-06-13T18:21:52.564Z', + createdBy: '00000000-0000-0000-0000-000000000000', + paymentTotal: 5.29, + id: '467b4df7-ced4-41b9-9710-b83808cddaf4', + projectId: 17234, + startDate: '2020-10-25', + paymentStatus: 'partially-completed', + updatedAt: '2021-06-13T18:25:08.492Z' + }, + workPeriodWithPayments: { + userHandle: 'pshah_manager', + updatedBy: null, + endDate: '2020-10-31', + daysPaid: 2, + resourceBookingId: '8694a939-45fe-482e-bee2-3b530acf4139', + daysWorked: 5, + createdAt: '2021-06-13T18:21:52.564Z', + createdBy: '00000000-0000-0000-0000-000000000000', + paymentTotal: 5.29, + id: '467b4df7-ced4-41b9-9710-b83808cddaf4', + projectId: 17234, + startDate: '2020-10-25', + paymentStatus: 'partially-completed', + updatedAt: '2021-06-13T18:25:08.492Z', + payments: [ + { + amount: 5.29, + updatedBy: null, + billingAccountId: 80000071, + workPeriodId: '467b4df7-ced4-41b9-9710-b83808cddaf4', + createdAt: '2021-06-13T18:22:10.258Z', + challengeId: '00000000-0000-0000-0000-000000000000', + memberRate: 13.23, + createdBy: '57646ff9-1cd3-4d3c-88ba-eb09a395366c', + customerRate: 13, + days: 2, + statusDetails: null, + id: '2a30b5a1-3558-4795-b516-d03cb098fc0f', + status: 'completed', + updatedAt: '2021-06-13T18:25:08.445Z' + }, + { + amount: 7.31, + updatedBy: null, + billingAccountId: 80000071, + workPeriodId: '467b4df7-ced4-41b9-9710-b83808cddaf4', + createdAt: '2021-06-13T18:22:10.258Z', + challengeId: '00000000-0000-0000-0000-000000000000', + memberRate: 13.23, + createdBy: '79a39efd-91af-494a-b0f6-62310495effd', + customerRate: 13, + days: 3, + statusDetails: null, + id: '01971e6f-0f09-4a2a-bc2e-2adac0f00622', + status: 'scheduled', + updatedAt: '2021-06-13T18:25:08.445Z' + } + ] }, ensureResourceBookingByIdResponse: { - billingAccountId: 68800079 + updatedBy: null, + endDate: '2020-10-27', + billingAccountId: 80000071, + userId: 'a55fe1bc-1754-45fa-9adc-cf3d6d7c377a', + jobId: '13c1fcd2-7bbb-4623-8643-ef025dac4c88', + rateType: 'hourly', + createdAt: '2021-06-13T18:21:48.474Z', + memberRate: 13.23, + createdBy: '57646ff9-1cd3-4d3c-88ba-eb09a395366c', + customerRate: 13, + id: '8694a939-45fe-482e-bee2-3b530acf4139', + projectId: 17234, + startDate: '2020-09-27', + status: 'placed', + updatedAt: '2021-06-13T18:21:48.474Z' + }, + workPeriodUpdateResponse: { + userHandle: 'pshah_manager', + updatedBy: null, + endDate: '2020-10-31', + daysPaid: 5, + resourceBookingId: '8694a939-45fe-482e-bee2-3b530acf4139', + daysWorked: 5, + createdAt: '2021-06-13T18:21:52.564Z', + createdBy: '00000000-0000-0000-0000-000000000000', + paymentTotal: 12.6, + id: '467b4df7-ced4-41b9-9710-b83808cddaf4', + projectId: 17234, + startDate: '2020-10-25', + paymentStatus: 'in-progress', + updatedAt: '2021-06-13T18:25:08.492Z' + }, + workPeriodUpdateRequest: { + daysPaid: 5, + paymentTotal: 12.6, + paymentStatus: 'in-progress' + }, + ensureResourceBookingByIdResponse02: { + updatedBy: null, + endDate: '2020-10-27', + billingAccountId: null, + userId: 'a55fe1bc-1754-45fa-9adc-cf3d6d7c377a', + jobId: '13c1fcd2-7bbb-4623-8643-ef025dac4c88', + rateType: 'hourly', + createdAt: '2021-06-13T18:21:48.474Z', + memberRate: 13.23, + createdBy: '57646ff9-1cd3-4d3c-88ba-eb09a395366c', + customerRate: 13, + id: '8694a939-45fe-482e-bee2-3b530acf4139', + projectId: 17234, + startDate: '2020-09-27', + status: 'placed', + updatedAt: '2021-06-13T18:21:48.474Z' }, - ensureResourceBookingByIdResponse02: {}, createPaymentResponse: { id: 'c65f0cbf-b197-423d-91cc-db6e3bad9075' } } workPeriodPayment01.response.toJSON = function () { - return workPeriodPayment01.response + return workPeriodPayment01.response.dataValues +} +workPeriodPayment01.ensureWorkPeriodByIdResponse.toJSON = function () { + return workPeriodPayment01.ensureWorkPeriodByIdResponse +} +workPeriodPayment01.ensureResourceBookingByIdResponse.toJSON = function () { + return workPeriodPayment01.ensureResourceBookingByIdResponse +} +workPeriodPayment01.workPeriodWithPayments.toJSON = function () { + return workPeriodPayment01.workPeriodWithPayments +} +workPeriodPayment01.workPeriodWithPayments.update = function () {} +workPeriodPayment01.workPeriodUpdateResponse.toJSON = function () { + return workPeriodPayment01.workPeriodUpdateResponse +} +workPeriodPayment01.ensureResourceBookingByIdResponse02.toJSON = function () { + return workPeriodPayment01.ensureResourceBookingByIdResponse02 } - module.exports = { workPeriodPayment01 }