@7365admin1/core 2.47.0 → 2.49.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
@@ -940,12 +940,16 @@ import {
940
940
  makeCacheKey as makeCacheKey3
941
941
  } from "@7365admin1/node-server-utils";
942
942
  var work_orders_namespace_collection = "work-orders";
943
+ var work_orders2_namespace_collection = "work-orders2";
943
944
  function useWorkOrderRepo() {
944
945
  const db = useAtlas3.getDb();
945
946
  if (!db) {
946
947
  throw new InternalServerError3("Unable to connect to server.");
947
948
  }
948
949
  const collection = db.collection(work_orders_namespace_collection);
950
+ const workOrders2Collection = db.collection(
951
+ work_orders2_namespace_collection
952
+ );
949
953
  async function createIndex() {
950
954
  try {
951
955
  await collection.createIndexes([
@@ -977,6 +981,12 @@ function useWorkOrderRepo() {
977
981
  const { delNamespace, setCache, getCache, delCache } = useCache3(
978
982
  work_orders_namespace_collection
979
983
  );
984
+ const {
985
+ delNamespace: delNamespaceWorkOrders2,
986
+ setCache: setCacheWorkOrders2,
987
+ getCache: getCacheWorkOrders2,
988
+ delCache: delCacheWorkOrders2
989
+ } = useCache3(work_orders2_namespace_collection);
980
990
  const { delNamespace: _delDashboardNameSpace } = useCache3("dashboard");
981
991
  async function createWorkOrder(value, session) {
982
992
  try {
@@ -1378,7 +1388,7 @@ function useWorkOrderRepo() {
1378
1388
  updatedAt: /* @__PURE__ */ new Date(),
1379
1389
  deletedAt: /* @__PURE__ */ new Date()
1380
1390
  };
1381
- const res = await collection.updateOne(
1391
+ const res = await workOrders2Collection.updateOne(
1382
1392
  { _id },
1383
1393
  { $set: updateValue },
1384
1394
  { session }
@@ -1386,13 +1396,13 @@ function useWorkOrderRepo() {
1386
1396
  if (res.modifiedCount === 0) {
1387
1397
  throw new InternalServerError3("Unable to delete work order.");
1388
1398
  }
1389
- delNamespace().then(() => {
1399
+ delNamespaceWorkOrders2().then(() => {
1390
1400
  logger5.info(
1391
- `Cache cleared for namespace: ${work_orders_namespace_collection}`
1401
+ `Cache cleared for namespace: ${work_orders2_namespace_collection}`
1392
1402
  );
1393
1403
  }).catch((err) => {
1394
1404
  logger5.error(
1395
- `Failed to clear cache for namespace: ${work_orders_namespace_collection}`,
1405
+ `Failed to clear cache for namespace: ${work_orders2_namespace_collection}`,
1396
1406
  err
1397
1407
  );
1398
1408
  });
@@ -2031,7 +2041,7 @@ function useOccurrenceEntryRepo() {
2031
2041
  logger6.info(`Cache hit for key: ${cacheKey}`);
2032
2042
  return cached;
2033
2043
  }
2034
- const bookId = new ObjectId7(dailyOccurrenceBookId);
2044
+ const bookId = typeof dailyOccurrenceBookId === "string" ? new ObjectId7(dailyOccurrenceBookId) : dailyOccurrenceBookId;
2035
2045
  const data = await collection.findOne(
2036
2046
  { dailyOccurrenceBookId: bookId },
2037
2047
  {
@@ -2046,6 +2056,16 @@ function useOccurrenceEntryRepo() {
2046
2056
  });
2047
2057
  return serialNumber;
2048
2058
  }
2059
+ async function getLatestSerialNumberInGroup(bookId, group) {
2060
+ const latestEntry = await collection.findOne(
2061
+ {
2062
+ dailyOccurrenceBookId: bookId,
2063
+ serialNumber: { $regex: `^${group}(\\.|$)` }
2064
+ },
2065
+ { sort: { serialNumber: -1 } }
2066
+ );
2067
+ return latestEntry ? Number(latestEntry.serialNumber) : group;
2068
+ }
2049
2069
  async function updateUserNameBySignatureId(_id, value, session) {
2050
2070
  try {
2051
2071
  const updateValue = {
@@ -2081,7 +2101,8 @@ function useOccurrenceEntryRepo() {
2081
2101
  createIndexes,
2082
2102
  createTextIndex,
2083
2103
  getLatestSerialNumber,
2084
- updateOccurrenceEntryByBookId
2104
+ updateOccurrenceEntryByBookId,
2105
+ getLatestSerialNumberInGroup
2085
2106
  };
2086
2107
  }
2087
2108
 
@@ -2748,6 +2769,7 @@ var APP_POOL_MAINTENANCE = process.env.APP_POOL_MAINTENANCE ?? "http://localhost
2748
2769
  var ENCRYPTION_KEY = process.env.ENCRYPTION_KEY ?? "";
2749
2770
  var DOMAIN = process.env.DOMAIN ?? "localhost";
2750
2771
  var OPEN_AI_API_KEY = process.env.OPEN_AI_API_KEY;
2772
+ var STORAGE_API = process.env.STORAGE_API;
2751
2773
 
2752
2774
  // src/services/auth.service.ts
2753
2775
  import jwt from "jsonwebtoken";
@@ -5155,6 +5177,39 @@ function useVerificationRepoV2() {
5155
5177
  throw new InternalServerError11("Error updating verification status.");
5156
5178
  }
5157
5179
  }
5180
+ async function countPendingOrgInvites(orgId) {
5181
+ try {
5182
+ orgId = new ObjectId18(orgId);
5183
+ } catch (error) {
5184
+ throw new BadRequestError19("Invalid organization ID format.");
5185
+ }
5186
+ const query = {
5187
+ status: "pending" /* PENDING */,
5188
+ type: { $in: ["user-invite", "member-invite"] },
5189
+ "metadata.org": orgId
5190
+ };
5191
+ const cacheKey = makeCacheKey10(namespace_collection, {
5192
+ status: "pending" /* PENDING */,
5193
+ type: JSON.stringify(["user-invite", "member-invite"]),
5194
+ org: orgId.toString()
5195
+ });
5196
+ const cachedData = await getCache(cacheKey);
5197
+ if (typeof cachedData === "number") {
5198
+ logger13.info(`Cache hit for key: ${cacheKey}`);
5199
+ return cachedData;
5200
+ }
5201
+ try {
5202
+ const count = await collection.countDocuments(query);
5203
+ setCache(cacheKey, count, 15 * 60).then(() => {
5204
+ logger13.info(`Cache set for key: ${cacheKey}`);
5205
+ }).catch((err) => {
5206
+ logger13.error(`Failed to set cache for key: ${cacheKey}`, err);
5207
+ });
5208
+ return count;
5209
+ } catch (error) {
5210
+ throw new InternalServerError11("Failed to count pending invitations.");
5211
+ }
5212
+ }
5158
5213
  return {
5159
5214
  createIndex,
5160
5215
  createTextIndex,
@@ -5163,7 +5218,8 @@ function useVerificationRepoV2() {
5163
5218
  getByVerificationCode,
5164
5219
  getVerificationById,
5165
5220
  getVerifications,
5166
- updateStatusById
5221
+ updateStatusById,
5222
+ countPendingOrgInvites
5167
5223
  };
5168
5224
  }
5169
5225
 
@@ -5241,6 +5297,46 @@ function useVerificationService() {
5241
5297
  throw error;
5242
5298
  }
5243
5299
  }
5300
+ async function createSimpleUserInvite({
5301
+ email,
5302
+ metadata
5303
+ }) {
5304
+ const type = "user-invite";
5305
+ const value = {
5306
+ type,
5307
+ email,
5308
+ metadata,
5309
+ expireAt: new Date(
5310
+ (/* @__PURE__ */ new Date()).getTime() + 72 * 60 * 60 * 1e3
5311
+ ).toISOString(),
5312
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
5313
+ };
5314
+ if (value.metadata?.org) {
5315
+ await getOrgById(value.metadata?.org);
5316
+ }
5317
+ if (value.metadata?.siteId) {
5318
+ await getSiteById(value.metadata?.siteId);
5319
+ }
5320
+ const res = await add(value);
5321
+ const dir = __dirname;
5322
+ const filePath = getDirectory(dir, "./public/handlebars/user-invite");
5323
+ const link = `${APP_MAIN}/verify/invitation/${res}`;
5324
+ const emailContent = compileHandlebar({
5325
+ context: {
5326
+ email,
5327
+ validity: VERIFICATION_USER_INVITE_DURATION,
5328
+ link
5329
+ },
5330
+ filePath
5331
+ });
5332
+ mailer.sendMail({
5333
+ to: email,
5334
+ subject: "User Invite",
5335
+ html: emailContent,
5336
+ sender: "iService365"
5337
+ });
5338
+ return res;
5339
+ }
5244
5340
  const {
5245
5341
  add: _add,
5246
5342
  updateVerificationStatusById: _updateVerificationStatusById,
@@ -5534,7 +5630,8 @@ function useVerificationService() {
5534
5630
  cancelUserInvitation,
5535
5631
  updateStatusById,
5536
5632
  signUp,
5537
- checkExpiredInvitation
5633
+ checkExpiredInvitation,
5634
+ createSimpleUserInvite
5538
5635
  };
5539
5636
  }
5540
5637
 
@@ -6780,7 +6877,16 @@ function useUserController() {
6780
6877
  async function updateUserFieldById(req, res, next) {
6781
6878
  const validation = Joi13.object({
6782
6879
  _id: Joi13.string().hex().required(),
6783
- field: Joi13.string().valid("name", "email", "contact", "nric", "dateOfBirth", "profile", "gender", "defaultOrg").required(),
6880
+ field: Joi13.string().valid(
6881
+ "name",
6882
+ "email",
6883
+ "contact",
6884
+ "nric",
6885
+ "dateOfBirth",
6886
+ "profile",
6887
+ "gender",
6888
+ "defaultOrg"
6889
+ ).required(),
6784
6890
  value: Joi13.when("field", {
6785
6891
  switch: [
6786
6892
  { is: "email", then: Joi13.string().email().required() },
@@ -7384,6 +7490,7 @@ import Joi16 from "joi";
7384
7490
  function useVerificationController() {
7385
7491
  const {
7386
7492
  createUserInvite: _createUserInvite,
7493
+ createSimpleUserInvite: _createSimpleUserInvite,
7387
7494
  createServiceProviderInvite: _createServiceProviderInvite,
7388
7495
  createForgetPassword: _createForgetPassword,
7389
7496
  verify: _verify,
@@ -7434,6 +7541,58 @@ function useVerificationController() {
7434
7541
  return;
7435
7542
  }
7436
7543
  }
7544
+ async function createSimpleUserInvite(req, res, next) {
7545
+ const payload = { ...req.body };
7546
+ const validation = Joi16.object({
7547
+ email: Joi16.string().email().required(),
7548
+ app: Joi16.string().optional().allow("", null),
7549
+ role: Joi16.string().hex().optional().allow("", null),
7550
+ name: Joi16.string().optional().allow("", null),
7551
+ org: Joi16.string().hex().optional().allow("", null),
7552
+ siteId: Joi16.string().hex().optional().allow("", null),
7553
+ siteName: Joi16.string().optional().allow("", null)
7554
+ });
7555
+ const { error } = validation.validate(payload);
7556
+ if (error) {
7557
+ logger22.log({
7558
+ level: "error",
7559
+ message: `${error.message}`
7560
+ });
7561
+ next(new BadRequestError31(error.message));
7562
+ return;
7563
+ }
7564
+ const email = req.body.email ?? "";
7565
+ const app = req.body.app ?? "";
7566
+ const role = req.body.role ?? "";
7567
+ const name = req.body.name ?? "";
7568
+ const org = req.body.org ?? "";
7569
+ const siteId = req.body.siteId ?? "";
7570
+ const siteName = req.body.siteName ?? "";
7571
+ try {
7572
+ await _createSimpleUserInvite({
7573
+ email,
7574
+ metadata: {
7575
+ app,
7576
+ role,
7577
+ name,
7578
+ org,
7579
+ siteId,
7580
+ siteName
7581
+ }
7582
+ });
7583
+ res.status(201).json({
7584
+ message: "Successfully invited user."
7585
+ });
7586
+ return;
7587
+ } catch (error2) {
7588
+ logger22.log({
7589
+ level: "error",
7590
+ message: `${error2.message}`
7591
+ });
7592
+ next(error2);
7593
+ return;
7594
+ }
7595
+ }
7437
7596
  async function createServiceProviderInvite(req, res, next) {
7438
7597
  const payload = req.body;
7439
7598
  const validation = Joi16.object({
@@ -7575,7 +7734,8 @@ function useVerificationController() {
7575
7734
  createServiceProviderInvite,
7576
7735
  createForgetPassword,
7577
7736
  verify,
7578
- cancelUserInvitation
7737
+ cancelUserInvitation,
7738
+ createSimpleUserInvite
7579
7739
  };
7580
7740
  }
7581
7741
 
@@ -13369,11 +13529,18 @@ function useVisitorTransactionRepo() {
13369
13529
  );
13370
13530
  }
13371
13531
  }
13372
- async function add(value, session) {
13532
+ async function add(value, session, returnValue = false) {
13373
13533
  try {
13374
13534
  value = MVisitorTransaction(value);
13375
13535
  const res = await collection.insertOne(value, { session });
13376
- return res.insertedId;
13536
+ if (returnValue) {
13537
+ return {
13538
+ ...value,
13539
+ _id: res.insertedId
13540
+ };
13541
+ } else {
13542
+ return res.insertedId;
13543
+ }
13377
13544
  } catch (error) {
13378
13545
  console.log("Error in add visitor transaction:", error);
13379
13546
  const isDuplicated = error.message.includes("duplicate");
@@ -14727,7 +14894,11 @@ function usePersonRepo() {
14727
14894
  try {
14728
14895
  await collection.createIndexes([
14729
14896
  { key: { contact: 1 } },
14730
- { key: { nric: 1 } }
14897
+ { key: { nric: 1 } },
14898
+ { key: { user: 1 } },
14899
+ { key: { site: 1, status: 1 } },
14900
+ { key: { "plates.plateNumber": 1, status: 1 } },
14901
+ { key: { unit: 1, status: 1 } }
14731
14902
  ]);
14732
14903
  } catch (error) {
14733
14904
  throw new InternalServerError26("Failed to create index on site people.");
@@ -16705,6 +16876,9 @@ function useVehicleService() {
16705
16876
  const _end = vehicle.end;
16706
16877
  const _recNo = plate.recNo;
16707
16878
  const _type = value.type ? value.type : plate.type;
16879
+ if (value.peopleId) {
16880
+ value.peopleId = new ObjectId46(value.peopleId);
16881
+ }
16708
16882
  const { name, plateNumber, start, end, recNo, type, unit, site, ...rest } = value;
16709
16883
  const startDahua = value.start ? formatDahuaDate(new Date(value.start)) : formatDahuaDate(new Date(_start));
16710
16884
  const endDahua = value.end ? formatDahuaDate(new Date(value.end)) : formatDahuaDate(new Date(_end));
@@ -16768,6 +16942,17 @@ function useVehicleService() {
16768
16942
  }
16769
16943
  const responseData = dahuaResponse?.data?.toString("utf-8") ?? "";
16770
16944
  value.recNo = responseData.split("=")[1]?.trim();
16945
+ const normalizedPlateNumber = Array.isArray(plateNumber) ? plateNumber[0] : plateNumber;
16946
+ if (value.peopleId && value.recNo) {
16947
+ await _pushVehicleById(
16948
+ value.peopleId,
16949
+ {
16950
+ plateNumber: normalizedPlateNumber,
16951
+ recNo: value.recNo
16952
+ },
16953
+ session
16954
+ );
16955
+ }
16771
16956
  } else {
16772
16957
  const dahuaPayload = {
16773
16958
  host,
@@ -16781,6 +16966,17 @@ function useVehicleService() {
16781
16966
  owner: name ? name : _name
16782
16967
  };
16783
16968
  const dahuaResponse = await _updatePlateNumber(dahuaPayload);
16969
+ const normalizedPlateNumber = Array.isArray(plateNumber) ? plateNumber[0] : plateNumber;
16970
+ if (value.peopleId && value.recNo) {
16971
+ await _pushVehicleById(
16972
+ value.peopleId,
16973
+ {
16974
+ plateNumber: normalizedPlateNumber,
16975
+ recNo: _recNo
16976
+ },
16977
+ session
16978
+ );
16979
+ }
16784
16980
  if (dahuaResponse?.statusCode !== 200) {
16785
16981
  throw new BadRequestError72(
16786
16982
  "Failed to update plate number to ANPR"
@@ -16975,7 +17171,7 @@ function useDahuaService() {
16975
17171
  const { createFile: _createFile } = useFileService();
16976
17172
  let currentTransactionId = null;
16977
17173
  let currentSnapshotField = null;
16978
- function useBufferQueue(boundary, site, gate, designation, host, username, password) {
17174
+ function useBufferQueue(boundary, site, gate, designation, host, username, password, onDetected) {
16979
17175
  const queue = [];
16980
17176
  let processing = false;
16981
17177
  let plateNumber = null;
@@ -17008,7 +17204,7 @@ function useDahuaService() {
17008
17204
  );
17009
17205
  streamRef.pause();
17010
17206
  }
17011
- processNext();
17207
+ processNext(onDetected);
17012
17208
  }
17013
17209
  function destroy() {
17014
17210
  queue.length = 0;
@@ -17024,30 +17220,30 @@ function useDahuaService() {
17024
17220
  `[${site}][${gate}] BufferQueue destroyed. Processed=${processedChunks}, Dropped=${droppedChunks}`
17025
17221
  );
17026
17222
  }
17027
- async function processNext() {
17223
+ async function processNext(onDetected2) {
17028
17224
  if (processing || queue.length === 0)
17029
17225
  return;
17030
17226
  processing = true;
17031
17227
  const buffer = queue.shift();
17032
17228
  try {
17033
- await handleBuffer(buffer);
17229
+ await handleBuffer(buffer, onDetected2);
17034
17230
  processedChunks++;
17035
17231
  if (queue.length <= RESUME_THRESHOLD && streamRef && streamRef.isPaused()) {
17036
17232
  loggerDahua.info(
17037
- `[${site}][${gate}] Queue at ${queue.length}/${MAX_QUEUE_SIZE}, resuming stream`
17233
+ `[${host}]Queue at ${queue.length}/${MAX_QUEUE_SIZE}, resuming stream`
17038
17234
  );
17039
17235
  streamRef.resume();
17040
17236
  }
17041
17237
  } catch (err) {
17042
- loggerDahua.error(`[${site}][${gate}] Error processing buffer:`, err);
17238
+ loggerDahua.error(`[${host}] Error processing buffer:`, err);
17043
17239
  } finally {
17044
17240
  processing = false;
17045
- processNext();
17241
+ processNext(onDetected2);
17046
17242
  }
17047
17243
  }
17048
- async function processVehicleTransaction() {
17244
+ async function processVehicleTransaction(onDetected2) {
17049
17245
  loggerDahua.info(
17050
- `[${site}][${gate}] Vehicle transaction: Plate=${plateNumber}, UTC=${UTCData}, UTCMs=${UTCMs}`
17246
+ `[${host}] Vehicle transaction: Plate=${plateNumber}, UTC=${UTCData}, UTCMs=${UTCMs}`
17051
17247
  );
17052
17248
  let org = "";
17053
17249
  try {
@@ -17055,7 +17251,7 @@ function useDahuaService() {
17055
17251
  org = theSite?.orgId.toString() || "unknown";
17056
17252
  } catch (error) {
17057
17253
  loggerDahua.error(
17058
- `[${site}][${gate}] Error fetching site for orgId:`,
17254
+ `[${host}] Error fetching site for orgId:`,
17059
17255
  error
17060
17256
  );
17061
17257
  }
@@ -17075,7 +17271,7 @@ function useDahuaService() {
17075
17271
  }
17076
17272
  } catch (error) {
17077
17273
  loggerDahua.error(
17078
- `[${site}][${gate}] Error closing existing open transaction:`,
17274
+ `[${host}] Error closing existing open transaction:`,
17079
17275
  error
17080
17276
  );
17081
17277
  }
@@ -17125,9 +17321,13 @@ function useDahuaService() {
17125
17321
  }
17126
17322
  try {
17127
17323
  await addPlateNumber(dahuaPayload);
17128
- const transactionId = await add(visitorTransaction);
17129
- currentTransactionId = transactionId.toString();
17324
+ const result = await add(visitorTransaction, void 0, true);
17325
+ const transactionId = result?._id;
17326
+ currentTransactionId = transactionId?.toString();
17130
17327
  currentSnapshotField = "snapshotEntryImage";
17328
+ if (onDetected2) {
17329
+ onDetected2({ _id: transactionId, site: result?.site?.toString(), plateNumber: result.plateNumber });
17330
+ }
17131
17331
  } catch (error) {
17132
17332
  console.log("failed to create visitor transaction", error);
17133
17333
  loggerDahua.error(
@@ -17161,7 +17361,7 @@ function useDahuaService() {
17161
17361
  }
17162
17362
  }
17163
17363
  }
17164
- async function handleBuffer(chunk) {
17364
+ async function handleBuffer(chunk, onDetected2) {
17165
17365
  partialBuffer = Buffer.concat([partialBuffer, chunk]);
17166
17366
  while (true) {
17167
17367
  const boundaryIndex = partialBuffer.indexOf(Buffer.from(boundary));
@@ -17187,7 +17387,7 @@ function useDahuaService() {
17187
17387
  direction = line.split("=")[1].trim();
17188
17388
  });
17189
17389
  if (plateNumber && UTCData) {
17190
- await processVehicleTransaction();
17390
+ await processVehicleTransaction(onDetected2);
17191
17391
  }
17192
17392
  } else if (part.includes("Content-Type: image/jpeg")) {
17193
17393
  const [headers, ...imageParts] = part.split("\r\n\r\n");
@@ -17214,7 +17414,7 @@ function useDahuaService() {
17214
17414
  try {
17215
17415
  await fsAsync.mkdir(dir, { recursive: true });
17216
17416
  await fsAsync.writeFile(snapFolder, accumulatedImageBuffer);
17217
- loggerDahua.debug(`[${site}][${gate}] Saved image locally: ${filename}`);
17417
+ loggerDahua.debug(`[${host}] Saved image locally: ${filename}`);
17218
17418
  const fileId = await _createFile(
17219
17419
  {
17220
17420
  originalname: filename,
@@ -17224,7 +17424,7 @@ function useDahuaService() {
17224
17424
  `anpr/${site}`
17225
17425
  );
17226
17426
  loggerDahua.info(
17227
- `[${site}][${gate}] Created file record for image: ${fileId.toString()}`
17427
+ `[${host}] Created file record for image: ${fileId.toString()}`
17228
17428
  );
17229
17429
  if (currentTransactionId && currentSnapshotField) {
17230
17430
  await updateById(currentTransactionId, {
@@ -17232,23 +17432,23 @@ function useDahuaService() {
17232
17432
  });
17233
17433
  }
17234
17434
  loggerDahua.info(
17235
- `[${site}][${gate}] Image stored with fileId: ${fileId.toString()}`
17435
+ `[${host}] Image stored with fileId: ${fileId.toString()}`
17236
17436
  );
17237
17437
  await fsAsync.unlink(snapFolder);
17238
- loggerDahua.debug(`[${site}][${gate}] Deleted local file: ${filename}`);
17438
+ loggerDahua.info(`[${host}] Deleted local file: ${filename}`);
17239
17439
  } catch (err) {
17240
17440
  loggerDahua.error(
17241
- `[${site}][${gate}] Failed to process image ${filename}:`,
17441
+ `[${host}] Failed to process image ${filename}:`,
17242
17442
  err
17243
17443
  );
17244
17444
  try {
17245
17445
  await fsAsync.unlink(snapFolder);
17246
- loggerDahua.debug(
17247
- `[${site}][${gate}] Cleaned up local file after error: ${filename}`
17446
+ loggerDahua.error(
17447
+ `[${host}] Cleaned up local file after error: ${filename}`
17248
17448
  );
17249
17449
  } catch (unlinkErr) {
17250
17450
  loggerDahua.error(
17251
- `[${site}][${gate}] Failed to clean up local file: ${filename}`,
17451
+ `[${host}] Failed to clean up local file: ${filename}`,
17252
17452
  unlinkErr
17253
17453
  );
17254
17454
  }
@@ -17288,7 +17488,7 @@ function useDahuaService() {
17288
17488
  throw error;
17289
17489
  }
17290
17490
  }
17291
- async function listenToCamera(camera) {
17491
+ async function listenToCamera(camera, onDetected) {
17292
17492
  if (!camera?._id) {
17293
17493
  loggerDahua.error(`Camera _id is required to listen to camera.`);
17294
17494
  throw new BadRequestError73("Camera _id is required to listen to camera.");
@@ -17309,10 +17509,11 @@ function useDahuaService() {
17309
17509
  `guard-post-${camera.guardPost}`,
17310
17510
  camera.direction,
17311
17511
  cameraId,
17312
- controller.signal
17512
+ controller.signal,
17513
+ onDetected
17313
17514
  );
17314
17515
  }
17315
- async function getTrafficJunction(host = "", username = "", password = "", site = "", gate = "", designation = "", cameraId, signal) {
17516
+ async function getTrafficJunctionOld(host = "", username = "", password = "", site = "", gate = "", designation = "", cameraId, signal, onDetected) {
17316
17517
  if (signal.aborted)
17317
17518
  return;
17318
17519
  try {
@@ -17335,7 +17536,8 @@ function useDahuaService() {
17335
17536
  designation,
17336
17537
  host,
17337
17538
  username,
17338
- password
17539
+ password,
17540
+ onDetected
17339
17541
  );
17340
17542
  bufferQueue.setStream(response.res);
17341
17543
  const onAbort = () => {
@@ -17389,7 +17591,7 @@ function useDahuaService() {
17389
17591
  await new Promise((res) => setTimeout(res, 5e3));
17390
17592
  if (signal.aborted)
17391
17593
  return;
17392
- getTrafficJunction(host, username, password, site, gate, designation, cameraId, signal);
17594
+ getTrafficJunction(host, username, password, site, gate, designation, cameraId, signal, onDetected);
17393
17595
  };
17394
17596
  response.res.on(
17395
17597
  "end",
@@ -17413,8 +17615,87 @@ function useDahuaService() {
17413
17615
  await new Promise((res) => setTimeout(res, 5e3));
17414
17616
  if (signal.aborted)
17415
17617
  return;
17416
- getTrafficJunction(host, username, password, site, gate, designation, cameraId, signal);
17618
+ getTrafficJunction(host, username, password, site, gate, designation, cameraId, signal, onDetected);
17619
+ }
17620
+ }
17621
+ async function getTrafficJunction(host = "", username = "", password = "", site = "", gate = "", designation = "", cameraId, signal, onDetected) {
17622
+ while (!signal.aborted) {
17623
+ let bufferQueue = null;
17624
+ let response = null;
17625
+ try {
17626
+ response = await useDahuaDigest({
17627
+ host,
17628
+ username,
17629
+ password,
17630
+ endpoint: "/cgi-bin/snapManager.cgi?action=attachFileProc&channel=1&heartbeat=5&Flags[0]=Event&Events=[TrafficJunction]",
17631
+ timeout: 2e4,
17632
+ streaming: true
17633
+ });
17634
+ if ([400, 401, 403, 500].includes(response.statusCode)) {
17635
+ loggerDahua.error(`[${host}] Connection error: ${response.statusCode}`);
17636
+ throw new Error(`Failed to connect to ANPR: ${response.statusCode}`);
17637
+ }
17638
+ loggerDahua.info(`[${host}] Successfully connected to ANPR.`);
17639
+ const contentType = response.res.headers["content-type"];
17640
+ const boundaryMatch = contentType?.match(/boundary=(.*)$/i);
17641
+ const boundary = boundaryMatch ? `--${boundaryMatch[1]}` : "--myboundary";
17642
+ bufferQueue = useBufferQueue(
17643
+ boundary,
17644
+ site,
17645
+ gate,
17646
+ designation,
17647
+ host,
17648
+ username,
17649
+ password,
17650
+ onDetected
17651
+ );
17652
+ bufferQueue.setStream(response.res);
17653
+ await new Promise((resolve, reject) => {
17654
+ const onAbort = () => {
17655
+ loggerDahua.info(`[${site}]-[${host}] Abort triggered. Cleaning up...`);
17656
+ if (response.res && !response.res.destroyed) {
17657
+ response.res.destroy();
17658
+ }
17659
+ resolve("aborted");
17660
+ };
17661
+ signal.addEventListener("abort", onAbort, { once: true });
17662
+ response.res.on("data", (chunk) => {
17663
+ if (signal.aborted) {
17664
+ response.res.destroy();
17665
+ return;
17666
+ }
17667
+ bufferQueue.enqueue(chunk);
17668
+ });
17669
+ response.res.on("end", () => {
17670
+ signal.removeEventListener("abort", onAbort);
17671
+ resolve("ended");
17672
+ });
17673
+ response.res.on("close", () => {
17674
+ signal.removeEventListener("abort", onAbort);
17675
+ resolve("closed");
17676
+ });
17677
+ response.res.on("error", (err) => {
17678
+ signal.removeEventListener("abort", onAbort);
17679
+ reject(err);
17680
+ });
17681
+ });
17682
+ } catch (error) {
17683
+ if (signal.aborted)
17684
+ break;
17685
+ loggerDahua.error(
17686
+ `[${host}] Connection lost or error: ${error.message || error}. Retrying in 5s...`
17687
+ );
17688
+ } finally {
17689
+ if (bufferQueue?.destroy)
17690
+ bufferQueue.destroy();
17691
+ if (response?.res && !response.res.destroyed)
17692
+ response.res.destroy();
17693
+ }
17694
+ if (!signal.aborted) {
17695
+ await new Promise((res) => setTimeout(res, 5e3));
17696
+ }
17417
17697
  }
17698
+ loggerDahua.info(`[${host}] ANPR Listener stopped.`);
17418
17699
  }
17419
17700
  async function addPlateNumber(value) {
17420
17701
  const validation = Joi40.object({
@@ -19545,7 +19826,7 @@ function useVehicleController() {
19545
19826
  next(new BadRequestError84("Spreadsheet file is required."));
19546
19827
  return;
19547
19828
  }
19548
- const { originalname, path: path5 } = req.file;
19829
+ const { originalname, path: path4 } = req.file;
19549
19830
  const lowerName = originalname.toLowerCase();
19550
19831
  const rowSchema = Joi46.object({
19551
19832
  fullName: Joi46.string().trim().required(),
@@ -19584,7 +19865,7 @@ function useVehicleController() {
19584
19865
  let rows = [];
19585
19866
  if (lowerName.endsWith(".xlsx") || lowerName.endsWith(".xls")) {
19586
19867
  const workbook = new ExcelJS.Workbook();
19587
- await workbook.xlsx.readFile(path5);
19868
+ await workbook.xlsx.readFile(path4);
19588
19869
  const worksheet = workbook.worksheets[0];
19589
19870
  if (!worksheet) {
19590
19871
  next(
@@ -19610,7 +19891,7 @@ function useVehicleController() {
19610
19891
  } else if (lowerName.endsWith(".csv")) {
19611
19892
  rows = await new Promise((resolve, reject) => {
19612
19893
  const parsed = [];
19613
- fs.createReadStream(path5).pipe(csv()).on("data", (row) => parsed.push(row)).on("end", () => resolve(parsed)).on("error", reject);
19894
+ fs.createReadStream(path4).pipe(csv()).on("data", (row) => parsed.push(row)).on("end", () => resolve(parsed)).on("error", reject);
19614
19895
  });
19615
19896
  } else {
19616
19897
  next(
@@ -19649,7 +19930,7 @@ function useVehicleController() {
19649
19930
  validationErrors: invalidRows,
19650
19931
  data
19651
19932
  });
19652
- fs.unlink(path5, () => {
19933
+ fs.unlink(path4, () => {
19653
19934
  });
19654
19935
  } catch (error) {
19655
19936
  logger65.log({ level: "error", message: error.message });
@@ -19790,7 +20071,9 @@ function useVehicleController() {
19790
20071
  start: Joi46.string().isoDate().optional().allow(null, ""),
19791
20072
  end: Joi46.string().isoDate().optional().allow(null, ""),
19792
20073
  recNo: Joi46.string().optional().allow(null, ""),
19793
- type: Joi46.string().optional().valid(...Object.values(VehicleType)).allow(null, "")
20074
+ type: Joi46.string().optional().valid(...Object.values(VehicleType)).allow(null, ""),
20075
+ peopleId: Joi46.string().hex().length(24).optional().allow(null, ""),
20076
+ seasonPassType: Joi46.string().optional().allow("", null)
19794
20077
  });
19795
20078
  const { error, value } = schema2.validate(
19796
20079
  {
@@ -20027,7 +20310,7 @@ function useSiteCameraService() {
20027
20310
  session.endSession();
20028
20311
  }
20029
20312
  }
20030
- async function listenToCapturedPlateNumber() {
20313
+ async function listenToCapturedPlateNumber(onDetected) {
20031
20314
  const siteCameras = [];
20032
20315
  let page = 1;
20033
20316
  let pages = 1;
@@ -20048,7 +20331,7 @@ function useSiteCameraService() {
20048
20331
  for (let index = 0; index < siteCameras.length; index++) {
20049
20332
  const siteCamera = siteCameras[index];
20050
20333
  if (siteCamera && siteCamera.status === "active" && siteCamera.host && siteCamera.username && siteCamera.password && siteCamera.site && siteCamera.guardPost) {
20051
- dahuaService.listenToCamera(siteCamera);
20334
+ dahuaService.listenToCamera(siteCamera, onDetected);
20052
20335
  }
20053
20336
  }
20054
20337
  }
@@ -24102,7 +24385,6 @@ import {
24102
24385
  compileHandlebar as compileHandlebar3,
24103
24386
  getDirectory as getDirectory3
24104
24387
  } from "@7365admin1/node-server-utils";
24105
- import path2 from "path";
24106
24388
  function usePersonService() {
24107
24389
  const MailerConfig = {
24108
24390
  host: MAILER_TRANSPORT_HOST,
@@ -24317,13 +24599,8 @@ function usePersonService() {
24317
24599
  value.status = "active";
24318
24600
  }
24319
24601
  await _reviewResidentPerson(id, value, session);
24320
- const logoPath = path2.join(
24321
- __dirname,
24322
- "public",
24323
- "images",
24324
- "seven-365.svg"
24325
- );
24326
- const statusIconPath = path2.join(__dirname, "public", "icons");
24602
+ const logoPath = `${STORAGE_API}/seven-365.svg`;
24603
+ const statusIconPath = STORAGE_API;
24327
24604
  let title = "";
24328
24605
  let message2 = "";
24329
24606
  let hideLogin = true;
@@ -25223,11 +25500,7 @@ function usePatrolQuestionRepo() {
25223
25500
  const { delNamespace, getCache, setCache } = useCache34(namespace_collection);
25224
25501
  async function createIndexes() {
25225
25502
  try {
25226
- await collection.createIndexes([
25227
- {
25228
- key: { site: 1 }
25229
- }
25230
- ]);
25503
+ await collection.createIndexes([{ key: { site: 1, status: 1 } }]);
25231
25504
  return `Successfully created indexes for ${namespace_collection}.`;
25232
25505
  } catch (error) {
25233
25506
  logger87.log({
@@ -25672,6 +25945,24 @@ function usePatrolRouteRepo() {
25672
25945
  const namespace_collection = "patrol.route";
25673
25946
  const collection = db.collection(namespace_collection);
25674
25947
  const { delNamespace, getCache, setCache } = useCache35(namespace_collection);
25948
+ async function createIndexes() {
25949
+ try {
25950
+ await collection.createIndexes([
25951
+ { key: { site: 1, status: 1 } },
25952
+ { key: { site: 1, repeat: 1 } },
25953
+ { key: { assignee: 1 } }
25954
+ ]);
25955
+ return `Successfully created indexes for ${namespace_collection}.`;
25956
+ } catch (error) {
25957
+ logger90.log({
25958
+ level: "error",
25959
+ message: error.message
25960
+ });
25961
+ throw new InternalServerError36(
25962
+ "Failed to create general indexes on patrol routes."
25963
+ );
25964
+ }
25965
+ }
25675
25966
  async function createTextIndex() {
25676
25967
  try {
25677
25968
  await collection.createIndex({
@@ -26045,7 +26336,8 @@ function usePatrolRouteRepo() {
26045
26336
  updateById,
26046
26337
  deleteById,
26047
26338
  getScheduledRoute,
26048
- getById
26339
+ getById,
26340
+ createIndexes
26049
26341
  };
26050
26342
  }
26051
26343
 
@@ -26392,9 +26684,8 @@ function usePatrolLogRepo() {
26392
26684
  async function createIndexes() {
26393
26685
  try {
26394
26686
  await collection.createIndexes([
26395
- {
26396
- key: { site: 1 }
26397
- }
26687
+ { key: { site: 1, createdAt: -1 } },
26688
+ { key: { assignee: 1 } }
26398
26689
  ]);
26399
26690
  return `Successfully created indexes for ${namespace_collection}.`;
26400
26691
  } catch (error) {
@@ -30285,6 +30576,20 @@ function useSiteBillingItemRepo() {
30285
30576
  const namespace_collection = "site.billing.items";
30286
30577
  const collection = db.collection(namespace_collection);
30287
30578
  const { delNamespace, setCache, getCache } = useCache42(namespace_collection);
30579
+ async function createIndexes() {
30580
+ try {
30581
+ await collection.createIndexes([{ key: { site: 1, status: 1 } }]);
30582
+ return `Successfully created indexes for ${namespace_collection}.`;
30583
+ } catch (error) {
30584
+ logger107.log({
30585
+ level: "error",
30586
+ message: error.message
30587
+ });
30588
+ throw new InternalServerError43(
30589
+ "Failed to create general indexes on billing item."
30590
+ );
30591
+ }
30592
+ }
30288
30593
  async function createTextIndex() {
30289
30594
  try {
30290
30595
  await collection.createIndex({
@@ -30504,7 +30809,8 @@ function useSiteBillingItemRepo() {
30504
30809
  getAll,
30505
30810
  getById,
30506
30811
  updateById,
30507
- deleteById
30812
+ deleteById,
30813
+ createIndexes
30508
30814
  };
30509
30815
  }
30510
30816
 
@@ -30658,6 +30964,20 @@ function useSiteBillingConfigurationRepo() {
30658
30964
  const namespace_collection = "site.billing.configuration";
30659
30965
  const collection = db.collection(namespace_collection);
30660
30966
  const { delNamespace, setCache, getCache } = useCache43(namespace_collection);
30967
+ async function createIndexes() {
30968
+ try {
30969
+ await collection.createIndexes([{ key: { site: 1, status: 1 } }]);
30970
+ return `Successfully created indexes for ${namespace_collection}.`;
30971
+ } catch (error) {
30972
+ logger109.log({
30973
+ level: "error",
30974
+ message: error.message
30975
+ });
30976
+ throw new InternalServerError44(
30977
+ "Failed to create general indexes on billing configuration."
30978
+ );
30979
+ }
30980
+ }
30661
30981
  async function createTextIndex() {
30662
30982
  try {
30663
30983
  await collection.createIndex({
@@ -30867,7 +31187,8 @@ function useSiteBillingConfigurationRepo() {
30867
31187
  getAll,
30868
31188
  getById,
30869
31189
  updateById,
30870
- deleteById
31190
+ deleteById,
31191
+ createIndexes
30871
31192
  };
30872
31193
  }
30873
31194
 
@@ -31929,9 +32250,8 @@ function useEventManagementController() {
31929
32250
  }
31930
32251
  }
31931
32252
  async function updateEventManagementById(req, res, next) {
31932
- const _id = req.params.id;
31933
- const payload = { _id, ...req.body };
31934
- const { error } = schemaUpdateEventManagement.validate(payload, {
32253
+ const payload = { _id: req.params.id, ...req.body };
32254
+ const { error, value } = schemaUpdateEventManagement.validate(payload, {
31935
32255
  abortEarly: false
31936
32256
  });
31937
32257
  if (error) {
@@ -31940,8 +32260,9 @@ function useEventManagementController() {
31940
32260
  next(new BadRequestError137(messages));
31941
32261
  return;
31942
32262
  }
32263
+ const { _id, ...rest } = value;
31943
32264
  try {
31944
- const result = await _updateEventManagementById(_id, req.body);
32265
+ const result = await _updateEventManagementById(_id, rest);
31945
32266
  res.status(200).json({ message: result });
31946
32267
  return;
31947
32268
  } catch (error2) {
@@ -32170,6 +32491,25 @@ function useSiteUnitBillingRepo() {
32170
32491
  const namespace_collection = "site.unit.billing";
32171
32492
  const collection = db.collection(namespace_collection);
32172
32493
  const { delNamespace, setCache, getCache } = useCache45(namespace_collection);
32494
+ async function createIndexes() {
32495
+ try {
32496
+ await collection.createIndexes([
32497
+ { key: { site: 1, status: 1, paymentStatus: 1 } },
32498
+ { key: { site: 1, unitId: 1, status: 1, paymentStatus: 1 } },
32499
+ { key: { site: 1, unitId: 1, issueDate: 1 } },
32500
+ { key: { createdAt: -1 } }
32501
+ ]);
32502
+ return `Successfully created indexes for ${namespace_collection}.`;
32503
+ } catch (error) {
32504
+ logger117.log({
32505
+ level: "error",
32506
+ message: error.message
32507
+ });
32508
+ throw new InternalServerError46(
32509
+ "Failed to create general indexes on unit billing."
32510
+ );
32511
+ }
32512
+ }
32173
32513
  async function createTextIndex() {
32174
32514
  try {
32175
32515
  await collection.createIndex({
@@ -32723,7 +33063,8 @@ function useSiteUnitBillingRepo() {
32723
33063
  deleteById,
32724
33064
  getUnitBillingBySite,
32725
33065
  getResidentUserBilling,
32726
- getResidentUserUnsettledBilling
33066
+ getResidentUserUnsettledBilling,
33067
+ createIndexes
32727
33068
  };
32728
33069
  }
32729
33070
 
@@ -33286,7 +33627,7 @@ import { ObjectId as ObjectId90 } from "mongodb";
33286
33627
 
33287
33628
  // src/utils/access-management.ts
33288
33629
  import fs2 from "fs";
33289
- import path3 from "path";
33630
+ import path2 from "path";
33290
33631
  import axios from "axios";
33291
33632
  import { parseStringPromise } from "xml2js";
33292
33633
  import crypto from "crypto";
@@ -33316,7 +33657,7 @@ var minifyXml = (xml) => {
33316
33657
  };
33317
33658
  var readTemplate = (name, params) => {
33318
33659
  const template = fs2.readFileSync(
33319
- path3.join(__dirname, `../dist/public/xml-templates/${name}.xml`),
33660
+ path2.join(__dirname, `../dist/public/xml-templates/${name}.xml`),
33320
33661
  "utf-8"
33321
33662
  );
33322
33663
  if (!params)
@@ -33447,9 +33788,9 @@ import { parseStringPromise as parseStringPromise2 } from "xml2js";
33447
33788
  // src/utils/rsa-encryption.ts
33448
33789
  import * as crypto2 from "crypto";
33449
33790
  import fs3 from "fs";
33450
- import path4 from "path";
33451
- var pub = path4.resolve(process.cwd(), "./src/public/rsa-keys/new_rsa_512_pub.pem");
33452
- var priv = path4.resolve(process.cwd(), "./src/public/rsa-keys/new_rsa_512_priv.pem");
33791
+ import path3 from "path";
33792
+ var pub = path3.resolve(process.cwd(), "./src/public/rsa-keys/new_rsa_512_pub.pem");
33793
+ var priv = path3.resolve(process.cwd(), "./src/public/rsa-keys/new_rsa_512_priv.pem");
33453
33794
  var EncryptionCredentials = class {
33454
33795
  };
33455
33796
  EncryptionCredentials.RAW_PUBLIC_KEY = fs3.readFileSync(pub, "utf8");
@@ -38581,6 +38922,22 @@ function useStatementOfAccountRepo() {
38581
38922
  const namespace_collection = "site.statement-of-accounts";
38582
38923
  const collection = db.collection(namespace_collection);
38583
38924
  const { delNamespace, getCache, setCache } = useCache50(namespace_collection);
38925
+ async function createIndexes() {
38926
+ try {
38927
+ await collection.createIndexes([
38928
+ { key: { site: 1, status: 1 } },
38929
+ { key: { site: 1, unitId: 1, status: 1 } },
38930
+ { key: { createdAt: -1 } }
38931
+ ]);
38932
+ return `Successfully created indexes for ${namespace_collection}.`;
38933
+ } catch (error) {
38934
+ logger128.log({
38935
+ level: "error",
38936
+ message: error.message
38937
+ });
38938
+ throw new InternalServerError51("Failed to create general indexes on SOA.");
38939
+ }
38940
+ }
38584
38941
  async function createTextIndex() {
38585
38942
  try {
38586
38943
  await collection.createIndex({
@@ -38931,7 +39288,8 @@ function useStatementOfAccountRepo() {
38931
39288
  deleteById,
38932
39289
  updateStatusById,
38933
39290
  getResidentUserSoa,
38934
- reviewSOA
39291
+ reviewSOA,
39292
+ createIndexes
38935
39293
  };
38936
39294
  }
38937
39295
 
@@ -42556,7 +42914,10 @@ function useOccurrenceEntryService() {
42556
42914
  updateOccurrenceEntryById: _updateOccurrenceEntryById,
42557
42915
  getOccurrenceEntryById: _getOccurrenceEntryById,
42558
42916
  getOccurrenceEntryByBookId: _getOccurrenceEntryByBookId,
42559
- updateOccurrenceEntryByBookId: _updateOccurrenceEntryByBookId
42917
+ updateOccurrenceEntryByBookId: _updateOccurrenceEntryByBookId,
42918
+ deleteOccurrenceEntryById: _deleteOccurrenceEntryById,
42919
+ getLatestSerialNumber: _getLatestSerialNumber,
42920
+ getLatestSerialNumberInGroup: _getLatestSerialNumberInGroup
42560
42921
  } = useOccurrenceEntryRepo();
42561
42922
  const {
42562
42923
  getOccurrenceBookById: _getOccurrenceBookById,
@@ -42608,8 +42969,20 @@ function useOccurrenceEntryService() {
42608
42969
  if (!occurrenceEntry) {
42609
42970
  throw new Error("Occurrence entry not found.");
42610
42971
  }
42611
- const entrySerialNumber = Number(occurrenceEntry.serialNumber);
42612
- const updatedSerialNumber = (entrySerialNumber + 0.1).toFixed(1);
42972
+ const entryCount = await _getLatestSerialNumberInGroup(
42973
+ occurrenceEntry.dailyOccurrenceBookId,
42974
+ Number(occurrenceEntry.serialNumber)
42975
+ );
42976
+ const currentSerial = Number(occurrenceEntry.serialNumber);
42977
+ const latestSerial = Number(entryCount);
42978
+ const currentGroup = Math.floor(currentSerial);
42979
+ const latestGroup = Math.floor(latestSerial);
42980
+ let updatedSerialNumber;
42981
+ if (currentGroup === latestGroup) {
42982
+ updatedSerialNumber = (latestSerial + 0.1).toFixed(1);
42983
+ } else {
42984
+ updatedSerialNumber = (currentSerial + 0.1).toFixed(1);
42985
+ }
42613
42986
  const dobId = occurrenceEntry.dailyOccurrenceBookId;
42614
42987
  const book = await _getOccurrenceBookById(dobId);
42615
42988
  const subject = await _getOccurrenceSubjectById(
@@ -44659,14 +45032,15 @@ async function hrmLabsAuthentication({
44659
45032
  showPassword: false
44660
45033
  },
44661
45034
  {
44662
- headers: { "Content-Type": "application/json" }
45035
+ headers: { "Content-Type": "application/json" },
45036
+ validateStatus: () => true
44663
45037
  }
44664
45038
  );
44665
45039
  if (res.data?.success && res.data.data?.token) {
44666
45040
  return res.data.data.token;
44667
45041
  }
44668
45042
  throw new Error(
44669
- "HRMLabs Authentication failed. Please check your credentials."
45043
+ res.status === 401 || res.status === 403 ? "HRMLabs Authentication failed. Please check your credentials." : `HRMLabs Authentication failed with status ${res.status}.`
44670
45044
  );
44671
45045
  }
44672
45046
  async function fetchAttendanceData({
@@ -45103,7 +45477,9 @@ function useManpowerMonitoringRepo() {
45103
45477
  {
45104
45478
  key: { siteId: 1 }
45105
45479
  },
45106
- { key: { createdAt: 1 } }
45480
+ { key: { createdAt: 1 } },
45481
+ { key: { siteId: 1, serviceProviderId: 1 } },
45482
+ { key: { siteName: 1 } }
45107
45483
  ]);
45108
45484
  return `Successfully created indexes for ${namespace_collection}.`;
45109
45485
  } catch (error) {
@@ -45372,7 +45748,9 @@ function useManpowerRemarksRepo() {
45372
45748
  {
45373
45749
  key: { siteId: 1 }
45374
45750
  },
45375
- { key: { createdAt: 1 } }
45751
+ { key: { createdAt: 1 } },
45752
+ { key: { siteId: 1, serviceProviderId: 1, createdAtSGT: 1 } },
45753
+ { key: { serviceProviderId: 1, status: 1, createdAtSGT: 1 } }
45376
45754
  ]);
45377
45755
  return `Successfully created indexes for ${namespace_collection}.`;
45378
45756
  } catch (error) {
@@ -45805,7 +46183,8 @@ function useManpowerDesignationRepo() {
45805
46183
  {
45806
46184
  key: { siteId: 1 }
45807
46185
  },
45808
- { key: { createdAt: 1 } }
46186
+ { key: { createdAt: 1 } },
46187
+ { key: { siteId: 1, serviceProviderId: 1 } }
45809
46188
  ]);
45810
46189
  return `Successfully created indexes for ${namespace_collection}.`;
45811
46190
  } catch (error) {
@@ -46890,7 +47269,7 @@ function useHrmLabsAttendanceSrvc() {
46890
47269
  } catch (error) {
46891
47270
  logger168.error(error.message || error);
46892
47271
  console.log("Error fetching attendance data:", error);
46893
- throw new Error(error?.message || "Internal Server Error!");
47272
+ return { success: false, message: error?.message || "Internal Server Error!", items: [], pages: 0, pageRange: "0-0 of 0", count: {} };
46894
47273
  }
46895
47274
  }
46896
47275
  async function getAttendanceDataCount(payload) {
@@ -47004,7 +47383,7 @@ function useHrmLabsAttendanceSrvc() {
47004
47383
  } catch (error) {
47005
47384
  logger168.error(error.message || error);
47006
47385
  console.log("Error fetching attendance data count:", error);
47007
- throw new Error(error?.message || "Internal Server Error!");
47386
+ return { success: false, message: error?.message || "Internal Server Error!", totalCount: null };
47008
47387
  }
47009
47388
  }
47010
47389
  async function getAllAttendance(payload) {
@@ -47176,7 +47555,7 @@ function useHrmLabsAttendanceSrvc() {
47176
47555
  } catch (error) {
47177
47556
  logger168.error(error.message || error);
47178
47557
  console.log("Error fetching attendance data:", error);
47179
- throw new Error(error?.message || "Internal Server Error!");
47558
+ return { success: false, message: error?.message || "Internal Server Error!", items: [], count: {}, countPerJobTitle: {}, totalCount: null, countPerStatus: {} };
47180
47559
  }
47181
47560
  }
47182
47561
  async function getChartAttendanceData(payload) {
@@ -47283,7 +47662,7 @@ function useHrmLabsAttendanceSrvc() {
47283
47662
  } catch (error) {
47284
47663
  logger168.error(error.message || error);
47285
47664
  console.log("Error fetching attendance data:", error);
47286
- throw new Error(error?.message || "Internal Server Error!");
47665
+ return { success: false, message: error?.message || "Internal Server Error!", chartCount: null };
47287
47666
  }
47288
47667
  }
47289
47668
  return {
@@ -48941,7 +49320,8 @@ function useVerificationServiceV2() {
48941
49320
  add: _add,
48942
49321
  updateVerificationStatusById: _updateVerificationStatusById,
48943
49322
  getByVerificationCode: _getByVerificationCode,
48944
- updateStatusById: _updateStatusById
49323
+ updateStatusById: _updateStatusById,
49324
+ countPendingOrgInvites: _countPendingOrgInvites
48945
49325
  } = useVerificationRepoV2();
48946
49326
  const {
48947
49327
  getUserByEmailStatus: _getUserByEmailStatus,
@@ -48949,6 +49329,8 @@ function useVerificationServiceV2() {
48949
49329
  } = useUserRepo();
48950
49330
  const { getById: getOrgById, getByEmail: _getByEmail } = useOrgRepo();
48951
49331
  const { getSiteById } = useSiteRepo();
49332
+ const { getByOrgId: _getSubscriptionByOrgId } = useSubscriptionRepo();
49333
+ const { countByOrg: _countMemberByOrg } = useMemberRepo();
48952
49334
  function errorByType(type, status) {
48953
49335
  if ((type === "user-invite" /* USER_INVITE */ || type === "member-invite" /* MEMBER_INVITE */ || type === "service-provider-invite" /* SERVICE_PROVIDER_INVITE */ || type === "service-provider-create-org" /* SERVICE_PROVIDER_CREATE_ORG */) && status === "expired" /* EXPIRED */) {
48954
49336
  throw new BadRequestError199(
@@ -49212,6 +49594,30 @@ function useVerificationServiceV2() {
49212
49594
  throw error2;
49213
49595
  }
49214
49596
  }
49597
+ async function createOrganizationInvite({
49598
+ email,
49599
+ metadata
49600
+ }) {
49601
+ const orgId = metadata.org?.toString() ?? "";
49602
+ if (!orgId) {
49603
+ throw new BadRequestError199("Organization is required.");
49604
+ }
49605
+ await getOrgById(orgId);
49606
+ const [subscription, memberCount, pendingInviteCount] = await Promise.all([
49607
+ _getSubscriptionByOrgId(orgId),
49608
+ _countMemberByOrg(orgId),
49609
+ _countPendingOrgInvites(orgId)
49610
+ ]);
49611
+ const maxSeats = subscription?.maxSeats ?? 0;
49612
+ if (!maxSeats) {
49613
+ throw new BadRequestError199("No seats configured for organization.");
49614
+ }
49615
+ const usedSeats = memberCount + pendingInviteCount;
49616
+ if (usedSeats >= maxSeats) {
49617
+ throw new BadRequestError199("No available seats for new invitation.");
49618
+ }
49619
+ return createUserInvite({ email, metadata });
49620
+ }
49215
49621
  async function createForgetPassword(email) {
49216
49622
  const value = {
49217
49623
  type: "forget-password" /* FORGET_PASSWORD */,
@@ -49262,6 +49668,7 @@ function useVerificationServiceV2() {
49262
49668
  signUp,
49263
49669
  verify,
49264
49670
  createUserInvite,
49671
+ createOrganizationInvite,
49265
49672
  createServiceProviderInvite,
49266
49673
  createForgetPassword,
49267
49674
  cancelUserInvitation
@@ -49275,6 +49682,7 @@ function useVerificationControllerV2() {
49275
49682
  const {
49276
49683
  verify: _verify,
49277
49684
  createUserInvite: _createUserInvite,
49685
+ createOrganizationInvite: _createOrganizationInvite,
49278
49686
  createServiceProviderInvite: _createServiceProviderInvite,
49279
49687
  createForgetPassword: _createForgetPassword,
49280
49688
  cancelUserInvitation: _cancelUserInvitation
@@ -49371,6 +49779,44 @@ function useVerificationControllerV2() {
49371
49779
  return;
49372
49780
  }
49373
49781
  }
49782
+ async function createOrganizationInvite(req, res, next) {
49783
+ const schema2 = Joi127.object({
49784
+ email: Joi127.string().email().lowercase().required(),
49785
+ role: Joi127.string().hex().length(24).required(),
49786
+ org: Joi127.string().hex().length(24).required(),
49787
+ app: Joi127.string().optional().allow("", null).default("organization"),
49788
+ name: Joi127.string().optional().allow("", null),
49789
+ siteId: Joi127.string().hex().length(24).optional().allow("", null),
49790
+ siteName: Joi127.string().optional().allow("", null)
49791
+ });
49792
+ const { error, value } = schema2.validate(req.body, { abortEarly: false });
49793
+ if (error) {
49794
+ const messages = error.details.map((d) => d.message).join(", ");
49795
+ logger178.log({ level: "error", message: messages });
49796
+ next(new BadRequestError200(messages));
49797
+ return;
49798
+ }
49799
+ try {
49800
+ const { email, app, role, name, org, siteId, siteName } = value;
49801
+ await _createOrganizationInvite({
49802
+ email,
49803
+ metadata: {
49804
+ app,
49805
+ role,
49806
+ name,
49807
+ org,
49808
+ siteId,
49809
+ siteName
49810
+ }
49811
+ });
49812
+ res.status(201).json({ message: "Successfully invited user." });
49813
+ return;
49814
+ } catch (error2) {
49815
+ logger178.log({ level: "error", message: `${error2.message}` });
49816
+ next(error2);
49817
+ return;
49818
+ }
49819
+ }
49374
49820
  async function createForgetPassword(req, res, next) {
49375
49821
  const schema2 = Joi127.object({
49376
49822
  email: Joi127.string().email().lowercase().required()
@@ -49456,6 +49902,7 @@ function useVerificationControllerV2() {
49456
49902
  return {
49457
49903
  verify,
49458
49904
  createUserInvite,
49905
+ createOrganizationInvite,
49459
49906
  createServiceProviderInvite,
49460
49907
  createForgetPassword,
49461
49908
  getVerifications,
@@ -51256,6 +51703,7 @@ export {
51256
51703
  vehicles_namespace_collection,
51257
51704
  visitors_namespace_collection,
51258
51705
  workOrderSchema,
51706
+ work_orders2_namespace_collection,
51259
51707
  work_orders_namespace_collection
51260
51708
  };
51261
51709
  //# sourceMappingURL=index.mjs.map