@7365admin1/core 3.34.1 → 3.34.3

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 CHANGED
@@ -1,5 +1,17 @@
1
1
  # @iservice365/core
2
2
 
3
+ ## 3.34.3
4
+
5
+ ### Patch Changes
6
+
7
+ - 195c268: Fix manpower alert email flood: dedupe daily remark creation per site, skip alerts for sites without recipient emails, send one alert per site per alert time, and enforce a configurable daily alert limit (MANPOWER_ALERT_DAILY_LIMIT, default 50)
8
+
9
+ ## 3.34.2
10
+
11
+ ### Patch Changes
12
+
13
+ - d81eaf1: Add request payload and response logging to the three invite endpoints (`createSimpleUserInvite`, `createSimpleMemberInvite`, `createServiceProviderInvite`) to diagnose reports of invites not sending. Logs at info level on success, and includes the payload alongside the existing error log on failure.
14
+
3
15
  ## 3.34.1
4
16
 
5
17
  ### Patch Changes
package/dist/index.js CHANGED
@@ -9208,6 +9208,9 @@ var MAILER_TRANSPORT_SECURE = process.env.MAILER_TRANSPORT_SECURE === "true";
9208
9208
  var MAILER_EMAIL = process.env.MAILER_EMAIL ?? "default@gmail.com";
9209
9209
  var MAILER_PASSWORD = process.env.MAILER_PASSWORD ?? "password";
9210
9210
  var MAILER_FROM_EMAIL = process.env.MAILER_FROM_EMAIL || void 0;
9211
+ var MANPOWER_ALERT_DAILY_LIMIT = Number(
9212
+ process.env.MANPOWER_ALERT_DAILY_LIMIT ?? 50
9213
+ );
9211
9214
  var ACCESS_TOKEN_SECRET = process.env.ACCESS_TOKEN_SECRET ?? "access_token_secret";
9212
9215
  var REFRESH_TOKEN_SECRET = process.env.REFRESH_TOKEN_SECRET ?? "refresh_token_secret";
9213
9216
  var ACCESS_TOKEN_EXPIRY = process.env.ACCESS_TOKEN_EXPIRY ?? "15s";
@@ -15062,6 +15065,10 @@ function useVerificationController() {
15062
15065
  }
