Skip to content
This repository was archived by the owner on Mar 13, 2025. It is now read-only.

Commit e705183

Browse files
author
dengjun
committed
API update finished
1 parent 5b509c2 commit e705183

File tree

5 files changed

+193
-3
lines changed

5 files changed

+193
-3
lines changed

.circleci/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ workflows:
7676
filters:
7777
branches:
7878
only:
79-
- dev
79+
- gigs-filter
8080

8181
# Production builds are exectuted only on tagged commits to the
8282
# master branch.

src/api/app-constants.js

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,60 @@ const Scopes = {
1111
ALL_PROFILE: "all:earn-profile",
1212
};
1313

14+
const MY_GIGS_JOB_STATUS = {
15+
APPLIED: "applied",
16+
SKILLS_TEST: "skills-test",
17+
PHONE_SCREEN: "phone-screen",
18+
SCREEN_PASS: "open",
19+
INTERVIEW: "interview",
20+
SELECTED: "selected",
21+
OFFERED: "offered",
22+
PLACED: "placed",
23+
REJECTED_OTHER: "rejected - other",
24+
REJECTED_PRE_SCREEN: "rejected-pre-screen",
25+
CLIENT_REJECTED_INTERVIEW: "client rejected - interview",
26+
CLIENT_REJECTED_SCREENING: "client rejected - screening",
27+
JOB_CLOSED: "job-closed",
28+
};
29+
30+
const JOB_APPLICATION_STATUS_MAPPER = {
31+
open_jobs: {
32+
statuses: [
33+
MY_GIGS_JOB_STATUS.SKILLS_TEST,
34+
MY_GIGS_JOB_STATUS.PHONE_SCREEN,
35+
MY_GIGS_JOB_STATUS.SCREEN_PASS,
36+
MY_GIGS_JOB_STATUS.INTERVIEW,
37+
MY_GIGS_JOB_STATUS.SELECTED,
38+
MY_GIGS_JOB_STATUS.OFFERED,
39+
MY_GIGS_JOB_STATUS.PLACED,
40+
],
41+
},
42+
completed_jobs: {
43+
statuses: [MY_GIGS_JOB_STATUS.PLACED],
44+
},
45+
archived_jobs: {
46+
statuses: [
47+
MY_GIGS_JOB_STATUS.SKILLS_TEST,
48+
MY_GIGS_JOB_STATUS.PHONE_SCREEN,
49+
MY_GIGS_JOB_STATUS.SCREEN_PASS,
50+
MY_GIGS_JOB_STATUS.INTERVIEW,
51+
MY_GIGS_JOB_STATUS.SELECTED,
52+
MY_GIGS_JOB_STATUS.OFFERED,
53+
MY_GIGS_JOB_STATUS.JOB_CLOSED,
54+
MY_GIGS_JOB_STATUS.REJECTED_OTHER,
55+
MY_GIGS_JOB_STATUS.REJECTED_PRE_SCREEN,
56+
MY_GIGS_JOB_STATUS.CLIENT_REJECTED_INTERVIEW,
57+
MY_GIGS_JOB_STATUS.CLIENT_REJECTED_SCREENING,
58+
MY_GIGS_JOB_STATUS.PLACED,
59+
],
60+
},
61+
};
62+
63+
const MIN_HOUR_PER_WEEK_TO_WITHDRAW = 20;
64+
1465
module.exports = {
1566
Scopes,
67+
MY_GIGS_JOB_STATUS,
68+
JOB_APPLICATION_STATUS_MAPPER,
69+
MIN_HOUR_PER_WEEK_TO_WITHDRAW,
1670
};

