@eeplatform/core 1.0.0 → 1.0.2

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
@@ -11342,6 +11342,7 @@ __export(src_exports, {
11342
11342
  MAILER_TRANSPORT_PORT: () => MAILER_TRANSPORT_PORT,
11343
11343
  MAILER_TRANSPORT_SECURE: () => MAILER_TRANSPORT_SECURE,
11344
11344
  MAddress: () => MAddress,
11345
+ MDivision: () => MDivision,
11345
11346
  MEntity: () => MEntity,
11346
11347
  MFile: () => MFile,
11347
11348
  MMember: () => MMember,
@@ -11351,7 +11352,9 @@ __export(src_exports, {
11351
11352
  MOrg: () => MOrg,
11352
11353
  MPaymentMethod: () => MPaymentMethod,
11353
11354
  MPromoCode: () => MPromoCode,
11355
+ MRegion: () => MRegion,
11354
11356
  MRole: () => MRole,
11357
+ MSchool: () => MSchool,
11355
11358
  MSubscription: () => MSubscription,
11356
11359
  MToken: () => MToken,
11357
11360
  MUser: () => MUser,
@@ -11379,12 +11382,17 @@ __export(src_exports, {
11379
11382
  addressSchema: () => addressSchema,
11380
11383
  isDev: () => isDev,
11381
11384
  schema: () => schema,
11385
+ schemaDivision: () => schemaDivision,
11386
+ schemaRegion: () => schemaRegion,
11387
+ schemaSchool: () => schemaSchool,
11382
11388
  useAddressController: () => useAddressController,
11383
11389
  useAddressRepo: () => useAddressRepo,
11384
11390
  useAuthController: () => useAuthController,
11385
11391
  useAuthService: () => useAuthService,
11386
11392
  useCounterModel: () => useCounterModel,
11387
11393
  useCounterRepo: () => useCounterRepo,
11394
+ useDivisionController: () => useDivisionController,
11395
+ useDivisionRepo: () => useDivisionRepo,
11388
11396
  useEntityController: () => useEntityController,
11389
11397
  useEntityRepo: () => useEntityRepo,
11390
11398
  useFileController: () => useFileController,
@@ -11413,8 +11421,13 @@ __export(src_exports, {
11413
11421
  usePriceRepo: () => usePriceRepo,
11414
11422
  usePromoCodeController: () => usePromoCodeController,
11415
11423
  usePromoCodeRepo: () => usePromoCodeRepo,
11424
+ useRegionController: () => useRegionController,
11425
+ useRegionRepo: () => useRegionRepo,
11416
11426
  useRoleController: () => useRoleController,
11417
11427
  useRoleRepo: () => useRoleRepo,
11428
+ useSchoolController: () => useSchoolController,
11429
+ useSchoolRepo: () => useSchoolRepo,
11430
+ useSchoolService: () => useSchoolService,
11418
11431
  useSubscriptionController: () => useSubscriptionController,
11419
11432
  useSubscriptionRepo: () => useSubscriptionRepo,
11420
11433
  useSubscriptionService: () => useSubscriptionService,
@@ -11791,10 +11804,12 @@ var MUser = class {
11791
11804
  this.createdAt = value.createdAt ?? (/* @__PURE__ */ new Date()).toISOString();
11792
11805
  this.updatedAt = value.updatedAt ?? "";
11793
11806
  this.deletedAt = value.deletedAt ?? "";
11794
- try {
11795
- value.defaultOrg = new import_mongodb3.ObjectId(value.defaultOrg);
11796
- } catch (error) {
11797
- throw new Error("Invalid defaultOrg ID.");
11807
+ if (value.defaultOrg) {
11808
+ try {
11809
+ value.defaultOrg = new import_mongodb3.ObjectId(value.defaultOrg);
11810
+ } catch (error) {
11811
+ throw new Error("Invalid defaultOrg ID.");
11812
+ }
11798
11813
  }
11799
11814
  this.defaultOrg = value.defaultOrg;
11800
11815
  }
@@ -12259,7 +12274,8 @@ function useMemberRepo() {
12259
12274
  await collection.createIndex(
12260
12275
  {
12261
12276
  org: 1,
12262
- user: 1
12277
+ user: 1,
12278
+ type: 1
12263
12279
  },
12264
12280
  { partialFilterExpression: { deletedAt: "" }, unique: true }
12265
12281
  );
@@ -12288,6 +12304,10 @@ function useMemberRepo() {
12288
12304
  delCachedData();
12289
12305
  return "Successfully added member.";
12290
12306
  } catch (error) {
12307
+ import_nodejs_utils5.logger.log({
12308
+ level: "error",
12309
+ message: `Failed to create member: ${error}`
12310
+ });
12291
12311
  if (error instanceof import_nodejs_utils5.AppError) {
12292
12312
  throw error;
12293
12313
  } else {
@@ -12829,9 +12849,6 @@ function useVerificationService() {
12829
12849
  if (!metadata.app) {
12830
12850
  throw new import_nodejs_utils6.BadRequestError("App metadata is required.");
12831
12851
  }
12832
- if (!metadata.org || !metadata.orgName) {
12833
- throw new import_nodejs_utils6.BadRequestError("Organization metadata is required.");
12834
- }
12835
12852
  try {
12836
12853
  const user = await getUserByEmail(email);
12837
12854
  const dir = __dirname;
@@ -12843,7 +12860,7 @@ function useVerificationService() {
12843
12860
  context: {
12844
12861
  validity: VERIFICATION_USER_INVITE_DURATION,
12845
12862
  link: `${APP_MAIN}/verify/member-invite/${res2}`,
12846
- organization_name: metadata.orgName
12863
+ organization_name: metadata.app === "admin" ? "Admin" : metadata.orgName
12847
12864
  },
12848
12865
  filePath: filePath2
12849
12866
  });
@@ -13014,11 +13031,6 @@ function useVerificationService() {
13014
13031
  "App metadata is required for member invite."
13015
13032
  );
13016
13033
  }
13017
- if (!_id.metadata?.org || !_id.metadata?.orgName) {
13018
- throw new import_nodejs_utils6.BadRequestError(
13019
- "Organization metadata is required for member invite."
13020
- );
13021
- }
13022
13034
  if (!_id.metadata?.role || !_id.metadata?.roleName) {
13023
13035
  throw new import_nodejs_utils6.BadRequestError(
13024
13036
  "Role metadata is required for member invite."
@@ -13028,8 +13040,8 @@ function useVerificationService() {
13028
13040
  {
13029
13041
  user: user._id?.toString() ?? "",
13030
13042
  type: _id.metadata?.app,
13031
- org: _id.metadata?.org,
13032
- orgName: _id.metadata?.orgName,
13043
+ org: _id.metadata?.org ?? "",
13044
+ orgName: _id.metadata?.orgName ?? "",
13033
13045
  role: _id.metadata?.role,
13034
13046
  roleName: _id.metadata?.roleName,
13035
13047
  name: `${user.firstName} ${user.lastName}`
@@ -13148,8 +13160,8 @@ function useVerificationController() {
13148
13160
  app: import_joi2.default.string().required(),
13149
13161
  role: import_joi2.default.string().hex().required(),
13150
13162
  roleName: import_joi2.default.string().required(),
13151
- org: import_joi2.default.string().required(),
13152
- orgName: import_joi2.default.string().required()
13163
+ org: import_joi2.default.string().hex().optional().optional().allow("", null),
13164
+ orgName: import_joi2.default.string().optional().optional().allow("", null)
13153
13165
  });
13154
13166
  const { error } = validation.validate(req.body);
13155
13167
  if (error) {
@@ -17441,14 +17453,14 @@ var MRole = class {
17441
17453
  throw new Error("Invalid _id.");
17442
17454
  }
17443
17455
  }
17444
- if (typeof value.org === "string" && value.org.length === 24) {
17456
+ if (typeof value.id === "string" && value.id.length === 24) {
17445
17457
  try {
17446
- value.org = new import_mongodb12.ObjectId(value.org);
17458
+ value.id = new import_mongodb12.ObjectId(value.id);
17447
17459
  } catch (error) {
17448
- throw new Error("Invalid org.");
17460
+ throw new Error("Invalid id.");
17449
17461
  }
17450
17462
  }
17451
- this.org = value.org ?? "";
17463
+ this.id = value.id ?? "";
17452
17464
  this._id = value._id ?? new import_mongodb12.ObjectId();
17453
17465
  this.name = value.name ?? "";
17454
17466
  this.description = value.description ?? "";
@@ -17498,6 +17510,7 @@ function useRoleRepo() {
17498
17510
  await collection.createIndex({ name: 1 });
17499
17511
  await collection.createIndex({ type: 1 });
17500
17512
  await collection.createIndex({ status: 1 });
17513
+ await collection.createIndex({ id: 1 });
17501
17514
  } catch (error) {
17502
17515
  throw new import_nodejs_utils11.InternalServerError("Failed to create index on role.");
17503
17516
  }
@@ -17512,7 +17525,7 @@ function useRoleRepo() {
17512
17525
  async function createUniqueIndex() {
17513
17526
  try {
17514
17527
  await collection.createIndex(
17515
- { name: 1, type: 1, org: 1 },
17528
+ { name: 1, type: 1, id: 1 },
17516
17529
  { unique: true }
17517
17530
  );
17518
17531
  } catch (error) {
@@ -17643,26 +17656,29 @@ function useRoleRepo() {
17643
17656
  limit = 10,
17644
17657
  sort = {},
17645
17658
  type = "",
17646
- org = ""
17659
+ id = ""
17647
17660
  } = {}) {
17648
17661
  limit = limit > 0 ? limit : 10;
17649
17662
  search = search || "";
17650
17663
  page = page > 0 ? page - 1 : 0;
17651
- if (org && typeof org === "string" && org.length === 24) {
17664
+ if (id && typeof id === "string" && id.length === 24) {
17652
17665
  try {
17653
- org = new import_mongodb13.ObjectId(org);
17666
+ id = new import_mongodb13.ObjectId(id);
17654
17667
  } catch (error) {
17655
- throw new import_nodejs_utils11.BadRequestError("Invalid organization ID.");
17668
+ throw new import_nodejs_utils11.BadRequestError("Invalid ID.");
17656
17669
  }
17657
17670
  }
17658
- const query = { status: "active", org };
17671
+ const query = { status: "active" };
17672
+ if (id) {
17673
+ query.id = id;
17674
+ }
17659
17675
  const cacheKeyOptions = {
17660
17676
  status: "active",
17661
17677
  limit,
17662
17678
  page
17663
17679
  };
17664
- if (org) {
17665
- cacheKeyOptions.org = String(org);
17680
+ if (id) {
17681
+ cacheKeyOptions.id = String(id);
17666
17682
  }
17667
17683
  if (type) {
17668
17684
  cacheKeyOptions.type = type;
@@ -17849,7 +17865,7 @@ function useUserService() {
17849
17865
  await _createUser(user, session);
17850
17866
  const roleId = await addRole(
17851
17867
  {
17852
- org: "",
17868
+ id: "",
17853
17869
  name: "Super Admin",
17854
17870
  type: "admin",
17855
17871
  permissions: ["*"],
@@ -17958,9 +17974,6 @@ function useUserService() {
17958
17974
  throw new import_nodejs_utils12.BadRequestError("Invitation expired.");
17959
17975
  }
17960
17976
  const email = invitation.email;
17961
- if (!invitation.metadata.org) {
17962
- throw new import_nodejs_utils12.BadRequestError("Invitation does not have an organization.");
17963
- }
17964
17977
  const _user = await getUserByEmail(invitation.email);
17965
17978
  let userId = _user?._id ?? "";
17966
17979
  if (!_user) {
@@ -17985,8 +17998,8 @@ function useUserService() {
17985
17998
  role: invitation.metadata?.role,
17986
17999
  roleName: invitation.metadata?.roleName,
17987
18000
  type: invitation.metadata?.app,
17988
- org: invitation.metadata?.org,
17989
- orgName: invitation.metadata?.orgName
18001
+ org: invitation.metadata?.org ?? "",
18002
+ orgName: invitation.metadata?.orgName ?? ""
17990
18003
  },
17991
18004
  session
17992
18005
  );
@@ -18796,8 +18809,8 @@ function useRoleController() {
18796
18809
  const validation = import_joi7.default.object({
18797
18810
  name: import_joi7.default.string().required(),
18798
18811
  permissions: import_joi7.default.array().items(import_joi7.default.string()).required(),
18799
- type: import_joi7.default.string().optional().allow("", null),
18800
- org: import_joi7.default.string().hex().optional().allow("", null)
18812
+ type: import_joi7.default.string().valid("school", "division", "region", "account").required(),
18813
+ id: import_joi7.default.string().hex().optional().allow("", null)
18801
18814
  });
18802
18815
  const { error } = validation.validate(payload);
18803
18816
  if (error) {
@@ -18817,21 +18830,21 @@ function useRoleController() {
18817
18830
  const page = parseInt(req.query.page ?? "1");
18818
18831
  const limit = parseInt(req.query.limit ?? "10");
18819
18832
  const type = req.query.type ?? "";
18820
- const org = req.query.org ?? "";
18833
+ const id = req.query.id ?? "";
18821
18834
  const validation = import_joi7.default.object({
18822
18835
  search: import_joi7.default.string().optional().allow("", null),
18823
18836
  page: import_joi7.default.number().required(),
18824
18837
  limit: import_joi7.default.number().required(),
18825
18838
  type: import_joi7.default.string().optional().allow("", null),
18826
- org: import_joi7.default.string().hex().optional().allow("", null)
18839
+ id: import_joi7.default.string().hex().optional().allow("", null)
18827
18840
  });
18828
- const { error } = validation.validate({ search, page, limit, type, org });
18841
+ const { error } = validation.validate({ search, page, limit, type, id });
18829
18842
  if (error) {
18830
18843
  next(new import_nodejs_utils18.BadRequestError(error.message));
18831
18844
  return;
18832
18845
  }
18833
18846
  try {
18834
- const data = await _getRoles({ search, page, limit, type, org });
18847
+ const data = await _getRoles({ search, page, limit, type, id });
18835
18848
  res.json(data);
18836
18849
  return;
18837
18850
  } catch (error2) {
@@ -21683,7 +21696,7 @@ function useSubscriptionService() {
21683
21696
  const roleName = "owner";
21684
21697
  const role = await addRole(
21685
21698
  {
21686
- org: orgId.toString(),
21699
+ id: orgId.toString(),
21687
21700
  name: roleName,
21688
21701
  permissions: ["*"],
21689
21702
  type: "organization",
@@ -21872,7 +21885,7 @@ function useSubscriptionService() {
21872
21885
  }
21873
21886
  const role = await addRole(
21874
21887
  {
21875
- org: orgId.toString(),
21888
+ id: orgId.toString(),
21876
21889
  name: "owner",
21877
21890
  permissions: ["*"],
21878
21891
  type: "organization",
@@ -24121,7 +24134,7 @@ function useOrgService() {
24121
24134
  );
24122
24135
  const role = await addRole(
24123
24136
  {
24124
- org,
24137
+ id: org,
24125
24138
  name: "Owner",
24126
24139
  description: "Owner of the organization",
24127
24140
  permissions: ["all"]
@@ -25263,6 +25276,1679 @@ function usePriceController() {
25263
25276
  getByNameType
25264
25277
  };
25265
25278
  }
25279
+
25280
+ // src/models/region.model.ts
25281
+ var import_nodejs_utils55 = require("@eeplatform/nodejs-utils");
25282
+ var import_joi27 = __toESM(require("joi"));
25283
+ var import_mongodb33 = require("mongodb");
25284
+ var schemaRegion = import_joi27.default.object({
25285
+ _id: import_joi27.default.string().hex().optional().allow(null, ""),
25286
+ name: import_joi27.default.string().min(1).max(100).required(),
25287
+ director: import_joi27.default.string().hex().optional().allow(null, ""),
25288
+ directorName: import_joi27.default.string().min(1).max(100).optional().allow(null, ""),
25289
+ createdAt: import_joi27.default.string().isoDate().optional(),
25290
+ updatedAt: import_joi27.default.string().isoDate().optional(),
25291
+ deletedAt: import_joi27.default.string().isoDate().optional().allow(null, "")
25292
+ });
25293
+ function MRegion(value) {
25294
+ const { error } = schemaRegion.validate(value);
25295
+ if (error) {
25296
+ throw new import_nodejs_utils55.BadRequestError(`Invalid region data: ${error.message}`);
25297
+ }
25298
+ if (value._id && typeof value._id === "string") {
25299
+ try {
25300
+ value._id = new import_mongodb33.ObjectId(value._id);
25301
+ } catch (error2) {
25302
+ throw new Error("Invalid _id.");
25303
+ }
25304
+ }
25305
+ if (value.director && typeof value.director === "string") {
25306
+ try {
25307
+ value.director = new import_mongodb33.ObjectId(value.director);
25308
+ } catch (error2) {
25309
+ throw new Error("Invalid director.");
25310
+ }
25311
+ }
25312
+ return {
25313
+ _id: value._id,
25314
+ name: value.name,
25315
+ director: value.director ?? "",
25316
+ directorName: value.directorName ?? "",
25317
+ createdAt: value.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
25318
+ updatedAt: value.updatedAt ?? "",
25319
+ deletedAt: value.deletedAt ?? ""
25320
+ };
25321
+ }
25322
+
25323
+ // src/repositories/region.repository.ts
25324
+ var import_nodejs_utils56 = require("@eeplatform/nodejs-utils");
25325
+ var import_mongodb34 = require("mongodb");
25326
+ function useRegionRepo() {
25327
+ const db = import_nodejs_utils56.useAtlas.getDb();
25328
+ if (!db) {
25329
+ throw new Error("Unable to connect to server.");
25330
+ }
25331
+ const namespace_collection = "regions";
25332
+ const collection = db.collection(namespace_collection);
25333
+ const { getCache, setCache, delNamespace } = (0, import_nodejs_utils56.useCache)();
25334
+ async function createIndex() {
25335
+ try {
25336
+ await collection.createIndex([
25337
+ { name: 1 },
25338
+ { director: 1 },
25339
+ { createdAt: 1 }
25340
+ ]);
25341
+ } catch (error) {
25342
+ throw new Error("Failed to create index on regions.");
25343
+ }
25344
+ }
25345
+ async function createTextIndex() {
25346
+ try {
25347
+ await collection.createIndex({
25348
+ name: "text",
25349
+ directorName: "text"
25350
+ });
25351
+ } catch (error) {
25352
+ throw new Error(
25353
+ "Failed to create text index on region name and director name."
25354
+ );
25355
+ }
25356
+ }
25357
+ async function createUniqueIndex() {
25358
+ try {
25359
+ await collection.createIndex(
25360
+ {
25361
+ name: 1
25362
+ },
25363
+ { unique: true }
25364
+ );
25365
+ } catch (error) {
25366
+ throw new Error("Failed to create unique index on region name.");
25367
+ }
25368
+ }
25369
+ function delCachedData() {
25370
+ delNamespace(namespace_collection).then(() => {
25371
+ import_nodejs_utils56.logger.log({
25372
+ level: "info",
25373
+ message: `Cache namespace cleared for ${namespace_collection}`
25374
+ });
25375
+ }).catch((err) => {
25376
+ import_nodejs_utils56.logger.log({
25377
+ level: "error",
25378
+ message: `Failed to clear cache namespace for ${namespace_collection}: ${err.message}`
25379
+ });
25380
+ });
25381
+ }
25382
+ async function add(value, session) {
25383
+ try {
25384
+ value = MRegion(value);
25385
+ const res = await collection.insertOne(value, { session });
25386
+ delCachedData();
25387
+ return res.insertedId;
25388
+ } catch (error) {
25389
+ import_nodejs_utils56.logger.log({
25390
+ level: "error",
25391
+ message: error.message
25392
+ });
25393
+ if (error instanceof import_nodejs_utils56.AppError) {
25394
+ throw error;
25395
+ } else {
25396
+ const isDuplicated = error.message.includes("duplicate");
25397
+ if (isDuplicated) {
25398
+ throw new import_nodejs_utils56.BadRequestError("Region already exists.");
25399
+ }
25400
+ throw new Error("Failed to create region.");
25401
+ }
25402
+ }
25403
+ }
25404
+ async function getAll({ search = "", page = 1, limit = 10, sort = {} } = {}) {
25405
+ page = page > 0 ? page - 1 : 0;
25406
+ const query = { deletedAt: { $in: ["", null] } };
25407
+ sort = Object.keys(sort).length > 0 ? sort : { _id: 1 };
25408
+ if (search) {
25409
+ query.$text = { $search: search };
25410
+ }
25411
+ const cacheKey = (0, import_nodejs_utils56.makeCacheKey)(namespace_collection, {
25412
+ search,
25413
+ page,
25414
+ limit,
25415
+ sort: JSON.stringify(sort)
25416
+ });
25417
+ import_nodejs_utils56.logger.log({
25418
+ level: "info",
25419
+ message: `Cache key for getAll regions: ${cacheKey}`
25420
+ });
25421
+ try {
25422
+ const cached = await getCache(cacheKey);
25423
+ if (cached) {
25424
+ import_nodejs_utils56.logger.log({
25425
+ level: "info",
25426
+ message: `Cache hit for getAll regions: ${cacheKey}`
25427
+ });
25428
+ return cached;
25429
+ }
25430
+ const items = await collection.aggregate([
25431
+ { $match: query },
25432
+ { $sort: sort },
25433
+ { $skip: page * limit },
25434
+ { $limit: limit },
25435
+ {
25436
+ $project: {
25437
+ _id: 1,
25438
+ name: 1,
25439
+ director: 1,
25440
+ directorName: 1,
25441
+ createdAt: 1,
25442
+ updatedAt: 1
25443
+ }
25444
+ }
25445
+ ]).toArray();
25446
+ const length = await collection.countDocuments(query);
25447
+ const data = (0, import_nodejs_utils56.paginate)(items, page, limit, length);
25448
+ setCache(cacheKey, data, 600, namespace_collection).then(() => {
25449
+ import_nodejs_utils56.logger.log({
25450
+ level: "info",
25451
+ message: `Cache set for getAll regions: ${cacheKey}`
25452
+ });
25453
+ }).catch((err) => {
25454
+ import_nodejs_utils56.logger.log({
25455
+ level: "error",
25456
+ message: `Failed to set cache for getAll regions: ${err.message}`
25457
+ });
25458
+ });
25459
+ return data;
25460
+ } catch (error) {
25461
+ import_nodejs_utils56.logger.log({ level: "error", message: `${error}` });
25462
+ throw error;
25463
+ }
25464
+ }
25465
+ async function getById(_id) {
25466
+ try {
25467
+ _id = new import_mongodb34.ObjectId(_id);
25468
+ } catch (error) {
25469
+ throw new import_nodejs_utils56.BadRequestError("Invalid ID.");
25470
+ }
25471
+ const cacheKey = (0, import_nodejs_utils56.makeCacheKey)(namespace_collection, { _id: String(_id) });
25472
+ try {
25473
+ const cached = await getCache(cacheKey);
25474
+ if (cached) {
25475
+ import_nodejs_utils56.logger.log({
25476
+ level: "info",
25477
+ message: `Cache hit for getById region: ${cacheKey}`
25478
+ });
25479
+ return cached;
25480
+ }
25481
+ const result = await collection.findOne({
25482
+ _id,
25483
+ deletedAt: { $in: ["", null] }
25484
+ });
25485
+ if (!result) {
25486
+ throw new import_nodejs_utils56.BadRequestError("Region not found.");
25487
+ }
25488
+ setCache(cacheKey, result, 300, namespace_collection).then(() => {
25489
+ import_nodejs_utils56.logger.log({
25490
+ level: "info",
25491
+ message: `Cache set for region by id: ${cacheKey}`
25492
+ });
25493
+ }).catch((err) => {
25494
+ import_nodejs_utils56.logger.log({
25495
+ level: "error",
25496
+ message: `Failed to set cache for region by id: ${err.message}`
25497
+ });
25498
+ });
25499
+ return result;
25500
+ } catch (error) {
25501
+ if (error instanceof import_nodejs_utils56.AppError) {
25502
+ throw error;
25503
+ } else {
25504
+ throw new import_nodejs_utils56.InternalServerError("Failed to get region.");
25505
+ }
25506
+ }
25507
+ }
25508
+ async function getByName(name) {
25509
+ const cacheKey = (0, import_nodejs_utils56.makeCacheKey)(namespace_collection, { name });
25510
+ try {
25511
+ const cached = await getCache(cacheKey);
25512
+ if (cached) {
25513
+ import_nodejs_utils56.logger.log({
25514
+ level: "info",
25515
+ message: `Cache hit for getByName region: ${cacheKey}`
25516
+ });
25517
+ return cached;
25518
+ }
25519
+ const result = await collection.findOne({
25520
+ name,
25521
+ deletedAt: { $in: ["", null] }
25522
+ });
25523
+ if (!result) {
25524
+ throw new import_nodejs_utils56.BadRequestError("Region not found.");
25525
+ }
25526
+ setCache(cacheKey, result, 300, namespace_collection).then(() => {
25527
+ import_nodejs_utils56.logger.log({
25528
+ level: "info",
25529
+ message: `Cache set for region by name: ${cacheKey}`
25530
+ });
25531
+ }).catch((err) => {
25532
+ import_nodejs_utils56.logger.log({
25533
+ level: "error",
25534
+ message: `Failed to set cache for region by name: ${err.message}`
25535
+ });
25536
+ });
25537
+ return result;
25538
+ } catch (error) {
25539
+ if (error instanceof import_nodejs_utils56.AppError) {
25540
+ throw error;
25541
+ } else {
25542
+ throw new import_nodejs_utils56.InternalServerError("Failed to get region.");
25543
+ }
25544
+ }
25545
+ }
25546
+ async function updateFieldById({ _id, field, value } = {}, session) {
25547
+ const allowedFields = ["name", "director", "directorName"];
25548
+ if (!allowedFields.includes(field)) {
25549
+ throw new import_nodejs_utils56.BadRequestError(
25550
+ `Field "${field}" is not allowed to be updated.`
25551
+ );
25552
+ }
25553
+ try {
25554
+ _id = new import_mongodb34.ObjectId(_id);
25555
+ } catch (error) {
25556
+ throw new import_nodejs_utils56.BadRequestError("Invalid ID.");
25557
+ }
25558
+ try {
25559
+ await collection.updateOne(
25560
+ { _id, deletedAt: { $in: ["", null] } },
25561
+ { $set: { [field]: value, updatedAt: (/* @__PURE__ */ new Date()).toISOString() } },
25562
+ { session }
25563
+ );
25564
+ delCachedData();
25565
+ return `Successfully updated region ${field}.`;
25566
+ } catch (error) {
25567
+ throw new import_nodejs_utils56.InternalServerError(`Failed to update region ${field}.`);
25568
+ }
25569
+ }
25570
+ async function deleteById(_id) {
25571
+ try {
25572
+ _id = new import_mongodb34.ObjectId(_id);
25573
+ } catch (error) {
25574
+ throw new import_nodejs_utils56.BadRequestError("Invalid ID.");
25575
+ }
25576
+ try {
25577
+ await collection.updateOne(
25578
+ { _id },
25579
+ { $set: { deletedAt: (/* @__PURE__ */ new Date()).toISOString() } }
25580
+ );
25581
+ delCachedData();
25582
+ return "Successfully deleted region.";
25583
+ } catch (error) {
25584
+ throw new import_nodejs_utils56.InternalServerError("Failed to delete region.");
25585
+ }
25586
+ }
25587
+ return {
25588
+ createIndex,
25589
+ createTextIndex,
25590
+ createUniqueIndex,
25591
+ add,
25592
+ getAll,
25593
+ getById,
25594
+ updateFieldById,
25595
+ deleteById,
25596
+ getByName
25597
+ };
25598
+ }
25599
+
25600
+ // src/controllers/region.controller.ts
25601
+ var import_nodejs_utils58 = require("@eeplatform/nodejs-utils");
25602
+ var import_joi28 = __toESM(require("joi"));
25603
+
25604
+ // src/services/region.service.ts
25605
+ var import_nodejs_utils57 = require("@eeplatform/nodejs-utils");
25606
+ function useRegionService() {
25607
+ const { add: _add } = useRegionRepo();
25608
+ const { addRole } = useRoleRepo();
25609
+ async function add(value) {
25610
+ const session = import_nodejs_utils57.useAtlas.getClient()?.startSession();
25611
+ if (!session) {
25612
+ throw new Error("Unable to start session for region service.");
25613
+ }
25614
+ try {
25615
+ session.startTransaction();
25616
+ const region = await _add(value, session);
25617
+ await addRole(
25618
+ {
25619
+ id: region.toString(),
25620
+ name: "Admin",
25621
+ type: "region",
25622
+ permissions: ["*"],
25623
+ status: "active",
25624
+ default: true
25625
+ },
25626
+ session
25627
+ );
25628
+ await session.commitTransaction();
25629
+ return "Region and admin role created successfully.";
25630
+ } catch (error) {
25631
+ await session.abortTransaction();
25632
+ throw error;
25633
+ } finally {
25634
+ session.endSession();
25635
+ }
25636
+ }
25637
+ return {
25638
+ add
25639
+ };
25640
+ }
25641
+
25642
+ // src/controllers/region.controller.ts
25643
+ function useRegionController() {
25644
+ const {
25645
+ getAll: _getAll,
25646
+ getById: _getById,
25647
+ getByName: _getByName,
25648
+ updateFieldById: _updateFieldById,
25649
+ deleteById: _deleteById
25650
+ } = useRegionRepo();
25651
+ const { add: _createRegion } = useRegionService();
25652
+ async function createRegion(req, res, next) {
25653
+ const value = req.body;
25654
+ const validation = import_joi28.default.object({
25655
+ name: import_joi28.default.string().min(1).max(100).required(),
25656
+ director: import_joi28.default.string().hex().optional().allow("", null),
25657
+ directorName: import_joi28.default.string().min(1).max(100).optional().allow("", null)
25658
+ });
25659
+ const { error } = validation.validate(value);
25660
+ if (error) {
25661
+ next(new import_nodejs_utils58.BadRequestError(error.message));
25662
+ return;
25663
+ }
25664
+ try {
25665
+ const regionId = await _createRegion(value);
25666
+ res.json({
25667
+ message: "Successfully created region.",
25668
+ data: { regionId }
25669
+ });
25670
+ return;
25671
+ } catch (error2) {
25672
+ next(error2);
25673
+ }
25674
+ }
25675
+ async function getAll(req, res, next) {
25676
+ const query = req.query;
25677
+ const validation = import_joi28.default.object({
25678
+ page: import_joi28.default.number().min(1).optional().allow("", null),
25679
+ limit: import_joi28.default.number().min(1).optional().allow("", null),
25680
+ search: import_joi28.default.string().optional().allow("", null)
25681
+ });
25682
+ const { error } = validation.validate(query);
25683
+ const page = typeof req.query.page === "string" ? Number(req.query.page) : 1;
25684
+ const limit = typeof req.query.limit === "string" ? Number(req.query.limit) : 10;
25685
+ const search = req.query.search ?? "";
25686
+ const isPageNumber = isFinite(page);
25687
+ if (!isPageNumber) {
25688
+ next(new import_nodejs_utils58.BadRequestError("Invalid page number."));
25689
+ return;
25690
+ }
25691
+ const isLimitNumber = isFinite(limit);
25692
+ if (!isLimitNumber) {
25693
+ next(new import_nodejs_utils58.BadRequestError("Invalid limit number."));
25694
+ return;
25695
+ }
25696
+ if (error) {
25697
+ next(new import_nodejs_utils58.BadRequestError(error.message));
25698
+ return;
25699
+ }
25700
+ try {
25701
+ const regions = await _getAll({ page, limit, search });
25702
+ res.json(regions);
25703
+ return;
25704
+ } catch (error2) {
25705
+ next(error2);
25706
+ }
25707
+ }
25708
+ async function getById(req, res, next) {
25709
+ const id = req.params.id;
25710
+ const validation = import_joi28.default.object({
25711
+ id: import_joi28.default.string().hex().required()
25712
+ });
25713
+ const { error } = validation.validate({ id });
25714
+ if (error) {
25715
+ next(new import_nodejs_utils58.BadRequestError(error.message));
25716
+ return;
25717
+ }
25718
+ try {
25719
+ const region = await _getById(id);
25720
+ res.json({
25721
+ message: "Successfully retrieved region.",
25722
+ data: { region }
25723
+ });
25724
+ return;
25725
+ } catch (error2) {
25726
+ next(error2);
25727
+ }
25728
+ }
25729
+ async function getByName(req, res, next) {
25730
+ const name = req.params.name;
25731
+ const validation = import_joi28.default.object({
25732
+ name: import_joi28.default.string().required()
25733
+ });
25734
+ const { error } = validation.validate({ name });
25735
+ if (error) {
25736
+ next(new import_nodejs_utils58.BadRequestError(error.message));
25737
+ return;
25738
+ }
25739
+ try {
25740
+ const region = await _getByName(name);
25741
+ res.json({
25742
+ message: "Successfully retrieved region.",
25743
+ data: { region }
25744
+ });
25745
+ return;
25746
+ } catch (error2) {
25747
+ next(error2);
25748
+ }
25749
+ }
25750
+ async function updateField(req, res, next) {
25751
+ const _id = req.params.id;
25752
+ const { field, value } = req.body;
25753
+ const validation = import_joi28.default.object({
25754
+ _id: import_joi28.default.string().hex().required(),
25755
+ field: import_joi28.default.string().valid("name", "director", "directorName").required(),
25756
+ value: import_joi28.default.string().required()
25757
+ });
25758
+ const { error } = validation.validate({ _id, field, value });
25759
+ if (error) {
25760
+ next(new import_nodejs_utils58.BadRequestError(error.message));
25761
+ return;
25762
+ }
25763
+ try {
25764
+ const message = await _updateFieldById({ _id, field, value });
25765
+ res.json({ message });
25766
+ return;
25767
+ } catch (error2) {
25768
+ next(error2);
25769
+ }
25770
+ }
25771
+ async function deleteRegion(req, res, next) {
25772
+ const _id = req.params.id;
25773
+ const validation = import_joi28.default.object({
25774
+ _id: import_joi28.default.string().hex().required()
25775
+ });
25776
+ const { error } = validation.validate({ _id });
25777
+ if (error) {
25778
+ next(new import_nodejs_utils58.BadRequestError(error.message));
25779
+ return;
25780
+ }
25781
+ try {
25782
+ const message = await _deleteById(_id);
25783
+ res.json({ message });
25784
+ return;
25785
+ } catch (error2) {
25786
+ next(error2);
25787
+ }
25788
+ }
25789
+ return {
25790
+ createRegion,
25791
+ getAll,
25792
+ getById,
25793
+ getByName,
25794
+ updateField,
25795
+ deleteRegion
25796
+ };
25797
+ }
25798
+
25799
+ // src/models/division.model.ts
25800
+ var import_nodejs_utils59 = require("@eeplatform/nodejs-utils");
25801
+ var import_joi29 = __toESM(require("joi"));
25802
+ var import_mongodb35 = require("mongodb");
25803
+ var schemaDivision = import_joi29.default.object({
25804
+ _id: import_joi29.default.string().hex().optional().allow(null, ""),
25805
+ name: import_joi29.default.string().min(1).max(100).required(),
25806
+ region: import_joi29.default.string().hex().optional().allow(null, ""),
25807
+ regionName: import_joi29.default.string().min(1).max(100).optional().allow(null, ""),
25808
+ superintendent: import_joi29.default.string().hex().optional().allow(null, ""),
25809
+ superintendentName: import_joi29.default.string().min(1).max(100).optional().allow(null, ""),
25810
+ createdAt: import_joi29.default.string().isoDate().optional(),
25811
+ updatedAt: import_joi29.default.string().isoDate().optional(),
25812
+ deletedAt: import_joi29.default.string().isoDate().optional().allow(null, "")
25813
+ });
25814
+ function MDivision(value) {
25815
+ const { error } = schemaDivision.validate(value);
25816
+ if (error) {
25817
+ throw new import_nodejs_utils59.BadRequestError(`Invalid division data: ${error.message}`);
25818
+ }
25819
+ if (value._id && typeof value._id === "string") {
25820
+ try {
25821
+ value._id = new import_mongodb35.ObjectId(value._id);
25822
+ } catch (error2) {
25823
+ throw new Error("Invalid _id.");
25824
+ }
25825
+ }
25826
+ if (value.region && typeof value.region === "string") {
25827
+ try {
25828
+ value.region = new import_mongodb35.ObjectId(value.region);
25829
+ } catch (error2) {
25830
+ throw new Error("Invalid region.");
25831
+ }
25832
+ }
25833
+ if (value.superintendent && typeof value.superintendent === "string") {
25834
+ try {
25835
+ value.superintendent = new import_mongodb35.ObjectId(value.superintendent);
25836
+ } catch (error2) {
25837
+ throw new Error("Invalid superintendent.");
25838
+ }
25839
+ }
25840
+ return {
25841
+ _id: value._id,
25842
+ name: value.name,
25843
+ region: value.region ?? "",
25844
+ regionName: value.regionName ?? "",
25845
+ superintendent: value.superintendent ?? "",
25846
+ superintendentName: value.superintendentName ?? "",
25847
+ createdAt: value.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
25848
+ updatedAt: value.updatedAt ?? "",
25849
+ deletedAt: value.deletedAt ?? ""
25850
+ };
25851
+ }
25852
+
25853
+ // src/repositories/division.repository.ts
25854
+ var import_nodejs_utils60 = require("@eeplatform/nodejs-utils");
25855
+ var import_mongodb36 = require("mongodb");
25856
+ function useDivisionRepo() {
25857
+ const db = import_nodejs_utils60.useAtlas.getDb();
25858
+ if (!db) {
25859
+ throw new Error("Unable to connect to server.");
25860
+ }
25861
+ const namespace_collection = "divisions";
25862
+ const collection = db.collection(namespace_collection);
25863
+ const { getCache, setCache, delNamespace } = (0, import_nodejs_utils60.useCache)();
25864
+ async function createIndex() {
25865
+ try {
25866
+ await collection.createIndex([
25867
+ { name: 1 },
25868
+ { region: 1 },
25869
+ { superintendent: 1 },
25870
+ { createdAt: 1 }
25871
+ ]);
25872
+ } catch (error) {
25873
+ throw new Error("Failed to create index on divisions.");
25874
+ }
25875
+ }
25876
+ async function createTextIndex() {
25877
+ try {
25878
+ await collection.createIndex({
25879
+ name: "text",
25880
+ regionName: "text",
25881
+ superintendentName: "text"
25882
+ });
25883
+ } catch (error) {
25884
+ throw new Error(
25885
+ "Failed to create text index on division name and superintendent name."
25886
+ );
25887
+ }
25888
+ }
25889
+ async function createUniqueIndex() {
25890
+ try {
25891
+ await collection.createIndex(
25892
+ {
25893
+ name: 1
25894
+ },
25895
+ { unique: true }
25896
+ );
25897
+ } catch (error) {
25898
+ throw new Error("Failed to create unique index on division name.");
25899
+ }
25900
+ }
25901
+ function delCachedData() {
25902
+ delNamespace(namespace_collection).then(() => {
25903
+ import_nodejs_utils60.logger.log({
25904
+ level: "info",
25905
+ message: `Cache namespace cleared for ${namespace_collection}`
25906
+ });
25907
+ }).catch((err) => {
25908
+ import_nodejs_utils60.logger.log({
25909
+ level: "error",
25910
+ message: `Failed to clear cache namespace for ${namespace_collection}: ${err.message}`
25911
+ });
25912
+ });
25913
+ }
25914
+ async function add(value, session) {
25915
+ try {
25916
+ value = MDivision(value);
25917
+ const res = await collection.insertOne(value, { session });
25918
+ delCachedData();
25919
+ return res.insertedId;
25920
+ } catch (error) {
25921
+ import_nodejs_utils60.logger.log({
25922
+ level: "error",
25923
+ message: error.message
25924
+ });
25925
+ if (error instanceof import_nodejs_utils60.AppError) {
25926
+ throw error;
25927
+ } else {
25928
+ const isDuplicated = error.message.includes("duplicate");
25929
+ if (isDuplicated) {
25930
+ throw new import_nodejs_utils60.BadRequestError("Division already exists.");
25931
+ }
25932
+ throw new Error("Failed to create division.");
25933
+ }
25934
+ }
25935
+ }
25936
+ async function getAll({
25937
+ search = "",
25938
+ page = 1,
25939
+ limit = 10,
25940
+ sort = {},
25941
+ region = ""
25942
+ } = {}) {
25943
+ page = page > 0 ? page - 1 : 0;
25944
+ const query = { deletedAt: { $in: ["", null] } };
25945
+ sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
25946
+ if (search) {
25947
+ query.$text = { $search: search };
25948
+ }
25949
+ if (region) {
25950
+ try {
25951
+ query.region = new import_mongodb36.ObjectId(region);
25952
+ } catch (error) {
25953
+ throw new import_nodejs_utils60.BadRequestError("Invalid region ID.");
25954
+ }
25955
+ }
25956
+ const cacheKey = (0, import_nodejs_utils60.makeCacheKey)(namespace_collection, {
25957
+ search,
25958
+ page,
25959
+ limit,
25960
+ sort: JSON.stringify(sort),
25961
+ region
25962
+ });
25963
+ import_nodejs_utils60.logger.log({
25964
+ level: "info",
25965
+ message: `Cache key for getAll divisions: ${cacheKey}`
25966
+ });
25967
+ try {
25968
+ const cached = await getCache(cacheKey);
25969
+ if (cached) {
25970
+ import_nodejs_utils60.logger.log({
25971
+ level: "info",
25972
+ message: `Cache hit for getAll divisions: ${cacheKey}`
25973
+ });
25974
+ return cached;
25975
+ }
25976
+ const items = await collection.aggregate([
25977
+ { $match: query },
25978
+ { $sort: sort },
25979
+ { $skip: page * limit },
25980
+ { $limit: limit },
25981
+ {
25982
+ $project: {
25983
+ _id: 1,
25984
+ name: 1,
25985
+ region: 1,
25986
+ regionName: 1,
25987
+ superintendent: 1,
25988
+ superintendentName: 1,
25989
+ createdAt: 1,
25990
+ updatedAt: 1
25991
+ }
25992
+ }
25993
+ ]).toArray();
25994
+ const length = await collection.countDocuments(query);
25995
+ const data = (0, import_nodejs_utils60.paginate)(items, page, limit, length);
25996
+ setCache(cacheKey, data, 600, namespace_collection).then(() => {
25997
+ import_nodejs_utils60.logger.log({
25998
+ level: "info",
25999
+ message: `Cache set for getAll divisions: ${cacheKey}`
26000
+ });
26001
+ }).catch((err) => {
26002
+ import_nodejs_utils60.logger.log({
26003
+ level: "error",
26004
+ message: `Failed to set cache for getAll divisions: ${err.message}`
26005
+ });
26006
+ });
26007
+ return data;
26008
+ } catch (error) {
26009
+ import_nodejs_utils60.logger.log({ level: "error", message: `${error}` });
26010
+ throw error;
26011
+ }
26012
+ }
26013
+ async function getById(_id) {
26014
+ try {
26015
+ _id = new import_mongodb36.ObjectId(_id);
26016
+ } catch (error) {
26017
+ throw new import_nodejs_utils60.BadRequestError("Invalid ID.");
26018
+ }
26019
+ const cacheKey = (0, import_nodejs_utils60.makeCacheKey)(namespace_collection, { _id: String(_id) });
26020
+ try {
26021
+ const cached = await getCache(cacheKey);
26022
+ if (cached) {
26023
+ import_nodejs_utils60.logger.log({
26024
+ level: "info",
26025
+ message: `Cache hit for getById division: ${cacheKey}`
26026
+ });
26027
+ return cached;
26028
+ }
26029
+ const result = await collection.findOne({
26030
+ _id,
26031
+ deletedAt: { $in: ["", null] }
26032
+ });
26033
+ if (!result) {
26034
+ throw new import_nodejs_utils60.BadRequestError("Division not found.");
26035
+ }
26036
+ setCache(cacheKey, result, 300, namespace_collection).then(() => {
26037
+ import_nodejs_utils60.logger.log({
26038
+ level: "info",
26039
+ message: `Cache set for division by id: ${cacheKey}`
26040
+ });
26041
+ }).catch((err) => {
26042
+ import_nodejs_utils60.logger.log({
26043
+ level: "error",
26044
+ message: `Failed to set cache for division by id: ${err.message}`
26045
+ });
26046
+ });
26047
+ return result;
26048
+ } catch (error) {
26049
+ if (error instanceof import_nodejs_utils60.AppError) {
26050
+ throw error;
26051
+ } else {
26052
+ throw new import_nodejs_utils60.InternalServerError("Failed to get division.");
26053
+ }
26054
+ }
26055
+ }
26056
+ async function getByName(name) {
26057
+ const cacheKey = (0, import_nodejs_utils60.makeCacheKey)(namespace_collection, { name });
26058
+ try {
26059
+ const cached = await getCache(cacheKey);
26060
+ if (cached) {
26061
+ import_nodejs_utils60.logger.log({
26062
+ level: "info",
26063
+ message: `Cache hit for getByName division: ${cacheKey}`
26064
+ });
26065
+ return cached;
26066
+ }
26067
+ const result = await collection.findOne({
26068
+ name,
26069
+ deletedAt: { $in: ["", null] }
26070
+ });
26071
+ if (!result) {
26072
+ throw new import_nodejs_utils60.BadRequestError("Division not found.");
26073
+ }
26074
+ setCache(cacheKey, result, 300, namespace_collection).then(() => {
26075
+ import_nodejs_utils60.logger.log({
26076
+ level: "info",
26077
+ message: `Cache set for division by name: ${cacheKey}`
26078
+ });
26079
+ }).catch((err) => {
26080
+ import_nodejs_utils60.logger.log({
26081
+ level: "error",
26082
+ message: `Failed to set cache for division by name: ${err.message}`
26083
+ });
26084
+ });
26085
+ return result;
26086
+ } catch (error) {
26087
+ if (error instanceof import_nodejs_utils60.AppError) {
26088
+ throw error;
26089
+ } else {
26090
+ throw new import_nodejs_utils60.InternalServerError("Failed to get division.");
26091
+ }
26092
+ }
26093
+ }
26094
+ async function updateFieldById({ _id, field, value } = {}, session) {
26095
+ const allowedFields = [
26096
+ "name",
26097
+ "region",
26098
+ "regionName",
26099
+ "superintendent",
26100
+ "superintendentName"
26101
+ ];
26102
+ if (!allowedFields.includes(field)) {
26103
+ throw new import_nodejs_utils60.BadRequestError(
26104
+ `Field "${field}" is not allowed to be updated.`
26105
+ );
26106
+ }
26107
+ try {
26108
+ _id = new import_mongodb36.ObjectId(_id);
26109
+ } catch (error) {
26110
+ throw new import_nodejs_utils60.BadRequestError("Invalid ID.");
26111
+ }
26112
+ try {
26113
+ await collection.updateOne(
26114
+ { _id, deletedAt: { $in: ["", null] } },
26115
+ { $set: { [field]: value, updatedAt: (/* @__PURE__ */ new Date()).toISOString() } },
26116
+ { session }
26117
+ );
26118
+ delCachedData();
26119
+ return `Successfully updated division ${field}.`;
26120
+ } catch (error) {
26121
+ throw new import_nodejs_utils60.InternalServerError(`Failed to update division ${field}.`);
26122
+ }
26123
+ }
26124
+ async function deleteById(_id) {
26125
+ try {
26126
+ _id = new import_mongodb36.ObjectId(_id);
26127
+ } catch (error) {
26128
+ throw new import_nodejs_utils60.BadRequestError("Invalid ID.");
26129
+ }
26130
+ try {
26131
+ await collection.updateOne(
26132
+ { _id },
26133
+ { $set: { deletedAt: (/* @__PURE__ */ new Date()).toISOString() } }
26134
+ );
26135
+ delCachedData();
26136
+ return "Successfully deleted division.";
26137
+ } catch (error) {
26138
+ throw new import_nodejs_utils60.InternalServerError("Failed to delete division.");
26139
+ }
26140
+ }
26141
+ return {
26142
+ createIndex,
26143
+ createTextIndex,
26144
+ createUniqueIndex,
26145
+ add,
26146
+ getAll,
26147
+ getById,
26148
+ updateFieldById,
26149
+ deleteById,
26150
+ getByName
26151
+ };
26152
+ }
26153
+
26154
+ // src/controllers/division.controller.ts
26155
+ var import_nodejs_utils62 = require("@eeplatform/nodejs-utils");
26156
+ var import_joi30 = __toESM(require("joi"));
26157
+
26158
+ // src/services/division.service.ts
26159
+ var import_nodejs_utils61 = require("@eeplatform/nodejs-utils");
26160
+ function useDivisionService() {
26161
+ const { add: _add } = useDivisionRepo();
26162
+ const { addRole } = useRoleRepo();
26163
+ async function add(value) {
26164
+ const session = import_nodejs_utils61.useAtlas.getClient()?.startSession();
26165
+ if (!session) {
26166
+ throw new Error("Unable to start session for division service.");
26167
+ }
26168
+ try {
26169
+ session.startTransaction();
26170
+ const division = await _add(value, session);
26171
+ await addRole(
26172
+ {
26173
+ id: division.toString(),
26174
+ name: "Admin",
26175
+ type: "division",
26176
+ permissions: ["*"],
26177
+ status: "active",
26178
+ default: true
26179
+ },
26180
+ session
26181
+ );
26182
+ await session.commitTransaction();
26183
+ return "Division and admin role created successfully.";
26184
+ } catch (error) {
26185
+ session.abortTransaction();
26186
+ throw error;
26187
+ } finally {
26188
+ session.endSession();
26189
+ }
26190
+ }
26191
+ return {
26192
+ add
26193
+ };
26194
+ }
26195
+
26196
+ // src/controllers/division.controller.ts
26197
+ function useDivisionController() {
26198
+ const {
26199
+ getAll: _getAll,
26200
+ getById: _getById,
26201
+ getByName: _getByName,
26202
+ updateFieldById: _updateFieldById,
26203
+ deleteById: _deleteById
26204
+ } = useDivisionRepo();
26205
+ const { add: _createDivision } = useDivisionService();
26206
+ async function createDivision(req, res, next) {
26207
+ const value = req.body;
26208
+ const validation = import_joi30.default.object({
26209
+ name: import_joi30.default.string().min(1).max(100).required(),
26210
+ region: import_joi30.default.string().hex().optional().allow("", null),
26211
+ regionName: import_joi30.default.string().min(1).max(100).optional().allow("", null),
26212
+ superintendent: import_joi30.default.string().hex().optional().allow("", null),
26213
+ superintendentName: import_joi30.default.string().min(1).max(100).optional().allow("", null)
26214
+ });
26215
+ const { error } = validation.validate(value);
26216
+ if (error) {
26217
+ next(new import_nodejs_utils62.BadRequestError(error.message));
26218
+ return;
26219
+ }
26220
+ try {
26221
+ const divisionId = await _createDivision(value);
26222
+ res.json({
26223
+ message: "Successfully created division.",
26224
+ data: { divisionId }
26225
+ });
26226
+ return;
26227
+ } catch (error2) {
26228
+ next(error2);
26229
+ }
26230
+ }
26231
+ async function getAll(req, res, next) {
26232
+ const query = req.query;
26233
+ const validation = import_joi30.default.object({
26234
+ page: import_joi30.default.number().min(1).optional().allow("", null),
26235
+ limit: import_joi30.default.number().min(1).optional().allow("", null),
26236
+ search: import_joi30.default.string().optional().allow("", null),
26237
+ region: import_joi30.default.string().hex().optional().allow("", null)
26238
+ });
26239
+ const { error } = validation.validate(query);
26240
+ const page = typeof req.query.page === "string" ? Number(req.query.page) : 1;
26241
+ const limit = typeof req.query.limit === "string" ? Number(req.query.limit) : 10;
26242
+ const search = req.query.search ?? "";
26243
+ const region = req.query.region ?? "";
26244
+ const isPageNumber = isFinite(page);
26245
+ if (!isPageNumber) {
26246
+ next(new import_nodejs_utils62.BadRequestError("Invalid page number."));
26247
+ return;
26248
+ }
26249
+ const isLimitNumber = isFinite(limit);
26250
+ if (!isLimitNumber) {
26251
+ next(new import_nodejs_utils62.BadRequestError("Invalid limit number."));
26252
+ return;
26253
+ }
26254
+ if (error) {
26255
+ next(new import_nodejs_utils62.BadRequestError(error.message));
26256
+ return;
26257
+ }
26258
+ try {
26259
+ const divisions = await _getAll({ page, limit, search, region });
26260
+ res.json(divisions);
26261
+ return;
26262
+ } catch (error2) {
26263
+ next(error2);
26264
+ }
26265
+ }
26266
+ async function getById(req, res, next) {
26267
+ const id = req.params.id;
26268
+ const validation = import_joi30.default.object({
26269
+ id: import_joi30.default.string().hex().required()
26270
+ });
26271
+ const { error } = validation.validate({ id });
26272
+ if (error) {
26273
+ next(new import_nodejs_utils62.BadRequestError(error.message));
26274
+ return;
26275
+ }
26276
+ try {
26277
+ const division = await _getById(id);
26278
+ res.json({
26279
+ message: "Successfully retrieved division.",
26280
+ data: { division }
26281
+ });
26282
+ return;
26283
+ } catch (error2) {
26284
+ next(error2);
26285
+ }
26286
+ }
26287
+ async function getByName(req, res, next) {
26288
+ const name = req.params.name;
26289
+ const validation = import_joi30.default.object({
26290
+ name: import_joi30.default.string().required()
26291
+ });
26292
+ const { error } = validation.validate({ name });
26293
+ if (error) {
26294
+ next(new import_nodejs_utils62.BadRequestError(error.message));
26295
+ return;
26296
+ }
26297
+ try {
26298
+ const division = await _getByName(name);
26299
+ res.json({
26300
+ message: "Successfully retrieved division.",
26301
+ data: { division }
26302
+ });
26303
+ return;
26304
+ } catch (error2) {
26305
+ next(error2);
26306
+ }
26307
+ }
26308
+ async function updateField(req, res, next) {
26309
+ const _id = req.params.id;
26310
+ const { field, value } = req.body;
26311
+ const validation = import_joi30.default.object({
26312
+ _id: import_joi30.default.string().hex().required(),
26313
+ field: import_joi30.default.string().valid(
26314
+ "name",
26315
+ "region",
26316
+ "regionName",
26317
+ "superintendent",
26318
+ "superintendentName"
26319
+ ).required(),
26320
+ value: import_joi30.default.string().required()
26321
+ });
26322
+ const { error } = validation.validate({ _id, field, value });
26323
+ if (error) {
26324
+ next(new import_nodejs_utils62.BadRequestError(error.message));
26325
+ return;
26326
+ }
26327
+ try {
26328
+ const message = await _updateFieldById({ _id, field, value });
26329
+ res.json({ message });
26330
+ return;
26331
+ } catch (error2) {
26332
+ next(error2);
26333
+ }
26334
+ }
26335
+ async function deleteDivision(req, res, next) {
26336
+ const _id = req.params.id;
26337
+ const validation = import_joi30.default.object({
26338
+ _id: import_joi30.default.string().hex().required()
26339
+ });
26340
+ const { error } = validation.validate({ _id });
26341
+ if (error) {
26342
+ next(new import_nodejs_utils62.BadRequestError(error.message));
26343
+ return;
26344
+ }
26345
+ try {
26346
+ const message = await _deleteById(_id);
26347
+ res.json({ message });
26348
+ return;
26349
+ } catch (error2) {
26350
+ next(error2);
26351
+ }
26352
+ }
26353
+ return {
26354
+ createDivision,
26355
+ getAll,
26356
+ getById,
26357
+ getByName,
26358
+ updateField,
26359
+ deleteDivision
26360
+ };
26361
+ }
26362
+
26363
+ // src/models/school.model.ts
26364
+ var import_joi31 = __toESM(require("joi"));
26365
+ var import_mongodb37 = require("mongodb");
26366
+ var schemaSchool = import_joi31.default.object({
26367
+ _id: import_joi31.default.string().hex().optional().allow("", null),
26368
+ id: import_joi31.default.string().required(),
26369
+ name: import_joi31.default.string().required(),
26370
+ country: import_joi31.default.string().required(),
26371
+ address: import_joi31.default.string().required(),
26372
+ continuedAddress: import_joi31.default.string().optional().allow("", null),
26373
+ city: import_joi31.default.string().required(),
26374
+ province: import_joi31.default.string().required(),
26375
+ postalCode: import_joi31.default.string().required(),
26376
+ courses: import_joi31.default.array().items(import_joi31.default.string()).required(),
26377
+ principalName: import_joi31.default.string().required(),
26378
+ principalEmail: import_joi31.default.string().email().optional().allow("", null),
26379
+ principalNumber: import_joi31.default.string().optional().allow("", null),
26380
+ region: import_joi31.default.string().hex().required(),
26381
+ regionName: import_joi31.default.string().optional().allow("", null),
26382
+ division: import_joi31.default.string().hex().required(),
26383
+ divisionName: import_joi31.default.string().optional().allow("", null),
26384
+ status: import_joi31.default.string().optional().allow(null, ""),
26385
+ createdAt: import_joi31.default.date().optional().allow("", null),
26386
+ updatedAt: import_joi31.default.date().optional().allow("", null),
26387
+ createdBy: import_joi31.default.string().hex().required()
26388
+ });
26389
+ function MSchool(value) {
26390
+ const { error } = schemaSchool.validate(value);
26391
+ if (error) {
26392
+ throw new Error(`Validation error: ${error.message}`);
26393
+ }
26394
+ if (value._id) {
26395
+ try {
26396
+ value._id = new import_mongodb37.ObjectId(value._id);
26397
+ } catch (error2) {
26398
+ throw new Error("Invalid _id.");
26399
+ }
26400
+ }
26401
+ if (value.region) {
26402
+ try {
26403
+ value.region = new import_mongodb37.ObjectId(value.region);
26404
+ } catch (error2) {
26405
+ throw new Error("Invalid region.");
26406
+ }
26407
+ }
26408
+ if (value.division) {
26409
+ try {
26410
+ value.division = new import_mongodb37.ObjectId(value.division);
26411
+ } catch (error2) {
26412
+ throw new Error("Invalid division.");
26413
+ }
26414
+ }
26415
+ if (value.createdBy) {
26416
+ try {
26417
+ value.createdBy = new import_mongodb37.ObjectId(value.createdBy);
26418
+ } catch (error2) {
26419
+ throw new Error("Invalid createdBy.");
26420
+ }
26421
+ }
26422
+ return {
26423
+ _id: value._id ? value._id : new import_mongodb37.ObjectId(),
26424
+ id: value.id,
26425
+ name: value.name,
26426
+ country: value.country,
26427
+ address: value.address,
26428
+ continuedAddress: value.continuedAddress ?? "",
26429
+ city: value.city,
26430
+ province: value.province,
26431
+ postalCode: value.postalCode,
26432
+ courses: value.courses || [],
26433
+ principalName: value.principalName,
26434
+ principalEmail: value.principalEmail,
26435
+ principalNumber: value.principalNumber ?? "",
26436
+ region: value.region,
26437
+ regionName: value.regionName ?? "",
26438
+ division: value.division,
26439
+ divisionName: value.divisionName ?? "",
26440
+ createdAt: value.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
26441
+ updatedAt: value.updatedAt ?? "",
26442
+ status: value.status ?? "pending",
26443
+ createdBy: value.createdBy
26444
+ };
26445
+ }
26446
+
26447
+ // src/repositories/school.repository.ts
26448
+ var import_nodejs_utils63 = require("@eeplatform/nodejs-utils");
26449
+ var import_mongodb38 = require("mongodb");
26450
+ function useSchoolRepo() {
26451
+ const db = import_nodejs_utils63.useAtlas.getDb();
26452
+ if (!db) {
26453
+ throw new import_nodejs_utils63.BadRequestError("Unable to connect to server.");
26454
+ }
26455
+ const namespace_collection = "schools";
26456
+ const collection = db.collection(namespace_collection);
26457
+ const { getCache, setCache, delNamespace } = (0, import_nodejs_utils63.useCache)();
26458
+ function delCachedData() {
26459
+ delNamespace(namespace_collection).then(() => {
26460
+ import_nodejs_utils63.logger.log({
26461
+ level: "info",
26462
+ message: `Cache namespace cleared for ${namespace_collection}`
26463
+ });
26464
+ }).catch((err) => {
26465
+ import_nodejs_utils63.logger.log({
26466
+ level: "error",
26467
+ message: `Failed to clear cache namespace for ${namespace_collection}: ${err.message}`
26468
+ });
26469
+ });
26470
+ }
26471
+ async function createIndex() {
26472
+ try {
26473
+ await collection.createIndexes([
26474
+ { key: { name: 1 } },
26475
+ { key: { id: 1 }, unique: true },
26476
+ { key: { region: 1 } },
26477
+ { key: { division: 1 } },
26478
+ {
26479
+ key: {
26480
+ name: "text",
26481
+ address: "text",
26482
+ continuedAddress: "text",
26483
+ city: "text",
26484
+ province: "text",
26485
+ postalCode: "text",
26486
+ regionName: "text",
26487
+ divisionName: "text"
26488
+ }
26489
+ }
26490
+ ]);
26491
+ } catch (error) {
26492
+ throw new import_nodejs_utils63.BadRequestError("Failed to create index on school.");
26493
+ }
26494
+ }
26495
+ async function add(value, session) {
26496
+ try {
26497
+ value = MSchool(value);
26498
+ const res = await collection.insertOne(value, { session });
26499
+ delCachedData();
26500
+ return res.insertedId;
26501
+ } catch (error) {
26502
+ import_nodejs_utils63.logger.log({
26503
+ level: "error",
26504
+ message: `Failed to add school: ${error}`
26505
+ });
26506
+ const isDuplicated = error.message.includes("duplicate");
26507
+ if (isDuplicated) {
26508
+ throw new import_nodejs_utils63.BadRequestError("School already exist.");
26509
+ }
26510
+ throw error;
26511
+ }
26512
+ }
26513
+ async function getAll({
26514
+ page = 1,
26515
+ limit = 20,
26516
+ sort = {},
26517
+ status = "active",
26518
+ org = "",
26519
+ app = "admin",
26520
+ search = ""
26521
+ } = {}) {
26522
+ page = Math.max(0, page - 1);
26523
+ if (sort && Object.keys(sort).length === 0) {
26524
+ sort = { name: 1 };
26525
+ }
26526
+ const query = { status };
26527
+ const cacheKeyOptions = {
26528
+ page,
26529
+ limit,
26530
+ sort: JSON.stringify(sort),
26531
+ status
26532
+ };
26533
+ if (search) {
26534
+ query.$text = { $search: search };
26535
+ cacheKeyOptions.search = search;
26536
+ }
26537
+ if (org) {
26538
+ try {
26539
+ query[app] = new import_mongodb38.ObjectId(org);
26540
+ cacheKeyOptions[app] = org;
26541
+ } catch (error) {
26542
+ throw new import_nodejs_utils63.BadRequestError("Invalid org.");
26543
+ }
26544
+ }
26545
+ try {
26546
+ const cacheKey = (0, import_nodejs_utils63.makeCacheKey)(namespace_collection, cacheKeyOptions);
26547
+ const cachedData = await getCache(cacheKey);
26548
+ if (cachedData) {
26549
+ return cachedData;
26550
+ }
26551
+ const items = await collection.aggregate([
26552
+ { $match: query },
26553
+ { $sort: sort },
26554
+ { $skip: page * limit },
26555
+ { $limit: limit }
26556
+ ]).toArray();
26557
+ const length = await collection.countDocuments(query);
26558
+ const data = (0, import_nodejs_utils63.paginate)(items, page, limit, length);
26559
+ setCache(cacheKey, data, 600, namespace_collection).then(() => {
26560
+ import_nodejs_utils63.logger.log({
26561
+ level: "info",
26562
+ message: `Cache set for key ${cacheKey}`
26563
+ });
26564
+ }).catch((err) => {
26565
+ import_nodejs_utils63.logger.log({
26566
+ level: "error",
26567
+ message: `Failed to set cache for key ${cacheKey}: ${err.message}`
26568
+ });
26569
+ });
26570
+ return data;
26571
+ } catch (error) {
26572
+ import_nodejs_utils63.logger.log({
26573
+ level: "error",
26574
+ message: `Failed to get all schools: ${error}`
26575
+ });
26576
+ throw error;
26577
+ }
26578
+ }
26579
+ async function updateStatusById(_id, status, session) {
26580
+ try {
26581
+ _id = new import_mongodb38.ObjectId(_id);
26582
+ } catch (error) {
26583
+ throw new import_nodejs_utils63.BadRequestError("Invalid school ID.");
26584
+ }
26585
+ const result = await collection.updateOne(
26586
+ { _id },
26587
+ { $set: { status, updatedAt: /* @__PURE__ */ new Date() } },
26588
+ { session }
26589
+ );
26590
+ delCachedData();
26591
+ return result;
26592
+ }
26593
+ async function updateFieldById({ _id, field, value } = {}, session) {
26594
+ const allowedFields = [
26595
+ "name",
26596
+ "country",
26597
+ "address",
26598
+ "continuedAddress",
26599
+ "city",
26600
+ "province",
26601
+ "postalCode",
26602
+ "courses",
26603
+ "email",
26604
+ "principalName",
26605
+ "principalEmail",
26606
+ "principalNumber",
26607
+ "region",
26608
+ "regionName",
26609
+ "division",
26610
+ "divisionName"
26611
+ ];
26612
+ if (!allowedFields.includes(field)) {
26613
+ throw new import_nodejs_utils63.BadRequestError(
26614
+ `Field "${field}" is not allowed to be updated.`
26615
+ );
26616
+ }
26617
+ try {
26618
+ _id = new import_mongodb38.ObjectId(_id);
26619
+ } catch (error) {
26620
+ throw new import_nodejs_utils63.BadRequestError("Invalid ID.");
26621
+ }
26622
+ try {
26623
+ const result = await collection.updateOne(
26624
+ { _id },
26625
+ { $set: { [field]: value } },
26626
+ { session }
26627
+ );
26628
+ delCachedData();
26629
+ return result;
26630
+ } catch (error) {
26631
+ throw new import_nodejs_utils63.BadRequestError(`Failed to update school ${field}.`);
26632
+ }
26633
+ }
26634
+ async function getPendingByCreatedBy(createdBy) {
26635
+ try {
26636
+ createdBy = new import_mongodb38.ObjectId(createdBy);
26637
+ } catch (error) {
26638
+ throw new import_nodejs_utils63.BadRequestError("Invalid createdBy ID.");
26639
+ }
26640
+ const cacheKey = (0, import_nodejs_utils63.makeCacheKey)(namespace_collection, {
26641
+ createdBy,
26642
+ status: "pending"
26643
+ });
26644
+ const cachedData = await getCache(cacheKey);
26645
+ if (cachedData) {
26646
+ return cachedData;
26647
+ }
26648
+ try {
26649
+ const school = await collection.findOne({ createdBy, status: "pending" });
26650
+ setCache(cacheKey, school, 600, namespace_collection).then(() => {
26651
+ import_nodejs_utils63.logger.log({
26652
+ level: "info",
26653
+ message: `Cache set for school by createdBy: ${cacheKey}`
26654
+ });
26655
+ }).catch((err) => {
26656
+ import_nodejs_utils63.logger.log({
26657
+ level: "error",
26658
+ message: `Failed to set cache for school by createdBy: ${err.message}`
26659
+ });
26660
+ });
26661
+ return school;
26662
+ } catch (error) {
26663
+ throw error;
26664
+ }
26665
+ }
26666
+ async function getPendingById(_id) {
26667
+ try {
26668
+ _id = new import_mongodb38.ObjectId(_id);
26669
+ } catch (error) {
26670
+ throw new import_nodejs_utils63.BadRequestError("Invalid ID.");
26671
+ }
26672
+ const cacheKey = (0, import_nodejs_utils63.makeCacheKey)(namespace_collection, {
26673
+ _id,
26674
+ status: "pending"
26675
+ });
26676
+ const cachedData = await getCache(cacheKey);
26677
+ if (cachedData) {
26678
+ return cachedData;
26679
+ }
26680
+ try {
26681
+ const school = await collection.findOne({ _id, status: "pending" });
26682
+ setCache(cacheKey, school, 600, namespace_collection).then(() => {
26683
+ import_nodejs_utils63.logger.log({
26684
+ level: "info",
26685
+ message: `Cache set for school by ID: ${cacheKey}`
26686
+ });
26687
+ }).catch((err) => {
26688
+ import_nodejs_utils63.logger.log({
26689
+ level: "error",
26690
+ message: `Failed to set cache for school by ID: ${err.message}`
26691
+ });
26692
+ });
26693
+ return school;
26694
+ } catch (error) {
26695
+ throw error;
26696
+ }
26697
+ }
26698
+ return {
26699
+ createIndex,
26700
+ add,
26701
+ getAll,
26702
+ updateStatusById,
26703
+ updateFieldById,
26704
+ getPendingByCreatedBy,
26705
+ getPendingById
26706
+ };
26707
+ }
26708
+
26709
+ // src/services/school.service.ts
26710
+ var import_nodejs_utils64 = require("@eeplatform/nodejs-utils");
26711
+ function useSchoolService() {
26712
+ const { add, getPendingByCreatedBy, updateStatusById, getPendingById } = useSchoolRepo();
26713
+ const { addRole } = useRoleRepo();
26714
+ const { getUserById } = useUserRepo();
26715
+ const { add: addMember } = useMemberRepo();
26716
+ async function register(value) {
26717
+ const { error } = schemaSchool.validate(value);
26718
+ if (error) {
26719
+ throw new import_nodejs_utils64.BadRequestError(error.message);
26720
+ }
26721
+ const existingSchool = await getPendingByCreatedBy(value.createdBy ?? "");
26722
+ if (existingSchool) {
26723
+ throw new import_nodejs_utils64.BadRequestError(
26724
+ "You already have a pending school registration."
26725
+ );
26726
+ }
26727
+ try {
26728
+ value.status = "pending";
26729
+ await add(value);
26730
+ return "Request to register school has been sent successfully. Please wait for approval.";
26731
+ } catch (error2) {
26732
+ throw error2;
26733
+ }
26734
+ }
26735
+ async function approve(id) {
26736
+ const school = await getPendingById(id);
26737
+ if (!school) {
26738
+ throw new import_nodejs_utils64.BadRequestError("School registration not found.");
26739
+ }
26740
+ const session = import_nodejs_utils64.useAtlas.getClient()?.startSession();
26741
+ if (!session) {
26742
+ throw new Error("Unable to start session for school service.");
26743
+ }
26744
+ try {
26745
+ session.startTransaction();
26746
+ school.status = "approved";
26747
+ await updateStatusById(id, "active", session);
26748
+ const roleType = "school";
26749
+ const roleName = "Admin";
26750
+ const roleId = await addRole(
26751
+ {
26752
+ id,
26753
+ type: roleType,
26754
+ name: roleName,
26755
+ permissions: ["*"],
26756
+ status: "active",
26757
+ default: true
26758
+ },
26759
+ session
26760
+ );
26761
+ if (!school.createdBy) {
26762
+ throw new import_nodejs_utils64.BadRequestError("School must have a creator.");
26763
+ }
26764
+ const user = await getUserById(school.createdBy ?? "");
26765
+ if (!user) {
26766
+ throw new import_nodejs_utils64.BadRequestError("User not found for the school creator.");
26767
+ }
26768
+ await addMember(
26769
+ {
26770
+ org: id,
26771
+ orgName: school.name,
26772
+ user: school.createdBy.toString(),
26773
+ name: `${user.firstName} ${user.lastName}`,
26774
+ role: roleId.toString(),
26775
+ roleName,
26776
+ type: roleType
26777
+ },
26778
+ session
26779
+ );
26780
+ await session.commitTransaction();
26781
+ return "School registration has been approved.";
26782
+ } catch (error) {
26783
+ import_nodejs_utils64.logger.log({
26784
+ level: "error",
26785
+ message: `Error approving school registration: ${error.message}`
26786
+ });
26787
+ await session.abortTransaction();
26788
+ throw error;
26789
+ } finally {
26790
+ await session.endSession();
26791
+ }
26792
+ }
26793
+ return {
26794
+ register,
26795
+ approve
26796
+ };
26797
+ }
26798
+
26799
+ // src/controllers/school.controller.ts
26800
+ var import_nodejs_utils65 = require("@eeplatform/nodejs-utils");
26801
+ var import_joi32 = __toESM(require("joi"));
26802
+ function useSchoolController() {
26803
+ const {
26804
+ add: _add,
26805
+ getAll: _getAll,
26806
+ getPendingByCreatedBy: _getPendingByCreatedBy,
26807
+ updateStatusById: _updateStatusById
26808
+ } = useSchoolRepo();
26809
+ async function add(req, res, next) {
26810
+ const payload = req.body;
26811
+ const { error } = schemaSchool.validate(payload);
26812
+ if (error) {
26813
+ next(new import_nodejs_utils65.BadRequestError(`Validation error: ${error.message}`));
26814
+ return;
26815
+ }
26816
+ try {
26817
+ const school = await _add(payload);
26818
+ res.status(201).json(school);
26819
+ return;
26820
+ } catch (error2) {
26821
+ next(error2);
26822
+ return;
26823
+ }
26824
+ }
26825
+ async function getAll(req, res, next) {
26826
+ const validation = import_joi32.default.object({
26827
+ page: import_joi32.default.number().optional().allow(null, ""),
26828
+ limit: import_joi32.default.number().optional().allow(null, ""),
26829
+ sort: import_joi32.default.string().optional().allow(null, ""),
26830
+ sortOrder: import_joi32.default.string().optional().allow(null, ""),
26831
+ status: import_joi32.default.string().optional().allow(null, ""),
26832
+ org: import_joi32.default.string().hex().optional().allow(null, ""),
26833
+ app: import_joi32.default.string().optional().allow(null, ""),
26834
+ search: import_joi32.default.string().optional().allow(null, "")
26835
+ });
26836
+ const { error } = validation.validate(req.query);
26837
+ if (error) {
26838
+ next(new import_nodejs_utils65.BadRequestError(`Validation error: ${error.message}`));
26839
+ return;
26840
+ }
26841
+ const page = parseInt(req.query.page) ?? 1;
26842
+ let limit = parseInt(req.query.limit) ?? 20;
26843
+ limit = isNaN(limit) ? 20 : limit;
26844
+ const sort = req.query.sort ? String(req.query.sort).split(",") : "";
26845
+ const sortOrder = req.query.sortOrder ? String(req.query.sortOrder).split(",") : "";
26846
+ const sortObj = {};
26847
+ if (sort && Array.isArray(sort) && sort.length && sortOrder && Array.isArray(sortOrder) && sortOrder.length) {
26848
+ sort.forEach((field, index) => {
26849
+ sortObj[field] = sortOrder[index] === "desc" ? -1 : 1;
26850
+ });
26851
+ }
26852
+ const status = req.query.status ?? "active";
26853
+ const org = req.query.org ?? "";
26854
+ const app = req.query.app ?? "admin";
26855
+ const search = req.query.search ?? "";
26856
+ try {
26857
+ const schools = await _getAll({
26858
+ page,
26859
+ limit,
26860
+ sort: sortObj,
26861
+ status,
26862
+ org,
26863
+ app,
26864
+ search
26865
+ });
26866
+ res.status(200).json(schools);
26867
+ return;
26868
+ } catch (error2) {
26869
+ next(error2);
26870
+ }
26871
+ }
26872
+ async function getByCreatedBy(req, res, next) {
26873
+ const createdBy = req.params.createdBy;
26874
+ const validation = import_joi32.default.string().hex().required();
26875
+ const { error } = validation.validate(createdBy);
26876
+ if (error) {
26877
+ next(new import_nodejs_utils65.BadRequestError(`Validation error: ${error.message}`));
26878
+ return;
26879
+ }
26880
+ try {
26881
+ const school = await _getPendingByCreatedBy(createdBy);
26882
+ res.status(200).json(school);
26883
+ return;
26884
+ } catch (error2) {
26885
+ next(error2);
26886
+ }
26887
+ }
26888
+ async function updateStatusById(req, res, next) {
26889
+ const schoolId = req.params.id;
26890
+ const status = req.params.status;
26891
+ const validation = import_joi32.default.object({
26892
+ id: import_joi32.default.string().hex().required(),
26893
+ status: import_joi32.default.string().valid("active", "deleted", "suspended").required()
26894
+ });
26895
+ const { error } = validation.validate({ id: schoolId, status });
26896
+ if (error) {
26897
+ next(new import_nodejs_utils65.BadRequestError(`Validation error: ${error.message}`));
26898
+ return;
26899
+ }
26900
+ try {
26901
+ const updatedSchool = await _updateStatusById(schoolId, status);
26902
+ res.status(200).json(updatedSchool);
26903
+ return;
26904
+ } catch (error2) {
26905
+ next(error2);
26906
+ }
26907
+ }
26908
+ const { register: _registerSchool, approve } = useSchoolService();
26909
+ async function registerSchool(req, res, next) {
26910
+ const payload = req.body;
26911
+ const { error } = schemaSchool.validate(payload);
26912
+ if (error) {
26913
+ next(new import_nodejs_utils65.BadRequestError(`Validation error: ${error.message}`));
26914
+ return;
26915
+ }
26916
+ try {
26917
+ const schoolId = await _registerSchool(payload);
26918
+ res.status(201).json({ schoolId });
26919
+ return;
26920
+ } catch (error2) {
26921
+ next(error2);
26922
+ return;
26923
+ }
26924
+ }
26925
+ async function approveSchool(req, res, next) {
26926
+ const schoolId = req.params.id;
26927
+ const validation = import_joi32.default.object({
26928
+ id: import_joi32.default.string().hex().required()
26929
+ });
26930
+ const { error } = validation.validate({ id: schoolId });
26931
+ if (error) {
26932
+ next(new import_nodejs_utils65.BadRequestError(`Validation error: ${error.message}`));
26933
+ return;
26934
+ }
26935
+ try {
26936
+ const updatedSchool = await approve(schoolId);
26937
+ res.status(200).json(updatedSchool);
26938
+ return;
26939
+ } catch (error2) {
26940
+ next(error2);
26941
+ }
26942
+ }
26943
+ return {
26944
+ add,
26945
+ getAll,
26946
+ getByCreatedBy,
26947
+ updateStatusById,
26948
+ registerSchool,
26949
+ approveSchool
26950
+ };
26951
+ }
25266
26952
  // Annotate the CommonJS export names for ESM import in node:
25267
26953
  0 && (module.exports = {
25268
26954
  ACCESS_TOKEN_EXPIRY,
@@ -25282,6 +26968,7 @@ function usePriceController() {
25282
26968
  MAILER_TRANSPORT_PORT,
25283
26969
  MAILER_TRANSPORT_SECURE,
25284
26970
  MAddress,
26971
+ MDivision,
25285
26972
  MEntity,
25286
26973
  MFile,
25287
26974
  MMember,
@@ -25291,7 +26978,9 @@ function usePriceController() {
25291
26978
  MOrg,
25292
26979
  MPaymentMethod,
25293
26980
  MPromoCode,
26981
+ MRegion,
25294
26982
  MRole,
26983
+ MSchool,
25295
26984
  MSubscription,
25296
26985
  MToken,
25297
26986
  MUser,
@@ -25319,12 +27008,17 @@ function usePriceController() {
25319
27008
  addressSchema,
25320
27009
  isDev,
25321
27010
  schema,
27011
+ schemaDivision,
27012
+ schemaRegion,
27013
+ schemaSchool,
25322
27014
  useAddressController,
25323
27015
  useAddressRepo,
25324
27016
  useAuthController,
25325
27017
  useAuthService,
25326
27018
  useCounterModel,
25327
27019
  useCounterRepo,
27020
+ useDivisionController,
27021
+ useDivisionRepo,
25328
27022
  useEntityController,
25329
27023
  useEntityRepo,
25330
27024
  useFileController,
@@ -25353,8 +27047,13 @@ function usePriceController() {
25353
27047
  usePriceRepo,
25354
27048
  usePromoCodeController,
25355
27049
  usePromoCodeRepo,
27050
+ useRegionController,
27051
+ useRegionRepo,
25356
27052
  useRoleController,
25357
27053
  useRoleRepo,
27054
+ useSchoolController,
27055
+ useSchoolRepo,
27056
+ useSchoolService,
25358
27057
  useSubscriptionController,
25359
27058
  useSubscriptionRepo,
25360
27059
  useSubscriptionService,