15063
15066
  async function createSimpleUserInvite(req, res, next) {
15064
15067
  const payload = { ...req.body };
15068
+ import_node_server_utils32.logger.log({
15069
+ level: "info",
15070
+ message: `[invite/user] payload: ${JSON.stringify(payload)}`
15071
+ });
15065
15072
  const validation = import_joi16.default.object({
15066
15073
  email: import_joi16.default.string().email().required(),
15067
15074
  app: import_joi16.default.array().items(import_joi16.default.string()).min(1).required(),
@@ -15101,16 +15108,21 @@ function useVerificationController() {
15101
15108
  siteName
15102
15109
  }
15103
15110
  });
15104
- res.status(201).json({
15111
+ const responseBody = {
15105
15112
  message: "Successfully invited user.",
15106
15113
  totalInvites: verificationIds.length,
15107
15114
  verificationIds
15115
+ };
15116
+ import_node_server_utils32.logger.log({
15117
+ level: "info",
15118
+ message: `[invite/user] response: ${JSON.stringify(responseBody)}`
15108
15119
  });
15120
+ res.status(201).json(responseBody);
15109
15121
  return;
15110
15122
  } catch (error2) {
15111
15123
  import_node_server_utils32.logger.log({
15112
15124
  level: "error",
15113
- message: `${error2.message}`
15125
+ message: `[invite/user] error for payload ${JSON.stringify(payload)}: ${error2.message}`
15114
15126
  });
15115
15127
  next(error2);
15116
15128
  return;
@@ -15118,6 +15130,10 @@ function useVerificationController() {
15118
15130
  }
15119
15131
  async function createSimpleMemberInvite(req, res, next) {
15120
15132
  const payload = { ...req.body };
15133
+ import_node_server_utils32.logger.log({
15134
+ level: "info",
15135
+ message: `[invite/member] payload: ${JSON.stringify(payload)}`
15136
+ });
15121
15137
  const validation = import_joi16.default.object({
15122
15138
  email: import_joi16.default.string().email().required(),
15123
15139
  app: import_joi16.default.string().optional().allow("", null),
@@ -15155,14 +15171,19 @@ function useVerificationController() {
15155
15171
  siteName
15156
15172
  }
15157
15173
  });
15158
- res.status(201).json({
15174
+ const responseBody = {
15159
15175
  message: "Successfully invited member."
15176
+ };
15177
+ import_node_server_utils32.logger.log({
15178
+ level: "info",
15179
+ message: `[invite/member] response: ${JSON.stringify(responseBody)}`
15160
15180
  });
15181
+ res.status(201).json(responseBody);
15161
15182
  return;
15162
15183
  } catch (error2) {
15163
15184
  import_node_server_utils32.logger.log({
15164
15185
  level: "error",
15165
- message: `${error2.message}`
15186
+ message: `[invite/member] error for payload ${JSON.stringify(payload)}: ${error2.message}`
15166
15187
  });
15167
15188
  next(error2);
15168
15189
  return;
@@ -15170,6 +15191,10 @@ function useVerificationController() {
15170
15191
  }
15171
15192
  async function createServiceProviderInvite(req, res, next) {
15172
15193
  const payload = req.body;
15194
+ import_node_server_utils32.logger.log({
15195
+ level: "info",
15196
+ message: `[service-providers/invite] payload: ${JSON.stringify(payload)}`
15197
+ });
15173
15198
  const validation = import_joi16.default.object({
15174
15199
  email: import_joi16.default.string().email().required(),
15175
15200
  orgId: import_joi16.default.string().hex().required(),
@@ -15209,14 +15234,19 @@ function useVerificationController() {
15209
15234
  secure: true,
15210
15235
  maxAge: 4 * 60 * 60 * 1e3
15211
15236
  };
15212
- res.cookie("service-provider-email", email, cookieOptions).json({
15237
+ const responseBody = {
15213
15238
  message: "Successfully invited service provider."
15239
+ };
15240
+ import_node_server_utils32.logger.log({
15241
+ level: "info",
15242
+ message: `[service-providers/invite] response: ${JSON.stringify(responseBody)}`
15214
15243
  });
15244
+ res.cookie("service-provider-email", email, cookieOptions).json(responseBody);
15215
15245
  return;
15216
15246
  } catch (error2) {
15217
15247
  import_node_server_utils32.logger.log({
15218
15248
  level: "error",
15219
- message: `controller - ${error2.message}`
15249
+ message: `[service-providers/invite] error for payload ${JSON.stringify(payload)}: ${error2.message}`
15220
15250
  });
15221
15251
  next(error2);
15222
15252
  return;
@@ -63791,7 +63821,16 @@ var createManpowerRemarksDaily = async () => {
63791
63821
  serviceProviderId: servideProvider._id,
63792
63822
  status: "active"
63793
63823
  }).toArray();
63824
+ const existingToday = await remarks.find({ createdAtSGT: nowSGT.format("DD-MM-YYYY") }).project({ siteId: 1 }).toArray();
63825
+ const skipSiteIds = new Set(
63826
+ existingToday.map((doc) => doc.siteId.toString())
63827
+ );
63794
63828
  for (const site of remark) {
63829
+ const siteKey = site.siteId.toString();
63830
+ if (skipSiteIds.has(siteKey)) {
63831
+ continue;
63832
+ }
63833
+ skipSiteIds.add(siteKey);
63795
63834
  const existingRemark = await settings.findOne({
63796
63835
  siteId: site.siteId,
63797
63836
  enabled: true
@@ -63858,7 +63897,7 @@ var createManpowerRemarksDaily = async () => {
63858
63897
  }
63859
63898
  }
63860
63899
  if (items.length > 0) {
63861
- await remarks.insertMany(items);
63900
+ await remarks.insertMany(items, { ordered: false });
63862
63901
  }
63863
63902
  console.log("Daily manpower remarks created successfully.");
63864
63903
  } catch (error) {
@@ -63922,12 +63961,30 @@ var updateRemarksisAcknowledged = async () => {
63922
63961
  },
63923
63962
  { $set: { "remarks.2.remark.isAcknowledged": false } }
63924
63963
  );
63964
+ const { getCache, setCache } = (0, import_node_server_utils221.useCache)("manpower-alerts");
63965
+ const capKey = `manpower-alert-count:${nowSGT}`;
63966
+ let sentToday = await getCache(capKey) ?? 0;
63967
+ const emailedSites = /* @__PURE__ */ new Set();
63925
63968
  for (const id of updatedIds) {
63926
63969
  const doc = await remarks.findOne({ _id: id });
63970
+ const docSiteKey = doc?.siteId?.toString() ?? "";
63971
+ if (emailedSites.has(docSiteKey)) {
63972
+ continue;
63973
+ }
63927
63974
  const setting = await settings.findOne(
63928
63975
  { siteId: new import_mongodb131.ObjectId(doc?.siteId) },
63929
63976
  { projection: { emails: 1 } }
63930
63977
  );
63978
+ if (!setting?.emails?.length) {
63979
+ continue;
63980
+ }
63981
+ if (sentToday >= MANPOWER_ALERT_DAILY_LIMIT) {
63982
+ import_node_server_utils221.logger.log({
63983
+ level: "warn",
63984
+ message: `Manpower alert daily limit (${MANPOWER_ALERT_DAILY_LIMIT}) reached, skipping remaining alerts for ${nowSGT}`
63985
+ });
63986
+ break;
63987
+ }
63931
63988
  const payload = {
63932
63989
  startDate: doc?.createdAtSGT,
63933
63990
  endDate: doc?.createdAtSGT,
@@ -63968,6 +64025,9 @@ var updateRemarksisAcknowledged = async () => {
63968
64025
  expected,
63969
64026
  status: newStatus
63970
64027
  });
64028
+ emailedSites.add(docSiteKey);
64029
+ sentToday++;
64030
+ await setCache(capKey, sentToday, 86400);
63971
64031
  }
63972
64032
  } catch (error) {
63973
64033
  console.error("Error updating remarks:", error);