@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/CHANGELOG.md +12 -0
- package/dist/index.d.ts +154 -5
- package/dist/index.js +1744 -45
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1756 -45
- 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,
|
|
@@ -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
|
-
|
|
11795
|
-
|
|
11796
|
-
|
|
11797
|
-
|
|
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().
|
|
13152
|
-
orgName: import_joi2.default.string().
|
|
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.
|
|
17456
|
+
if (typeof value.id === "string" && value.id.length === 24) {
|
|
17445
17457
|
try {
|
|
17446
|
-
value.
|
|
17458
|
+
value.id = new import_mongodb12.ObjectId(value.id);
|
|
17447
17459
|
} catch (error) {
|
|
17448
|
-
throw new Error("Invalid
|
|
17460
|
+
throw new Error("Invalid id.");
|
|
17449
17461
|
}
|
|
17450
17462
|
}
|
|
17451
|
-
this.
|
|
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,
|
|
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
|
-
|
|
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 (
|
|
17664
|
+
if (id && typeof id === "string" && id.length === 24) {
|
|
17652
17665
|
try {
|
|
17653
|
-
|
|
17666
|
+
id = new import_mongodb13.ObjectId(id);
|
|
17654
17667
|
} catch (error) {
|
|
17655
|
-
throw new import_nodejs_utils11.BadRequestError("Invalid
|
|
17668
|
+
throw new import_nodejs_utils11.BadRequestError("Invalid ID.");
|
|
17656
17669
|
}
|
|
17657
17670
|
}
|
|
17658
|
-
const query = { status: "active"
|
|
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 (
|
|
17665
|
-
cacheKeyOptions.
|
|
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
|
-
|
|
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().
|
|
18800
|
-
|
|
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
|
|
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
|
-
|
|
18839
|
+
id: import_joi7.default.string().hex().optional().allow("", null)
|
|
18827
18840
|
});
|
|
18828
|
-
const { error } = validation.validate({ search, page, limit, type,
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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,
|