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.
- package/configs/firebase-admin.js +24 -0
- package/configs/index.js +3 -0
- package/constants/configuration.js +6 -0
- package/constants/database.js +6 -0
- package/constants/index.js +6 -0
- package/constants/org.js +30 -0
- package/constants/time-constant.js +4 -0
- package/helpers/index.js +4 -0
- package/helpers/otp-helper.js +48 -0
- package/helpers/validateMongoId.js +13 -0
- package/index.js +15 -0
- package/models/admin-models/admin-model.js +62 -0
- package/models/admin-models/index.js +4 -0
- package/models/admin-models/token-model.js +20 -0
- package/models/candidate-models/candidateModel.js +375 -0
- package/models/candidate-models/index.js +8 -0
- package/models/candidate-models/mobileOTPModel.js +75 -0
- package/models/candidate-models/otpModel.js +75 -0
- package/models/candidate-models/requestModel.js +26 -0
- package/models/candidate-models/savedJobModel.js +20 -0
- package/models/candidate-models/searchAppearanceModel.js +50 -0
- package/models/candidate-models/tokenModel.js +20 -0
- package/models/common-models/course-model.js +20 -0
- package/models/common-models/downloadedResumeHistory-model.js +54 -0
- package/models/common-models/education-model.js +17 -0
- package/models/common-models/index.js +19 -0
- package/models/common-models/jobApplication-model.js +57 -0
- package/models/common-models/jobApproach-model.js +14 -0
- package/models/common-models/jobOffer-model.js +20 -0
- package/models/common-models/jobType-model.js +22 -0
- package/models/common-models/noticePeriod.js +14 -0
- package/models/common-models/paymentHistory-model.js +128 -0
- package/models/common-models/plan-model.js +144 -0
- package/models/common-models/role-model.js +22 -0
- package/models/common-models/searchAppearanceHistory-model.js +36 -0
- package/models/common-models/skill-model.js +21 -0
- package/models/common-models/sms-student-model.js +44 -0
- package/models/common-models/speakingLanguage.js +14 -0
- package/models/common-models/specialization-model.js +20 -0
- package/models/common-models/viewedProfileHistory-model.js +44 -0
- package/models/index.js +8 -0
- package/models/jobPost-models/active-model.js +71 -0
- package/models/jobPost-models/draft-model.js +42 -0
- package/models/jobPost-models/expired-model.js +46 -0
- package/models/jobPost-models/index.js +10 -0
- package/models/jobPost-models/invitation-model.js +72 -0
- package/models/jobPost-models/onHold-model.js +58 -0
- package/models/jobPost-models/pending-model.js +45 -0
- package/models/jobPost-models/rejected-model.js +51 -0
- package/models/jobPost-models/verification-model.js +50 -0
- package/models/organization-models/active-model.js +111 -0
- package/models/organization-models/index.js +4 -0
- package/models/organization-models/verification-model.js +52 -0
- package/models/recruiter-models/active-model.js +45 -0
- package/models/recruiter-models/basicDetail-model.js +113 -0
- package/models/recruiter-models/counter-model.js +13 -0
- package/models/recruiter-models/emailOTP-model.js +68 -0
- package/models/recruiter-models/index.js +10 -0
- package/models/recruiter-models/mobileOTP-model.js +88 -0
- package/models/recruiter-models/pending-model.js +44 -0
- package/models/recruiter-models/request-model.js +75 -0
- package/models/recruiter-models/token-model.js +15 -0
- package/models/recruiter-models/verification-model.js +63 -0
- package/package.json +28 -0
- package/schemes/address-schema.js +43 -0
- package/schemes/index.js +7 -0
- package/schemes/pendingJobPostStep1-schema.js +192 -0
- package/schemes/pendingJobPostStep2-scheme.js +117 -0
- package/schemes/pendingJobPostStep3-scheme.js +21 -0
- package/schemes/pendingJobPostStep4-scheme.js +22 -0
- package/utils/env-utils.js +12 -0
- package/utils/firebase-utils.js +220 -0
- package/utils/index.js +12 -0
- package/utils/invoiceTemplate.js +123 -0
- package/utils/otp-utils.js +23 -0
- package/utils/password-utils.js +49 -0
- package/utils/percentageWeights.js +106 -0
- package/utils/populate-utils.js +57 -0
- package/utils/sendEmail-utils.js +40 -0
- package/utils/sendInvoice-utils.js +139 -0
- package/utils/token-utils.js +18 -0
- package/utils/validate-utils.js +118 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const mongoose = require("mongoose");
|
|
2
|
+
const {
|
|
3
|
+
pendingJobPostStep1Schema,
|
|
4
|
+
pendingJobPostStep2Schema,
|
|
5
|
+
pendingJobPostStep3Schema,
|
|
6
|
+
pendingJobPostStep4Schema,
|
|
7
|
+
} = require("../../schemes");
|
|
8
|
+
const { getDatabaseName } = require("../../constants");
|
|
9
|
+
const { ObjectId } = mongoose.Schema.Types;
|
|
10
|
+
|
|
11
|
+
const schema = new mongoose.Schema(
|
|
12
|
+
{
|
|
13
|
+
recruiterId: {
|
|
14
|
+
type: ObjectId,
|
|
15
|
+
required: [true, "Recruiter ID is required"],
|
|
16
|
+
validate: {
|
|
17
|
+
validator: mongoose.Types.ObjectId.isValid,
|
|
18
|
+
message: "Invalid recruiter ID",
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
step1: {
|
|
22
|
+
type: pendingJobPostStep1Schema,
|
|
23
|
+
required: [true, "Step 1 data is required"],
|
|
24
|
+
},
|
|
25
|
+
step2: {
|
|
26
|
+
type: pendingJobPostStep2Schema,
|
|
27
|
+
required: [true, "Step 2 data is required"],
|
|
28
|
+
},
|
|
29
|
+
step3: {
|
|
30
|
+
type: pendingJobPostStep3Schema,
|
|
31
|
+
required: [true, "Step 3 data is required"],
|
|
32
|
+
},
|
|
33
|
+
step4: pendingJobPostStep4Schema, // This will not be required
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
timestamps: { createdAt: true, updatedAt: true },
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
// Create the model
|
|
41
|
+
const myDB = mongoose.connection.useDb(getDatabaseName());
|
|
42
|
+
|
|
43
|
+
const PendingJobPostModel = myDB.model("pending-jobPost", schema);
|
|
44
|
+
|
|
45
|
+
module.exports = PendingJobPostModel;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
const mongoose = require("mongoose");
|
|
2
|
+
const {
|
|
3
|
+
pendingJobPostStep1Schema,
|
|
4
|
+
pendingJobPostStep2Schema,
|
|
5
|
+
pendingJobPostStep3Schema,
|
|
6
|
+
pendingJobPostStep4Schema,
|
|
7
|
+
} = require("../../schemes");
|
|
8
|
+
const { validateReason } = require("../../utils");
|
|
9
|
+
const { getDatabaseName } = require("../../constants");
|
|
10
|
+
const { ObjectId } = mongoose.Schema.Types;
|
|
11
|
+
|
|
12
|
+
const schema = new mongoose.Schema(
|
|
13
|
+
{
|
|
14
|
+
recruiterId: {
|
|
15
|
+
type: ObjectId,
|
|
16
|
+
required: [true, "Recruiter ID is required"],
|
|
17
|
+
validate: {
|
|
18
|
+
validator: mongoose.Types.ObjectId.isValid,
|
|
19
|
+
message: "Invalid recruiter ID",
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
step1: {
|
|
23
|
+
type: pendingJobPostStep1Schema,
|
|
24
|
+
required: [true, "Step 1 data is required"],
|
|
25
|
+
},
|
|
26
|
+
step2: {
|
|
27
|
+
type: pendingJobPostStep2Schema,
|
|
28
|
+
required: [true, "Step 2 data is required"],
|
|
29
|
+
},
|
|
30
|
+
step3: {
|
|
31
|
+
type: pendingJobPostStep3Schema,
|
|
32
|
+
required: [true, "Step 3 data is required"],
|
|
33
|
+
},
|
|
34
|
+
step4: pendingJobPostStep4Schema, // This will not be required
|
|
35
|
+
reason: {
|
|
36
|
+
type: String,
|
|
37
|
+
required: [true, "Reason is required"],
|
|
38
|
+
validate: [validateReason, "Reason must be at least 5 characters long"],
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
timestamps: { createdAt: true, updatedAt: true },
|
|
43
|
+
}
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
// Create the model
|
|
47
|
+
const myDB = mongoose.connection.useDb(getDatabaseName());
|
|
48
|
+
|
|
49
|
+
const RejectedJobPostModel = myDB.model("rejected-jobPost", schema);
|
|
50
|
+
|
|
51
|
+
module.exports = RejectedJobPostModel;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
const mongoose = require("mongoose");
|
|
2
|
+
const {
|
|
3
|
+
pendingJobPostStep1Schema,
|
|
4
|
+
pendingJobPostStep2Schema,
|
|
5
|
+
pendingJobPostStep3Schema,
|
|
6
|
+
pendingJobPostStep4Schema,
|
|
7
|
+
} = require("../../schemes");
|
|
8
|
+
const { getDatabaseName } = require("../../constants");
|
|
9
|
+
const { ObjectId } = mongoose.Schema.Types;
|
|
10
|
+
|
|
11
|
+
const schema = new mongoose.Schema(
|
|
12
|
+
{
|
|
13
|
+
recruiterId: {
|
|
14
|
+
type: ObjectId,
|
|
15
|
+
required: [true, "Recruiter ID is required"],
|
|
16
|
+
validate: {
|
|
17
|
+
validator: mongoose.Types.ObjectId.isValid,
|
|
18
|
+
message: "Invalid recruiter ID",
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
step1: {
|
|
22
|
+
type: pendingJobPostStep1Schema,
|
|
23
|
+
required: [true, "Step 1 data is required"],
|
|
24
|
+
},
|
|
25
|
+
step2: {
|
|
26
|
+
type: pendingJobPostStep2Schema,
|
|
27
|
+
required: [true, "Step 2 data is required"],
|
|
28
|
+
},
|
|
29
|
+
step3: {
|
|
30
|
+
type: pendingJobPostStep3Schema,
|
|
31
|
+
required: [true, "Step 3 data is required"],
|
|
32
|
+
},
|
|
33
|
+
step4: {
|
|
34
|
+
type: pendingJobPostStep4Schema,
|
|
35
|
+
required: [true, "Step 4 data is required"],
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
timestamps: { createdAt: true, updatedAt: true },
|
|
40
|
+
}
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
schema.index({ recruiterId: 1 });
|
|
44
|
+
|
|
45
|
+
// Create the model
|
|
46
|
+
const myDB = mongoose.connection.useDb(getDatabaseName());
|
|
47
|
+
|
|
48
|
+
const VerificationJobPostModel = myDB.model("verification-jobPost", schema);
|
|
49
|
+
|
|
50
|
+
module.exports = VerificationJobPostModel;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
const mongoose = require("mongoose");
|
|
2
|
+
const { addressSchema } = require("../../schemes");
|
|
3
|
+
const { getDatabaseName } = require("../../constants");
|
|
4
|
+
|
|
5
|
+
const { ObjectId } = mongoose.Schema.Types;
|
|
6
|
+
|
|
7
|
+
// Define the schema
|
|
8
|
+
const schema = new mongoose.Schema(
|
|
9
|
+
{
|
|
10
|
+
recruiterId: {
|
|
11
|
+
type: ObjectId,
|
|
12
|
+
required: [true, "Recruiter ID is required"],
|
|
13
|
+
ref: "RecruiterModel",
|
|
14
|
+
},
|
|
15
|
+
organizationLogo: {
|
|
16
|
+
type: String,
|
|
17
|
+
required: [true, "Organization logo is required"],
|
|
18
|
+
// match: [
|
|
19
|
+
// /^(https?:\/\/.*\.(?:png|jpg|jpeg|svg))$/i,
|
|
20
|
+
// "Organization logo must be a valid URL and of type png, jpg, jpeg, or svg",
|
|
21
|
+
// ],
|
|
22
|
+
},
|
|
23
|
+
organizationName: {
|
|
24
|
+
type: String,
|
|
25
|
+
required: [true, "Organization name is required"],
|
|
26
|
+
trim: true,
|
|
27
|
+
minlength: [2, "Organization name must be at least 2 characters long"],
|
|
28
|
+
maxlength: [100, "Organization name cannot exceed 100 characters"],
|
|
29
|
+
},
|
|
30
|
+
normalizedOrganizationName: {
|
|
31
|
+
type: String,
|
|
32
|
+
trim: true,
|
|
33
|
+
minlength: [
|
|
34
|
+
2,
|
|
35
|
+
"Normalized organization name must be at least 2 characters long",
|
|
36
|
+
],
|
|
37
|
+
maxlength: [
|
|
38
|
+
100,
|
|
39
|
+
"Normalized organization name cannot exceed 100 characters",
|
|
40
|
+
],
|
|
41
|
+
lowercase: true, // Ensuring normalization for consistent database querying
|
|
42
|
+
},
|
|
43
|
+
about: {
|
|
44
|
+
type: String,
|
|
45
|
+
required: [true, "About section is required"],
|
|
46
|
+
trim: true,
|
|
47
|
+
minlength: [10, "About section must be at least 10 characters long"],
|
|
48
|
+
maxlength: [1000, "About section cannot exceed 1000 characters"],
|
|
49
|
+
},
|
|
50
|
+
websiteLink: {
|
|
51
|
+
type: String,
|
|
52
|
+
required: [true, "Website link is required"],
|
|
53
|
+
// match: [
|
|
54
|
+
// /^(https?:\/\/)?(www\.)?([a-zA-Z0-9]+)(\.[a-z]{2,})+(\/[^\s]*)?$/,
|
|
55
|
+
// "Website link must be a valid URL",
|
|
56
|
+
// ],
|
|
57
|
+
trim: true,
|
|
58
|
+
},
|
|
59
|
+
gallery: {
|
|
60
|
+
type: [String],
|
|
61
|
+
validate: {
|
|
62
|
+
validator: function (v) {
|
|
63
|
+
return Array.isArray(v) && v.length >= 3 && v.length <= 6;
|
|
64
|
+
},
|
|
65
|
+
message:
|
|
66
|
+
"Gallery should have at least 3 images and a maximum of 6 images.",
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
teamSize: {
|
|
70
|
+
type: String,
|
|
71
|
+
required: [true, "Team size is required"],
|
|
72
|
+
// enum: {
|
|
73
|
+
// values: ["1-10", "11-50", "51-200", "201-500", "501-1000", "1001+"],
|
|
74
|
+
// message: "Team size must be one of the predefined values",
|
|
75
|
+
// },
|
|
76
|
+
},
|
|
77
|
+
foundedYear: {
|
|
78
|
+
type: Number,
|
|
79
|
+
required: [true, "Founded year is required"],
|
|
80
|
+
min: [1800, "Founded year cannot be before 1800"],
|
|
81
|
+
max: [new Date().getFullYear(), "Founded year cannot be in the future"],
|
|
82
|
+
},
|
|
83
|
+
address: {
|
|
84
|
+
type: addressSchema,
|
|
85
|
+
required: [true, "Address is required"],
|
|
86
|
+
},
|
|
87
|
+
gstNumber: {
|
|
88
|
+
type: String,
|
|
89
|
+
required: [true, "GST number is required"],
|
|
90
|
+
match: [
|
|
91
|
+
/^[0-9]{2}[A-Z]{5}[0-9]{4}[A-Z]{1}[1-9A-Z]{1}[Z]{1}[A-Z0-9]{1}$/,
|
|
92
|
+
"Invalid GST number format",
|
|
93
|
+
],
|
|
94
|
+
unique: true, // Ensures that the GST number is unique in the collection
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
timestamps: { createdAt: true, updatedAt: true },
|
|
99
|
+
}
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
// Indexing for better performance
|
|
103
|
+
schema.index({ recruiterId: 1 });
|
|
104
|
+
schema.index({ normalizedOrganizationName: 1 });
|
|
105
|
+
|
|
106
|
+
const myDB = mongoose.connection.useDb(getDatabaseName());
|
|
107
|
+
|
|
108
|
+
// Create the model
|
|
109
|
+
const ActiveOrganizationModel = myDB.model("active-organization", schema);
|
|
110
|
+
|
|
111
|
+
module.exports = ActiveOrganizationModel;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const mongoose = require("mongoose");
|
|
2
|
+
const { addressSchema } = require("../../schemes");
|
|
3
|
+
const { getDatabaseName } = require("../../constants");
|
|
4
|
+
|
|
5
|
+
const { ObjectId } = mongoose.Schema.Types;
|
|
6
|
+
|
|
7
|
+
// Define the schema
|
|
8
|
+
const schema = new mongoose.Schema(
|
|
9
|
+
{
|
|
10
|
+
recruiterId: { type: ObjectId, required: true },
|
|
11
|
+
organizationLogo: { type: String, required: true },
|
|
12
|
+
organizationName: { type: String, required: true }, // For display purposes
|
|
13
|
+
normalizedOrganizationName: { type: String }, // For database queries and comparisons
|
|
14
|
+
about: { type: String, required: true },
|
|
15
|
+
websiteLink: {
|
|
16
|
+
type: String,
|
|
17
|
+
required: true,
|
|
18
|
+
},
|
|
19
|
+
gallery: {
|
|
20
|
+
type: [String],
|
|
21
|
+
validate: {
|
|
22
|
+
validator: function (v) {
|
|
23
|
+
return Array.isArray(v) && v.length >= 3 && v.length <= 6;
|
|
24
|
+
},
|
|
25
|
+
message:
|
|
26
|
+
"Gallery should have at least 3 images and a maximum of 6 images.",
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
teamSize: { type: String, required: true },
|
|
30
|
+
foundedYear: { type: Number, required: true },
|
|
31
|
+
address: { type: addressSchema, required: true },
|
|
32
|
+
gstNumber: {
|
|
33
|
+
type: String,
|
|
34
|
+
required: [true, "GST number is required"],
|
|
35
|
+
match: [
|
|
36
|
+
/^[0-9]{2}[A-Z]{5}[0-9]{4}[A-Z]{1}[1-9A-Z]{1}[Z]{1}[A-Z0-9]{1}$/,
|
|
37
|
+
"Invalid GST number format",
|
|
38
|
+
],
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
{ timestamps: { createdAt: true, updatedAt: true } }
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
const myDB = mongoose.connection.useDb(getDatabaseName());
|
|
45
|
+
|
|
46
|
+
// Create the model
|
|
47
|
+
const OrganizationVerificationModel = myDB.model(
|
|
48
|
+
"verification-organization",
|
|
49
|
+
schema
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
module.exports = OrganizationVerificationModel;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const mongoose = require("mongoose");
|
|
2
|
+
const { getDatabaseName } = require("../../constants");
|
|
3
|
+
|
|
4
|
+
const { ObjectId } = mongoose.Schema.Types;
|
|
5
|
+
|
|
6
|
+
// Define the schema
|
|
7
|
+
const schema = new mongoose.Schema(
|
|
8
|
+
{
|
|
9
|
+
avatar: { type: String, required: true },
|
|
10
|
+
fullName: { type: String, required: true, minlength: 2, maxlength: 50 },
|
|
11
|
+
designation: { type: String, required: true, minlength: 2, maxlength: 50 },
|
|
12
|
+
email: {
|
|
13
|
+
type: String,
|
|
14
|
+
required: true,
|
|
15
|
+
match: /^\S+@\S+\.\S+$/,
|
|
16
|
+
unique: true, // Unique index (no need for manual index)
|
|
17
|
+
lowercase: true, // Ensure case-insensitive uniqueness
|
|
18
|
+
trim: true, // Remove accidental spaces
|
|
19
|
+
},
|
|
20
|
+
countryCode: { type: String, required: true, enum: ["+91"] },
|
|
21
|
+
mobileNumber: {
|
|
22
|
+
type: String,
|
|
23
|
+
required: true,
|
|
24
|
+
minlength: 10,
|
|
25
|
+
maxlength: 10,
|
|
26
|
+
unique: true, // Unique index (no need for manual index)
|
|
27
|
+
},
|
|
28
|
+
password: { type: String, required: true },
|
|
29
|
+
organizationId: {
|
|
30
|
+
type: ObjectId,
|
|
31
|
+
required: true,
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
{ timestamps: { createdAt: true, updatedAt: true } }
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
// Indexing for performance
|
|
38
|
+
schema.index({ organizationId: 1 });
|
|
39
|
+
|
|
40
|
+
const myDB = mongoose.connection.useDb(getDatabaseName());
|
|
41
|
+
|
|
42
|
+
// Create the model
|
|
43
|
+
const ActiveRecruiterModel = myDB.model("active-recruiter", schema);
|
|
44
|
+
|
|
45
|
+
module.exports = ActiveRecruiterModel;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
const mongoose = require("mongoose");
|
|
2
|
+
const bcrypt = require("bcrypt");
|
|
3
|
+
const { isMobilePhone } = require("validator");
|
|
4
|
+
const { getDatabaseName } = require("../../constants");
|
|
5
|
+
const {
|
|
6
|
+
Schema,
|
|
7
|
+
Types: { ObjectId },
|
|
8
|
+
} = mongoose;
|
|
9
|
+
|
|
10
|
+
// Define the schema
|
|
11
|
+
const schema = new Schema(
|
|
12
|
+
{
|
|
13
|
+
recruiterId: {
|
|
14
|
+
type: ObjectId,
|
|
15
|
+
required: [true, "Recruiter ID is required"],
|
|
16
|
+
},
|
|
17
|
+
fullName: {
|
|
18
|
+
type: String,
|
|
19
|
+
required: [true, "Full name is required"],
|
|
20
|
+
trim: true,
|
|
21
|
+
minlength: [3, "Full name must be at least 3 characters long"],
|
|
22
|
+
maxlength: [50, "Full name must be at most 50 characters long"],
|
|
23
|
+
},
|
|
24
|
+
designation: {
|
|
25
|
+
type: String,
|
|
26
|
+
required: [true, "Designation is optional"], // Optional field
|
|
27
|
+
minlength: [2, "Designation must be at least 2 characters long"],
|
|
28
|
+
maxlength: [50, "Designation cannot exceed 50 characters"],
|
|
29
|
+
},
|
|
30
|
+
// mobileNumber: {
|
|
31
|
+
// type: String,
|
|
32
|
+
// required: [true, "Mobile number is required"],
|
|
33
|
+
// minlength: [10, "Mobile number must be exactly 10 digits long"],
|
|
34
|
+
// maxlength: [10, "Mobile number must be exactly 10 digits long"],
|
|
35
|
+
// match: [/^\d{10}$/, "Mobile number must be exactly 10 digits"],
|
|
36
|
+
// unique: true, // Ensure mobileNumber is unique
|
|
37
|
+
// },
|
|
38
|
+
// countryCode: {
|
|
39
|
+
// type: String,
|
|
40
|
+
// required: [true, "Country code is required"],
|
|
41
|
+
// minlength: [1, "Country code must be at least 1 character long"],
|
|
42
|
+
// maxlength: [4, "Country code cannot exceed 4 characters"],
|
|
43
|
+
// enum: ["+91"], // Only allow +91
|
|
44
|
+
// },
|
|
45
|
+
password: {
|
|
46
|
+
type: String,
|
|
47
|
+
required: [true, "Password is required"],
|
|
48
|
+
},
|
|
49
|
+
email: {
|
|
50
|
+
type: String,
|
|
51
|
+
required: [true, "Email is required"],
|
|
52
|
+
unique: true,
|
|
53
|
+
match: [
|
|
54
|
+
/^[^\s@]+@[^\s@]+\.[^\s@]+$/,
|
|
55
|
+
"Please enter a valid email address",
|
|
56
|
+
],
|
|
57
|
+
maxlength: 100,
|
|
58
|
+
},
|
|
59
|
+
OTP: {
|
|
60
|
+
type: String,
|
|
61
|
+
required: [true, "OTP is required"],
|
|
62
|
+
},
|
|
63
|
+
requests: [
|
|
64
|
+
{
|
|
65
|
+
date: {
|
|
66
|
+
type: Date,
|
|
67
|
+
required: [true, "Request date is required"],
|
|
68
|
+
default: Date.now,
|
|
69
|
+
},
|
|
70
|
+
attempts: {
|
|
71
|
+
type: Number,
|
|
72
|
+
default: 0,
|
|
73
|
+
min: [0, "Attempts cannot be negative"],
|
|
74
|
+
},
|
|
75
|
+
successful: {
|
|
76
|
+
type: Boolean,
|
|
77
|
+
default: false,
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
expiryDate: {
|
|
82
|
+
type: Date,
|
|
83
|
+
required: [true, "Expiry date is required"],
|
|
84
|
+
validate: {
|
|
85
|
+
validator: function (v) {
|
|
86
|
+
return v > Date.now();
|
|
87
|
+
},
|
|
88
|
+
message: "Expiry date must be in the future.",
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
deleteAt: {
|
|
92
|
+
type: Date,
|
|
93
|
+
required: [true, "Deletion time is required"],
|
|
94
|
+
validate: {
|
|
95
|
+
validator: function (v) {
|
|
96
|
+
return v > Date.now();
|
|
97
|
+
},
|
|
98
|
+
message: "Deletion time must be in the future.",
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
{ timestamps: { createdAt: true, updatedAt: true } }
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
// Define indexes for TTL and other fields
|
|
106
|
+
schema.index({ deleteAt: 1 }, { expireAfterSeconds: 0 });
|
|
107
|
+
schema.index({ recruiterId: 1 });
|
|
108
|
+
|
|
109
|
+
// Create the model
|
|
110
|
+
const myDB = mongoose.connection.useDb(getDatabaseName());
|
|
111
|
+
const RecruiterBasicDetailModel = myDB.model("recruiter-basic-detail", schema);
|
|
112
|
+
|
|
113
|
+
module.exports = { RecruiterBasicDetailModel };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const mongoose = require("mongoose");
|
|
2
|
+
const { getDatabaseName } = require("../../constants");
|
|
3
|
+
|
|
4
|
+
const counterSchema = new mongoose.Schema({
|
|
5
|
+
_id: { type: String, required: true },
|
|
6
|
+
sequenceValue: { type: Number, default: 0 },
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
// Create the model
|
|
10
|
+
const myDB = mongoose.connection.useDb(getDatabaseName());
|
|
11
|
+
const CounterModel = myDB.model("counter", counterSchema);
|
|
12
|
+
|
|
13
|
+
module.exports = { CounterModel };
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
const mongoose = require("mongoose");
|
|
2
|
+
const { getDatabaseName } = require("../../constants");
|
|
3
|
+
const {
|
|
4
|
+
Schema,
|
|
5
|
+
Types: { ObjectId },
|
|
6
|
+
} = mongoose;
|
|
7
|
+
|
|
8
|
+
// Define the schema
|
|
9
|
+
const schema = new Schema(
|
|
10
|
+
{
|
|
11
|
+
recruiterId: {
|
|
12
|
+
type: ObjectId,
|
|
13
|
+
required: [true, "Recruiter ID is required"],
|
|
14
|
+
},
|
|
15
|
+
email: { type: String, required: true },
|
|
16
|
+
OTP: {
|
|
17
|
+
type: String, // Encrypted OTP
|
|
18
|
+
required: [true, "OTP is required"],
|
|
19
|
+
maxlength: [6, "OTP must be 6 digits"], // Adjust based on encryption
|
|
20
|
+
},
|
|
21
|
+
attempts: [
|
|
22
|
+
{
|
|
23
|
+
date: {
|
|
24
|
+
type: Date,
|
|
25
|
+
required: [true, "Attempt date is required"],
|
|
26
|
+
},
|
|
27
|
+
successful: {
|
|
28
|
+
type: Boolean,
|
|
29
|
+
default: false,
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
expiry: {
|
|
34
|
+
type: Date,
|
|
35
|
+
required: [true, "Expiry date is required"],
|
|
36
|
+
validate: {
|
|
37
|
+
validator: function (v) {
|
|
38
|
+
return v > new Date(); // Ensure expiry is in the future
|
|
39
|
+
},
|
|
40
|
+
message: "Expiry must be a future date.",
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
deleteAt: {
|
|
45
|
+
type: Date,
|
|
46
|
+
required: [true, "DeleteAt date is required"],
|
|
47
|
+
validate: {
|
|
48
|
+
validator: function (v) {
|
|
49
|
+
return v > new Date(); // Ensure deleteAt is in the future
|
|
50
|
+
},
|
|
51
|
+
message: "DeleteAt must be a future date.",
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
{ timestamps: { createdAt: true, updatedAt: true } }
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
// Create the model
|
|
59
|
+
const myDB = mongoose.connection.useDb(getDatabaseName());
|
|
60
|
+
const RecruiterEmailOTPModel = myDB.model("recruiter-email-otp", schema);
|
|
61
|
+
|
|
62
|
+
// Ensure deleteAt index is created (for document expiry)
|
|
63
|
+
schema.index({ deleteAt: 1 }, { expireAfterSeconds: 0 });
|
|
64
|
+
|
|
65
|
+
// Consider adding indexes for frequently queried fields
|
|
66
|
+
schema.index({ recruiterId: 1 });
|
|
67
|
+
|
|
68
|
+
module.exports = { RecruiterEmailOTPModel };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
ActiveRecruiterModel: require("./active-model"),
|
|
3
|
+
PendingRecruiterModel: require("./pending-model"),
|
|
4
|
+
RecruiterBasicDetailModel: require("./basicDetail-model"),
|
|
5
|
+
RecruiterTokenModel: require("./token-model"),
|
|
6
|
+
CounterModel: require("./counter-model"),
|
|
7
|
+
RequestRecruiterModel: require("./request-model"),
|
|
8
|
+
VerificationRecruiterModel: require("./verification-model"),
|
|
9
|
+
RecruiterMobileOTPModel: require("./mobileOTP-model"),
|
|
10
|
+
};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
const mongoose = require("mongoose");
|
|
2
|
+
const { getDatabaseName } = require("../../constants");
|
|
3
|
+
const {
|
|
4
|
+
Schema,
|
|
5
|
+
Types: { ObjectId },
|
|
6
|
+
} = mongoose;
|
|
7
|
+
|
|
8
|
+
// Define the schema
|
|
9
|
+
const schema = new Schema(
|
|
10
|
+
{
|
|
11
|
+
recruiterId: {
|
|
12
|
+
type: ObjectId,
|
|
13
|
+
required: [true, "Recruiter ID is required"],
|
|
14
|
+
},
|
|
15
|
+
mobileNumber: {
|
|
16
|
+
type: String,
|
|
17
|
+
required: [true, "Mobile number is required"],
|
|
18
|
+
validate: {
|
|
19
|
+
validator: function (v) {
|
|
20
|
+
return /^\d{10}$/.test(v); // Example validation for a 10-digit number
|
|
21
|
+
},
|
|
22
|
+
message: "Invalid mobile number format.",
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
countryCode: {
|
|
26
|
+
type: String,
|
|
27
|
+
required: [true, "Country code is required"],
|
|
28
|
+
validate: {
|
|
29
|
+
validator: function (v) {
|
|
30
|
+
return /^\+\d{1,4}$/.test(v); // Example validation for country code (e.g., +1, +44)
|
|
31
|
+
},
|
|
32
|
+
message: "Invalid country code format.",
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
OTP: {
|
|
36
|
+
type: String, // Encrypted OTP
|
|
37
|
+
required: [true, "OTP is required"],
|
|
38
|
+
maxlength: [6, "OTP must be 6 digits"], // Adjust based on encryption
|
|
39
|
+
},
|
|
40
|
+
attempts: [
|
|
41
|
+
{
|
|
42
|
+
date: {
|
|
43
|
+
type: Date,
|
|
44
|
+
required: [true, "Attempt date is required"],
|
|
45
|
+
},
|
|
46
|
+
successful: {
|
|
47
|
+
type: Boolean,
|
|
48
|
+
default: false,
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
expiry: {
|
|
53
|
+
type: Date,
|
|
54
|
+
required: [true, "Expiry date is required"],
|
|
55
|
+
validate: {
|
|
56
|
+
validator: function (v) {
|
|
57
|
+
return v > new Date(); // Ensure expiry is in the future
|
|
58
|
+
},
|
|
59
|
+
message: "Expiry must be a future date.",
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
deleteAt: {
|
|
63
|
+
type: Date,
|
|
64
|
+
required: [true, "DeleteAt date is required"],
|
|
65
|
+
validate: {
|
|
66
|
+
validator: function (v) {
|
|
67
|
+
return v > new Date(); // Ensure deleteAt is in the future
|
|
68
|
+
},
|
|
69
|
+
message: "DeleteAt must be a future date.",
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
{ timestamps: { createdAt: true, updatedAt: true } }
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
// Create the model
|
|
77
|
+
const myDB = mongoose.connection.useDb(getDatabaseName());
|
|
78
|
+
const RecruiterMobileOTPModel = myDB.model("recruiter-mobile-otp", schema);
|
|
79
|
+
|
|
80
|
+
// Ensure deleteAt index is created (for document expiry)
|
|
81
|
+
schema.index({ deleteAt: 1 }, { expireAfterSeconds: 0 });
|
|
82
|
+
|
|
83
|
+
// Consider adding indexes for frequently queried fields
|
|
84
|
+
schema.index({ recruiterId: 1 });
|
|
85
|
+
schema.index({ mobileNumber: 1 });
|
|
86
|
+
schema.index({ countryCode: 1 });
|
|
87
|
+
|
|
88
|
+
module.exports = RecruiterMobileOTPModel;
|