@goweekdays/core 2.11.16 → 2.11.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/index.d.ts +56 -2
- package/dist/index.js +361 -7
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +364 -7
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1947,6 +1947,49 @@ function useMemberRepo() {
|
|
|
1947
1947
|
);
|
|
1948
1948
|
}
|
|
1949
1949
|
}
|
|
1950
|
+
async function getByUserOrg(user, org) {
|
|
1951
|
+
try {
|
|
1952
|
+
org = new ObjectId7(org);
|
|
1953
|
+
} catch (error) {
|
|
1954
|
+
throw new BadRequestError7("Invalid organization ID.");
|
|
1955
|
+
}
|
|
1956
|
+
try {
|
|
1957
|
+
user = new ObjectId7(user);
|
|
1958
|
+
} catch (error) {
|
|
1959
|
+
throw new BadRequestError7("Invalid user ID.");
|
|
1960
|
+
}
|
|
1961
|
+
try {
|
|
1962
|
+
const cacheKey = makeCacheKey4(namespace_collection, {
|
|
1963
|
+
user: String(user),
|
|
1964
|
+
org: String(org)
|
|
1965
|
+
});
|
|
1966
|
+
const cached = await getCache(cacheKey);
|
|
1967
|
+
if (cached) {
|
|
1968
|
+
logger4.log({
|
|
1969
|
+
level: "info",
|
|
1970
|
+
message: `Cache hit for getByUserOrg member: ${cacheKey}`
|
|
1971
|
+
});
|
|
1972
|
+
return cached;
|
|
1973
|
+
}
|
|
1974
|
+
const data = await collection.findOne({ user, org });
|
|
1975
|
+
setCache(cacheKey, data, 300).then(() => {
|
|
1976
|
+
logger4.log({
|
|
1977
|
+
level: "info",
|
|
1978
|
+
message: `Cache set for member by user and org: ${cacheKey}`
|
|
1979
|
+
});
|
|
1980
|
+
}).catch((err) => {
|
|
1981
|
+
logger4.log({
|
|
1982
|
+
level: "error",
|
|
1983
|
+
message: `Failed to set cache for member by user and org: ${err.message}`
|
|
1984
|
+
});
|
|
1985
|
+
});
|
|
1986
|
+
return data;
|
|
1987
|
+
} catch (error) {
|
|
1988
|
+
throw new InternalServerError5(
|
|
1989
|
+
"Internal server error, failed to retrieve member."
|
|
1990
|
+
);
|
|
1991
|
+
}
|
|
1992
|
+
}
|
|
1950
1993
|
return {
|
|
1951
1994
|
createIndexes,
|
|
1952
1995
|
add,
|
|
@@ -1966,7 +2009,8 @@ function useMemberRepo() {
|
|
|
1966
2009
|
updateStatusById,
|
|
1967
2010
|
deleteById,
|
|
1968
2011
|
updateStatusByOrg,
|
|
1969
|
-
countUserByOrg
|
|
2012
|
+
countUserByOrg,
|
|
2013
|
+
getByUserOrg
|
|
1970
2014
|
};
|
|
1971
2015
|
}
|
|
1972
2016
|
|
|
@@ -10806,7 +10850,11 @@ function useVerificationService() {
|
|
|
10806
10850
|
getVerifications: _getVerifications
|
|
10807
10851
|
} = useVerificationRepo();
|
|
10808
10852
|
const { getUserByEmail } = useUserRepo();
|
|
10809
|
-
const {
|
|
10853
|
+
const {
|
|
10854
|
+
add: addMember,
|
|
10855
|
+
countUserByOrg,
|
|
10856
|
+
getByUserOrg: getMemberByUserOrg
|
|
10857
|
+
} = useMemberRepo();
|
|
10810
10858
|
const { getById: getOrgById } = useOrgRepo();
|
|
10811
10859
|
const { getById: getRoleById } = useRoleRepo();
|
|
10812
10860
|
async function createUserInvite({
|
|
@@ -11138,8 +11186,17 @@ function useVerificationService() {
|
|
|
11138
11186
|
);
|
|
11139
11187
|
}
|
|
11140
11188
|
}
|
|
11189
|
+
const user = await getUserByEmail(value.email);
|
|
11190
|
+
let userId = "";
|
|
11191
|
+
if (user) {
|
|
11192
|
+
userId = String(user._id);
|
|
11193
|
+
}
|
|
11141
11194
|
const memberCount = await countUserByOrg(String(value.org));
|
|
11142
|
-
|
|
11195
|
+
const existingMember = await getMemberByUserOrg(
|
|
11196
|
+
userId,
|
|
11197
|
+
String(value.org)
|
|
11198
|
+
);
|
|
11199
|
+
if (subscription.seats <= memberCount && !existingMember) {
|
|
11143
11200
|
throw new BadRequestError49(
|
|
11144
11201
|
"Organization has reached the maximum number of members for its subscription plan."
|
|
11145
11202
|
);
|
|
@@ -12964,10 +13021,12 @@ function modelJobPost(value) {
|
|
|
12964
13021
|
} catch (error2) {
|
|
12965
13022
|
throw new BadRequestError59("Invalid Org ID");
|
|
12966
13023
|
}
|
|
12967
|
-
|
|
12968
|
-
|
|
12969
|
-
|
|
12970
|
-
|
|
13024
|
+
if (value.company && typeof value.company === "string" && value.company.length === 24) {
|
|
13025
|
+
try {
|
|
13026
|
+
value.company = new ObjectId29(value.company);
|
|
13027
|
+
} catch (error2) {
|
|
13028
|
+
throw new BadRequestError59("Invalid Company ID");
|
|
13029
|
+
}
|
|
12971
13030
|
}
|
|
12972
13031
|
return {
|
|
12973
13032
|
_id: value._id,
|
|
@@ -13101,7 +13160,11 @@ function useJobPostRepo() {
|
|
|
13101
13160
|
{
|
|
13102
13161
|
$project: {
|
|
13103
13162
|
_id: 1,
|
|
13163
|
+
org: 1,
|
|
13104
13164
|
orgName: 1,
|
|
13165
|
+
company: 1,
|
|
13166
|
+
companyName: 1,
|
|
13167
|
+
description: 1,
|
|
13105
13168
|
minSalary: 1,
|
|
13106
13169
|
maxSalary: 1,
|
|
13107
13170
|
currency: 1,
|
|
@@ -13909,6 +13972,295 @@ function useJobPostController() {
|
|
|
13909
13972
|
getCurrencies
|
|
13910
13973
|
};
|
|
13911
13974
|
}
|
|
13975
|
+
|
|
13976
|
+
// src/resources/job-applications/job.applications.model.ts
|
|
13977
|
+
import { BadRequestError as BadRequestError65 } from "@goweekdays/utils";
|
|
13978
|
+
import Joi54 from "joi";
|
|
13979
|
+
import { ObjectId as ObjectId32 } from "mongodb";
|
|
13980
|
+
var jobApplicationStatuses = [
|
|
13981
|
+
"new",
|
|
13982
|
+
"shortlisted",
|
|
13983
|
+
"interview-scheduled",
|
|
13984
|
+
"interviewed",
|
|
13985
|
+
"offer-extended",
|
|
13986
|
+
"hired",
|
|
13987
|
+
"on-hold",
|
|
13988
|
+
"withdrawn",
|
|
13989
|
+
"rejected",
|
|
13990
|
+
// Agency specific
|
|
13991
|
+
"contacted",
|
|
13992
|
+
"endorsed",
|
|
13993
|
+
"client-interested",
|
|
13994
|
+
"pooled",
|
|
13995
|
+
// HR specific
|
|
13996
|
+
"under-review",
|
|
13997
|
+
"for-approval"
|
|
13998
|
+
];
|
|
13999
|
+
var schemaJobApplication = Joi54.object({
|
|
14000
|
+
post: Joi54.string().required(),
|
|
14001
|
+
jobTitle: Joi54.string().optional().allow(""),
|
|
14002
|
+
company: Joi54.string().hex().optional().allow(""),
|
|
14003
|
+
companyName: Joi54.string().optional().allow(""),
|
|
14004
|
+
location: Joi54.string().optional().allow(""),
|
|
14005
|
+
user: Joi54.string().required(),
|
|
14006
|
+
name: Joi54.string().required(),
|
|
14007
|
+
email: Joi54.string().email().required(),
|
|
14008
|
+
contact: Joi54.string().optional().allow(""),
|
|
14009
|
+
metadata: Joi54.object({
|
|
14010
|
+
resume: Joi54.string().optional().allow(""),
|
|
14011
|
+
resumeUrl: Joi54.string().uri().optional().allow(""),
|
|
14012
|
+
portfolio: Joi54.string().optional().allow(""),
|
|
14013
|
+
portfolioUrl: Joi54.string().uri().optional().allow(""),
|
|
14014
|
+
coverLetter: Joi54.string().optional().allow(""),
|
|
14015
|
+
coverLetterUrl: Joi54.string().uri().optional().allow("")
|
|
14016
|
+
}).optional()
|
|
14017
|
+
});
|
|
14018
|
+
function modelJobApplication(data) {
|
|
14019
|
+
const { error } = schemaJobApplication.validate(data);
|
|
14020
|
+
if (error) {
|
|
14021
|
+
throw new BadRequestError65(`Invalid job application data: ${error.message}`);
|
|
14022
|
+
}
|
|
14023
|
+
if (data._id && typeof data._id === "string") {
|
|
14024
|
+
try {
|
|
14025
|
+
data._id = new ObjectId32(data._id);
|
|
14026
|
+
} catch (error2) {
|
|
14027
|
+
throw new BadRequestError65(`Invalid job application _id: ${data._id}`);
|
|
14028
|
+
}
|
|
14029
|
+
}
|
|
14030
|
+
try {
|
|
14031
|
+
data.post = new ObjectId32(data.post);
|
|
14032
|
+
} catch (error2) {
|
|
14033
|
+
throw new BadRequestError65(`Invalid job application post id: ${data.post}`);
|
|
14034
|
+
}
|
|
14035
|
+
if (data.company && typeof data.company === "string") {
|
|
14036
|
+
try {
|
|
14037
|
+
data.company = new ObjectId32(data.company);
|
|
14038
|
+
} catch (error2) {
|
|
14039
|
+
throw new BadRequestError65(
|
|
14040
|
+
`Invalid job application company id: ${data.company}`
|
|
14041
|
+
);
|
|
14042
|
+
}
|
|
14043
|
+
}
|
|
14044
|
+
return {
|
|
14045
|
+
_id: data._id,
|
|
14046
|
+
post: data.post,
|
|
14047
|
+
jobTitle: data.jobTitle,
|
|
14048
|
+
company: data.company,
|
|
14049
|
+
companyName: data.companyName ?? "",
|
|
14050
|
+
location: data.location ?? "",
|
|
14051
|
+
user: data.user,
|
|
14052
|
+
name: data.name,
|
|
14053
|
+
email: data.email,
|
|
14054
|
+
contact: data.contact ?? "",
|
|
14055
|
+
metadata: data.metadata ?? {},
|
|
14056
|
+
status: data.status ?? "new",
|
|
14057
|
+
createdAt: data.createdAt ?? /* @__PURE__ */ new Date(),
|
|
14058
|
+
updatedAt: data.updatedAt ?? "",
|
|
14059
|
+
deletedAt: data.deletedAt ?? ""
|
|
14060
|
+
};
|
|
14061
|
+
}
|
|
14062
|
+
|
|
14063
|
+
// src/resources/job-applications/job.application.repository.ts
|
|
14064
|
+
import {
|
|
14065
|
+
AppError as AppError32,
|
|
14066
|
+
BadRequestError as BadRequestError66,
|
|
14067
|
+
logger as logger37,
|
|
14068
|
+
makeCacheKey as makeCacheKey22,
|
|
14069
|
+
paginate as paginate19,
|
|
14070
|
+
useAtlas as useAtlas31,
|
|
14071
|
+
useCache as useCache23
|
|
14072
|
+
} from "@goweekdays/utils";
|
|
14073
|
+
function useJobApplicationRepo() {
|
|
14074
|
+
const db = useAtlas31.getDb();
|
|
14075
|
+
if (!db) {
|
|
14076
|
+
throw new BadRequestError66("Unable to connect to server.");
|
|
14077
|
+
}
|
|
14078
|
+
const namespace_collection = "job.applications";
|
|
14079
|
+
const collection = db.collection(namespace_collection);
|
|
14080
|
+
const { getCache, setCache, delNamespace } = useCache23(namespace_collection);
|
|
14081
|
+
function delCachedData() {
|
|
14082
|
+
delNamespace().then(() => {
|
|
14083
|
+
logger37.log({
|
|
14084
|
+
level: "info",
|
|
14085
|
+
message: `Cache namespace cleared for ${namespace_collection}`
|
|
14086
|
+
});
|
|
14087
|
+
}).catch((err) => {
|
|
14088
|
+
logger37.log({
|
|
14089
|
+
level: "error",
|
|
14090
|
+
message: `Failed to clear cache namespace for ${namespace_collection}: ${err.message}`
|
|
14091
|
+
});
|
|
14092
|
+
});
|
|
14093
|
+
}
|
|
14094
|
+
async function createIndexes() {
|
|
14095
|
+
try {
|
|
14096
|
+
await collection.createIndexes([
|
|
14097
|
+
{ key: { jobTitle: 1 } },
|
|
14098
|
+
{ key: { company: 1 } },
|
|
14099
|
+
{ key: { companyName: 1 } },
|
|
14100
|
+
{ key: { location: 1 } },
|
|
14101
|
+
{ key: { user: 1 } },
|
|
14102
|
+
{ key: { email: 1 } },
|
|
14103
|
+
{
|
|
14104
|
+
key: {
|
|
14105
|
+
jobTitle: "text",
|
|
14106
|
+
company: "text",
|
|
14107
|
+
companyName: "text",
|
|
14108
|
+
location: "text",
|
|
14109
|
+
name: "text"
|
|
14110
|
+
},
|
|
14111
|
+
name: "job_application_text_search"
|
|
14112
|
+
}
|
|
14113
|
+
]);
|
|
14114
|
+
return "Successfully created job application indexes.";
|
|
14115
|
+
} catch (error) {
|
|
14116
|
+
throw new BadRequestError66("Failed to create job application indexes.");
|
|
14117
|
+
}
|
|
14118
|
+
}
|
|
14119
|
+
async function add(data) {
|
|
14120
|
+
const { error } = schemaJobApplication.validate(data);
|
|
14121
|
+
if (error) {
|
|
14122
|
+
throw new BadRequestError66(
|
|
14123
|
+
`Invalid job application data: ${error.message}`
|
|
14124
|
+
);
|
|
14125
|
+
}
|
|
14126
|
+
try {
|
|
14127
|
+
data = modelJobApplication(data);
|
|
14128
|
+
const res = await collection.insertOne(data);
|
|
14129
|
+
delCachedData();
|
|
14130
|
+
return res.insertedId;
|
|
14131
|
+
} catch (error2) {
|
|
14132
|
+
if (error2 instanceof AppError32) {
|
|
14133
|
+
throw error2;
|
|
14134
|
+
}
|
|
14135
|
+
throw new BadRequestError66(
|
|
14136
|
+
`Failed to create job application: ${error2.message}`
|
|
14137
|
+
);
|
|
14138
|
+
}
|
|
14139
|
+
}
|
|
14140
|
+
async function getAll({
|
|
14141
|
+
page = 1,
|
|
14142
|
+
limit = 10,
|
|
14143
|
+
search = "",
|
|
14144
|
+
status = "new"
|
|
14145
|
+
} = {}) {
|
|
14146
|
+
page = page > 0 ? page - 1 : 0;
|
|
14147
|
+
const query = { status };
|
|
14148
|
+
const cacheKeyOptions = {
|
|
14149
|
+
page,
|
|
14150
|
+
limit,
|
|
14151
|
+
status,
|
|
14152
|
+
tag: "getAll"
|
|
14153
|
+
};
|
|
14154
|
+
if (search) {
|
|
14155
|
+
query.$text = { $search: search };
|
|
14156
|
+
cacheKeyOptions.search = search;
|
|
14157
|
+
}
|
|
14158
|
+
const cacheKey = makeCacheKey22(namespace_collection, cacheKeyOptions);
|
|
14159
|
+
const cachedData = await getCache(cacheKey);
|
|
14160
|
+
if (cachedData) {
|
|
14161
|
+
return cachedData;
|
|
14162
|
+
}
|
|
14163
|
+
try {
|
|
14164
|
+
const items = await collection.aggregate([
|
|
14165
|
+
{ $match: query },
|
|
14166
|
+
{ $skip: page * limit },
|
|
14167
|
+
{ $limit: limit }
|
|
14168
|
+
]).toArray();
|
|
14169
|
+
const length = await collection.countDocuments(query);
|
|
14170
|
+
const data = paginate19(items, page, limit, length);
|
|
14171
|
+
setCache(cacheKey, data).then(() => {
|
|
14172
|
+
logger37.log({
|
|
14173
|
+
level: "info",
|
|
14174
|
+
message: `Cache set for getAll job applications: ${cacheKey}`
|
|
14175
|
+
});
|
|
14176
|
+
}).catch((err) => {
|
|
14177
|
+
logger37.log({
|
|
14178
|
+
level: "error",
|
|
14179
|
+
message: `Failed to set cache for getAll job applications: ${cacheKey}, error: ${err.message}`
|
|
14180
|
+
});
|
|
14181
|
+
});
|
|
14182
|
+
return data;
|
|
14183
|
+
} catch (error) {
|
|
14184
|
+
if (error instanceof AppError32) {
|
|
14185
|
+
throw error;
|
|
14186
|
+
}
|
|
14187
|
+
throw new BadRequestError66(
|
|
14188
|
+
`Failed to get job applications: ${error.message}`
|
|
14189
|
+
);
|
|
14190
|
+
}
|
|
14191
|
+
}
|
|
14192
|
+
return {
|
|
14193
|
+
createIndexes,
|
|
14194
|
+
delCachedData,
|
|
14195
|
+
add,
|
|
14196
|
+
getAll
|
|
14197
|
+
};
|
|
14198
|
+
}
|
|
14199
|
+
|
|
14200
|
+
// src/resources/job-applications/job.application.controller.ts
|
|
14201
|
+
import { AppError as AppError33, BadRequestError as BadRequestError67 } from "@goweekdays/utils";
|
|
14202
|
+
import Joi55 from "joi";
|
|
14203
|
+
function useJobApplicationController() {
|
|
14204
|
+
const { add: _add, getAll: _getAll } = useJobApplicationRepo();
|
|
14205
|
+
async function add(req, res, next) {
|
|
14206
|
+
const { error } = schemaJobApplication.validate(req.body);
|
|
14207
|
+
if (error) {
|
|
14208
|
+
next(
|
|
14209
|
+
new BadRequestError67(`Invalid job application data: ${error.message}`)
|
|
14210
|
+
);
|
|
14211
|
+
return;
|
|
14212
|
+
}
|
|
14213
|
+
try {
|
|
14214
|
+
const message = await _add(req.body);
|
|
14215
|
+
res.json({ message });
|
|
14216
|
+
return;
|
|
14217
|
+
} catch (error2) {
|
|
14218
|
+
if (error2 instanceof AppError33) {
|
|
14219
|
+
next(error2);
|
|
14220
|
+
return;
|
|
14221
|
+
}
|
|
14222
|
+
next(
|
|
14223
|
+
new BadRequestError67(
|
|
14224
|
+
`Failed to create job application: ${error2.message}`
|
|
14225
|
+
)
|
|
14226
|
+
);
|
|
14227
|
+
}
|
|
14228
|
+
}
|
|
14229
|
+
async function getAll(req, res, next) {
|
|
14230
|
+
const validation = Joi55.object({
|
|
14231
|
+
page: Joi55.number().integer().min(1).optional(),
|
|
14232
|
+
limit: Joi55.number().integer().min(1).max(100).optional(),
|
|
14233
|
+
search: Joi55.string().optional().allow(""),
|
|
14234
|
+
status: Joi55.string().valid(...jobApplicationStatuses).optional()
|
|
14235
|
+
});
|
|
14236
|
+
const { error } = validation.validate(req.query);
|
|
14237
|
+
if (error) {
|
|
14238
|
+
next(new BadRequestError67(`Invalid query parameters: ${error.message}`));
|
|
14239
|
+
return;
|
|
14240
|
+
}
|
|
14241
|
+
const page = req.query.page ? parseInt(req.query.page) : 1;
|
|
14242
|
+
const limit = req.query.limit ? parseInt(req.query.limit) : 10;
|
|
14243
|
+
const search = req.query.search ? req.query.search : "";
|
|
14244
|
+
const status = req.query.status ? req.query.status : "new";
|
|
14245
|
+
try {
|
|
14246
|
+
const data = await _getAll({ page, limit, search, status });
|
|
14247
|
+
res.json(data);
|
|
14248
|
+
return;
|
|
14249
|
+
} catch (error2) {
|
|
14250
|
+
if (error2 instanceof AppError33) {
|
|
14251
|
+
next(error2);
|
|
14252
|
+
return;
|
|
14253
|
+
}
|
|
14254
|
+
next(
|
|
14255
|
+
new BadRequestError67(`Failed to get job applications: ${error2.message}`)
|
|
14256
|
+
);
|
|
14257
|
+
}
|
|
14258
|
+
}
|
|
14259
|
+
return {
|
|
14260
|
+
add,
|
|
14261
|
+
getAll
|
|
14262
|
+
};
|
|
14263
|
+
}
|
|
13912
14264
|
export {
|
|
13913
14265
|
ACCESS_TOKEN_EXPIRY,
|
|
13914
14266
|
ACCESS_TOKEN_SECRET,
|
|
@@ -13952,9 +14304,11 @@ export {
|
|
|
13952
14304
|
XENDIT_SECRET_KEY,
|
|
13953
14305
|
currencies,
|
|
13954
14306
|
isDev,
|
|
14307
|
+
jobApplicationStatuses,
|
|
13955
14308
|
ledgerBillStatuses,
|
|
13956
14309
|
ledgerBillTypes,
|
|
13957
14310
|
modelApp,
|
|
14311
|
+
modelJobApplication,
|
|
13958
14312
|
modelJobPost,
|
|
13959
14313
|
modelLedgerBill,
|
|
13960
14314
|
modelMember,
|
|
@@ -13973,6 +14327,7 @@ export {
|
|
|
13973
14327
|
schemaBuilding,
|
|
13974
14328
|
schemaBuildingUnit,
|
|
13975
14329
|
schemaInviteMember,
|
|
14330
|
+
schemaJobApplication,
|
|
13976
14331
|
schemaJobPost,
|
|
13977
14332
|
schemaJobPostUpdate,
|
|
13978
14333
|
schemaLedgerBill,
|
|
@@ -14021,6 +14376,8 @@ export {
|
|
|
14021
14376
|
useFileRepo,
|
|
14022
14377
|
useFileService,
|
|
14023
14378
|
useGitHubService,
|
|
14379
|
+
useJobApplicationController,
|
|
14380
|
+
useJobApplicationRepo,
|
|
14024
14381
|
useJobPostController,
|
|
14025
14382
|
useJobPostRepo,
|
|
14026
14383
|
useJobPostService,
|