src/api/common/helper.js

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
const _ = require("lodash");
66
const config = require("config");
7+
const constants = require("../app-constants");
78
const logger = require("./logger");
89
const httpStatus = require("http-status");
910
const Interceptor = require("express-interceptor");
@@ -265,10 +266,18 @@ async function getCurrentUserDetails(token) {
265266
*/
266267
async function getJobCandidates(criteria) {
267268
const token = await getM2MToken();
269+
let body = { statuses: [] };
270+
if (criteria.status) {
271+
body = constants.JOB_APPLICATION_STATUS_MAPPER[criteria.status] || {
272+
statuses: [],
273+
};
274+
}
275+
delete criteria.status;
268276
const url = `${config.API.V5}/jobCandidates`;
269277
const res = await request
270278
.get(url)
271279
.query(criteria)
280+
.send(body)
272281
.set("Authorization", `Bearer ${token}`)
273282
.set("Accept", "application/json");
274283
localLogger.debug({
@@ -283,6 +292,103 @@ async function getJobCandidates(criteria) {
283292
};
284293
}
285294

295+
/**
296+
*
297+
* @param {*} jobCandidates
298+
* @param {*} userId
299+
* @returns
300+
*/
301+
async function handlePlacedJobCandidates(jobCandidates, userId) {
302+
if (!jobCandidates || jobCandidates.length == 0 || !userId) {
303+
return;
304+
}
305+
const placedJobs = jobCandidates.filter(
306+
(item) => item.status == constants.MY_GIGS_JOB_STATUS.PLACED
307+
);
308+
if (placedJobs.length == 0) {
309+
return;
310+
}
311+
const token = await getM2MToken();
312+
const url = `${config.API.V5}/resourceBookings`;
313+
const criteria = {
314+
userId: userId,
315+
page: 1,
316+
perPage: placedJobs.length,
317+
};
318+
const body = {
319+
jobIds: _.map(placedJobs, "jobId"),
320+
};
321+
const res = await request
322+
.get(url)
323+
.query(criteria)
324+
.send(body)
325+
.set("Authorization", `Bearer ${token}`)
326+
.set("Accept", "application/json");
327+
localLogger.debug({
328+
context: "handlePlacedJobCandidates",
329+
message: `response body: ${JSON.stringify(res.body)}`,
330+
});
331+
if (res.body && res.body.length == 0) {
332+
return;
333+
}
334+
// Handle placed job status with RB result
335+
const rbRes = res.body;
336+
_.each(rbRes, (rb) => {
337+
const jc = jobCandidates.find(
338+
(item) => item.userId == rb.userId && item.jobId == rb.jobId
339+
);
340+
if (jc) {
341+
// jc.completed = (new Date(rb.endDate) <= new Date()) && rb.status == 'placed'
342+
jc.completed = new Date(rb.endDate) <= new Date();
343+
}
344+
});
345+
return;
346+
}
347+
348+
function handleArchivedJobCandidates(jobCandidates, jobs) {
349+
if (
350+
!jobCandidates ||
351+
jobCandidates.length == 0 ||
352+
!jobs ||
353+
jobs.length == 0
354+
) {
355+
return;
356+
}
357+
// find at least one placed jobCandidate whose job is having hoursPerWeek >= 20
358+
// if true, assign all open application with a withdraw status = true
359+
// else, assign all open application with a withdraw status = false
360+
let assignWithDraw = false;
361+
const jcs = jobCandidates.filter(
362+
(item) =>
363+
item.status == constants.MY_GIGS_JOB_STATUS.PLACED && !item.completed
364+
);
365+
_.each(jcs, (jc) => {
366+
const job = _.find(jobs, ["id", jc.jobId]);
367+
if (job.hoursPerWeek >= constants.MIN_HOUR_PER_WEEK_TO_WITHDRAW) {
368+
assignWithDraw = true;
369+
return;
370+
}
371+
});
372+
373+
const openJobs = [
374+
constants.MY_GIGS_JOB_STATUS.SKILLS_TEST,
375+
constants.MY_GIGS_JOB_STATUS.PHONE_SCREEN,
376+
constants.MY_GIGS_JOB_STATUS.SCREEN_PASS,
377+
constants.MY_GIGS_JOB_STATUS.INTERVIEW,
378+
constants.MY_GIGS_JOB_STATUS.SELECTED,
379+
constants.MY_GIGS_JOB_STATUS.OFFERED,
380+
];
381+
_.each(jobCandidates, (jobCandidate) => {
382+
if (openJobs.indexOf(jobCandidate.status) >= 0) {
383+
jobCandidate.withdraw = assignWithDraw;
384+
} else if (jobCandidate.status == constants.MY_GIGS_JOB_STATUS.PLACED) {
385+
jobCandidate.withdraw = !!jobCandidate.completed;
386+
} else {
387+
jobCandidate.withdraw = true;
388+
}
389+
});
390+
}
391+
286392
/**
287393
* Return jobs by given criteria
288394
* @param {string} criteria the search criteria
@@ -467,6 +573,8 @@ module.exports = {
467573
getM2MToken,
468574
getCurrentUserDetails,
469575
getJobCandidates,
576+
handlePlacedJobCandidates,
577+
handleArchivedJobCandidates,
470578
getJobs,
471579
getMember,
472580
getMemberTraits,

src/api/docs/swagger.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@ paths:
4949
type: string
5050
default: desc
5151
enum: ["desc", "asc"]
52+
- in: query
53+
name: status
54+
required: false
55+
schema:
56+
type: string
57+
enum: ["open_jobs", "completed_jobs", "archived_jobs"]
5258
responses:
5359
"200":
5460
description: OK

src/api/services/JobApplicationService.js

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ async function getMyJobApplications(currentUser, criteria) {
1818
const perPage = criteria.perPage;
1919
const sortBy = criteria.sortBy;
2020
const sortOrder = criteria.sortOrder;
21+
const status = criteria.status || "";
2122
const emptyResult = {
2223
total: 0,
2324
page,
@@ -44,16 +45,32 @@ async function getMyJobApplications(currentUser, criteria) {
4445
perPage,
4546
sortBy,
4647
sortOrder,
48+
status,
4749
});
4850
// if no candidates found then return empty result
4951
if (jobCandidates.result.length === 0) {
5052
return emptyResult;
5153
}
52-
const jobIds = _.map(jobCandidates.result, "jobId");
54+
let jcResult = jobCandidates.result;
55+
// handle placed status for completed_jobs, archived_jobs query
56+
if (status && status != "open_jobs") {
57+
await helper.handlePlacedJobCandidates(jobCandidates.result, userId);
58+
jcResult = jobCandidates.result.filter(
59+
(item) =>
60+
item.status != "placed" || (item.status == "placed" && item.completed)
61+
);
62+
}
63+
64+
const jobIds = _.map(jcResult, "jobId");
5365
// get jobs of current user by calling taas-api
5466
const { result: jobs } = await helper.getJobs({ jobIds, page: 1, perPage });
67+
68+
if (status && status == "archived_jobs") {
69+
helper.handleArchivedJobCandidates(jcResult, jobs);
70+
jcResult = jcResult.filter((item) => item.withdraw);
71+
}
5572
// apply desired structure
56-
const jobApplications = _.map(jobCandidates.result, (jobCandidate) => {
73+
const jobApplications = _.map(jcResult, (jobCandidate) => {
5774
const job = _.find(jobs, ["id", jobCandidate.jobId]);
5875
return {
5976
title: job.title,
@@ -92,6 +109,11 @@ getMyJobApplications.schema = Joi.object()
92109
perPage: Joi.perPage(),
93110
sortBy: Joi.string().valid("id", "status").default("id"),
94111
sortOrder: Joi.string().valid("desc", "asc").default("desc"),
112+
status: Joi.string().valid(
113+
"open_jobs",
114+
"completed_jobs",
115+
"archived_jobs"
116+
),
95117
})
96118
.required(),
97119
})

0 commit comments

Comments
 (0)