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