@eeplatform/core 1.4.5 → 1.5.1

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/dist/index.js CHANGED
@@ -10384,7 +10384,7 @@ var require_ms = __commonJS({
10384
10384
  options = options || {};
10385
10385
  var type = typeof val;
10386
10386
  if (type === "string" && val.length > 0) {
10387
- return parse3(val);
10387
+ return parse4(val);
10388
10388
  } else if (type === "number" && isNaN(val) === false) {
10389
10389
  return options.long ? fmtLong(val) : fmtShort(val);
10390
10390
  }
@@ -10392,7 +10392,7 @@ var require_ms = __commonJS({
10392
10392
  "val is not a non-empty string or a valid number. val=" + JSON.stringify(val)
10393
10393
  );
10394
10394
  };
10395
- function parse3(str) {
10395
+ function parse4(str) {
10396
10396
  str = String(str);
10397
10397
  if (str.length > 100) {
10398
10398
  return;
@@ -11345,12 +11345,15 @@ __export(src_exports, {
11345
11345
  MAsset: () => MAsset,
11346
11346
  MBuilding: () => MBuilding,
11347
11347
  MBuildingUnit: () => MBuildingUnit,
11348
+ MCurriculum: () => MCurriculum,
11348
11349
  MDivision: () => MDivision,
11349
11350
  MEntity: () => MEntity,
11350
11351
  MFile: () => MFile,
11352
+ MGradeLevel: () => MGradeLevel,
11351
11353
  MMember: () => MMember,
11352
11354
  MONGO_DB: () => MONGO_DB,
11353
11355
  MONGO_URI: () => MONGO_URI,
11356
+ MOffice: () => MOffice,
11354
11357
  MOrder: () => MOrder,
11355
11358
  MOrg: () => MOrg,
11356
11359
  MPaymentMethod: () => MPaymentMethod,
@@ -11391,7 +11394,10 @@ __export(src_exports, {
11391
11394
  schemaAssetUpdateOption: () => schemaAssetUpdateOption,
11392
11395
  schemaBuilding: () => schemaBuilding,
11393
11396
  schemaBuildingUnit: () => schemaBuildingUnit,
11397
+ schemaCurriculum: () => schemaCurriculum,
11394
11398
  schemaDivision: () => schemaDivision,
11399
+ schemaGradeLevel: () => schemaGradeLevel,
11400
+ schemaOffice: () => schemaOffice,
11395
11401
  schemaPlantilla: () => schemaPlantilla,
11396
11402
  schemaRegion: () => schemaRegion,
11397
11403
  schemaSchool: () => schemaSchool,
@@ -11409,6 +11415,8 @@ __export(src_exports, {
11409
11415
  useBuildingUnitRepo: () => useBuildingUnitRepo,
11410
11416
  useCounterModel: () => useCounterModel,
11411
11417
  useCounterRepo: () => useCounterRepo,
11418
+ useCurriculumController: () => useCurriculumController,
11419
+ useCurriculumRepo: () => useCurriculumRepo,
11412
11420
  useDivisionController: () => useDivisionController,
11413
11421
  useDivisionRepo: () => useDivisionRepo,
11414
11422
  useDivisionService: () => useDivisionService,
@@ -11418,12 +11426,17 @@ __export(src_exports, {
11418
11426
  useFileRepo: () => useFileRepo,
11419
11427
  useFileService: () => useFileService,
11420
11428
  useGitHubService: () => useGitHubService,
11429
+ useGradeLevelController: () => useGradeLevelController,
11430
+ useGradeLevelRepo: () => useGradeLevelRepo,
11421
11431
  useInvoiceController: () => useInvoiceController,
11422
11432
  useInvoiceModel: () => useInvoiceModel,
11423
11433
  useInvoiceRepo: () => useInvoiceRepo,
11424
11434
  useInvoiceService: () => useInvoiceService,
11425
11435
  useMemberController: () => useMemberController,
11426
11436
  useMemberRepo: () => useMemberRepo,
11437
+ useOfficeController: () => useOfficeController,
11438
+ useOfficeRepo: () => useOfficeRepo,
11439
+ useOfficeService: () => useOfficeService,
11427
11440
  useOrderController: () => useOrderController,
11428
11441
  useOrderRepo: () => useOrderRepo,
11429
11442
  useOrgController: () => useOrgController,
@@ -28328,7 +28341,10 @@ function useBuildingUnitService() {
28328
28341
  try {
28329
28342
  await session.startTransaction();
28330
28343
  for (let index = 0; index < value.qty; index++) {
28331
- await _add({ ...value.building }, session);
28344
+ await _add(
28345
+ { ...value.building, name: `${value.building.name} ${index + 1}` },
28346
+ session
28347
+ );
28332
28348
  }
28333
28349
  await session.commitTransaction();
28334
28350
  return "Building unit added successfully.";
@@ -29820,6 +29836,10 @@ var import_joi41 = __toESM(require("joi"));
29820
29836
  var import_mongodb46 = require("mongodb");
29821
29837
  var schemaPlantilla = import_joi41.default.object({
29822
29838
  _id: import_joi41.default.string().hex().optional().allow(null, ""),
29839
+ org: import_joi41.default.string().hex().required(),
29840
+ orgUnitCode: import_joi41.default.string().optional().allow(null, ""),
29841
+ employmentType: import_joi41.default.string().optional().allow(null, ""),
29842
+ personnelType: import_joi41.default.string().required(),
29823
29843
  itemNumber: import_joi41.default.string().required(),
29824
29844
  positionTitle: import_joi41.default.string().required(),
29825
29845
  positionCategory: import_joi41.default.string().required(),
@@ -29828,8 +29848,7 @@ var schemaPlantilla = import_joi41.default.object({
29828
29848
  division: import_joi41.default.string().hex().optional().allow(null, ""),
29829
29849
  divisionName: import_joi41.default.string().optional().allow(null, ""),
29830
29850
  salaryGrade: import_joi41.default.number().required(),
29831
- step: import_joi41.default.number().optional().allow(null, 0),
29832
- incumbent: import_joi41.default.string().optional().allow(null, ""),
29851
+ employeeName: import_joi41.default.string().optional().allow(null, ""),
29833
29852
  annualSalary: import_joi41.default.number().optional().allow(null, 0),
29834
29853
  monthlySalary: import_joi41.default.number().optional().allow(null, 0),
29835
29854
  status: import_joi41.default.string().required(),
@@ -29857,14 +29876,18 @@ function MPlantilla(data) {
29857
29876
  positionCategory: data.positionCategory ?? "",
29858
29877
  status: data.status ?? "active",
29859
29878
  salaryGrade: data.salaryGrade ?? 0,
29860
- step: data.step ?? 0,
29861
29879
  monthlySalary: data.monthlySalary ?? 0,
29862
29880
  annualSalary: data.annualSalary ?? 0,
29863
29881
  region: data.region ?? "",
29864
29882
  regionName: data.regionName ?? "",
29865
29883
  division: data.division ?? "",
29866
29884
  divisionName: data.divisionName ?? "",
29867
- incumbent: data.incumbent ?? "",
29885
+ org: data.org ?? "",
29886
+ orgUnitCode: data.orgUnitCode ?? "",
29887
+ employmentType: data.employmentType ?? "",
29888
+ personnelType: data.personnelType ?? "",
29889
+ employee: data.employee ?? "",
29890
+ employeeName: data.employeeName ?? "",
29868
29891
  createdAt: data.createdAt ? new Date(data.createdAt) : /* @__PURE__ */ new Date(),
29869
29892
  updatedAt: data.updatedAt ? new Date(data.updatedAt) : "",
29870
29893
  deletedAt: data.deletedAt ? new Date(data.deletedAt) : ""
@@ -30205,7 +30228,8 @@ function usePlantillaService() {
30205
30228
  salaryGrade: parseInt(
30206
30229
  plantillaData.salarygrade || plantillaData.salary_grade || "1"
30207
30230
  ) || 1,
30208
- step: parseInt(plantillaData.step || "1") || 1,
30231
+ org: "",
30232
+ personnelType: "",
30209
30233
  status: status.trim() || "active"
30210
30234
  };
30211
30235
  if (region)
@@ -30218,9 +30242,6 @@ function usePlantillaService() {
30218
30242
  if (plantillaData.divisionname || plantillaData.division_name) {
30219
30243
  plantilla.divisionName = plantillaData.divisionname || plantillaData.division_name;
30220
30244
  }
30221
- if (plantillaData.incumbent) {
30222
- plantilla.incumbent = plantillaData.incumbent;
30223
- }
30224
30245
  if (plantillaData.employee) {
30225
30246
  plantilla.employee = plantillaData.employee;
30226
30247
  }
@@ -30501,6 +30522,1731 @@ function usePlantillaController() {
30501
30522
  bulkAddPlantillas
30502
30523
  };
30503
30524
  }
30525
+
30526
+ // src/models/office.model.ts
30527
+ var import_nodejs_utils86 = require("@eeplatform/nodejs-utils");
30528
+ var import_joi43 = __toESM(require("joi"));
30529
+ var import_mongodb48 = require("mongodb");
30530
+ var schemaOffice = import_joi43.default.object({
30531
+ _id: import_joi43.default.string().hex().optional().allow(null, ""),
30532
+ name: import_joi43.default.string().required(),
30533
+ code: import_joi43.default.string().required(),
30534
+ type: import_joi43.default.string().required(),
30535
+ parent: import_joi43.default.string().hex().optional().allow(null, ""),
30536
+ path: import_joi43.default.string().required(),
30537
+ status: import_joi43.default.string().required(),
30538
+ createdAt: import_joi43.default.date().iso().optional().allow(null, ""),
30539
+ updatedAt: import_joi43.default.date().iso().optional().allow(null, ""),
30540
+ deletedAt: import_joi43.default.date().iso().optional().allow(null, "")
30541
+ });
30542
+ function MOffice(data) {
30543
+ const { error } = schemaOffice.validate(data);
30544
+ if (error) {
30545
+ throw new import_nodejs_utils86.BadRequestError(error.message);
30546
+ }
30547
+ if (data._id && typeof data._id === "string") {
30548
+ try {
30549
+ data._id = new import_mongodb48.ObjectId(data._id);
30550
+ } catch (error2) {
30551
+ throw new import_nodejs_utils86.BadRequestError("Invalid _id.");
30552
+ }
30553
+ }
30554
+ if (data.parent && typeof data.parent === "string") {
30555
+ try {
30556
+ data.parent = new import_mongodb48.ObjectId(data.parent);
30557
+ } catch (error2) {
30558
+ throw new import_nodejs_utils86.BadRequestError("Invalid parent.");
30559
+ }
30560
+ }
30561
+ return {
30562
+ _id: data._id,
30563
+ name: data.name ?? "",
30564
+ code: data.code ?? "",
30565
+ type: data.type ?? "",
30566
+ parent: data.parent ?? "",
30567
+ path: data.path ?? "",
30568
+ status: data.status ?? "active",
30569
+ createdAt: data.createdAt ? new Date(data.createdAt) : /* @__PURE__ */ new Date(),
30570
+ updatedAt: data.updatedAt ? new Date(data.updatedAt) : "",
30571
+ deletedAt: data.deletedAt ? new Date(data.deletedAt) : ""
30572
+ };
30573
+ }
30574
+
30575
+ // src/repositories/office.repository.ts
30576
+ var import_nodejs_utils87 = require("@eeplatform/nodejs-utils");
30577
+ var import_mongodb49 = require("mongodb");
30578
+ function useOfficeRepo() {
30579
+ const db = import_nodejs_utils87.useAtlas.getDb();
30580
+ if (!db) {
30581
+ throw new Error("Unable to connect to server.");
30582
+ }
30583
+ const namespace_collection = "offices";
30584
+ const collection = db.collection(namespace_collection);
30585
+ const { getCache, setCache, delNamespace } = (0, import_nodejs_utils87.useCache)(namespace_collection);
30586
+ async function createIndexes() {
30587
+ try {
30588
+ await collection.createIndexes([
30589
+ {
30590
+ key: { name: 1, code: 1 },
30591
+ unique: true,
30592
+ name: "unique_name_code_index"
30593
+ },
30594
+ { key: { type: 1 } },
30595
+ { key: { parent: 1 } },
30596
+ { key: { status: 1 } }
30597
+ ]);
30598
+ } catch (error) {
30599
+ throw new Error("Failed to create index on offices.");
30600
+ }
30601
+ }
30602
+ async function add(value, session, clearCache = true) {
30603
+ try {
30604
+ value = MOffice(value);
30605
+ const res = await collection.insertOne(value, { session });
30606
+ if (clearCache) {
30607
+ delCachedData();
30608
+ }
30609
+ return res.insertedId;
30610
+ } catch (error) {
30611
+ import_nodejs_utils87.logger.log({
30612
+ level: "error",
30613
+ message: error.message
30614
+ });
30615
+ if (error instanceof import_nodejs_utils87.AppError) {
30616
+ throw error;
30617
+ } else {
30618
+ const isDuplicated = error.message.includes("duplicate");
30619
+ if (isDuplicated) {
30620
+ throw new import_nodejs_utils87.BadRequestError("Office already exists.");
30621
+ }
30622
+ throw new Error("Failed to create office.");
30623
+ }
30624
+ }
30625
+ }
30626
+ async function updateById(_id, value, session) {
30627
+ try {
30628
+ _id = new import_mongodb49.ObjectId(_id);
30629
+ } catch (error) {
30630
+ throw new import_nodejs_utils87.BadRequestError("Invalid ID.");
30631
+ }
30632
+ value.updatedAt = /* @__PURE__ */ new Date();
30633
+ try {
30634
+ const res = await collection.updateOne(
30635
+ { _id },
30636
+ { $set: value },
30637
+ { session }
30638
+ );
30639
+ delCachedData();
30640
+ return res;
30641
+ } catch (error) {
30642
+ import_nodejs_utils87.logger.log({
30643
+ level: "error",
30644
+ message: error.message
30645
+ });
30646
+ if (error instanceof import_nodejs_utils87.AppError) {
30647
+ throw error;
30648
+ } else {
30649
+ throw new Error("Failed to update office.");
30650
+ }
30651
+ }
30652
+ }
30653
+ async function getAll({
30654
+ search = "",
30655
+ page = 1,
30656
+ limit = 10,
30657
+ sort = {},
30658
+ type = "",
30659
+ parent = "",
30660
+ status = "active"
30661
+ } = {}) {
30662
+ page = page > 0 ? page - 1 : 0;
30663
+ const query = {
30664
+ status
30665
+ };
30666
+ sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
30667
+ if (search) {
30668
+ query.$text = { $search: search };
30669
+ }
30670
+ if (type) {
30671
+ query.type = type;
30672
+ }
30673
+ if (parent) {
30674
+ try {
30675
+ query.parent = new import_mongodb49.ObjectId(parent);
30676
+ } catch (error) {
30677
+ throw new import_nodejs_utils87.BadRequestError("Invalid parent ID.");
30678
+ }
30679
+ }
30680
+ const cacheParams = {
30681
+ page,
30682
+ limit,
30683
+ sort: JSON.stringify(sort)
30684
+ };
30685
+ if (search)
30686
+ cacheParams.search = search;
30687
+ if (type)
30688
+ cacheParams.type = type;
30689
+ if (parent)
30690
+ cacheParams.parent = parent;
30691
+ if (status !== "active")
30692
+ cacheParams.status = status;
30693
+ const cacheKey = (0, import_nodejs_utils87.makeCacheKey)(namespace_collection, cacheParams);
30694
+ import_nodejs_utils87.logger.log({
30695
+ level: "info",
30696
+ message: `Cache key for getAll offices: ${cacheKey}`
30697
+ });
30698
+ try {
30699
+ const cached = await getCache(cacheKey);
30700
+ if (cached) {
30701
+ import_nodejs_utils87.logger.log({
30702
+ level: "info",
30703
+ message: `Cache hit for getAll offices: ${cacheKey}`
30704
+ });
30705
+ return cached;
30706
+ }
30707
+ const items = await collection.aggregate([
30708
+ { $match: query },
30709
+ { $sort: sort },
30710
+ { $skip: page * limit },
30711
+ { $limit: limit }
30712
+ ]).toArray();
30713
+ const length = await collection.countDocuments(query);
30714
+ const data = (0, import_nodejs_utils87.paginate)(items, page, limit, length);
30715
+ setCache(cacheKey, data, 600).then(() => {
30716
+ import_nodejs_utils87.logger.log({
30717
+ level: "info",
30718
+ message: `Cache set for getAll offices: ${cacheKey}`
30719
+ });
30720
+ }).catch((err) => {
30721
+ import_nodejs_utils87.logger.log({
30722
+ level: "error",
30723
+ message: `Failed to set cache for getAll offices: ${err.message}`
30724
+ });
30725
+ });
30726
+ return data;
30727
+ } catch (error) {
30728
+ import_nodejs_utils87.logger.log({ level: "error", message: `${error}` });
30729
+ throw error;
30730
+ }
30731
+ }
30732
+ async function getById(_id) {
30733
+ try {
30734
+ _id = new import_mongodb49.ObjectId(_id);
30735
+ } catch (error) {
30736
+ throw new import_nodejs_utils87.BadRequestError("Invalid ID.");
30737
+ }
30738
+ const cacheKey = (0, import_nodejs_utils87.makeCacheKey)(namespace_collection, { _id: String(_id) });
30739
+ try {
30740
+ const cached = await getCache(cacheKey);
30741
+ if (cached) {
30742
+ import_nodejs_utils87.logger.log({
30743
+ level: "info",
30744
+ message: `Cache hit for getById office: ${cacheKey}`
30745
+ });
30746
+ return cached;
30747
+ }
30748
+ const result = await collection.findOne({
30749
+ _id
30750
+ });
30751
+ setCache(cacheKey, result, 300).then(() => {
30752
+ import_nodejs_utils87.logger.log({
30753
+ level: "info",
30754
+ message: `Cache set for office by id: ${cacheKey}`
30755
+ });
30756
+ }).catch((err) => {
30757
+ import_nodejs_utils87.logger.log({
30758
+ level: "error",
30759
+ message: `Failed to set cache for office by id: ${err.message}`
30760
+ });
30761
+ });
30762
+ return result;
30763
+ } catch (error) {
30764
+ if (error instanceof import_nodejs_utils87.AppError) {
30765
+ throw error;
30766
+ } else {
30767
+ throw new import_nodejs_utils87.InternalServerError("Failed to get office.");
30768
+ }
30769
+ }
30770
+ }
30771
+ async function deleteById(_id, session) {
30772
+ try {
30773
+ _id = new import_mongodb49.ObjectId(_id);
30774
+ } catch (error) {
30775
+ throw new import_nodejs_utils87.BadRequestError("Invalid ID.");
30776
+ }
30777
+ try {
30778
+ const res = await collection.updateOne(
30779
+ { _id },
30780
+ { $set: { status: "deleted", deletedAt: /* @__PURE__ */ new Date() } }
30781
+ );
30782
+ delCachedData();
30783
+ return res;
30784
+ } catch (error) {
30785
+ import_nodejs_utils87.logger.log({
30786
+ level: "error",
30787
+ message: error.message
30788
+ });
30789
+ if (error instanceof import_nodejs_utils87.AppError) {
30790
+ throw error;
30791
+ } else {
30792
+ throw new import_nodejs_utils87.InternalServerError("Failed to delete office.");
30793
+ }
30794
+ }
30795
+ }
30796
+ function delCachedData() {
30797
+ delNamespace().then(() => {
30798
+ import_nodejs_utils87.logger.log({
30799
+ level: "info",
30800
+ message: `Cache namespace cleared for ${namespace_collection}`
30801
+ });
30802
+ }).catch((err) => {
30803
+ import_nodejs_utils87.logger.log({
30804
+ level: "error",
30805
+ message: `Failed to clear cache namespace for ${namespace_collection}: ${err.message}`
30806
+ });
30807
+ });
30808
+ }
30809
+ return {
30810
+ createIndexes,
30811
+ add,
30812
+ getAll,
30813
+ getById,
30814
+ updateById,
30815
+ deleteById,
30816
+ delCachedData
30817
+ };
30818
+ }
30819
+
30820
+ // src/services/office.service.ts
30821
+ var import_nodejs_utils88 = require("@eeplatform/nodejs-utils");
30822
+ var XLSX3 = __toESM(require("xlsx"));
30823
+ var Papa3 = __toESM(require("papaparse"));
30824
+ function useOfficeService() {
30825
+ const { add: addOffice, delCachedData } = useOfficeRepo();
30826
+ async function addBulk(file) {
30827
+ import_nodejs_utils88.logger.log({
30828
+ level: "info",
30829
+ message: `Starting office bulk upload. File: ${file.originalname}, Size: ${file.size} bytes`
30830
+ });
30831
+ const MAX_SIZE = 16 * 1024 * 1024;
30832
+ let offices = [];
30833
+ let totalSize = 0;
30834
+ let validatedOffices = [];
30835
+ if (!file.buffer) {
30836
+ throw new import_nodejs_utils88.BadRequestError("File buffer is empty or corrupted");
30837
+ }
30838
+ try {
30839
+ const fileExtension = file.originalname.split(".").pop()?.toLowerCase();
30840
+ if (fileExtension === "csv") {
30841
+ const csvData = file.buffer.toString("utf-8");
30842
+ totalSize = Buffer.byteLength(csvData, "utf8");
30843
+ if (totalSize > MAX_SIZE) {
30844
+ throw new import_nodejs_utils88.BadRequestError(
30845
+ `File size exceeds limit. Maximum allowed: ${MAX_SIZE / 1024 / 1024}MB, Received: ${(totalSize / 1024 / 1024).toFixed(2)}MB`
30846
+ );
30847
+ }
30848
+ const parseResult = Papa3.parse(csvData, {
30849
+ header: true,
30850
+ skipEmptyLines: true,
30851
+ transformHeader: (header) => {
30852
+ return header.toLowerCase().replace(/\s+/g, "").replace(/[^\w]/g, "");
30853
+ }
30854
+ });
30855
+ if (parseResult.errors.length > 0) {
30856
+ throw new import_nodejs_utils88.BadRequestError(
30857
+ `CSV parsing errors: ${parseResult.errors.map((e) => e.message).join(", ")}`
30858
+ );
30859
+ }
30860
+ offices = parseResult.data || [];
30861
+ } else if (["xlsx", "xls"].includes(fileExtension || "")) {
30862
+ totalSize = file.buffer.length;
30863
+ if (totalSize > MAX_SIZE) {
30864
+ throw new import_nodejs_utils88.BadRequestError(
30865
+ `File size exceeds limit. Maximum allowed: ${MAX_SIZE / 1024 / 1024}MB, Received: ${(totalSize / 1024 / 1024).toFixed(2)}MB`
30866
+ );
30867
+ }
30868
+ const workbook = XLSX3.read(file.buffer, { type: "buffer" });
30869
+ const sheetName = workbook.SheetNames[0];
30870
+ if (!sheetName) {
30871
+ throw new import_nodejs_utils88.BadRequestError("Excel file contains no sheets");
30872
+ }
30873
+ const worksheet = workbook.Sheets[sheetName];
30874
+ offices = XLSX3.utils.sheet_to_json(worksheet, {
30875
+ header: 1,
30876
+ defval: ""
30877
+ });
30878
+ if (offices.length > 0) {
30879
+ const headers = offices[0];
30880
+ offices = offices.slice(1).map((row) => {
30881
+ const obj = {};
30882
+ headers.forEach((header, index) => {
30883
+ obj[header.trim()] = row[index] || "";
30884
+ });
30885
+ return obj;
30886
+ });
30887
+ }
30888
+ } else {
30889
+ throw new import_nodejs_utils88.BadRequestError(
30890
+ "Unsupported file format. Please upload CSV, XLS, or XLSX files."
30891
+ );
30892
+ }
30893
+ if (!offices || offices.length === 0) {
30894
+ throw new import_nodejs_utils88.BadRequestError("File is empty or contains no valid data");
30895
+ }
30896
+ const results = {
30897
+ total: offices.length,
30898
+ successful: 0,
30899
+ failed: 0,
30900
+ errors: []
30901
+ };
30902
+ import_nodejs_utils88.logger.log({
30903
+ level: "info",
30904
+ message: `Processing ${offices.length} offices from file`
30905
+ });
30906
+ for (let i = 0; i < offices.length; i++) {
30907
+ const officeData = offices[i];
30908
+ try {
30909
+ const cleanOffice = {
30910
+ name: String(officeData.name || "").trim(),
30911
+ code: String(officeData.code || "").trim(),
30912
+ type: String(officeData.type || "").trim(),
30913
+ path: String(officeData.path || "").trim(),
30914
+ status: String(officeData.status || "active").trim()
30915
+ };
30916
+ if (officeData.parent && String(officeData.parent).trim()) {
30917
+ cleanOffice.parent = String(officeData.parent).trim();
30918
+ }
30919
+ const { error } = schemaOffice.validate(cleanOffice);
30920
+ if (error) {
30921
+ results.errors.push(`Row ${i + 1}: ${error.message}`);
30922
+ results.failed++;
30923
+ continue;
30924
+ }
30925
+ validatedOffices.push(cleanOffice);
30926
+ } catch (error) {
30927
+ results.errors.push(`Row ${i + 1}: ${error.message}`);
30928
+ results.failed++;
30929
+ }
30930
+ }
30931
+ if (validatedOffices.length === 0) {
30932
+ throw new import_nodejs_utils88.BadRequestError(
30933
+ "No valid offices found in file. Please check the format and data."
30934
+ );
30935
+ }
30936
+ const db = import_nodejs_utils88.useAtlas.getDb();
30937
+ if (!db) {
30938
+ throw new Error("Database connection not available");
30939
+ }
30940
+ const session = db.client.startSession();
30941
+ try {
30942
+ await session.withTransaction(async () => {
30943
+ const batchSize = 100;
30944
+ for (let i = 0; i < validatedOffices.length; i += batchSize) {
30945
+ const batch = validatedOffices.slice(i, i + batchSize);
30946
+ for (const office of batch) {
30947
+ try {
30948
+ await addOffice(office, session, false);
30949
+ results.successful++;
30950
+ } catch (error) {
30951
+ results.failed++;
30952
+ results.errors.push(
30953
+ `Failed to insert office "${office.name}": ${error.message}`
30954
+ );
30955
+ import_nodejs_utils88.logger.log({
30956
+ level: "error",
30957
+ message: `Failed to insert office: ${error.message}`
30958
+ });
30959
+ }
30960
+ }
30961
+ }
30962
+ });
30963
+ delCachedData();
30964
+ import_nodejs_utils88.logger.log({
30965
+ level: "info",
30966
+ message: `Bulk upload completed. Successful: ${results.successful}, Failed: ${results.failed}`
30967
+ });
30968
+ return results;
30969
+ } catch (error) {
30970
+ import_nodejs_utils88.logger.log({
30971
+ level: "error",
30972
+ message: `Transaction failed: ${error.message}`
30973
+ });
30974
+ throw new import_nodejs_utils88.BadRequestError(`Bulk upload failed: ${error.message}`);
30975
+ } finally {
30976
+ await session.endSession();
30977
+ }
30978
+ } catch (error) {
30979
+ import_nodejs_utils88.logger.log({
30980
+ level: "error",
30981
+ message: `Bulk office upload failed: ${error.message}`
30982
+ });
30983
+ if (error instanceof import_nodejs_utils88.BadRequestError) {
30984
+ throw error;
30985
+ }
30986
+ throw new import_nodejs_utils88.BadRequestError(`File processing failed: ${error.message}`);
30987
+ }
30988
+ }
30989
+ return {
30990
+ addBulk
30991
+ };
30992
+ }
30993
+
30994
+ // src/controllers/office.controller.ts
30995
+ var import_nodejs_utils89 = require("@eeplatform/nodejs-utils");
30996
+ var import_joi44 = __toESM(require("joi"));
30997
+ function useOfficeController() {
30998
+ const {
30999
+ add: _add,
31000
+ getAll: _getAll,
31001
+ getById: _getById,
31002
+ updateById: _updateByIdById,
31003
+ deleteById: _deleteByIdById
31004
+ } = useOfficeRepo();
31005
+ const { addBulk: _addBulk } = useOfficeService();
31006
+ async function add(req, res, next) {
31007
+ const value = req.body;
31008
+ const validation = import_joi44.default.object({
31009
+ name: import_joi44.default.string().required(),
31010
+ code: import_joi44.default.string().required(),
31011
+ type: import_joi44.default.string().required(),
31012
+ path: import_joi44.default.string().required(),
31013
+ parent: import_joi44.default.string().hex().optional().allow(null, ""),
31014
+ status: import_joi44.default.string().optional().allow(null, "")
31015
+ });
31016
+ const { error } = validation.validate(value);
31017
+ if (error) {
31018
+ next(new import_nodejs_utils89.BadRequestError(error.message));
31019
+ return;
31020
+ }
31021
+ try {
31022
+ const id = await _add(value);
31023
+ res.json({ message: "Office created successfully", id });
31024
+ return;
31025
+ } catch (error2) {
31026
+ next(error2);
31027
+ }
31028
+ }
31029
+ async function getAll(req, res, next) {
31030
+ const page = typeof req.query.page === "string" ? Number(req.query.page) : 1;
31031
+ const limit = typeof req.query.limit === "string" ? Number(req.query.limit) : 10;
31032
+ const search = req.query.search ?? "";
31033
+ const type = req.query.type ?? "";
31034
+ const parent = req.query.parent ?? "";
31035
+ const status = req.query.status ?? "active";
31036
+ const isPageNumber = isFinite(page);
31037
+ if (!isPageNumber) {
31038
+ next(new import_nodejs_utils89.BadRequestError("Invalid page number."));
31039
+ return;
31040
+ }
31041
+ const isLimitNumber = isFinite(limit);
31042
+ if (!isLimitNumber) {
31043
+ next(new import_nodejs_utils89.BadRequestError("Invalid limit number."));
31044
+ return;
31045
+ }
31046
+ const validation = import_joi44.default.object({
31047
+ page: import_joi44.default.number().min(1).optional().allow("", null),
31048
+ limit: import_joi44.default.number().min(1).optional().allow("", null),
31049
+ search: import_joi44.default.string().optional().allow("", null),
31050
+ type: import_joi44.default.string().optional().allow("", null),
31051
+ parent: import_joi44.default.string().optional().allow("", null),
31052
+ status: import_joi44.default.string().optional().allow("", null)
31053
+ });
31054
+ const { error } = validation.validate({
31055
+ page,
31056
+ limit,
31057
+ search,
31058
+ type,
31059
+ parent,
31060
+ status
31061
+ });
31062
+ if (error) {
31063
+ next(new import_nodejs_utils89.BadRequestError(error.message));
31064
+ return;
31065
+ }
31066
+ try {
31067
+ const offices = await _getAll({
31068
+ search,
31069
+ page,
31070
+ limit,
31071
+ type,
31072
+ parent,
31073
+ status
31074
+ });
31075
+ res.json(offices);
31076
+ return;
31077
+ } catch (error2) {
31078
+ next(error2);
31079
+ }
31080
+ }
31081
+ async function getById(req, res, next) {
31082
+ const id = req.params.id;
31083
+ const validation = import_joi44.default.object({
31084
+ id: import_joi44.default.string().hex().required()
31085
+ });
31086
+ const { error } = validation.validate({ id });
31087
+ if (error) {
31088
+ next(new import_nodejs_utils89.BadRequestError(error.message));
31089
+ return;
31090
+ }
31091
+ try {
31092
+ const office = await _getById(id);
31093
+ if (!office) {
31094
+ next(new import_nodejs_utils89.BadRequestError("Office not found."));
31095
+ return;
31096
+ }
31097
+ res.json(office);
31098
+ return;
31099
+ } catch (error2) {
31100
+ next(error2);
31101
+ }
31102
+ }
31103
+ async function updateById(req, res, next) {
31104
+ const id = req.params.id;
31105
+ const value = req.body;
31106
+ const validation = import_joi44.default.object({
31107
+ id: import_joi44.default.string().hex().required(),
31108
+ name: import_joi44.default.string().optional(),
31109
+ code: import_joi44.default.string().optional(),
31110
+ type: import_joi44.default.string().optional(),
31111
+ parent: import_joi44.default.string().hex().optional().allow(null, ""),
31112
+ path: import_joi44.default.string().optional(),
31113
+ status: import_joi44.default.string().optional()
31114
+ });
31115
+ const { error } = validation.validate({ id, ...value });
31116
+ if (error) {
31117
+ next(new import_nodejs_utils89.BadRequestError(error.message));
31118
+ return;
31119
+ }
31120
+ try {
31121
+ const result = await _updateByIdById(id, value);
31122
+ if (result.matchedCount === 0) {
31123
+ next(new import_nodejs_utils89.BadRequestError("Office not found."));
31124
+ return;
31125
+ }
31126
+ res.json({ message: "Office updated successfully" });
31127
+ return;
31128
+ } catch (error2) {
31129
+ next(error2);
31130
+ }
31131
+ }
31132
+ async function deleteById(req, res, next) {
31133
+ const id = req.params.id;
31134
+ const validation = import_joi44.default.object({
31135
+ id: import_joi44.default.string().hex().required()
31136
+ });
31137
+ const { error } = validation.validate({ id });
31138
+ if (error) {
31139
+ next(new import_nodejs_utils89.BadRequestError(error.message));
31140
+ return;
31141
+ }
31142
+ try {
31143
+ const result = await _deleteByIdById(id);
31144
+ if (result.matchedCount === 0) {
31145
+ next(new import_nodejs_utils89.BadRequestError("Office not found."));
31146
+ return;
31147
+ }
31148
+ res.json({ message: "Office deleted successfully" });
31149
+ return;
31150
+ } catch (error2) {
31151
+ next(error2);
31152
+ }
31153
+ }
31154
+ async function bulkAddOffices(req, res, next) {
31155
+ if (!req.file) {
31156
+ res.status(400).send("File is required!");
31157
+ return;
31158
+ }
31159
+ try {
31160
+ const result = await _addBulk(req.file);
31161
+ res.status(201).json(result);
31162
+ return;
31163
+ } catch (error) {
31164
+ next(error);
31165
+ return;
31166
+ }
31167
+ }
31168
+ return {
31169
+ add,
31170
+ getAll,
31171
+ getById,
31172
+ updateById,
31173
+ deleteById,
31174
+ bulkAddOffices
31175
+ };
31176
+ }
31177
+
31178
+ // src/models/curriculum.model.ts
31179
+ var import_nodejs_utils90 = require("@eeplatform/nodejs-utils");
31180
+ var import_joi45 = __toESM(require("joi"));
31181
+ var import_mongodb50 = require("mongodb");
31182
+ var schemaCurriculum = import_joi45.default.object({
31183
+ _id: import_joi45.default.string().hex().optional(),
31184
+ school: import_joi45.default.string().hex().required(),
31185
+ code: import_joi45.default.string().required(),
31186
+ effectiveSchoolYear: import_joi45.default.string().required(),
31187
+ maxTeachingHoursPerDay: import_joi45.default.number().integer().min(1).required(),
31188
+ subjects: import_joi45.default.array().items(
31189
+ import_joi45.default.object({
31190
+ educationLevel: import_joi45.default.string().required(),
31191
+ gradeLevel: import_joi45.default.string().required(),
31192
+ subjectCode: import_joi45.default.string().required(),
31193
+ subjectName: import_joi45.default.string().required(),
31194
+ subjectType: import_joi45.default.string().required(),
31195
+ sessionFrequency: import_joi45.default.number().integer().min(0).required(),
31196
+ sessionDuration: import_joi45.default.number().integer().min(0).required(),
31197
+ totalMinutesPerWeek: import_joi45.default.number().integer().min(0).required()
31198
+ })
31199
+ ),
31200
+ curriculumMemoRef: import_joi45.default.string().optional().allow("", null),
31201
+ status: import_joi45.default.string().optional().allow("", null),
31202
+ createdAt: import_joi45.default.date().optional().allow("", null),
31203
+ updatedAt: import_joi45.default.date().optional().allow("", null),
31204
+ deletedAt: import_joi45.default.date().optional().allow("", null),
31205
+ createdBy: import_joi45.default.string().optional().allow("", null),
31206
+ updatedBy: import_joi45.default.string().optional().allow("", null),
31207
+ deletedBy: import_joi45.default.string().optional().allow("", null)
31208
+ });
31209
+ function MCurriculum(value) {
31210
+ const { error } = schemaCurriculum.validate(value);
31211
+ if (error) {
31212
+ import_nodejs_utils90.logger.info(`Curriculum Model: ${error.message}`);
31213
+ throw new import_nodejs_utils90.BadRequestError(error.message);
31214
+ }
31215
+ if (value._id && typeof value._id === "string") {
31216
+ try {
31217
+ value._id = new import_mongodb50.ObjectId(value._id);
31218
+ } catch (error2) {
31219
+ throw new import_nodejs_utils90.BadRequestError("Invalid _id format");
31220
+ }
31221
+ }
31222
+ return {
31223
+ _id: value._id ?? void 0,
31224
+ school: value.school ?? "",
31225
+ code: value.code ?? "",
31226
+ effectiveSchoolYear: value.effectiveSchoolYear ?? "",
31227
+ maxTeachingHoursPerDay: value.maxTeachingHoursPerDay ?? 0,
31228
+ subjects: value.subjects ?? [],
31229
+ curriculumMemoRef: value.curriculumMemoRef ?? "",
31230
+ status: value.status ?? "active",
31231
+ createdAt: value.createdAt ?? /* @__PURE__ */ new Date(),
31232
+ updatedAt: value.updatedAt ?? "",
31233
+ deletedAt: value.deletedAt ?? "",
31234
+ createdBy: value.createdBy ?? "",
31235
+ updatedBy: value.updatedBy ?? "",
31236
+ deletedBy: value.deletedBy ?? ""
31237
+ };
31238
+ }
31239
+
31240
+ // src/repositories/curriculum.repository.ts
31241
+ var import_nodejs_utils91 = require("@eeplatform/nodejs-utils");
31242
+ var import_mongodb51 = require("mongodb");
31243
+ function useCurriculumRepo() {
31244
+ const db = import_nodejs_utils91.useAtlas.getDb();
31245
+ if (!db) {
31246
+ throw new Error("Unable to connect to server.");
31247
+ }
31248
+ const namespace_collection = "school.curriculums";
31249
+ const collection = db.collection(namespace_collection);
31250
+ const { getCache, setCache, delNamespace } = (0, import_nodejs_utils91.useCache)(namespace_collection);
31251
+ async function createIndexes() {
31252
+ try {
31253
+ await collection.createIndexes([
31254
+ {
31255
+ key: {
31256
+ school: 1,
31257
+ code: 1,
31258
+ status: 1
31259
+ },
31260
+ unique: true,
31261
+ partialFilterExpression: { status: "active" },
31262
+ name: "unique_code_index"
31263
+ },
31264
+ { key: { status: 1 } }
31265
+ ]);
31266
+ } catch (error) {
31267
+ throw new Error("Failed to create index on curriculums.");
31268
+ }
31269
+ }
31270
+ async function add(value, session) {
31271
+ try {
31272
+ value = MCurriculum(value);
31273
+ const res = await collection.insertOne(value, { session });
31274
+ delCachedData();
31275
+ return res.insertedId;
31276
+ } catch (error) {
31277
+ import_nodejs_utils91.logger.log({
31278
+ level: "error",
31279
+ message: error.message
31280
+ });
31281
+ if (error instanceof import_nodejs_utils91.AppError) {
31282
+ throw error;
31283
+ } else {
31284
+ const isDuplicated = error.message.includes("duplicate");
31285
+ if (isDuplicated) {
31286
+ throw new import_nodejs_utils91.BadRequestError("Curriculum already exists.");
31287
+ }
31288
+ throw new Error("Failed to create curriculum.");
31289
+ }
31290
+ }
31291
+ }
31292
+ async function updateById(_id, value, session) {
31293
+ try {
31294
+ _id = new import_mongodb51.ObjectId(_id);
31295
+ } catch (error) {
31296
+ throw new import_nodejs_utils91.BadRequestError("Invalid ID.");
31297
+ }
31298
+ try {
31299
+ const res = await collection.updateOne(
31300
+ { _id },
31301
+ { $set: { ...value, updatedAt: /* @__PURE__ */ new Date() } },
31302
+ { session }
31303
+ );
31304
+ delCachedData();
31305
+ return res;
31306
+ } catch (error) {
31307
+ import_nodejs_utils91.logger.log({
31308
+ level: "error",
31309
+ message: error.message
31310
+ });
31311
+ if (error instanceof import_nodejs_utils91.AppError) {
31312
+ throw error;
31313
+ } else {
31314
+ throw new Error("Failed to update curriculum.");
31315
+ }
31316
+ }
31317
+ }
31318
+ async function getAll({
31319
+ search = "",
31320
+ page = 1,
31321
+ limit = 10,
31322
+ sort = {},
31323
+ status = "active"
31324
+ } = {}) {
31325
+ page = page > 0 ? page - 1 : 0;
31326
+ const query = {
31327
+ status
31328
+ };
31329
+ sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
31330
+ if (search) {
31331
+ query.$or = [
31332
+ { code: { $regex: search, $options: "i" } },
31333
+ { subjectName: { $regex: search, $options: "i" } },
31334
+ { subjectCode: { $regex: search, $options: "i" } }
31335
+ ];
31336
+ }
31337
+ const cacheParams = {
31338
+ page,
31339
+ limit,
31340
+ sort: JSON.stringify(sort)
31341
+ };
31342
+ if (search)
31343
+ cacheParams.search = search;
31344
+ if (status !== "active")
31345
+ cacheParams.status = status;
31346
+ const cacheKey = (0, import_nodejs_utils91.makeCacheKey)(namespace_collection, cacheParams);
31347
+ import_nodejs_utils91.logger.log({
31348
+ level: "info",
31349
+ message: `Cache key for getAll curriculums: ${cacheKey}`
31350
+ });
31351
+ try {
31352
+ const cached = await getCache(cacheKey);
31353
+ if (cached) {
31354
+ import_nodejs_utils91.logger.log({
31355
+ level: "info",
31356
+ message: `Cache hit for getAll curriculums: ${cacheKey}`
31357
+ });
31358
+ return cached;
31359
+ }
31360
+ const items = await collection.aggregate([
31361
+ { $match: query },
31362
+ { $sort: sort },
31363
+ { $skip: page * limit },
31364
+ { $limit: limit },
31365
+ {
31366
+ $project: {
31367
+ _id: 1,
31368
+ school: 1,
31369
+ code: 1,
31370
+ effectiveSchoolYear: 1,
31371
+ maxTeachingHoursPerDay: 1,
31372
+ curriculumMemoRef: 1,
31373
+ status: 1,
31374
+ createdAt: 1,
31375
+ updatedAt: 1
31376
+ }
31377
+ }
31378
+ ]).toArray();
31379
+ const length = await collection.countDocuments(query);
31380
+ const data = (0, import_nodejs_utils91.paginate)(items, page, limit, length);
31381
+ setCache(cacheKey, data, 600).then(() => {
31382
+ import_nodejs_utils91.logger.log({
31383
+ level: "info",
31384
+ message: `Cache set for getAll curriculums: ${cacheKey}`
31385
+ });
31386
+ }).catch((err) => {
31387
+ import_nodejs_utils91.logger.log({
31388
+ level: "error",
31389
+ message: `Failed to set cache for getAll curriculums: ${err.message}`
31390
+ });
31391
+ });
31392
+ return data;
31393
+ } catch (error) {
31394
+ import_nodejs_utils91.logger.log({ level: "error", message: `${error}` });
31395
+ throw error;
31396
+ }
31397
+ }
31398
+ async function getById(_id) {
31399
+ try {
31400
+ _id = new import_mongodb51.ObjectId(_id);
31401
+ } catch (error) {
31402
+ throw new import_nodejs_utils91.BadRequestError("Invalid ID.");
31403
+ }
31404
+ const cacheKey = (0, import_nodejs_utils91.makeCacheKey)(namespace_collection, { _id: String(_id) });
31405
+ try {
31406
+ const cached = await getCache(cacheKey);
31407
+ if (cached) {
31408
+ import_nodejs_utils91.logger.log({
31409
+ level: "info",
31410
+ message: `Cache hit for getById curriculum: ${cacheKey}`
31411
+ });
31412
+ return cached;
31413
+ }
31414
+ const result = await collection.findOne({
31415
+ _id
31416
+ });
31417
+ setCache(cacheKey, result, 300).then(() => {
31418
+ import_nodejs_utils91.logger.log({
31419
+ level: "info",
31420
+ message: `Cache set for curriculum by id: ${cacheKey}`
31421
+ });
31422
+ }).catch((err) => {
31423
+ import_nodejs_utils91.logger.log({
31424
+ level: "error",
31425
+ message: `Failed to set cache for curriculum by id: ${err.message}`
31426
+ });
31427
+ });
31428
+ return result;
31429
+ } catch (error) {
31430
+ if (error instanceof import_nodejs_utils91.AppError) {
31431
+ throw error;
31432
+ } else {
31433
+ throw new import_nodejs_utils91.InternalServerError("Failed to get curriculum.");
31434
+ }
31435
+ }
31436
+ }
31437
+ async function deleteById(_id, session) {
31438
+ try {
31439
+ _id = new import_mongodb51.ObjectId(_id);
31440
+ } catch (error) {
31441
+ throw new import_nodejs_utils91.BadRequestError("Invalid ID.");
31442
+ }
31443
+ try {
31444
+ const res = await collection.updateOne(
31445
+ { _id },
31446
+ { $set: { status: "deleted", deletedAt: /* @__PURE__ */ new Date() } }
31447
+ );
31448
+ delCachedData();
31449
+ return res;
31450
+ } catch (error) {
31451
+ import_nodejs_utils91.logger.log({
31452
+ level: "error",
31453
+ message: error.message
31454
+ });
31455
+ if (error instanceof import_nodejs_utils91.AppError) {
31456
+ throw error;
31457
+ } else {
31458
+ throw new import_nodejs_utils91.InternalServerError("Failed to delete curriculum.");
31459
+ }
31460
+ }
31461
+ }
31462
+ function delCachedData() {
31463
+ delNamespace().then(() => {
31464
+ import_nodejs_utils91.logger.log({
31465
+ level: "info",
31466
+ message: `Cache namespace cleared for ${namespace_collection}`
31467
+ });
31468
+ }).catch((err) => {
31469
+ import_nodejs_utils91.logger.log({
31470
+ level: "error",
31471
+ message: `Failed to clear cache namespace for ${namespace_collection}: ${err.message}`
31472
+ });
31473
+ });
31474
+ }
31475
+ return {
31476
+ createIndexes,
31477
+ add,
31478
+ getAll,
31479
+ getById,
31480
+ updateById,
31481
+ deleteById
31482
+ };
31483
+ }
31484
+
31485
+ // src/controllers/curriculum.controller.ts
31486
+ var import_nodejs_utils92 = require("@eeplatform/nodejs-utils");
31487
+ var import_joi46 = __toESM(require("joi"));
31488
+ function useCurriculumController() {
31489
+ const {
31490
+ getAll: _getAll,
31491
+ getById: _getById,
31492
+ add: _add,
31493
+ updateById: _updateById,
31494
+ deleteById: _deleteById
31495
+ } = useCurriculumRepo();
31496
+ async function add(req, res, next) {
31497
+ const value = req.body;
31498
+ const { error } = schemaCurriculum.validate(value);
31499
+ if (error) {
31500
+ next(new import_nodejs_utils92.BadRequestError(error.message));
31501
+ import_nodejs_utils92.logger.info(`Controller: ${error.message}`);
31502
+ return;
31503
+ }
31504
+ try {
31505
+ const result = await _add(value);
31506
+ res.json(result);
31507
+ return;
31508
+ } catch (error2) {
31509
+ next(error2);
31510
+ }
31511
+ }
31512
+ async function updateById(req, res, next) {
31513
+ const value = req.body;
31514
+ const id = req.params.id ?? "";
31515
+ const validation = import_joi46.default.object({
31516
+ id: import_joi46.default.string().hex().required(),
31517
+ value: import_joi46.default.object({
31518
+ code: import_joi46.default.string().optional(),
31519
+ educationLevel: import_joi46.default.string().optional(),
31520
+ gradeLevel: import_joi46.default.string().optional(),
31521
+ subjectCode: import_joi46.default.string().optional(),
31522
+ subjectName: import_joi46.default.string().optional(),
31523
+ subjectType: import_joi46.default.string().optional(),
31524
+ sessionFrequency: import_joi46.default.number().integer().min(0).optional(),
31525
+ sessionDuration: import_joi46.default.number().integer().min(0).optional(),
31526
+ totalMinutesPerWeek: import_joi46.default.number().integer().min(0).optional(),
31527
+ curriculumMemoRef: import_joi46.default.string().optional().allow("", null)
31528
+ }).min(1)
31529
+ });
31530
+ const { error } = validation.validate({ id, value });
31531
+ if (error) {
31532
+ next(new import_nodejs_utils92.BadRequestError(error.message));
31533
+ import_nodejs_utils92.logger.info(`Controller: ${error.message}`);
31534
+ return;
31535
+ }
31536
+ try {
31537
+ const result = await _updateById(id, value);
31538
+ res.json(result);
31539
+ return;
31540
+ } catch (error2) {
31541
+ next(error2);
31542
+ }
31543
+ }
31544
+ async function getAll(req, res, next) {
31545
+ const query = req.query;
31546
+ const validation = import_joi46.default.object({
31547
+ page: import_joi46.default.number().min(1).optional().allow("", null),
31548
+ limit: import_joi46.default.number().min(1).optional().allow("", null),
31549
+ search: import_joi46.default.string().optional().allow("", null),
31550
+ status: import_joi46.default.string().optional().allow("", null)
31551
+ });
31552
+ const { error } = validation.validate(query);
31553
+ if (error) {
31554
+ next(new import_nodejs_utils92.BadRequestError(error.message));
31555
+ return;
31556
+ }
31557
+ const page = parseInt(req.query.page) ?? 1;
31558
+ let limit = parseInt(req.query.limit) ?? 20;
31559
+ limit = isNaN(limit) ? 20 : limit;
31560
+ const sort = req.query.sort ? String(req.query.sort).split(",") : "";
31561
+ const sortOrder = req.query.sortOrder ? String(req.query.sortOrder).split(",") : "";
31562
+ const sortObj = {};
31563
+ if (sort && Array.isArray(sort) && sort.length && sortOrder && Array.isArray(sortOrder) && sortOrder.length) {
31564
+ sort.forEach((field, index) => {
31565
+ sortObj[field] = sortOrder[index] === "desc" ? -1 : 1;
31566
+ });
31567
+ }
31568
+ const status = req.query.status ?? "active";
31569
+ const search = req.query.search ?? "";
31570
+ try {
31571
+ const curriculums = await _getAll({
31572
+ page,
31573
+ limit,
31574
+ sort: sortObj,
31575
+ status,
31576
+ search
31577
+ });
31578
+ res.json(curriculums);
31579
+ return;
31580
+ } catch (error2) {
31581
+ next(error2);
31582
+ }
31583
+ }
31584
+ async function getById(req, res, next) {
31585
+ const id = req.params.id;
31586
+ const validation = import_joi46.default.object({
31587
+ id: import_joi46.default.string().hex().required()
31588
+ });
31589
+ const { error } = validation.validate({ id });
31590
+ if (error) {
31591
+ next(new import_nodejs_utils92.BadRequestError(error.message));
31592
+ return;
31593
+ }
31594
+ try {
31595
+ const curriculum = await _getById(id);
31596
+ res.json({
31597
+ message: "Successfully retrieved curriculum.",
31598
+ data: { curriculum }
31599
+ });
31600
+ return;
31601
+ } catch (error2) {
31602
+ next(error2);
31603
+ }
31604
+ }
31605
+ async function deleteById(req, res, next) {
31606
+ const id = req.params.id;
31607
+ const validation = import_joi46.default.object({
31608
+ id: import_joi46.default.string().hex().required()
31609
+ });
31610
+ const { error } = validation.validate({ id });
31611
+ if (error) {
31612
+ next(new import_nodejs_utils92.BadRequestError(error.message));
31613
+ return;
31614
+ }
31615
+ try {
31616
+ const result = await _deleteById(id);
31617
+ res.json({
31618
+ message: "Successfully deleted curriculum.",
31619
+ data: result
31620
+ });
31621
+ return;
31622
+ } catch (error2) {
31623
+ next(error2);
31624
+ }
31625
+ }
31626
+ return {
31627
+ add,
31628
+ getAll,
31629
+ getById,
31630
+ updateById,
31631
+ deleteById
31632
+ };
31633
+ }
31634
+
31635
+ // src/models/grade-level.model.ts
31636
+ var import_nodejs_utils93 = require("@eeplatform/nodejs-utils");
31637
+ var import_joi47 = __toESM(require("joi"));
31638
+ var import_mongodb52 = require("mongodb");
31639
+ var schemaGradeLevel = import_joi47.default.object({
31640
+ _id: import_joi47.default.string().hex().optional(),
31641
+ school: import_joi47.default.string().hex().optional(),
31642
+ educationLevel: import_joi47.default.string().required(),
31643
+ gradeLevel: import_joi47.default.string().required(),
31644
+ teachingStyle: import_joi47.default.string().required(),
31645
+ defaultStartTime: import_joi47.default.string().optional().allow("", null),
31646
+ defaultEndTime: import_joi47.default.string().optional().allow("", null),
31647
+ status: import_joi47.default.string().optional().allow("", null),
31648
+ createdAt: import_joi47.default.date().optional().allow("", null),
31649
+ updatedAt: import_joi47.default.date().optional().allow("", null),
31650
+ deletedAt: import_joi47.default.date().optional().allow("", null),
31651
+ createdBy: import_joi47.default.string().optional().allow("", null),
31652
+ updatedBy: import_joi47.default.string().optional().allow("", null),
31653
+ deletedBy: import_joi47.default.string().optional().allow("", null)
31654
+ });
31655
+ function MGradeLevel(value) {
31656
+ const { error } = schemaGradeLevel.validate(value);
31657
+ if (error) {
31658
+ import_nodejs_utils93.logger.info(`Grade Level Model: ${error.message}`);
31659
+ throw new import_nodejs_utils93.BadRequestError(error.message);
31660
+ }
31661
+ if (value._id && typeof value._id === "string") {
31662
+ try {
31663
+ value._id = new import_mongodb52.ObjectId(value._id);
31664
+ } catch (error2) {
31665
+ throw new import_nodejs_utils93.BadRequestError("Invalid _id format");
31666
+ }
31667
+ }
31668
+ if (value.school && typeof value.school === "string") {
31669
+ try {
31670
+ value.school = new import_mongodb52.ObjectId(value.school);
31671
+ } catch (error2) {
31672
+ throw new import_nodejs_utils93.BadRequestError("Invalid school format");
31673
+ }
31674
+ }
31675
+ return {
31676
+ _id: value._id ?? void 0,
31677
+ school: value.school ?? void 0,
31678
+ educationLevel: value.educationLevel ?? "",
31679
+ gradeLevel: value.gradeLevel ?? "",
31680
+ teachingStyle: value.teachingStyle ?? "",
31681
+ defaultStartTime: value.defaultStartTime ?? "",
31682
+ defaultEndTime: value.defaultEndTime ?? "",
31683
+ status: value.status ?? "active",
31684
+ createdAt: value.createdAt ?? /* @__PURE__ */ new Date(),
31685
+ updatedAt: value.updatedAt ?? "",
31686
+ deletedAt: value.deletedAt ?? "",
31687
+ createdBy: value.createdBy ?? "",
31688
+ updatedBy: value.updatedBy ?? "",
31689
+ deletedBy: value.deletedBy ?? ""
31690
+ };
31691
+ }
31692
+
31693
+ // src/repositories/grade-level.repository.ts
31694
+ var import_nodejs_utils94 = require("@eeplatform/nodejs-utils");
31695
+ var import_mongodb53 = require("mongodb");
31696
+ function useGradeLevelRepo() {
31697
+ const db = import_nodejs_utils94.useAtlas.getDb();
31698
+ if (!db) {
31699
+ throw new Error("Unable to connect to server.");
31700
+ }
31701
+ const namespace_collection = "school.grade-levels";
31702
+ const collection = db.collection(namespace_collection);
31703
+ const { getCache, setCache, delNamespace } = (0, import_nodejs_utils94.useCache)(namespace_collection);
31704
+ async function createIndexes() {
31705
+ try {
31706
+ await collection.createIndexes([
31707
+ { key: { educationLevel: 1 } },
31708
+ { key: { gradeLevel: 1 } },
31709
+ { key: { teachingStyle: 1 } },
31710
+ { key: { school: 1 } },
31711
+ { key: { status: 1 } },
31712
+ {
31713
+ key: { educationLevel: 1, gradeLevel: 1, school: 1 },
31714
+ unique: true,
31715
+ partialFilterExpression: { status: { $in: ["active", "suspended"] } },
31716
+ name: "unique_grade_level_per_school_index"
31717
+ }
31718
+ ]);
31719
+ } catch (error) {
31720
+ throw new Error("Failed to create index on grade levels.");
31721
+ }
31722
+ }
31723
+ async function add(value, session) {
31724
+ try {
31725
+ value = MGradeLevel(value);
31726
+ const res = await collection.insertOne(value, { session });
31727
+ delCachedData();
31728
+ return res.insertedId;
31729
+ } catch (error) {
31730
+ import_nodejs_utils94.logger.log({
31731
+ level: "error",
31732
+ message: error.message
31733
+ });
31734
+ if (error instanceof import_nodejs_utils94.AppError) {
31735
+ throw error;
31736
+ } else {
31737
+ const isDuplicated = error.message.includes("duplicate");
31738
+ if (isDuplicated) {
31739
+ throw new import_nodejs_utils94.BadRequestError(
31740
+ "Grade level already exists for this education level and school."
31741
+ );
31742
+ }
31743
+ throw new Error("Failed to create grade level.");
31744
+ }
31745
+ }
31746
+ }
31747
+ async function updateById(_id, value, session) {
31748
+ try {
31749
+ _id = new import_mongodb53.ObjectId(_id);
31750
+ } catch (error) {
31751
+ throw new import_nodejs_utils94.BadRequestError("Invalid ID.");
31752
+ }
31753
+ if (value.school && typeof value.school === "string") {
31754
+ try {
31755
+ value.school = new import_mongodb53.ObjectId(value.school);
31756
+ } catch (error) {
31757
+ throw new import_nodejs_utils94.BadRequestError("Invalid school ID format.");
31758
+ }
31759
+ }
31760
+ try {
31761
+ const res = await collection.updateOne(
31762
+ { _id },
31763
+ { $set: { ...value, updatedAt: /* @__PURE__ */ new Date() } },
31764
+ { session }
31765
+ );
31766
+ delCachedData();
31767
+ return res;
31768
+ } catch (error) {
31769
+ import_nodejs_utils94.logger.log({
31770
+ level: "error",
31771
+ message: error.message
31772
+ });
31773
+ if (error instanceof import_nodejs_utils94.AppError) {
31774
+ throw error;
31775
+ } else {
31776
+ const isDuplicated = error.message.includes("duplicate");
31777
+ if (isDuplicated) {
31778
+ throw new import_nodejs_utils94.BadRequestError(
31779
+ "Grade level already exists for this education level and school."
31780
+ );
31781
+ }
31782
+ throw new Error("Failed to update grade level.");
31783
+ }
31784
+ }
31785
+ }
31786
+ async function getAll({
31787
+ search = "",
31788
+ page = 1,
31789
+ limit = 10,
31790
+ sort = {},
31791
+ educationLevel = "",
31792
+ gradeLevel = "",
31793
+ teachingStyle = "",
31794
+ school = "",
31795
+ status = "active"
31796
+ } = {}) {
31797
+ page = page > 0 ? page - 1 : 0;
31798
+ const query = {
31799
+ status
31800
+ };
31801
+ sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
31802
+ if (search) {
31803
+ query.$or = [
31804
+ { educationLevel: { $regex: search, $options: "i" } },
31805
+ { gradeLevel: { $regex: search, $options: "i" } },
31806
+ { teachingStyle: { $regex: search, $options: "i" } }
31807
+ ];
31808
+ }
31809
+ if (educationLevel) {
31810
+ query.educationLevel = educationLevel;
31811
+ }
31812
+ if (gradeLevel) {
31813
+ query.gradeLevel = gradeLevel;
31814
+ }
31815
+ if (teachingStyle) {
31816
+ query.teachingStyle = teachingStyle;
31817
+ }
31818
+ if (school) {
31819
+ try {
31820
+ query.school = new import_mongodb53.ObjectId(school);
31821
+ } catch (error) {
31822
+ throw new import_nodejs_utils94.BadRequestError("Invalid school ID format.");
31823
+ }
31824
+ }
31825
+ const cacheParams = {
31826
+ page,
31827
+ limit,
31828
+ sort: JSON.stringify(sort)
31829
+ };
31830
+ if (search)
31831
+ cacheParams.search = search;
31832
+ if (educationLevel)
31833
+ cacheParams.educationLevel = educationLevel;
31834
+ if (gradeLevel)
31835
+ cacheParams.gradeLevel = gradeLevel;
31836
+ if (teachingStyle)
31837
+ cacheParams.teachingStyle = teachingStyle;
31838
+ if (school)
31839
+ cacheParams.school = school;
31840
+ if (status !== "active")
31841
+ cacheParams.status = status;
31842
+ const cacheKey = (0, import_nodejs_utils94.makeCacheKey)(namespace_collection, cacheParams);
31843
+ import_nodejs_utils94.logger.log({
31844
+ level: "info",
31845
+ message: `Cache key for getAll grade levels: ${cacheKey}`
31846
+ });
31847
+ try {
31848
+ const cached = await getCache(cacheKey);
31849
+ if (cached) {
31850
+ import_nodejs_utils94.logger.log({
31851
+ level: "info",
31852
+ message: `Cache hit for getAll grade levels: ${cacheKey}`
31853
+ });
31854
+ return cached;
31855
+ }
31856
+ const items = await collection.aggregate([
31857
+ { $match: query },
31858
+ { $sort: sort },
31859
+ { $skip: page * limit },
31860
+ { $limit: limit },
31861
+ {
31862
+ $lookup: {
31863
+ from: "school.schools",
31864
+ localField: "school",
31865
+ foreignField: "_id",
31866
+ as: "schoolDetails"
31867
+ }
31868
+ },
31869
+ {
31870
+ $addFields: {
31871
+ schoolName: { $arrayElemAt: ["$schoolDetails.name", 0] }
31872
+ }
31873
+ },
31874
+ {
31875
+ $project: {
31876
+ schoolDetails: 0
31877
+ }
31878
+ }
31879
+ ]).toArray();
31880
+ const length = await collection.countDocuments(query);
31881
+ const data = (0, import_nodejs_utils94.paginate)(items, page, limit, length);
31882
+ setCache(cacheKey, data, 600).then(() => {
31883
+ import_nodejs_utils94.logger.log({
31884
+ level: "info",
31885
+ message: `Cache set for getAll grade levels: ${cacheKey}`
31886
+ });
31887
+ }).catch((err) => {
31888
+ import_nodejs_utils94.logger.log({
31889
+ level: "error",
31890
+ message: `Failed to set cache for getAll grade levels: ${err.message}`
31891
+ });
31892
+ });
31893
+ return data;
31894
+ } catch (error) {
31895
+ import_nodejs_utils94.logger.log({ level: "error", message: `${error}` });
31896
+ throw error;
31897
+ }
31898
+ }
31899
+ async function getById(_id) {
31900
+ try {
31901
+ _id = new import_mongodb53.ObjectId(_id);
31902
+ } catch (error) {
31903
+ throw new import_nodejs_utils94.BadRequestError("Invalid ID.");
31904
+ }
31905
+ const cacheKey = (0, import_nodejs_utils94.makeCacheKey)(namespace_collection, { _id: String(_id) });
31906
+ try {
31907
+ const cached = await getCache(cacheKey);
31908
+ if (cached) {
31909
+ import_nodejs_utils94.logger.log({
31910
+ level: "info",
31911
+ message: `Cache hit for getById grade level: ${cacheKey}`
31912
+ });
31913
+ return cached;
31914
+ }
31915
+ const result = await collection.aggregate([
31916
+ { $match: { _id } },
31917
+ {
31918
+ $lookup: {
31919
+ from: "school.schools",
31920
+ localField: "school",
31921
+ foreignField: "_id",
31922
+ as: "schoolDetails"
31923
+ }
31924
+ },
31925
+ {
31926
+ $addFields: {
31927
+ schoolName: { $arrayElemAt: ["$schoolDetails.name", 0] }
31928
+ }
31929
+ },
31930
+ {
31931
+ $project: {
31932
+ schoolDetails: 0
31933
+ }
31934
+ }
31935
+ ]).toArray();
31936
+ const gradeLevel = result[0] || null;
31937
+ setCache(cacheKey, gradeLevel, 300).then(() => {
31938
+ import_nodejs_utils94.logger.log({
31939
+ level: "info",
31940
+ message: `Cache set for grade level by id: ${cacheKey}`
31941
+ });
31942
+ }).catch((err) => {
31943
+ import_nodejs_utils94.logger.log({
31944
+ level: "error",
31945
+ message: `Failed to set cache for grade level by id: ${err.message}`
31946
+ });
31947
+ });
31948
+ return gradeLevel;
31949
+ } catch (error) {
31950
+ if (error instanceof import_nodejs_utils94.AppError) {
31951
+ throw error;
31952
+ } else {
31953
+ throw new import_nodejs_utils94.InternalServerError("Failed to get grade level.");
31954
+ }
31955
+ }
31956
+ }
31957
+ async function deleteById(_id, session) {
31958
+ try {
31959
+ _id = new import_mongodb53.ObjectId(_id);
31960
+ } catch (error) {
31961
+ throw new import_nodejs_utils94.BadRequestError("Invalid ID.");
31962
+ }
31963
+ try {
31964
+ const res = await collection.updateOne(
31965
+ { _id },
31966
+ { $set: { status: "deleted", deletedAt: /* @__PURE__ */ new Date() } },
31967
+ { session }
31968
+ );
31969
+ delCachedData();
31970
+ return res;
31971
+ } catch (error) {
31972
+ import_nodejs_utils94.logger.log({
31973
+ level: "error",
31974
+ message: error.message
31975
+ });
31976
+ if (error instanceof import_nodejs_utils94.AppError) {
31977
+ throw error;
31978
+ } else {
31979
+ throw new import_nodejs_utils94.InternalServerError("Failed to delete grade level.");
31980
+ }
31981
+ }
31982
+ }
31983
+ async function getByEducationLevel(educationLevel, school) {
31984
+ const query = {
31985
+ educationLevel,
31986
+ status: "active"
31987
+ };
31988
+ if (school) {
31989
+ try {
31990
+ query.school = new import_mongodb53.ObjectId(school);
31991
+ } catch (error) {
31992
+ throw new import_nodejs_utils94.BadRequestError("Invalid school ID format.");
31993
+ }
31994
+ }
31995
+ const cacheKey = (0, import_nodejs_utils94.makeCacheKey)(namespace_collection, {
31996
+ educationLevel,
31997
+ school: school || "all",
31998
+ method: "getByEducationLevel"
31999
+ });
32000
+ try {
32001
+ const cached = await getCache(cacheKey);
32002
+ if (cached) {
32003
+ import_nodejs_utils94.logger.log({
32004
+ level: "info",
32005
+ message: `Cache hit for getByEducationLevel: ${cacheKey}`
32006
+ });
32007
+ return cached;
32008
+ }
32009
+ const result = await collection.find(query).sort({ gradeLevel: 1 }).toArray();
32010
+ setCache(cacheKey, result, 300).then(() => {
32011
+ import_nodejs_utils94.logger.log({
32012
+ level: "info",
32013
+ message: `Cache set for getByEducationLevel: ${cacheKey}`
32014
+ });
32015
+ }).catch((err) => {
32016
+ import_nodejs_utils94.logger.log({
32017
+ level: "error",
32018
+ message: `Failed to set cache for getByEducationLevel: ${err.message}`
32019
+ });
32020
+ });
32021
+ return result;
32022
+ } catch (error) {
32023
+ import_nodejs_utils94.logger.log({ level: "error", message: `${error}` });
32024
+ throw error;
32025
+ }
32026
+ }
32027
+ function delCachedData() {
32028
+ delNamespace().then(() => {
32029
+ import_nodejs_utils94.logger.log({
32030
+ level: "info",
32031
+ message: `Cache namespace cleared for ${namespace_collection}`
32032
+ });
32033
+ }).catch((err) => {
32034
+ import_nodejs_utils94.logger.log({
32035
+ level: "error",
32036
+ message: `Failed to clear cache namespace for ${namespace_collection}: ${err.message}`
32037
+ });
32038
+ });
32039
+ }
32040
+ return {
32041
+ createIndexes,
32042
+ add,
32043
+ getAll,
32044
+ getById,
32045
+ updateById,
32046
+ deleteById,
32047
+ getByEducationLevel
32048
+ };
32049
+ }
32050
+
32051
+ // src/controllers/grade-level.controller.ts
32052
+ var import_nodejs_utils95 = require("@eeplatform/nodejs-utils");
32053
+ var import_joi48 = __toESM(require("joi"));
32054
+ function useGradeLevelController() {
32055
+ const {
32056
+ getAll: _getAll,
32057
+ getById: _getById,
32058
+ add: _add,
32059
+ updateById: _updateById,
32060
+ deleteById: _deleteById,
32061
+ getByEducationLevel: _getByEducationLevel
32062
+ } = useGradeLevelRepo();
32063
+ async function add(req, res, next) {
32064
+ const value = req.body;
32065
+ const validation = import_joi48.default.object({
32066
+ school: import_joi48.default.string().hex().optional(),
32067
+ educationLevel: import_joi48.default.string().required(),
32068
+ gradeLevel: import_joi48.default.string().required(),
32069
+ teachingStyle: import_joi48.default.string().required(),
32070
+ defaultStartTime: import_joi48.default.string().optional().allow("", null),
32071
+ defaultEndTime: import_joi48.default.string().optional().allow("", null),
32072
+ status: import_joi48.default.string().optional().allow("", null)
32073
+ });
32074
+ const { error } = validation.validate(value);
32075
+ if (error) {
32076
+ next(new import_nodejs_utils95.BadRequestError(error.message));
32077
+ import_nodejs_utils95.logger.info(`Controller: ${error.message}`);
32078
+ return;
32079
+ }
32080
+ try {
32081
+ const result = await _add(value);
32082
+ res.json({
32083
+ message: "Successfully created grade level.",
32084
+ data: { _id: result }
32085
+ });
32086
+ return;
32087
+ } catch (error2) {
32088
+ next(error2);
32089
+ }
32090
+ }
32091
+ async function updateById(req, res, next) {
32092
+ const value = req.body;
32093
+ const id = req.params.id ?? "";
32094
+ const validation = import_joi48.default.object({
32095
+ id: import_joi48.default.string().hex().required(),
32096
+ value: import_joi48.default.object({
32097
+ school: import_joi48.default.string().hex().optional(),
32098
+ educationLevel: import_joi48.default.string().optional(),
32099
+ gradeLevel: import_joi48.default.string().optional(),
32100
+ teachingStyle: import_joi48.default.string().optional(),
32101
+ maxTeachingHoursPerDay: import_joi48.default.number().integer().min(0).optional(),
32102
+ maxTeachingHoursPerWeek: import_joi48.default.number().integer().min(0).optional(),
32103
+ defaultStartTime: import_joi48.default.string().optional().allow("", null),
32104
+ defaultEndTime: import_joi48.default.string().optional().allow("", null)
32105
+ }).min(1)
32106
+ });
32107
+ const { error } = validation.validate({ id, value });
32108
+ if (error) {
32109
+ next(new import_nodejs_utils95.BadRequestError(error.message));
32110
+ import_nodejs_utils95.logger.info(`Controller: ${error.message}`);
32111
+ return;
32112
+ }
32113
+ try {
32114
+ const result = await _updateById(id, value);
32115
+ res.json({
32116
+ message: "Successfully updated grade level.",
32117
+ data: result
32118
+ });
32119
+ return;
32120
+ } catch (error2) {
32121
+ next(error2);
32122
+ }
32123
+ }
32124
+ async function getAll(req, res, next) {
32125
+ const query = req.query;
32126
+ const validation = import_joi48.default.object({
32127
+ page: import_joi48.default.number().min(1).optional().allow("", null),
32128
+ limit: import_joi48.default.number().min(1).optional().allow("", null),
32129
+ search: import_joi48.default.string().optional().allow("", null),
32130
+ educationLevel: import_joi48.default.string().optional().allow("", null),
32131
+ gradeLevel: import_joi48.default.string().optional().allow("", null),
32132
+ teachingStyle: import_joi48.default.string().optional().allow("", null),
32133
+ school: import_joi48.default.string().hex().optional().allow("", null),
32134
+ status: import_joi48.default.string().optional().allow("", null)
32135
+ });
32136
+ const { error } = validation.validate(query);
32137
+ if (error) {
32138
+ next(new import_nodejs_utils95.BadRequestError(error.message));
32139
+ return;
32140
+ }
32141
+ const page = parseInt(req.query.page) ?? 1;
32142
+ let limit = parseInt(req.query.limit) ?? 20;
32143
+ limit = isNaN(limit) ? 20 : limit;
32144
+ const sort = req.query.sort ? String(req.query.sort).split(",") : "";
32145
+ const sortOrder = req.query.sortOrder ? String(req.query.sortOrder).split(",") : "";
32146
+ const sortObj = {};
32147
+ if (sort && Array.isArray(sort) && sort.length && sortOrder && Array.isArray(sortOrder) && sortOrder.length) {
32148
+ sort.forEach((field, index) => {
32149
+ sortObj[field] = sortOrder[index] === "desc" ? -1 : 1;
32150
+ });
32151
+ }
32152
+ const status = req.query.status ?? "active";
32153
+ const educationLevel = req.query.educationLevel ?? "";
32154
+ const gradeLevel = req.query.gradeLevel ?? "";
32155
+ const teachingStyle = req.query.teachingStyle ?? "";
32156
+ const school = req.query.school ?? "";
32157
+ const search = req.query.search ?? "";
32158
+ try {
32159
+ const gradeLevels = await _getAll({
32160
+ page,
32161
+ limit,
32162
+ sort: sortObj,
32163
+ status,
32164
+ educationLevel,
32165
+ gradeLevel,
32166
+ teachingStyle,
32167
+ school,
32168
+ search
32169
+ });
32170
+ res.json(gradeLevels);
32171
+ return;
32172
+ } catch (error2) {
32173
+ next(error2);
32174
+ }
32175
+ }
32176
+ async function getById(req, res, next) {
32177
+ const id = req.params.id;
32178
+ const validation = import_joi48.default.object({
32179
+ id: import_joi48.default.string().hex().required()
32180
+ });
32181
+ const { error } = validation.validate({ id });
32182
+ if (error) {
32183
+ next(new import_nodejs_utils95.BadRequestError(error.message));
32184
+ return;
32185
+ }
32186
+ try {
32187
+ const gradeLevel = await _getById(id);
32188
+ res.json({
32189
+ message: "Successfully retrieved grade level.",
32190
+ data: { gradeLevel }
32191
+ });
32192
+ return;
32193
+ } catch (error2) {
32194
+ next(error2);
32195
+ }
32196
+ }
32197
+ async function deleteById(req, res, next) {
32198
+ const id = req.params.id;
32199
+ const validation = import_joi48.default.object({
32200
+ id: import_joi48.default.string().hex().required()
32201
+ });
32202
+ const { error } = validation.validate({ id });
32203
+ if (error) {
32204
+ next(new import_nodejs_utils95.BadRequestError(error.message));
32205
+ return;
32206
+ }
32207
+ try {
32208
+ const result = await _deleteById(id);
32209
+ res.json({
32210
+ message: "Successfully deleted grade level.",
32211
+ data: result
32212
+ });
32213
+ return;
32214
+ } catch (error2) {
32215
+ next(error2);
32216
+ }
32217
+ }
32218
+ async function getByEducationLevel(req, res, next) {
32219
+ const educationLevel = req.params.educationLevel;
32220
+ const school = req.query.school;
32221
+ const validation = import_joi48.default.object({
32222
+ educationLevel: import_joi48.default.string().required(),
32223
+ school: import_joi48.default.string().hex().optional().allow("", null)
32224
+ });
32225
+ const { error } = validation.validate({ educationLevel, school });
32226
+ if (error) {
32227
+ next(new import_nodejs_utils95.BadRequestError(error.message));
32228
+ return;
32229
+ }
32230
+ try {
32231
+ const gradeLevels = await _getByEducationLevel(educationLevel, school);
32232
+ res.json({
32233
+ message: "Successfully retrieved grade levels by education level.",
32234
+ data: { gradeLevels }
32235
+ });
32236
+ return;
32237
+ } catch (error2) {
32238
+ next(error2);
32239
+ }
32240
+ }
32241
+ return {
32242
+ add,
32243
+ getAll,
32244
+ getById,
32245
+ updateById,
32246
+ deleteById,
32247
+ getByEducationLevel
32248
+ };
32249
+ }
30504
32250
  // Annotate the CommonJS export names for ESM import in node:
30505
32251
  0 && (module.exports = {
30506
32252
  ACCESS_TOKEN_EXPIRY,
@@ -30523,12 +32269,15 @@ function usePlantillaController() {
30523
32269
  MAsset,
30524
32270
  MBuilding,
30525
32271
  MBuildingUnit,
32272
+ MCurriculum,
30526
32273
  MDivision,
30527
32274
  MEntity,
30528
32275
  MFile,
32276
+ MGradeLevel,
30529
32277
  MMember,
30530
32278
  MONGO_DB,
30531
32279
  MONGO_URI,
32280
+ MOffice,
30532
32281
  MOrder,
30533
32282
  MOrg,
30534
32283
  MPaymentMethod,
@@ -30569,7 +32318,10 @@ function usePlantillaController() {
30569
32318
  schemaAssetUpdateOption,
30570
32319
  schemaBuilding,
30571
32320
  schemaBuildingUnit,
32321
+ schemaCurriculum,
30572
32322
  schemaDivision,
32323
+ schemaGradeLevel,
32324
+ schemaOffice,
30573
32325
  schemaPlantilla,
30574
32326
  schemaRegion,
30575
32327
  schemaSchool,
@@ -30587,6 +32339,8 @@ function usePlantillaController() {
30587
32339
  useBuildingUnitRepo,
30588
32340
  useCounterModel,
30589
32341
  useCounterRepo,
32342
+ useCurriculumController,
32343
+ useCurriculumRepo,
30590
32344
  useDivisionController,
30591
32345
  useDivisionRepo,
30592
32346
  useDivisionService,
@@ -30596,12 +32350,17 @@ function usePlantillaController() {
30596
32350
  useFileRepo,
30597
32351
  useFileService,
30598
32352
  useGitHubService,
32353
+ useGradeLevelController,
32354
+ useGradeLevelRepo,
30599
32355
  useInvoiceController,
30600
32356
  useInvoiceModel,
30601
32357
  useInvoiceRepo,
30602
32358
  useInvoiceService,
30603
32359
  useMemberController,
30604
32360
  useMemberRepo,
32361
+ useOfficeController,
32362
+ useOfficeRepo,
32363
+ useOfficeService,
30605
32364
  useOrderController,
30606
32365
  useOrderRepo,
30607
32366
  useOrgController,