@eeplatform/basic-edu 1.8.6 → 1.8.8
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 +5 -0
- package/dist/index.js +208 -13
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +208 -13
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -2875,7 +2875,7 @@ var learnerInfoSchema = Joi5.object({
|
|
|
2875
2875
|
});
|
|
2876
2876
|
var schemaUpdateStatus = Joi5.object({
|
|
2877
2877
|
_id: Joi5.string().hex().length(24).required(),
|
|
2878
|
-
status: Joi5.string().valid("pending", "accepted", "rejected").required()
|
|
2878
|
+
status: Joi5.string().valid("pending", "accepted", "rejected", "cancelled").required()
|
|
2879
2879
|
});
|
|
2880
2880
|
var gradeLevels = [
|
|
2881
2881
|
"K1",
|
|
@@ -3580,17 +3580,16 @@ function useLearnerRepo() {
|
|
|
3580
3580
|
school: Joi7.string().hex().required(),
|
|
3581
3581
|
schoolYear: Joi7.string().required(),
|
|
3582
3582
|
gradeLevel: Joi7.string().required(),
|
|
3583
|
+
specialProgram: Joi7.string().hex().optional().allow(null, ""),
|
|
3583
3584
|
status: Joi7.string().optional()
|
|
3584
3585
|
});
|
|
3585
3586
|
const { error } = validation.validate(value);
|
|
3586
3587
|
if (error) {
|
|
3587
3588
|
throw new BadRequestError9(`Invalid data: ${error.message}`);
|
|
3588
3589
|
}
|
|
3589
|
-
const status = value.status ?? "active";
|
|
3590
3590
|
const query = {
|
|
3591
3591
|
schoolYear: value.schoolYear,
|
|
3592
|
-
gradeLevel: value.gradeLevel
|
|
3593
|
-
status
|
|
3592
|
+
gradeLevel: value.gradeLevel
|
|
3594
3593
|
};
|
|
3595
3594
|
const cacheKeyOptions = {
|
|
3596
3595
|
...query,
|
|
@@ -3604,6 +3603,16 @@ function useLearnerRepo() {
|
|
|
3604
3603
|
}
|
|
3605
3604
|
cacheKeyOptions.school = value.school.toString();
|
|
3606
3605
|
}
|
|
3606
|
+
if (value.specialProgram) {
|
|
3607
|
+
try {
|
|
3608
|
+
query["learnerInfo.specialProgram"] = new ObjectId7(
|
|
3609
|
+
value.specialProgram
|
|
3610
|
+
);
|
|
3611
|
+
} catch (error2) {
|
|
3612
|
+
throw new BadRequestError9("Invalid special program ID.");
|
|
3613
|
+
}
|
|
3614
|
+
cacheKeyOptions.specialProgram = value.specialProgram.toString();
|
|
3615
|
+
}
|
|
3607
3616
|
const cacheKey = makeCacheKey4(namespace_collection, cacheKeyOptions);
|
|
3608
3617
|
const cachedData = await getCache(cacheKey);
|
|
3609
3618
|
if (cachedData !== void 0 && cachedData !== null) {
|
|
@@ -4337,6 +4346,51 @@ function useProgramScreeningRepo() {
|
|
|
4337
4346
|
}
|
|
4338
4347
|
}
|
|
4339
4348
|
}
|
|
4349
|
+
async function getByApplicantId(_id) {
|
|
4350
|
+
try {
|
|
4351
|
+
_id = new ObjectId10(_id);
|
|
4352
|
+
} catch (error) {
|
|
4353
|
+
throw new BadRequestError14("Invalid ID.");
|
|
4354
|
+
}
|
|
4355
|
+
const cacheKey = makeCacheKey6(namespace_collection, {
|
|
4356
|
+
applicant: String(_id)
|
|
4357
|
+
});
|
|
4358
|
+
try {
|
|
4359
|
+
const cached = await getCache(cacheKey);
|
|
4360
|
+
if (cached) {
|
|
4361
|
+
logger11.log({
|
|
4362
|
+
level: "info",
|
|
4363
|
+
message: `Cache hit for getById program screening: ${cacheKey}`
|
|
4364
|
+
});
|
|
4365
|
+
return cached;
|
|
4366
|
+
}
|
|
4367
|
+
const result = await collection.findOne({
|
|
4368
|
+
applicant: _id,
|
|
4369
|
+
status: { $ne: "deleted" }
|
|
4370
|
+
});
|
|
4371
|
+
if (!result) {
|
|
4372
|
+
throw new BadRequestError14("Program screening not found.");
|
|
4373
|
+
}
|
|
4374
|
+
setCache(cacheKey, result, 300).then(() => {
|
|
4375
|
+
logger11.log({
|
|
4376
|
+
level: "info",
|
|
4377
|
+
message: `Cache set for program screening by id: ${cacheKey}`
|
|
4378
|
+
});
|
|
4379
|
+
}).catch((err) => {
|
|
4380
|
+
logger11.log({
|
|
4381
|
+
level: "error",
|
|
4382
|
+
message: `Failed to set cache for program screening by id: ${err.message}`
|
|
4383
|
+
});
|
|
4384
|
+
});
|
|
4385
|
+
return result;
|
|
4386
|
+
} catch (error) {
|
|
4387
|
+
if (error instanceof AppError7) {
|
|
4388
|
+
throw error;
|
|
4389
|
+
} else {
|
|
4390
|
+
throw new InternalServerError5("Failed to get program screening.");
|
|
4391
|
+
}
|
|
4392
|
+
}
|
|
4393
|
+
}
|
|
4340
4394
|
async function getByCode(code, school) {
|
|
4341
4395
|
try {
|
|
4342
4396
|
school = new ObjectId10(school);
|
|
@@ -4460,6 +4514,26 @@ function useProgramScreeningRepo() {
|
|
|
4460
4514
|
);
|
|
4461
4515
|
}
|
|
4462
4516
|
}
|
|
4517
|
+
async function updateStatusByApplicantId(_id, status, session) {
|
|
4518
|
+
try {
|
|
4519
|
+
_id = new ObjectId10(_id);
|
|
4520
|
+
} catch (error) {
|
|
4521
|
+
throw new BadRequestError14("Invalid ID.");
|
|
4522
|
+
}
|
|
4523
|
+
try {
|
|
4524
|
+
await collection.updateOne(
|
|
4525
|
+
{ applicant: _id },
|
|
4526
|
+
{ $set: { status, updatedAt: /* @__PURE__ */ new Date() } },
|
|
4527
|
+
{ session }
|
|
4528
|
+
);
|
|
4529
|
+
delCachedData();
|
|
4530
|
+
return "Successfully updated program screening status.";
|
|
4531
|
+
} catch (error) {
|
|
4532
|
+
throw new InternalServerError5(
|
|
4533
|
+
"Failed to update program screening status."
|
|
4534
|
+
);
|
|
4535
|
+
}
|
|
4536
|
+
}
|
|
4463
4537
|
return {
|
|
4464
4538
|
createIndexes,
|
|
4465
4539
|
add,
|
|
@@ -4468,7 +4542,9 @@ function useProgramScreeningRepo() {
|
|
|
4468
4542
|
getByCode,
|
|
4469
4543
|
updateFieldById,
|
|
4470
4544
|
deleteById,
|
|
4471
|
-
updateById
|
|
4545
|
+
updateById,
|
|
4546
|
+
updateStatusByApplicantId,
|
|
4547
|
+
getByApplicantId
|
|
4472
4548
|
};
|
|
4473
4549
|
}
|
|
4474
4550
|
|
|
@@ -5364,7 +5440,11 @@ function useEnrollmentService() {
|
|
|
5364
5440
|
getById: _getById,
|
|
5365
5441
|
updateStatusById: _updateStatusById
|
|
5366
5442
|
} = useEnrollmentRepo();
|
|
5367
|
-
const {
|
|
5443
|
+
const {
|
|
5444
|
+
add: addProgramScreening,
|
|
5445
|
+
updateStatusByApplicantId,
|
|
5446
|
+
getByApplicantId
|
|
5447
|
+
} = useProgramScreeningRepo();
|
|
5368
5448
|
const { getById: getProgramById } = useProgramRepo();
|
|
5369
5449
|
async function add(value) {
|
|
5370
5450
|
const session = useAtlas10.getClient()?.startSession();
|
|
@@ -5495,6 +5575,11 @@ function useEnrollmentService() {
|
|
|
5495
5575
|
if (status === "rejected" && enrollment.status == "accepted") {
|
|
5496
5576
|
throw new BadRequestError19("Accepted enrollments cannot be rejected.");
|
|
5497
5577
|
}
|
|
5578
|
+
if (status === "withdrawn" && enrollment.status !== "screening") {
|
|
5579
|
+
throw new BadRequestError19(
|
|
5580
|
+
"Only enrollments in screening status can be withdrawn."
|
|
5581
|
+
);
|
|
5582
|
+
}
|
|
5498
5583
|
const result = await _updateStatusById(_id, status, session);
|
|
5499
5584
|
if (result.modifiedCount === 0) {
|
|
5500
5585
|
throw new InternalServerError7("Failed to accept enrollment");
|
|
@@ -5534,6 +5619,14 @@ function useEnrollmentService() {
|
|
|
5534
5619
|
enrollment.createdBy = enrollment.createdBy?.toString();
|
|
5535
5620
|
await addLearner(enrollment, session);
|
|
5536
5621
|
}
|
|
5622
|
+
const programScreening = await getByApplicantId(_id);
|
|
5623
|
+
if (programScreening) {
|
|
5624
|
+
if (["cancelled", "withdrawn"].includes(status)) {
|
|
5625
|
+
await updateStatusByApplicantId(_id, "cancelled", session);
|
|
5626
|
+
} else {
|
|
5627
|
+
await updateStatusByApplicantId(_id, status, session);
|
|
5628
|
+
}
|
|
5629
|
+
}
|
|
5537
5630
|
await session.commitTransaction();
|
|
5538
5631
|
return "Enrollment accepted successfully";
|
|
5539
5632
|
} catch (error2) {
|
|
@@ -6168,7 +6261,8 @@ function useGradeLevelController() {
|
|
|
6168
6261
|
add: _add,
|
|
6169
6262
|
updateById: _updateById,
|
|
6170
6263
|
deleteById: _deleteById,
|
|
6171
|
-
getByEducationLevel: _getByEducationLevel
|
|
6264
|
+
getByEducationLevel: _getByEducationLevel,
|
|
6265
|
+
getByGradeLevel: _getByGradeLevel
|
|
6172
6266
|
} = useGradeLevelRepo();
|
|
6173
6267
|
async function add(req, res, next) {
|
|
6174
6268
|
const value = req.body;
|
|
@@ -6339,13 +6433,34 @@ function useGradeLevelController() {
|
|
|
6339
6433
|
next(error2);
|
|
6340
6434
|
}
|
|
6341
6435
|
}
|
|
6436
|
+
async function getByGradeLevel(req, res, next) {
|
|
6437
|
+
const gradeLevel = req.params.gradeLevel;
|
|
6438
|
+
const school = req.params.school;
|
|
6439
|
+
const validation = Joi16.object({
|
|
6440
|
+
gradeLevel: Joi16.string().required(),
|
|
6441
|
+
school: Joi16.string().hex().required()
|
|
6442
|
+
});
|
|
6443
|
+
const { error } = validation.validate({ gradeLevel, school });
|
|
6444
|
+
if (error) {
|
|
6445
|
+
next(new BadRequestError23(error.message));
|
|
6446
|
+
return;
|
|
6447
|
+
}
|
|
6448
|
+
try {
|
|
6449
|
+
const data = await _getByGradeLevel({ gradeLevel, school });
|
|
6450
|
+
res.json(data);
|
|
6451
|
+
return;
|
|
6452
|
+
} catch (error2) {
|
|
6453
|
+
next(error2);
|
|
6454
|
+
}
|
|
6455
|
+
}
|
|
6342
6456
|
return {
|
|
6343
6457
|
add,
|
|
6344
6458
|
getAll,
|
|
6345
6459
|
getById,
|
|
6346
6460
|
updateById,
|
|
6347
6461
|
deleteById,
|
|
6348
|
-
getByEducationLevel
|
|
6462
|
+
getByEducationLevel,
|
|
6463
|
+
getByGradeLevel
|
|
6349
6464
|
};
|
|
6350
6465
|
}
|
|
6351
6466
|
|
|
@@ -38966,6 +39081,9 @@ var schemaGenerateSections = Joi31.object({
|
|
|
38966
39081
|
school: Joi31.string().hex().required(),
|
|
38967
39082
|
schoolYear: Joi31.string().required(),
|
|
38968
39083
|
gradeLevel: Joi31.string().required(),
|
|
39084
|
+
minStudents: Joi31.number().integer().min(1).required(),
|
|
39085
|
+
maxStudents: Joi31.number().integer().min(Joi31.ref("minStudents")).required(),
|
|
39086
|
+
specialProgram: Joi31.string().hex().optional().allow(null, ""),
|
|
38969
39087
|
set: Joi31.array().items(Joi31.string().min(1).max(100)).required()
|
|
38970
39088
|
});
|
|
38971
39089
|
function modelSection(value) {
|
|
@@ -42435,7 +42553,8 @@ function useSectionService() {
|
|
|
42435
42553
|
{
|
|
42436
42554
|
school: value.school,
|
|
42437
42555
|
schoolYear: value.schoolYear,
|
|
42438
|
-
gradeLevel: value.gradeLevel
|
|
42556
|
+
gradeLevel: value.gradeLevel,
|
|
42557
|
+
specialProgram: value.specialProgram
|
|
42439
42558
|
},
|
|
42440
42559
|
session
|
|
42441
42560
|
);
|
|
@@ -42452,8 +42571,8 @@ function useSectionService() {
|
|
|
42452
42571
|
if (!gradeLevelData) {
|
|
42453
42572
|
throw new BadRequestError64("Grade level not found.");
|
|
42454
42573
|
}
|
|
42455
|
-
const minPerSection = gradeLevelData.minNumberOfLearners;
|
|
42456
|
-
const maxPerSection = gradeLevelData.maxNumberOfLearners;
|
|
42574
|
+
const minPerSection = value.minStudents ?? gradeLevelData.minNumberOfLearners;
|
|
42575
|
+
const maxPerSection = value.maxStudents ?? gradeLevelData.maxNumberOfLearners;
|
|
42457
42576
|
const sectionsNeeded = Math.ceil(studentCount / minPerSection);
|
|
42458
42577
|
if (sectionsNeeded > value.set.length) {
|
|
42459
42578
|
throw new BadRequestError64(
|
|
@@ -42599,7 +42718,64 @@ function useSectionService() {
|
|
|
42599
42718
|
await session?.endSession();
|
|
42600
42719
|
}
|
|
42601
42720
|
}
|
|
42602
|
-
|
|
42721
|
+
async function generateSectionPreview(value) {
|
|
42722
|
+
const { error } = schemaGenerateSections.validate(value);
|
|
42723
|
+
if (error) {
|
|
42724
|
+
throw new BadRequestError64(
|
|
42725
|
+
`Invalid section generation data: ${error.message}`
|
|
42726
|
+
);
|
|
42727
|
+
}
|
|
42728
|
+
try {
|
|
42729
|
+
const studentCount = await getCountByGradeLevel({
|
|
42730
|
+
school: value.school,
|
|
42731
|
+
schoolYear: value.schoolYear,
|
|
42732
|
+
gradeLevel: value.gradeLevel,
|
|
42733
|
+
specialProgram: value.specialProgram
|
|
42734
|
+
});
|
|
42735
|
+
if (studentCount === 0) {
|
|
42736
|
+
throw new BadRequestError64("No learners found for this grade level.");
|
|
42737
|
+
}
|
|
42738
|
+
const gradeLevelData = await getByGradeLevel({
|
|
42739
|
+
school: value.school,
|
|
42740
|
+
gradeLevel: value.gradeLevel
|
|
42741
|
+
});
|
|
42742
|
+
if (!gradeLevelData) {
|
|
42743
|
+
throw new BadRequestError64("Grade level not found.");
|
|
42744
|
+
}
|
|
42745
|
+
const minPerSection = value.minStudents ?? gradeLevelData.minNumberOfLearners;
|
|
42746
|
+
const maxPerSection = value.maxStudents ?? gradeLevelData.maxNumberOfLearners;
|
|
42747
|
+
const sectionsNeeded = Math.ceil(studentCount / minPerSection);
|
|
42748
|
+
if (sectionsNeeded > value.set.length) {
|
|
42749
|
+
throw new BadRequestError64(
|
|
42750
|
+
"Insufficient number of section names in set[]."
|
|
42751
|
+
);
|
|
42752
|
+
}
|
|
42753
|
+
const sectionSizes = distributeStudents(
|
|
42754
|
+
studentCount,
|
|
42755
|
+
minPerSection,
|
|
42756
|
+
maxPerSection
|
|
42757
|
+
);
|
|
42758
|
+
if (sectionSizes.length === 0) {
|
|
42759
|
+
throw new BadRequestError64("Unable to compute section sizes.");
|
|
42760
|
+
}
|
|
42761
|
+
const sections = sectionSizes.map((size, index) => ({
|
|
42762
|
+
name: value.set[index],
|
|
42763
|
+
value: size
|
|
42764
|
+
}));
|
|
42765
|
+
return {
|
|
42766
|
+
totalSectionsGenerated: sectionSizes.length,
|
|
42767
|
+
totalStudentsAssigned: studentCount,
|
|
42768
|
+
sections
|
|
42769
|
+
};
|
|
42770
|
+
} catch (error2) {
|
|
42771
|
+
if (error2 instanceof AppError25) {
|
|
42772
|
+
throw error2;
|
|
42773
|
+
} else {
|
|
42774
|
+
throw new InternalServerError21("Failed to generate section preview.");
|
|
42775
|
+
}
|
|
42776
|
+
}
|
|
42777
|
+
}
|
|
42778
|
+
return { generateSections, generateSectionPreview };
|
|
42603
42779
|
}
|
|
42604
42780
|
|
|
42605
42781
|
// src/resources/section/section.controller.ts
|
|
@@ -42615,7 +42791,10 @@ function useSectionController() {
|
|
|
42615
42791
|
removeStudentFromSection: _removeStudentFromSection,
|
|
42616
42792
|
deleteById: _deleteById
|
|
42617
42793
|
} = useSectionRepo();
|
|
42618
|
-
const {
|
|
42794
|
+
const {
|
|
42795
|
+
generateSections: _generateSections,
|
|
42796
|
+
generateSectionPreview: _generateSectionPreview
|
|
42797
|
+
} = useSectionService();
|
|
42619
42798
|
async function add(req, res, next) {
|
|
42620
42799
|
const value = req.body;
|
|
42621
42800
|
const { error } = schemaSection.validate(value);
|
|
@@ -42652,6 +42831,21 @@ function useSectionController() {
|
|
|
42652
42831
|
next(error2);
|
|
42653
42832
|
}
|
|
42654
42833
|
}
|
|
42834
|
+
async function generateSectionPreview(req, res, next) {
|
|
42835
|
+
const value = req.body;
|
|
42836
|
+
const { error } = schemaGenerateSections.validate(value);
|
|
42837
|
+
if (error) {
|
|
42838
|
+
next(new BadRequestError65(error.message));
|
|
42839
|
+
return;
|
|
42840
|
+
}
|
|
42841
|
+
try {
|
|
42842
|
+
const data = await _generateSectionPreview(value);
|
|
42843
|
+
res.json(data);
|
|
42844
|
+
return;
|
|
42845
|
+
} catch (error2) {
|
|
42846
|
+
next(error2);
|
|
42847
|
+
}
|
|
42848
|
+
}
|
|
42655
42849
|
async function getAll(req, res, next) {
|
|
42656
42850
|
const query = req.query;
|
|
42657
42851
|
const validation = Joi43.object({
|
|
@@ -42843,6 +43037,7 @@ function useSectionController() {
|
|
|
42843
43037
|
return {
|
|
42844
43038
|
add,
|
|
42845
43039
|
generateSections,
|
|
43040
|
+
generateSectionPreview,
|
|
42846
43041
|
getAll,
|
|
42847
43042
|
getById,
|
|
42848
43043
|
getByName,
|