jp-shared 1.0.0

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.
Files changed (82) hide show
  1. package/configs/firebase-admin.js +24 -0
  2. package/configs/index.js +3 -0
  3. package/constants/configuration.js +6 -0
  4. package/constants/database.js +6 -0
  5. package/constants/index.js +6 -0
  6. package/constants/org.js +30 -0
  7. package/constants/time-constant.js +4 -0
  8. package/helpers/index.js +4 -0
  9. package/helpers/otp-helper.js +48 -0
  10. package/helpers/validateMongoId.js +13 -0
  11. package/index.js +15 -0
  12. package/models/admin-models/admin-model.js +62 -0
  13. package/models/admin-models/index.js +4 -0
  14. package/models/admin-models/token-model.js +20 -0
  15. package/models/candidate-models/candidateModel.js +375 -0
  16. package/models/candidate-models/index.js +8 -0
  17. package/models/candidate-models/mobileOTPModel.js +75 -0
  18. package/models/candidate-models/otpModel.js +75 -0
  19. package/models/candidate-models/requestModel.js +26 -0
  20. package/models/candidate-models/savedJobModel.js +20 -0
  21. package/models/candidate-models/searchAppearanceModel.js +50 -0
  22. package/models/candidate-models/tokenModel.js +20 -0
  23. package/models/common-models/course-model.js +20 -0
  24. package/models/common-models/downloadedResumeHistory-model.js +54 -0
  25. package/models/common-models/education-model.js +17 -0
  26. package/models/common-models/index.js +19 -0
  27. package/models/common-models/jobApplication-model.js +57 -0
  28. package/models/common-models/jobApproach-model.js +14 -0
  29. package/models/common-models/jobOffer-model.js +20 -0
  30. package/models/common-models/jobType-model.js +22 -0
  31. package/models/common-models/noticePeriod.js +14 -0
  32. package/models/common-models/paymentHistory-model.js +128 -0
  33. package/models/common-models/plan-model.js +144 -0
  34. package/models/common-models/role-model.js +22 -0
  35. package/models/common-models/searchAppearanceHistory-model.js +36 -0
  36. package/models/common-models/skill-model.js +21 -0
  37. package/models/common-models/sms-student-model.js +44 -0
  38. package/models/common-models/speakingLanguage.js +14 -0
  39. package/models/common-models/specialization-model.js +20 -0
  40. package/models/common-models/viewedProfileHistory-model.js +44 -0
  41. package/models/index.js +8 -0
  42. package/models/jobPost-models/active-model.js +71 -0
  43. package/models/jobPost-models/draft-model.js +42 -0
  44. package/models/jobPost-models/expired-model.js +46 -0
  45. package/models/jobPost-models/index.js +10 -0
  46. package/models/jobPost-models/invitation-model.js +72 -0
  47. package/models/jobPost-models/onHold-model.js +58 -0
  48. package/models/jobPost-models/pending-model.js +45 -0
  49. package/models/jobPost-models/rejected-model.js +51 -0
  50. package/models/jobPost-models/verification-model.js +50 -0
  51. package/models/organization-models/active-model.js +111 -0
  52. package/models/organization-models/index.js +4 -0
  53. package/models/organization-models/verification-model.js +52 -0
  54. package/models/recruiter-models/active-model.js +45 -0
  55. package/models/recruiter-models/basicDetail-model.js +113 -0
  56. package/models/recruiter-models/counter-model.js +13 -0
  57. package/models/recruiter-models/emailOTP-model.js +68 -0
  58. package/models/recruiter-models/index.js +10 -0
  59. package/models/recruiter-models/mobileOTP-model.js +88 -0
  60. package/models/recruiter-models/pending-model.js +44 -0
  61. package/models/recruiter-models/request-model.js +75 -0
  62. package/models/recruiter-models/token-model.js +15 -0
  63. package/models/recruiter-models/verification-model.js +63 -0
  64. package/package.json +28 -0
  65. package/schemes/address-schema.js +43 -0
  66. package/schemes/index.js +7 -0
  67. package/schemes/pendingJobPostStep1-schema.js +192 -0
  68. package/schemes/pendingJobPostStep2-scheme.js +117 -0
  69. package/schemes/pendingJobPostStep3-scheme.js +21 -0
  70. package/schemes/pendingJobPostStep4-scheme.js +22 -0
  71. package/utils/env-utils.js +12 -0
  72. package/utils/firebase-utils.js +220 -0
  73. package/utils/index.js +12 -0
  74. package/utils/invoiceTemplate.js +123 -0
  75. package/utils/otp-utils.js +23 -0
  76. package/utils/password-utils.js +49 -0
  77. package/utils/percentageWeights.js +106 -0
  78. package/utils/populate-utils.js +57 -0
  79. package/utils/sendEmail-utils.js +40 -0
  80. package/utils/sendInvoice-utils.js +139 -0
  81. package/utils/token-utils.js +18 -0
  82. package/utils/validate-utils.js +118 -0
