@eeplatform/core 1.0.3 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -25667,10 +25667,6 @@ function useRegionRepo() {
25667
25667
  };
25668
25668
  }
25669
25669
 
25670
- // src/controllers/region.controller.ts
25671
- import { BadRequestError as BadRequestError52 } from "@eeplatform/nodejs-utils";
25672
- import Joi28 from "joi";
25673
-
25674
25670
  // src/services/region.service.ts
25675
25671
  import { useAtlas as useAtlas26 } from "@eeplatform/nodejs-utils";
25676
25672
  function useRegionService() {
@@ -25710,6 +25706,8 @@ function useRegionService() {
25710
25706
  }
25711
25707
 
25712
25708
  // src/controllers/region.controller.ts
25709
+ import { BadRequestError as BadRequestError52 } from "@eeplatform/nodejs-utils";
25710
+ import Joi28 from "joi";
25713
25711
  function useRegionController() {
25714
25712
  const {
25715
25713
  getAll: _getAll,
@@ -26230,10 +26228,6 @@ function useDivisionRepo() {
26230
26228
  };
26231
26229
  }
26232
26230
 
26233
- // src/controllers/division.controller.ts
26234
- import { BadRequestError as BadRequestError55 } from "@eeplatform/nodejs-utils";
26235
- import Joi30 from "joi";
26236
-
26237
26231
  // src/services/division.service.ts
26238
26232
  import { useAtlas as useAtlas28 } from "@eeplatform/nodejs-utils";
26239
26233
  function useDivisionService() {
@@ -26273,6 +26267,8 @@ function useDivisionService() {
26273
26267
  }
26274
26268
 
26275
26269
  // src/controllers/division.controller.ts
26270
+ import { BadRequestError as BadRequestError55 } from "@eeplatform/nodejs-utils";
26271
+ import Joi30 from "joi";
26276
26272
  function useDivisionController() {
26277
26273
  const {
26278
26274
  getAll: _getAll,
@@ -27035,6 +27031,1111 @@ function useSchoolController() {
27035
27031
  approveSchool
27036
27032
  };
27037
27033
  }
27034
+
27035
+ // src/models/building.model.ts
27036
+ import { BadRequestError as BadRequestError59, logger as logger29 } from "@eeplatform/nodejs-utils";
27037
+ import Joi33 from "joi";
27038
+ import { ObjectId as ObjectId39 } from "mongodb";
27039
+ var schemaBuilding = Joi33.object({
27040
+ _id: Joi33.string().hex().optional(),
27041
+ school: Joi33.string().hex().required(),
27042
+ serial: Joi33.string().optional().allow("", null),
27043
+ name: Joi33.string().required(),
27044
+ levels: Joi33.number().integer().min(1).required(),
27045
+ createdAt: Joi33.date().optional().allow("", null),
27046
+ updatedAt: Joi33.date().optional().allow("", null),
27047
+ deletedAt: Joi33.date().optional().allow("", null),
27048
+ status: Joi33.string().optional().allow("", null)
27049
+ });
27050
+ var schemaBuildingUnit = Joi33.object({
27051
+ _id: Joi33.string().hex().optional(),
27052
+ school: Joi33.string().hex().required(),
27053
+ name: Joi33.string().optional().allow("", null),
27054
+ building: Joi33.string().hex().required(),
27055
+ buildingName: Joi33.string().optional().allow("", null),
27056
+ level: Joi33.number().integer().min(1).required(),
27057
+ category: Joi33.string().required(),
27058
+ type: Joi33.string().required(),
27059
+ seating_capacity: Joi33.number().integer().min(0).required(),
27060
+ standing_capacity: Joi33.number().integer().min(0).required(),
27061
+ description: Joi33.string().optional().allow("", null),
27062
+ unit_of_measurement: Joi33.string().valid("sqm").required(),
27063
+ area: Joi33.number().positive().required(),
27064
+ status: Joi33.string().optional().allow("", null)
27065
+ });
27066
+ var schemaUpdateOptions = Joi33.object({
27067
+ name: Joi33.string().optional().allow("", null),
27068
+ building: Joi33.string().hex().optional().allow("", null),
27069
+ level: Joi33.number().integer().min(1).optional().allow("", null),
27070
+ category: Joi33.string().optional().allow("", null),
27071
+ type: Joi33.string().optional().allow("", null),
27072
+ seating_capacity: Joi33.number().integer().min(0).optional().allow("", null),
27073
+ standing_capacity: Joi33.number().integer().min(0).optional().allow("", null),
27074
+ area: Joi33.number().positive().optional().allow("", null)
27075
+ });
27076
+ function MBuilding(value) {
27077
+ const { error } = schemaBuilding.validate(value);
27078
+ if (error) {
27079
+ logger29.info(`Building Model: ${error.message}`);
27080
+ throw new BadRequestError59(error.message);
27081
+ }
27082
+ if (value._id && typeof value._id === "string") {
27083
+ try {
27084
+ value._id = new ObjectId39(value._id);
27085
+ } catch (error2) {
27086
+ throw new BadRequestError59("Invalid _id format");
27087
+ }
27088
+ }
27089
+ try {
27090
+ value.school = new ObjectId39(value.school);
27091
+ } catch (error2) {
27092
+ throw new BadRequestError59("Invalid school format");
27093
+ }
27094
+ return {
27095
+ _id: value._id ?? void 0,
27096
+ school: value.school,
27097
+ serial: value.serial ?? "",
27098
+ name: value.name ?? "",
27099
+ levels: value.levels ?? 0,
27100
+ status: value.status ?? "active",
27101
+ createdAt: value.createdAt ?? /* @__PURE__ */ new Date(),
27102
+ updatedAt: value.updatedAt ?? "",
27103
+ deletedAt: value.deletedAt ?? ""
27104
+ };
27105
+ }
27106
+ function MBuildingUnit(value) {
27107
+ const { error } = schemaBuildingUnit.validate(value);
27108
+ if (error) {
27109
+ logger29.info(`Building Unit Model: ${error.message}`);
27110
+ throw new BadRequestError59(error.message);
27111
+ }
27112
+ if (value._id && typeof value._id === "string") {
27113
+ try {
27114
+ value._id = new ObjectId39(value._id);
27115
+ } catch (error2) {
27116
+ throw new BadRequestError59("Invalid ID");
27117
+ }
27118
+ }
27119
+ try {
27120
+ value.school = new ObjectId39(value.school);
27121
+ } catch (error2) {
27122
+ throw new BadRequestError59("Invalid school ID");
27123
+ }
27124
+ try {
27125
+ value.building = new ObjectId39(value.building);
27126
+ } catch (error2) {
27127
+ throw new BadRequestError59("Invalid building ID");
27128
+ }
27129
+ return {
27130
+ _id: value._id ?? void 0,
27131
+ school: value.school,
27132
+ name: value.name ?? "",
27133
+ building: value.building,
27134
+ buildingName: value.buildingName ?? "",
27135
+ level: value.level ?? 0,
27136
+ category: value.category ?? "",
27137
+ type: value.type ?? "",
27138
+ seating_capacity: value.seating_capacity ?? 0,
27139
+ standing_capacity: value.standing_capacity ?? 0,
27140
+ description: value.description ?? "",
27141
+ unit_of_measurement: value.unit_of_measurement ?? "sqm",
27142
+ area: value.area ?? 0,
27143
+ status: value.status ?? "active",
27144
+ createdAt: value.createdAt ?? /* @__PURE__ */ new Date(),
27145
+ updatedAt: value.updatedAt ?? "",
27146
+ deletedAt: value.deletedAt ?? ""
27147
+ };
27148
+ }
27149
+
27150
+ // src/repositories/building.repository.ts
27151
+ import {
27152
+ AppError as AppError14,
27153
+ BadRequestError as BadRequestError60,
27154
+ InternalServerError as InternalServerError25,
27155
+ logger as logger30,
27156
+ makeCacheKey as makeCacheKey19,
27157
+ paginate as paginate15,
27158
+ useAtlas as useAtlas31,
27159
+ useCache as useCache20
27160
+ } from "@eeplatform/nodejs-utils";
27161
+ import { ObjectId as ObjectId40 } from "mongodb";
27162
+ function useBuildingRepo() {
27163
+ const db = useAtlas31.getDb();
27164
+ if (!db) {
27165
+ throw new Error("Unable to connect to server.");
27166
+ }
27167
+ const namespace_collection = "school.buildings";
27168
+ const collection = db.collection(namespace_collection);
27169
+ const { getCache, setCache, delNamespace } = useCache20(namespace_collection);
27170
+ async function createIndex() {
27171
+ try {
27172
+ await collection.createIndex([
27173
+ { name: 1 },
27174
+ { school: 1 },
27175
+ { createdAt: 1 }
27176
+ ]);
27177
+ } catch (error) {
27178
+ throw new Error("Failed to create index on buildings.");
27179
+ }
27180
+ }
27181
+ async function createTextIndex() {
27182
+ try {
27183
+ await collection.createIndex({
27184
+ name: "text"
27185
+ });
27186
+ } catch (error) {
27187
+ throw new Error("Failed to create text index on building name.");
27188
+ }
27189
+ }
27190
+ async function add(value, session) {
27191
+ try {
27192
+ value = MBuilding(value);
27193
+ const res = await collection.insertOne(value, { session });
27194
+ delCachedData();
27195
+ return res.insertedId;
27196
+ } catch (error) {
27197
+ logger30.log({
27198
+ level: "error",
27199
+ message: error.message
27200
+ });
27201
+ if (error instanceof AppError14) {
27202
+ throw error;
27203
+ } else {
27204
+ const isDuplicated = error.message.includes("duplicate");
27205
+ if (isDuplicated) {
27206
+ throw new BadRequestError60("Building already exists.");
27207
+ }
27208
+ throw new Error("Failed to create building.");
27209
+ }
27210
+ }
27211
+ }
27212
+ async function updateById(_id, value, session) {
27213
+ try {
27214
+ _id = new ObjectId40(_id);
27215
+ } catch (error) {
27216
+ throw new BadRequestError60("Invalid ID.");
27217
+ }
27218
+ try {
27219
+ const res = await collection.updateOne(
27220
+ { _id },
27221
+ { $set: value },
27222
+ { session }
27223
+ );
27224
+ delCachedData();
27225
+ return res;
27226
+ } catch (error) {
27227
+ logger30.log({
27228
+ level: "error",
27229
+ message: error.message
27230
+ });
27231
+ if (error instanceof AppError14) {
27232
+ throw error;
27233
+ } else {
27234
+ throw new Error("Failed to update building.");
27235
+ }
27236
+ }
27237
+ }
27238
+ async function getAll({
27239
+ search = "",
27240
+ page = 1,
27241
+ limit = 10,
27242
+ sort = {},
27243
+ school = "",
27244
+ status = "active"
27245
+ } = {}) {
27246
+ page = page > 0 ? page - 1 : 0;
27247
+ const query = {
27248
+ status
27249
+ };
27250
+ sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
27251
+ if (search) {
27252
+ query.$text = { $search: search };
27253
+ }
27254
+ if (school) {
27255
+ try {
27256
+ query.school = new ObjectId40(school);
27257
+ } catch (error) {
27258
+ throw new BadRequestError60("Invalid school ID.");
27259
+ }
27260
+ }
27261
+ const cacheParams = {
27262
+ page,
27263
+ limit,
27264
+ sort: JSON.stringify(sort)
27265
+ };
27266
+ if (search)
27267
+ cacheParams.search = search;
27268
+ if (school)
27269
+ cacheParams.school = school;
27270
+ if (status !== "active")
27271
+ cacheParams.status = status;
27272
+ const cacheKey = makeCacheKey19(namespace_collection, cacheParams);
27273
+ logger30.log({
27274
+ level: "info",
27275
+ message: `Cache key for getAll buildings: ${cacheKey}`
27276
+ });
27277
+ try {
27278
+ const cached = await getCache(cacheKey);
27279
+ if (cached) {
27280
+ logger30.log({
27281
+ level: "info",
27282
+ message: `Cache hit for getAll buildings: ${cacheKey}`
27283
+ });
27284
+ return cached;
27285
+ }
27286
+ const items = await collection.aggregate([
27287
+ { $match: query },
27288
+ { $sort: sort },
27289
+ { $skip: page * limit },
27290
+ { $limit: limit }
27291
+ ]).toArray();
27292
+ const length = await collection.countDocuments(query);
27293
+ const data = paginate15(items, page, limit, length);
27294
+ setCache(cacheKey, data, 600).then(() => {
27295
+ logger30.log({
27296
+ level: "info",
27297
+ message: `Cache set for getAll buildings: ${cacheKey}`
27298
+ });
27299
+ }).catch((err) => {
27300
+ logger30.log({
27301
+ level: "error",
27302
+ message: `Failed to set cache for getAll buildings: ${err.message}`
27303
+ });
27304
+ });
27305
+ return data;
27306
+ } catch (error) {
27307
+ logger30.log({ level: "error", message: `${error}` });
27308
+ throw error;
27309
+ }
27310
+ }
27311
+ async function getById(_id) {
27312
+ try {
27313
+ _id = new ObjectId40(_id);
27314
+ } catch (error) {
27315
+ throw new BadRequestError60("Invalid ID.");
27316
+ }
27317
+ const cacheKey = makeCacheKey19(namespace_collection, { _id: String(_id) });
27318
+ try {
27319
+ const cached = await getCache(cacheKey);
27320
+ if (cached) {
27321
+ logger30.log({
27322
+ level: "info",
27323
+ message: `Cache hit for getById building: ${cacheKey}`
27324
+ });
27325
+ return cached;
27326
+ }
27327
+ const result = await collection.findOne({
27328
+ _id
27329
+ });
27330
+ setCache(cacheKey, result, 300).then(() => {
27331
+ logger30.log({
27332
+ level: "info",
27333
+ message: `Cache set for building by id: ${cacheKey}`
27334
+ });
27335
+ }).catch((err) => {
27336
+ logger30.log({
27337
+ level: "error",
27338
+ message: `Failed to set cache for building by id: ${err.message}`
27339
+ });
27340
+ });
27341
+ return result;
27342
+ } catch (error) {
27343
+ if (error instanceof AppError14) {
27344
+ throw error;
27345
+ } else {
27346
+ throw new InternalServerError25("Failed to get building.");
27347
+ }
27348
+ }
27349
+ }
27350
+ async function deleteById(_id, session) {
27351
+ try {
27352
+ _id = new ObjectId40(_id);
27353
+ } catch (error) {
27354
+ throw new BadRequestError60("Invalid ID.");
27355
+ }
27356
+ try {
27357
+ const res = await collection.updateOne(
27358
+ { _id },
27359
+ { $set: { status: "deleted", deletedAt: /* @__PURE__ */ new Date() } }
27360
+ );
27361
+ delCachedData();
27362
+ return res;
27363
+ } catch (error) {
27364
+ logger30.log({
27365
+ level: "error",
27366
+ message: error.message
27367
+ });
27368
+ if (error instanceof AppError14) {
27369
+ throw error;
27370
+ } else {
27371
+ throw new InternalServerError25("Failed to delete building.");
27372
+ }
27373
+ }
27374
+ }
27375
+ function delCachedData() {
27376
+ delNamespace().then(() => {
27377
+ logger30.log({
27378
+ level: "info",
27379
+ message: `Cache namespace cleared for ${namespace_collection}`
27380
+ });
27381
+ }).catch((err) => {
27382
+ logger30.log({
27383
+ level: "error",
27384
+ message: `Failed to clear cache namespace for ${namespace_collection}: ${err.message}`
27385
+ });
27386
+ });
27387
+ }
27388
+ return {
27389
+ createIndex,
27390
+ createTextIndex,
27391
+ add,
27392
+ getAll,
27393
+ getById,
27394
+ updateById,
27395
+ deleteById
27396
+ };
27397
+ }
27398
+
27399
+ // src/repositories/building-unit.repository.ts
27400
+ import {
27401
+ AppError as AppError15,
27402
+ BadRequestError as BadRequestError61,
27403
+ InternalServerError as InternalServerError26,
27404
+ logger as logger31,
27405
+ makeCacheKey as makeCacheKey20,
27406
+ paginate as paginate16,
27407
+ useAtlas as useAtlas32,
27408
+ useCache as useCache21
27409
+ } from "@eeplatform/nodejs-utils";
27410
+ import { ObjectId as ObjectId41 } from "mongodb";
27411
+ function useBuildingUnitRepo() {
27412
+ const db = useAtlas32.getDb();
27413
+ if (!db) {
27414
+ throw new Error("Unable to connect to server.");
27415
+ }
27416
+ const namespace_collection = "school.building-units";
27417
+ const collection = db.collection(namespace_collection);
27418
+ const { getCache, setCache, delNamespace } = useCache21(namespace_collection);
27419
+ async function createIndex() {
27420
+ try {
27421
+ await collection.createIndexes([
27422
+ { key: { school: 1 } },
27423
+ { key: { building: 1 } },
27424
+ { key: { status: 1 } },
27425
+ { key: { createdAt: 1 } },
27426
+ {
27427
+ key: {
27428
+ name: "text",
27429
+ buildingName: "text",
27430
+ category: "text",
27431
+ type: "text"
27432
+ }
27433
+ }
27434
+ ]);
27435
+ } catch (error) {
27436
+ throw new Error("Failed to create index on building units.");
27437
+ }
27438
+ }
27439
+ function delCachedData() {
27440
+ delNamespace().then(() => {
27441
+ logger31.log({
27442
+ level: "info",
27443
+ message: `Cache namespace cleared for ${namespace_collection}`
27444
+ });
27445
+ }).catch((err) => {
27446
+ logger31.log({
27447
+ level: "error",
27448
+ message: `Failed to clear cache namespace for ${namespace_collection}: ${err.message}`
27449
+ });
27450
+ });
27451
+ }
27452
+ async function add(value, session) {
27453
+ try {
27454
+ value = MBuildingUnit(value);
27455
+ const res = await collection.insertOne(value, { session });
27456
+ delCachedData();
27457
+ return res.insertedId;
27458
+ } catch (error) {
27459
+ logger31.log({
27460
+ level: "error",
27461
+ message: error.message
27462
+ });
27463
+ if (error instanceof AppError15) {
27464
+ throw error;
27465
+ } else {
27466
+ throw new Error("Failed to create building unit.");
27467
+ }
27468
+ }
27469
+ }
27470
+ async function updateById(_id, value, session) {
27471
+ const { error } = schemaUpdateOptions.validate(value);
27472
+ if (error) {
27473
+ throw new BadRequestError61(error.message);
27474
+ }
27475
+ try {
27476
+ _id = new ObjectId41(_id);
27477
+ } catch (error2) {
27478
+ throw new BadRequestError61("Invalid ID.");
27479
+ }
27480
+ try {
27481
+ const res = await collection.updateOne(
27482
+ { _id },
27483
+ { $set: value },
27484
+ { session }
27485
+ );
27486
+ delCachedData();
27487
+ return res;
27488
+ } catch (error2) {
27489
+ logger31.log({
27490
+ level: "error",
27491
+ message: error2.message
27492
+ });
27493
+ if (error2 instanceof AppError15) {
27494
+ throw error2;
27495
+ } else {
27496
+ throw new Error("Failed to create building unit.");
27497
+ }
27498
+ }
27499
+ }
27500
+ async function getAll({
27501
+ search = "",
27502
+ page = 1,
27503
+ limit = 10,
27504
+ sort = {},
27505
+ school = "",
27506
+ building = "",
27507
+ status = "active"
27508
+ } = {}) {
27509
+ page = page > 0 ? page - 1 : 0;
27510
+ const query = {
27511
+ deletedAt: { $in: ["", null] },
27512
+ status: { $in: [status, "", null] }
27513
+ };
27514
+ sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
27515
+ if (search) {
27516
+ query.$text = { $search: search };
27517
+ }
27518
+ if (school) {
27519
+ try {
27520
+ query.school = new ObjectId41(school);
27521
+ } catch (error) {
27522
+ throw new BadRequestError61("Invalid school ID.");
27523
+ }
27524
+ }
27525
+ if (building) {
27526
+ try {
27527
+ query.building = new ObjectId41(building);
27528
+ } catch (error) {
27529
+ throw new BadRequestError61("Invalid building ID.");
27530
+ }
27531
+ }
27532
+ const cacheParams = {
27533
+ page,
27534
+ limit,
27535
+ sort: JSON.stringify(sort)
27536
+ };
27537
+ if (search)
27538
+ cacheParams.search = search;
27539
+ if (school)
27540
+ cacheParams.school = school;
27541
+ if (building)
27542
+ cacheParams.building = building;
27543
+ if (status !== "active")
27544
+ cacheParams.status = status;
27545
+ const cacheKey = makeCacheKey20(namespace_collection, cacheParams);
27546
+ logger31.log({
27547
+ level: "info",
27548
+ message: `Cache key for getAll building units: ${cacheKey}`
27549
+ });
27550
+ try {
27551
+ const cached = await getCache(cacheKey);
27552
+ if (cached) {
27553
+ logger31.log({
27554
+ level: "info",
27555
+ message: `Cache hit for getAll building units: ${cacheKey}`
27556
+ });
27557
+ return cached;
27558
+ }
27559
+ const items = await collection.aggregate([
27560
+ { $match: query },
27561
+ { $sort: sort },
27562
+ { $skip: page * limit },
27563
+ { $limit: limit }
27564
+ ]).toArray();
27565
+ const length = await collection.countDocuments(query);
27566
+ const data = paginate16(items, page, limit, length);
27567
+ setCache(cacheKey, data, 600).then(() => {
27568
+ logger31.log({
27569
+ level: "info",
27570
+ message: `Cache set for getAll building units: ${cacheKey}`
27571
+ });
27572
+ }).catch((err) => {
27573
+ logger31.log({
27574
+ level: "error",
27575
+ message: `Failed to set cache for getAll building units: ${err.message}`
27576
+ });
27577
+ });
27578
+ return data;
27579
+ } catch (error) {
27580
+ logger31.log({ level: "error", message: `${error}` });
27581
+ throw error;
27582
+ }
27583
+ }
27584
+ async function getById(_id) {
27585
+ try {
27586
+ _id = new ObjectId41(_id);
27587
+ } catch (error) {
27588
+ throw new BadRequestError61("Invalid ID.");
27589
+ }
27590
+ const cacheKey = makeCacheKey20(namespace_collection, { _id: String(_id) });
27591
+ try {
27592
+ const cached = await getCache(cacheKey);
27593
+ if (cached) {
27594
+ logger31.log({
27595
+ level: "info",
27596
+ message: `Cache hit for getById building unit: ${cacheKey}`
27597
+ });
27598
+ return cached;
27599
+ }
27600
+ const result = await collection.findOne({
27601
+ _id,
27602
+ deletedAt: { $in: ["", null] }
27603
+ });
27604
+ if (!result) {
27605
+ throw new BadRequestError61("Building unit not found.");
27606
+ }
27607
+ setCache(cacheKey, result, 300).then(() => {
27608
+ logger31.log({
27609
+ level: "info",
27610
+ message: `Cache set for building unit by id: ${cacheKey}`
27611
+ });
27612
+ }).catch((err) => {
27613
+ logger31.log({
27614
+ level: "error",
27615
+ message: `Failed to set cache for building unit by id: ${err.message}`
27616
+ });
27617
+ });
27618
+ return result;
27619
+ } catch (error) {
27620
+ if (error instanceof AppError15) {
27621
+ throw error;
27622
+ } else {
27623
+ throw new InternalServerError26("Failed to get building unit.");
27624
+ }
27625
+ }
27626
+ }
27627
+ async function getByBuildingLevel(building, level) {
27628
+ try {
27629
+ building = new ObjectId41(building);
27630
+ } catch (error) {
27631
+ throw new BadRequestError61("Invalid building ID.");
27632
+ }
27633
+ const cacheKey = makeCacheKey20(namespace_collection, {
27634
+ building: String(building),
27635
+ level
27636
+ });
27637
+ try {
27638
+ const cached = await getCache(cacheKey);
27639
+ if (cached) {
27640
+ logger31.log({
27641
+ level: "info",
27642
+ message: `Cache hit for getById building unit: ${cacheKey}`
27643
+ });
27644
+ return cached;
27645
+ }
27646
+ const result = await collection.findOne({
27647
+ building,
27648
+ level,
27649
+ status: "active"
27650
+ });
27651
+ setCache(cacheKey, result, 300).then(() => {
27652
+ logger31.log({
27653
+ level: "info",
27654
+ message: `Cache set for building unit by id: ${cacheKey}`
27655
+ });
27656
+ }).catch((err) => {
27657
+ logger31.log({
27658
+ level: "error",
27659
+ message: `Failed to set cache for building unit by id: ${err.message}`
27660
+ });
27661
+ });
27662
+ return result;
27663
+ } catch (error) {
27664
+ if (error instanceof AppError15) {
27665
+ throw error;
27666
+ } else {
27667
+ throw new InternalServerError26("Failed to get building unit.");
27668
+ }
27669
+ }
27670
+ }
27671
+ async function getByBuilding(building) {
27672
+ try {
27673
+ building = new ObjectId41(building);
27674
+ } catch (error) {
27675
+ throw new BadRequestError61("Invalid building ID.");
27676
+ }
27677
+ const cacheKey = makeCacheKey20(namespace_collection, {
27678
+ building: String(building)
27679
+ });
27680
+ try {
27681
+ const cached = await getCache(cacheKey);
27682
+ if (cached) {
27683
+ logger31.log({
27684
+ level: "info",
27685
+ message: `Cache hit for getById building unit: ${cacheKey}`
27686
+ });
27687
+ return cached;
27688
+ }
27689
+ const result = await collection.findOne({
27690
+ building,
27691
+ status: "active"
27692
+ });
27693
+ setCache(cacheKey, result, 300).then(() => {
27694
+ logger31.log({
27695
+ level: "info",
27696
+ message: `Cache set for building unit by id: ${cacheKey}`
27697
+ });
27698
+ }).catch((err) => {
27699
+ logger31.log({
27700
+ level: "error",
27701
+ message: `Failed to set cache for building unit by id: ${err.message}`
27702
+ });
27703
+ });
27704
+ return result;
27705
+ } catch (error) {
27706
+ if (error instanceof AppError15) {
27707
+ throw error;
27708
+ } else {
27709
+ throw new InternalServerError26("Failed to get building unit.");
27710
+ }
27711
+ }
27712
+ }
27713
+ async function deleteById(_id, session) {
27714
+ try {
27715
+ _id = new ObjectId41(_id);
27716
+ } catch (error) {
27717
+ throw new BadRequestError61("Invalid ID.");
27718
+ }
27719
+ try {
27720
+ const res = await collection.updateOne(
27721
+ { _id },
27722
+ { $set: { status: "deleted", deletedAt: /* @__PURE__ */ new Date() } },
27723
+ { session }
27724
+ );
27725
+ delCachedData();
27726
+ return "Room/Facility deleted successfully.";
27727
+ } catch (error) {
27728
+ logger31.log({
27729
+ level: "error",
27730
+ message: error.message
27731
+ });
27732
+ if (error instanceof AppError15) {
27733
+ throw error;
27734
+ } else {
27735
+ throw new Error("Failed to deleted room/facility.");
27736
+ }
27737
+ }
27738
+ }
27739
+ return {
27740
+ createIndex,
27741
+ add,
27742
+ getAll,
27743
+ getById,
27744
+ getByBuildingLevel,
27745
+ updateById,
27746
+ getByBuilding,
27747
+ deleteById
27748
+ };
27749
+ }
27750
+
27751
+ // src/controllers/building.controller.ts
27752
+ import { BadRequestError as BadRequestError63, logger as logger32 } from "@eeplatform/nodejs-utils";
27753
+ import Joi34 from "joi";
27754
+
27755
+ // src/services/building.service.ts
27756
+ import { BadRequestError as BadRequestError62, NotFoundError as NotFoundError11 } from "@eeplatform/nodejs-utils";
27757
+ function useBuildingService() {
27758
+ const {
27759
+ updateById: _updateById,
27760
+ getById: _getById,
27761
+ deleteById: _deleteById
27762
+ } = useBuildingRepo();
27763
+ const { getByBuildingLevel, getByBuilding } = useBuildingUnitRepo();
27764
+ async function updateById(id, data) {
27765
+ data.levels = Number(data.levels);
27766
+ try {
27767
+ const building = await _getById(id);
27768
+ if (!building) {
27769
+ throw new NotFoundError11("Building not found.");
27770
+ }
27771
+ if (data.levels < building.levels) {
27772
+ const unit = await getByBuildingLevel(id, building.levels);
27773
+ if (unit) {
27774
+ throw new BadRequestError62(
27775
+ "Cannot reduce floors, there are existing building units at higher floors."
27776
+ );
27777
+ }
27778
+ }
27779
+ const result = await _updateById(id, data);
27780
+ return result;
27781
+ } catch (error) {
27782
+ throw error;
27783
+ }
27784
+ }
27785
+ async function deleteById(id) {
27786
+ const building = await getByBuilding(id);
27787
+ if (building) {
27788
+ throw new BadRequestError62(
27789
+ "Cannot delete building with existing room/facility. Please delete room/facility first."
27790
+ );
27791
+ }
27792
+ try {
27793
+ await _deleteById(id);
27794
+ return "Building deleted successfully.";
27795
+ } catch (error) {
27796
+ throw error;
27797
+ }
27798
+ }
27799
+ return {
27800
+ updateById,
27801
+ deleteById
27802
+ };
27803
+ }
27804
+
27805
+ // src/controllers/building.controller.ts
27806
+ function useBuildingController() {
27807
+ const { getAll: _getAll, getById: _getById, add: _add } = useBuildingRepo();
27808
+ const { updateById: _updateById, deleteById: _deleteById } = useBuildingService();
27809
+ async function createBuilding(req, res, next) {
27810
+ const value = req.body;
27811
+ const validation = Joi34.object({
27812
+ name: Joi34.string().required(),
27813
+ school: Joi34.string().hex().required(),
27814
+ levels: Joi34.number().integer().min(1).required(),
27815
+ serial: Joi34.string().optional().allow("", null),
27816
+ status: Joi34.string().optional().allow("", null)
27817
+ });
27818
+ const { error } = validation.validate(value);
27819
+ if (error) {
27820
+ next(new BadRequestError63(error.message));
27821
+ logger32.info(`Controller: ${error.message}`);
27822
+ return;
27823
+ }
27824
+ try {
27825
+ const result = await _add(value);
27826
+ res.json(result);
27827
+ return;
27828
+ } catch (error2) {
27829
+ next(error2);
27830
+ }
27831
+ }
27832
+ async function updateById(req, res, next) {
27833
+ const value = req.body;
27834
+ const id = req.params.id ?? "";
27835
+ const validation = Joi34.object({
27836
+ id: Joi34.string().hex().required(),
27837
+ value: Joi34.object({
27838
+ name: Joi34.string().required(),
27839
+ serial: Joi34.string().optional().allow("", null),
27840
+ levels: Joi34.number().integer().min(1).required()
27841
+ })
27842
+ });
27843
+ const { error } = validation.validate({ id, value });
27844
+ if (error) {
27845
+ next(new BadRequestError63(error.message));
27846
+ logger32.info(`Controller: ${error.message}`);
27847
+ return;
27848
+ }
27849
+ try {
27850
+ const result = await _updateById(id, value);
27851
+ res.json(result);
27852
+ return;
27853
+ } catch (error2) {
27854
+ next(error2);
27855
+ }
27856
+ }
27857
+ async function getAll(req, res, next) {
27858
+ const query = req.query;
27859
+ const validation = Joi34.object({
27860
+ page: Joi34.number().min(1).optional().allow("", null),
27861
+ limit: Joi34.number().min(1).optional().allow("", null),
27862
+ search: Joi34.string().optional().allow("", null),
27863
+ school: Joi34.string().hex().optional().allow("", null),
27864
+ status: Joi34.string().optional().allow("", null)
27865
+ });
27866
+ const { error } = validation.validate(query);
27867
+ if (error) {
27868
+ next(new BadRequestError63(error.message));
27869
+ return;
27870
+ }
27871
+ const page = parseInt(req.query.page) ?? 1;
27872
+ let limit = parseInt(req.query.limit) ?? 20;
27873
+ limit = isNaN(limit) ? 20 : limit;
27874
+ const sort = req.query.sort ? String(req.query.sort).split(",") : "";
27875
+ const sortOrder = req.query.sortOrder ? String(req.query.sortOrder).split(",") : "";
27876
+ const sortObj = {};
27877
+ if (sort && Array.isArray(sort) && sort.length && sortOrder && Array.isArray(sortOrder) && sortOrder.length) {
27878
+ sort.forEach((field, index) => {
27879
+ sortObj[field] = sortOrder[index] === "desc" ? -1 : 1;
27880
+ });
27881
+ }
27882
+ const status = req.query.status ?? "active";
27883
+ const school = req.query.school ?? "";
27884
+ const search = req.query.search ?? "";
27885
+ try {
27886
+ const buildings = await _getAll({
27887
+ page,
27888
+ limit,
27889
+ sort: sortObj,
27890
+ status,
27891
+ school,
27892
+ search
27893
+ });
27894
+ res.json(buildings);
27895
+ return;
27896
+ } catch (error2) {
27897
+ next(error2);
27898
+ }
27899
+ }
27900
+ async function getById(req, res, next) {
27901
+ const id = req.params.id;
27902
+ const validation = Joi34.object({
27903
+ id: Joi34.string().hex().required()
27904
+ });
27905
+ const { error } = validation.validate({ id });
27906
+ if (error) {
27907
+ next(new BadRequestError63(error.message));
27908
+ return;
27909
+ }
27910
+ try {
27911
+ const building = await _getById(id);
27912
+ res.json({
27913
+ message: "Successfully retrieved building.",
27914
+ data: { building }
27915
+ });
27916
+ return;
27917
+ } catch (error2) {
27918
+ next(error2);
27919
+ }
27920
+ }
27921
+ async function deleteById(req, res, next) {
27922
+ const id = req.params.id;
27923
+ const validation = Joi34.object({
27924
+ id: Joi34.string().hex().required()
27925
+ });
27926
+ const { error } = validation.validate({ id });
27927
+ if (error) {
27928
+ next(new BadRequestError63(error.message));
27929
+ return;
27930
+ }
27931
+ try {
27932
+ const message = await _deleteById(id);
27933
+ res.json(message);
27934
+ return;
27935
+ } catch (error2) {
27936
+ next(error2);
27937
+ }
27938
+ }
27939
+ return {
27940
+ createBuilding,
27941
+ getAll,
27942
+ getById,
27943
+ updateById,
27944
+ deleteById
27945
+ };
27946
+ }
27947
+
27948
+ // src/controllers/building-unit.controller.ts
27949
+ import { BadRequestError as BadRequestError64 } from "@eeplatform/nodejs-utils";
27950
+ import Joi35 from "joi";
27951
+
27952
+ // src/services/building-unit.service.ts
27953
+ import { useAtlas as useAtlas33 } from "@eeplatform/nodejs-utils";
27954
+ function useBuildingUnitService() {
27955
+ const { add: _add } = useBuildingUnitRepo();
27956
+ async function add(value) {
27957
+ const session = useAtlas33.getClient()?.startSession();
27958
+ if (!session) {
27959
+ throw new Error("Unable to start session for building unit service.");
27960
+ }
27961
+ try {
27962
+ await session.startTransaction();
27963
+ for (let index = 0; index < value.qty; index++) {
27964
+ await _add({ ...value.building }, session);
27965
+ }
27966
+ await session.commitTransaction();
27967
+ return "Building unit added successfully.";
27968
+ } catch (error) {
27969
+ await session.abortTransaction();
27970
+ throw error;
27971
+ } finally {
27972
+ session.endSession();
27973
+ }
27974
+ }
27975
+ return {
27976
+ add
27977
+ };
27978
+ }
27979
+
27980
+ // src/controllers/building-unit.controller.ts
27981
+ function useBuildingUnitController() {
27982
+ const {
27983
+ getAll: _getAll,
27984
+ getById: _getById,
27985
+ updateById: _updateById,
27986
+ deleteById: _deleteById
27987
+ } = useBuildingUnitRepo();
27988
+ const { add: _add } = useBuildingUnitService();
27989
+ async function add(req, res, next) {
27990
+ const data = req.body;
27991
+ const validation = Joi35.object({
27992
+ building: Joi35.object({
27993
+ school: Joi35.string().hex().required(),
27994
+ name: Joi35.string().optional().allow("", null),
27995
+ building: Joi35.string().hex().required(),
27996
+ buildingName: Joi35.string().optional().allow("", null),
27997
+ level: Joi35.number().integer().min(1).required(),
27998
+ category: Joi35.string().required(),
27999
+ type: Joi35.string().required(),
28000
+ seating_capacity: Joi35.number().integer().min(0).required(),
28001
+ standing_capacity: Joi35.number().integer().min(0).required(),
28002
+ description: Joi35.string().optional().allow("", null),
28003
+ unit_of_measurement: Joi35.string().valid("sqm").required(),
28004
+ area: Joi35.number().positive().required(),
28005
+ status: Joi35.string().optional().allow("", null)
28006
+ }),
28007
+ qty: Joi35.number().integer().min(1).max(20).optional().default(1)
28008
+ });
28009
+ const { error } = validation.validate(data);
28010
+ if (error) {
28011
+ next(new BadRequestError64(error.message));
28012
+ return;
28013
+ }
28014
+ try {
28015
+ const buildingUnit = await _add(data);
28016
+ res.json({
28017
+ message: "Building unit added successfully.",
28018
+ data: { buildingUnit }
28019
+ });
28020
+ } catch (error2) {
28021
+ next(error2);
28022
+ }
28023
+ }
28024
+ async function updateById(req, res, next) {
28025
+ const data = req.body;
28026
+ const id = req.params.id ?? "";
28027
+ const validation = Joi35.object({
28028
+ id: Joi35.string().hex().required(),
28029
+ value: schemaUpdateOptions
28030
+ });
28031
+ const { error } = validation.validate({ id, value: data });
28032
+ if (error) {
28033
+ next(new BadRequestError64(error.message));
28034
+ return;
28035
+ }
28036
+ try {
28037
+ const buildingUnit = await _updateById(id, data);
28038
+ res.json({
28039
+ message: "Building unit updated successfully.",
28040
+ data: { buildingUnit }
28041
+ });
28042
+ } catch (error2) {
28043
+ next(error2);
28044
+ }
28045
+ }
28046
+ async function getAll(req, res, next) {
28047
+ const query = req.query;
28048
+ const validation = Joi35.object({
28049
+ page: Joi35.number().min(1).optional().allow("", null),
28050
+ limit: Joi35.number().min(1).optional().allow("", null),
28051
+ search: Joi35.string().optional().allow("", null),
28052
+ school: Joi35.string().hex().optional().allow("", null),
28053
+ building: Joi35.string().hex().optional().allow("", null),
28054
+ status: Joi35.string().optional().allow("", null)
28055
+ });
28056
+ const { error } = validation.validate(query);
28057
+ if (error) {
28058
+ next(new BadRequestError64(error.message));
28059
+ return;
28060
+ }
28061
+ const page = parseInt(req.query.page) ?? 1;
28062
+ let limit = parseInt(req.query.limit) ?? 20;
28063
+ limit = isNaN(limit) ? 20 : limit;
28064
+ const sort = req.query.sort ? String(req.query.sort).split(",") : "";
28065
+ const sortOrder = req.query.sortOrder ? String(req.query.sortOrder).split(",") : "";
28066
+ const sortObj = {};
28067
+ if (sort && Array.isArray(sort) && sort.length && sortOrder && Array.isArray(sortOrder) && sortOrder.length) {
28068
+ sort.forEach((field, index) => {
28069
+ sortObj[field] = sortOrder[index] === "desc" ? -1 : 1;
28070
+ });
28071
+ }
28072
+ const status = req.query.status ?? "active";
28073
+ const school = req.query.school ?? "";
28074
+ const building = req.query.building ?? "";
28075
+ const search = req.query.search ?? "";
28076
+ try {
28077
+ const buildings = await _getAll({
28078
+ page,
28079
+ limit,
28080
+ sort: sortObj,
28081
+ status,
28082
+ school,
28083
+ search,
28084
+ building
28085
+ });
28086
+ res.json(buildings);
28087
+ return;
28088
+ } catch (error2) {
28089
+ next(error2);
28090
+ }
28091
+ }
28092
+ async function getById(req, res, next) {
28093
+ const id = req.params.id;
28094
+ const validation = Joi35.object({
28095
+ id: Joi35.string().hex().required()
28096
+ });
28097
+ const { error } = validation.validate({ id });
28098
+ if (error) {
28099
+ next(new BadRequestError64(error.message));
28100
+ return;
28101
+ }
28102
+ try {
28103
+ const buildingUnit = await _getById(id);
28104
+ res.json({
28105
+ message: "Successfully retrieved building unit.",
28106
+ data: { buildingUnit }
28107
+ });
28108
+ return;
28109
+ } catch (error2) {
28110
+ next(error2);
28111
+ }
28112
+ }
28113
+ async function deleteById(req, res, next) {
28114
+ const id = req.params.id;
28115
+ const validation = Joi35.object({
28116
+ id: Joi35.string().hex().required()
28117
+ });
28118
+ const { error } = validation.validate({ id });
28119
+ if (error) {
28120
+ next(new BadRequestError64(error.message));
28121
+ return;
28122
+ }
28123
+ try {
28124
+ const message = await _deleteById(id);
28125
+ res.json({ message });
28126
+ return;
28127
+ } catch (error2) {
28128
+ next(error2);
28129
+ }
28130
+ }
28131
+ return {
28132
+ add,
28133
+ getAll,
28134
+ getById,
28135
+ updateById,
28136
+ deleteById
28137
+ };
28138
+ }
27038
28139
  export {
27039
28140
  ACCESS_TOKEN_EXPIRY,
27040
28141
  ACCESS_TOKEN_SECRET,
@@ -27053,6 +28154,8 @@ export {
27053
28154
  MAILER_TRANSPORT_PORT,
27054
28155
  MAILER_TRANSPORT_SECURE,
27055
28156
  MAddress,
28157
+ MBuilding,
28158
+ MBuildingUnit,
27056
28159
  MDivision,
27057
28160
  MEntity,
27058
28161
  MFile,
@@ -27093,17 +28196,25 @@ export {
27093
28196
  addressSchema,
27094
28197
  isDev,
27095
28198
  schema,
28199
+ schemaBuilding,
28200
+ schemaBuildingUnit,
27096
28201
  schemaDivision,
27097
28202
  schemaRegion,
27098
28203
  schemaSchool,
28204
+ schemaUpdateOptions,
27099
28205
  useAddressController,
27100
28206
  useAddressRepo,
27101
28207
  useAuthController,
27102
28208
  useAuthService,
28209
+ useBuildingController,
28210
+ useBuildingRepo,
28211
+ useBuildingUnitController,
28212
+ useBuildingUnitRepo,
27103
28213
  useCounterModel,
27104
28214
  useCounterRepo,
27105
28215
  useDivisionController,
27106
28216
  useDivisionRepo,
28217
+ useDivisionService,
27107
28218
  useEntityController,
27108
28219
  useEntityRepo,
27109
28220
  useFileController,
@@ -27134,6 +28245,7 @@ export {
27134
28245
  usePromoCodeRepo,
27135
28246
  useRegionController,
27136
28247
  useRegionRepo,
28248
+ useRegionService,
27137
28249
  useRoleController,
27138
28250
  useRoleRepo,
27139
28251
  useSchoolController,