@@ -0,0 +1,24 @@
1
+ require("dotenv").config();
2
+ const admin = require("firebase-admin");
3
+
4
+ // console.log(process.env.MY_FIREBASE_SERVICE_ACCOUNT, "serviceAccount");
5
+
6
+ const serviceAccount = JSON.parse(process.env.MY_FIREBASE_SERVICE_ACCOUNT);
7
+
8
+ if (!serviceAccount) {
9
+ console.error(
10
+ "MY_FIREBASE_SERVICE_ACCOUNT is not set in the environment or is invalid."
11
+ );
12
+ process.exit(1); // Exit the process if the service account is not set
13
+ }
14
+
15
+ // Initialize Firebase Admin SDK
16
+ admin.initializeApp({
17
+ credential: admin.credential.cert(serviceAccount),
18
+ storageBucket: process.env.STORAGE_BUCKET_NAME, // Ensure this matches your Firebase storage bucket
19
+ });
20
+
21
+ const storage = admin.storage();
22
+ const bucket = storage.bucket();
23
+
24
+ module.exports = { bucket };
@@ -0,0 +1,3 @@
1
+ module.exports = {
2
+ ...require("./firebase-admin"),
3
+ };
@@ -0,0 +1,6 @@
1
+ module.exports = {
2
+ // Configuration constants
3
+ REGION: "asia-south1",
4
+ MONGO_URI: `mongodb+srv://${process.env.MONGODB_USERNAME}:${process.env.MONGODB_PASSWORD}@oceanacademy.atrtb.mongodb.net/?retryWrites=true&w=majority&appName=OceanAcademy`,
5
+ MONGO_OPTIONS: { maxPoolSize: 20 }, // Connection Pooling
6
+ };
@@ -0,0 +1,6 @@
1
+ const { isProduction } = require("../utils/env-utils");
2
+
3
+ module.exports = {
4
+ // Database constants
5
+ getDatabaseName: () => isProduction() ? "OA_Job_Portal_API" : "OA_Job_Portal_API_TEST",
6
+ };
@@ -0,0 +1,6 @@
1
+ module.exports = {
2
+ ...require("./time-constant"),
3
+ ...require("./database"),
4
+ ...require("./configuration"),
5
+ ...require("./org"),
6
+ };
@@ -0,0 +1,30 @@
1
+ const COMPANY_NAME = "Ocean Academy IT Solution";
2
+ const COMPANY_ADDRESS =
3
+ "No. 10, 2nd Floor, 45 Feet Road, Vengateswara Nagar, Near HDFC Bank, Saram, Puducherry-605013.";
4
+ const LOGO_URL =
5
+ "https://recruiter.oceanacademy.co.in/assets/recuiterLogo-Pau498dW.png";
6
+ const SUPPORT_EMAIL = "Oceanacademy@gmail.com";
7
+ const SUPPORT_MOBILE = "9458348957";
8
+ const GST_NUMBER = "85734985fhjd92347128";
9
+ const TERMS_URL = "https://recruiter.oceanacademy.co.in/terms-condition";
10
+
11
+ const OUR_ORG_INFO = {
12
+ companyName: COMPANY_NAME,
13
+ companyAddress: COMPANY_ADDRESS,
14
+ logoUrl: LOGO_URL,
15
+ supportEmail: SUPPORT_EMAIL,
16
+ supportMobile: SUPPORT_MOBILE,
17
+ gstNumber: GST_NUMBER,
18
+ termsUrl: TERMS_URL,
19
+ };
20
+
21
+ module.exports = {
22
+ OUR_ORG_INFO,
23
+ LOGO_URL,
24
+ COMPANY_ADDRESS,
25
+ COMPANY_NAME,
26
+ SUPPORT_EMAIL,
27
+ SUPPORT_MOBILE,
28
+ GST_NUMBER,
29
+ TERMS_URL,
30
+ };
@@ -0,0 +1,4 @@
1
+ const TEN_MINUTES_IN_MS = 10 * 60 * 1000;
2
+ const TWO_MINUTES_IN_MS = 2 * 60 * 1000;
3
+
4
+ module.exports = { TEN_MINUTES_IN_MS, TWO_MINUTES_IN_MS };
@@ -0,0 +1,4 @@
1
+ module.exports = {
2
+ ...require("./otp-helper"),
3
+ ...require("./validateMongoId"),
4
+ };
@@ -0,0 +1,48 @@
1
+ // Helper function to send OTP via SMS
2
+ const axios = require("axios");
3
+
4
+ const sendOTPviaSMS = async (name, mobileNumber, otpCode) => {
5
+ // Validate name
6
+ if (!name || typeof name !== "string" || name.trim().length === 0) {
7
+ throw new Error(
8
+ "Invalid or missing name. Name must be a non-empty string."
9
+ );
10
+ }
11
+
12
+ // Validate mobile number
13
+ if (
14
+ !mobileNumber ||
15
+ typeof mobileNumber !== "string" ||
16
+ !/^\d{10}$/.test(mobileNumber)
17
+ ) {
18
+ throw new Error(
19
+ "Invalid or missing mobile number. It must be exactly 10 digits."
20
+ );
21
+ }
22
+
23
+ // Validate OTP code as a string
24
+ if (!otpCode || typeof otpCode !== "string" || !/^\d{4,6}$/.test(otpCode)) {
25
+ throw new Error(
26
+ "Invalid or missing OTP. OTP must be a string with 4 to 6 digits."
27
+ );
28
+ }
29
+
30
+ // Construct the message
31
+ const message = `Dear ${name}, Your OTP is: ${otpCode}. Please enter this code to verify your identity. Do not share this OTP with anyone. - OCEAN ACADEMY`;
32
+
33
+ // Construct the SMS URL
34
+ const smsUrl = `https://sapteleservices.com/SMS_API/sendsms.php?username=oceanacademy&password=Ocean@123&mobile=${mobileNumber}&sendername=OCEAJP&message=${encodeURIComponent(
35
+ message
36
+ )}&routetype=1&tid=1707172233290230214`;
37
+
38
+ try {
39
+ // Send the SMS
40
+ await axios.get(smsUrl);
41
+ } catch (error) {
42
+ // Log and rethrow the error
43
+ console.error("Error in sendOTPviaSMS:", error.message);
44
+ throw new Error("Failed to send OTP. Reason: " + error.message);
45
+ }
46
+ };
47
+
48
+ module.exports = { sendOTPviaSMS };
@@ -0,0 +1,13 @@
1
+ const mongoose = require("mongoose");
2
+
3
+ // Helper function to check if an array contains valid MongoDB ObjectIds
4
+ const areValidObjectIds = (ids) =>
5
+ ids.every((id) => mongoose.Types.ObjectId.isValid(id));
6
+
7
+ // Helper function to check if it contains valid MongoDB ObjectIds
8
+ const isValidObjectId = (id) => mongoose.Types.ObjectId.isValid(id);
9
+
10
+ module.exports = {
11
+ areValidObjectIds,
12
+ isValidObjectId,
13
+ };
package/index.js ADDED
@@ -0,0 +1,15 @@
1
+ const configs = require("./configs");
2
+ const constants = require("./constants");
3
+ const helpers = require("./helpers");
4
+ const models = require("./models");
5
+ const schemes = require("./schemes");
6
+ const utils = require("./utils");
7
+
8
+ module.exports = {
9
+ configs,
10
+ constants,
11
+ helpers,
12
+ models,
13
+ schemes,
14
+ utils,
15
+ };
@@ -0,0 +1,62 @@
1
+ const mongoose = require("mongoose");
2
+ const { hashPassword } = require("../../utils");
3
+ const { getDatabaseName } = require("../../constants");
4
+
5
+ // Define the schema with validation and best practices
6
+ const schema = new mongoose.Schema(
7
+ {
8
+ email: {
9
+ type: String,
10
+ required: true,
11
+ unique: true,
12
+ lowercase: true,
13
+ trim: true,
14
+ validate: {
15
+ validator: function (v) {
16
+ return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v);
17
+ },
18
+ message: (props) => `${props.value} is not a valid email!`,
19
+ },
20
+ },
21
+ otp: {
22
+ type: String,
23
+ required: true,
24
+ // minlength: 6, // Ensure a minimum OTP length
25
+ // maxlength: 6, // Ensure a maximum OTP length
26
+ },
27
+ sentAt: {
28
+ type: Date,
29
+ required: true,
30
+ default: Date.now,
31
+ },
32
+ expiresAt: {
33
+ type: Date,
34
+ required: true,
35
+ },
36
+ },
37
+ {
38
+ timestamps: true, // Automatically adds createdAt and updatedAt fields
39
+ }
40
+ );
41
+
42
+ // Pre-save hook to hash the OTP before saving
43
+ schema.pre("save", async function (next) {
44
+ if (!this.isModified("otp")) {
45
+ return next();
46
+ }
47
+
48
+ try {
49
+ this.otp = await hashPassword(this.otp); // Hash the OTP
50
+ next();
51
+ } catch (error) {
52
+ next(error); // Pass the error to the next middleware
53
+ }
54
+ });
55
+
56
+ // Using a separate database instance
57
+ const myDB = mongoose.connection.useDb(getDatabaseName());
58
+
59
+ // Model definition
60
+ const AdminModel = myDB.model("Admin", schema);
61
+
62
+ module.exports = AdminModel;
@@ -0,0 +1,4 @@
1
+ module.exports = {
2
+ AdminModel: require("./admin-model"),
3
+ AdminTokenModel: require("./token-model"),
4
+ };
@@ -0,0 +1,20 @@
1
+ const mongoose = require("mongoose");
2
+ const { getDatabaseName } = require("../../constants");
3
+
4
+ const schema = new mongoose.Schema({
5
+ adminId: {
6
+ type: mongoose.Schema.Types.ObjectId,
7
+ ref: "Admin", // Reference to the Admin model
8
+ required: true,
9
+ },
10
+ token: {
11
+ type: String,
12
+ required: true,
13
+ },
14
+ });
15
+
16
+ const myDB = mongoose.connection.useDb(getDatabaseName());
17
+
18
+ const AdminTokenModel = myDB.model("admin-token", schema);
19
+
20
+ module.exports = AdminTokenModel;
@@ -0,0 +1,375 @@
1
+ const mongoose = require("mongoose");
2
+ const { percentageWeights } = require("../../utils");
3
+ const { getDatabaseName } = require("../../constants");
4
+ const { ObjectId } = mongoose.Types;
5
+
6
+ // Enum Definitions
7
+ const WORK_STATUS = ["fresher", "experienced", null];
8
+ const MARITAL_STATUS = [
9
+ "married",
10
+ "unmarried",
11
+ "widowed",
12
+ "divorced",
13
+ "separated",
14
+ "other",
15
+ null,
16
+ ];
17
+ const GENDER = ["male", "female", "other", null];
18
+ const PROJECT_STATUS = ["completed", "notCompleted", null];
19
+
20
+ const educationSchema = new mongoose.Schema({
21
+ _id: { type: ObjectId, auto: true },
22
+ qualificationId: { type: ObjectId, required: true },
23
+ // qualification: { type: String, required: true },
24
+ specializationId: {
25
+ type: ObjectId,
26
+ required: function () {
27
+ return !this.isOther;
28
+ },
29
+ default: null,
30
+ },
31
+ // specialization: { type: String, required: true },
32
+ courseId: {
33
+ type: ObjectId,
34
+ required: function () {
35
+ return !this.isOther;
36
+ },
37
+ default: null,
38
+ },
39
+ // course: { type: String, required: true },
40
+ institute: { type: String, required: true },
41
+ courseType: { type: String, required: true },
42
+ courseStartYear: {
43
+ type: Number,
44
+ required: true,
45
+ validate: {
46
+ validator: Number.isInteger,
47
+ message: "Course start year must be an integer.",
48
+ },
49
+ },
50
+ courseEndYear: {
51
+ type: Number,
52
+ required: true,
53
+ validate: [
54
+ {
55
+ validator: Number.isInteger,
56
+ message: "Course end year must be an integer.",
57
+ },
58
+ {
59
+ validator: function (value) {
60
+ return this.courseStartYear <= value;
61
+ },
62
+ message:
63
+ "Course start year must be less than or equal to course end year.",
64
+ },
65
+ ],
66
+ },
67
+ courseStartMonth: {
68
+ type: Number,
69
+ required: true,
70
+ min: 1,
71
+ max: 12,
72
+ },
73
+ courseEndMonth: {
74
+ type: Number,
75
+ required: true,
76
+ min: 1,
77
+ max: 12,
78
+ validate: {
79
+ validator: function (value) {
80
+ if (this.courseStartYear === this.courseEndYear) {
81
+ return this.courseStartMonth <= value;
82
+ }
83
+ return true;
84
+ },
85
+ message:
86
+ "Course start month must be less than or equal to course end month within the same year.",
87
+ },
88
+ },
89
+ markPercentage: { type: Number, default: null },
90
+ isPrimary: { type: Boolean, required: true },
91
+ isOther: { type: Boolean, default: false },
92
+ });
93
+
94
+ const schoolSchema = new mongoose.Schema({
95
+ _id: { type: ObjectId, auto: true },
96
+ qualification: { type: String, required: true },
97
+ schoolBoard: { type: String, required: true },
98
+ schoolPassedOutYear: {
99
+ type: Number,
100
+ required: true,
101
+ validate: {
102
+ validator: Number.isInteger,
103
+ message: "School passed-out year must be an integer.",
104
+ },
105
+ },
106
+ schoolPassedOutMonth: {
107
+ type: Number,
108
+ required: true,
109
+ min: 1,
110
+ max: 12,
111
+ validate: {
112
+ validator: Number.isInteger,
113
+ message: "School passed-out month must be an integer.",
114
+ },
115
+ },
116
+ schoolMedium: {
117
+ type: String,
118
+ default: null,
119
+ validate: {
120
+ validator: function (value) {
121
+ return value === null || value.trim().length > 0;
122
+ },
123
+ message: "School medium cannot be an empty string.",
124
+ },
125
+ },
126
+ markPercentage: {
127
+ type: Number,
128
+ default: null,
129
+ min: 0,
130
+ max: 100,
131
+ validate: {
132
+ validator: function (value) {
133
+ if (value !== null && (value < 0 || value > 100)) {
134
+ return false;
135
+ }
136
+ return true;
137
+ },
138
+ message: "Mark percentage must be between 0 and 100.",
139
+ },
140
+ },
141
+ });
142
+
143
+ // Define the schema
144
+ const schema = new mongoose.Schema(
145
+ {
146
+ profilePercentage: { type: Number, default: 0 },
147
+ skillIds: { type: [ObjectId], ref: "skill", default: [] },
148
+ roleIds: { type: [ObjectId], ref: "role", default: [] },
149
+ resume: {
150
+ type: {
151
+ resumeName: { type: String, default: null },
152
+ resumeLink: { type: String, default: null },
153
+ createdAt: { type: Date, default: Date.now },
154
+ },
155
+ default: null,
156
+ },
157
+ linkedIn: { type: String, default: null },
158
+ workStatus: {
159
+ type: String,
160
+ enum: WORK_STATUS,
161
+ default: null,
162
+ validate: {
163
+ validator: function (value) {
164
+ return WORK_STATUS.includes(value);
165
+ },
166
+ message: "Invalid work status",
167
+ },
168
+ },
169
+ experience: {
170
+ type: {
171
+ years: {
172
+ type: Number,
173
+ default: null,
174
+ validate: {
175
+ validator: function (value) {
176
+ return (
177
+ this.workStatus === "fresher" || (value !== null && value >= 0)
178
+ );
179
+ },
180
+ message: "Years of experience must be at least 0 for non-freshers.",
181
+ },
182
+ },
183
+ months: {
184
+ type: Number,
185
+ default: null,
186
+ validate: {
187
+ validator: function (value) {
188
+ return (
189
+ this.workStatus === "fresher" || (value !== null && value >= 0)
190
+ );
191
+ },
192
+ message:
193
+ "Months of experience must be at least 0 for non-freshers.",
194
+ },
195
+ },
196
+ },
197
+ default: null,
198
+ validate: {
199
+ validator: function (value) {
200
+ if (this.workStatus === "fresher") {
201
+ return (
202
+ value === null || (value.years === null && value.months === null)
203
+ );
204
+ }
205
+ return true;
206
+ },
207
+ message: "Experience should be null for freshers.",
208
+ },
209
+ },
210
+ currentSalary: {
211
+ type: Number,
212
+ default: null,
213
+ validate: {
214
+ validator: function (value) {
215
+ return this.workStatus !== "fresher" || value === null;
216
+ },
217
+ message: "currentSalary is required for non-freshers",
218
+ },
219
+ },
220
+ salaryExpectation: {
221
+ type: Number,
222
+ default: null,
223
+ validate: {
224
+ validator: function (value) {
225
+ return value === null || value > 0;
226
+ },
227
+ message: "Salary expectation must be a positive number.",
228
+ },
229
+ },
230
+ noticePeriod: { type: String, default: null },
231
+ profileSummary: { type: String, default: null },
232
+ avatar: { type: String, default: null },
233
+ fullName: { type: String, default: null },
234
+ mobileNumber: { type: Number, default: null },
235
+ email: { type: String, default: null, required: true },
236
+ countryCode: { type: String, default: "+91" },
237
+ maritalStatus: {
238
+ type: String,
239
+ enum: MARITAL_STATUS,
240
+ default: null,
241
+ validate: {
242
+ validator: function (value) {
243
+ return MARITAL_STATUS.includes(value);
244
+ },
245
+ message: "Invalid marital status",
246
+ },
247
+ },
248
+ gender: {
249
+ type: String,
250
+ enum: GENDER,
251
+ default: null,
252
+ validate: {
253
+ validator: function (value) {
254
+ return GENDER.includes(value);
255
+ },
256
+ message: "Invalid gender",
257
+ },
258
+ },
259
+ dob: { type: Date, default: null },
260
+ address: {
261
+ type: {
262
+ city: { type: String, default: null },
263
+ area: { type: String, default: null },
264
+ street: { type: String, default: null },
265
+ pincode: { type: Number, default: null },
266
+ },
267
+ default: null,
268
+ },
269
+ speakingLanguageIds: {
270
+ type: [ObjectId],
271
+ ref: "speaking-language",
272
+ default: [],
273
+ },
274
+ educations: {
275
+ type: [educationSchema],
276
+ default: [],
277
+ },
278
+ // Fields for 10th and 12th qualifications
279
+ schools: {
280
+ type: [schoolSchema],
281
+ default: [],
282
+ validate: {
283
+ validator: function (schools) {
284
+ // Count how many entries are there for 10th and 12th grades
285
+ const count10th = schools.filter(
286
+ (school) => school.qualification === "10th"
287
+ ).length;
288
+ const count12th = schools.filter(
289
+ (school) => school.qualification === "12th"
290
+ ).length;
291
+
292
+ // Ensure there's exactly one entry for 10th and one entry for 12th
293
+ return count10th <= 1 && count12th <= 1;
294
+ },
295
+ message:
296
+ "Candidate must have exactly one school entry for 10th grade and one entry for 12th grade.",
297
+ },
298
+ },
299
+ projects: {
300
+ type: [
301
+ {
302
+ _id: { type: ObjectId, auto: true },
303
+ projectName: { type: String, default: null },
304
+ projectStatus: {
305
+ type: String,
306
+ enum: PROJECT_STATUS,
307
+ default: null,
308
+ validate: {
309
+ validator: function (value) {
310
+ return PROJECT_STATUS.includes(value);
311
+ },
312
+ message: "Invalid project status",
313
+ },
314
+ },
315
+ projectURL: { type: String, default: null },
316
+ projectDescription: { type: String, default: null },
317
+ projectStartYear: { type: Number, default: null },
318
+ projectStartMonth: { type: Number, default: null },
319
+ projectEndYear: {
320
+ type: Number,
321
+ default: null,
322
+ validate: {
323
+ validator: function (value) {
324
+ // Allow non-null value only if the project status is 'completed'
325
+ if (this.projectStatus === "completed" && value === null) {
326
+ return false;
327
+ }
328
+ // Ensure projectEndYear is null if projectStatus is not 'completed'
329
+ if (this.projectStatus !== "completed" && value !== null) {
330
+ return false;
331
+ }
332
+ return true;
333
+ },
334
+ message:
335
+ "projectEndYear must be provided only for completed projects.",
336
+ },
337
+ },
338
+ projectEndMonth: {
339
+ type: Number,
340
+ default: null,
341
+ validate: {
342
+ validator: function (value) {
343
+ if (this.projectStatus === "completed" && value === null) {
344
+ return false;
345
+ }
346
+ if (this.projectStatus !== "completed" && value !== null) {
347
+ return false;
348
+ }
349
+ return true;
350
+ },
351
+ message:
352
+ "projectEndMonth must be provided only for completed projects.",
353
+ },
354
+ },
355
+ },
356
+ ],
357
+ default: [],
358
+ },
359
+ isActive: { type: Boolean, default: true },
360
+ isVerified: { type: Boolean, default: true },
361
+ password: { type: String, default: null },
362
+ isResetPassword: { type: Boolean, default: false },
363
+ },
364
+ { timestamps: { createdAt: true, updatedAt: true } }
365
+ );
366
+
367
+ const myDB = mongoose.connection.useDb(getDatabaseName());
368
+
369
+ schema.index({ isActive: 1 });
370
+ schema.index({ profilePercentage: 1 });
371
+
372
+ // Create the model
373
+ const CandidateModel = myDB.model("candidate", schema);
374
+
375
+ module.exports = CandidateModel;
@@ -0,0 +1,8 @@
1
+ module.exports = {
2
+ CandidateModel: require("./candidateModel"),
3
+ CandidateMobileOTPModel: require("./mobileOTPModel"),
4
+ CandidateOTPModel: require("./otpModel"),
5
+ CandidateRequestModel: require("./requestModel"),
6
+ CandidateSavedJobModel: require("./savedJobModel"),
7
+ SearchAppearanceModel: require("./searchAppearanceModel"),
8
+ };