nodebb-plugin-onekite-calendar 2.0.26 → 2.0.28

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,13 @@
1
1
  # Changelog – calendar-onekite
2
2
 
3
+ ## 1.3.23
4
+ - Scheduler (paiement en attente) : correction de la garde "send-once" pour compatibilité avec tous les adaptateurs DB NodeBB (fallback si `db.setAdd` n'est pas disponible).
5
+ - Scheduler : les erreurs ne sont plus avalées silencieusement (logs `Scheduler error ...`).
6
+ - Fix : les **rappels de paiement**, l’**expiration automatique** et la **notification Discord d’annulation automatique** refonctionnent.
7
+
8
+ ## 1.3.22
9
+ - ACP / Comptabilisation : le nombre de **sorties gratuites** correspond maintenant au **nombre de matériels sortis** (une réservation pouvant contenir plusieurs matériels).
10
+
3
11
  ## 1.3.21
4
12
  - Comptabilisation : les **sorties gratuites annulées** ne sont plus comptées (elles sont exclues si `cancelledAt` est présent, même si le statut est resté `paid`).
5
13
 
package/lib/admin.js CHANGED
@@ -530,7 +530,9 @@ admin.getAccounting = async function (req, res) {
530
530
  const endDate = formatFR(r.end);
531
531
 
532
532
  if (isFree) {
533
- freeCount += 1;
533
+ // In accounting, "Sorties gratuites" should reflect the number of items actually taken out,
534
+ // not the number of reservation lines (a single reservation can include multiple items).
535
+ freeCount += Math.max(1, itemNames.length || 0);
534
536
  } else {
535
537
  paidCount += 1;
536
538
  grandTotal += total;
package/lib/scheduler.js CHANGED
@@ -10,6 +10,33 @@ const groups = require.main.require('./src/groups');
10
10
 
11
11
  let timer = null;
12
12
 
13
+ // Some NodeBB database adapters don't expose setAdd/setRemove helpers.
14
+ // Use a safe "add once" guard to avoid crashing the scheduler.
15
+ async function addOnce(key, value) {
16
+ const v = String(value);
17
+ if (!v) return false;
18
+
19
+ // Preferred atomic helper (Redis + some adapters)
20
+ if (typeof db.setAdd === 'function') {
21
+ try {
22
+ return !!(await db.setAdd(key, v));
23
+ } catch (e) {
24
+ // fall through
25
+ }
26
+ }
27
+
28
+ // Fallback: store a marker in an object map.
29
+ // Not perfectly atomic across clustered processes, but avoids a hard failure.
30
+ try {
31
+ const existing = await db.getObjectField(key, v);
32
+ if (existing) return false;
33
+ await db.setObjectField(key, v, 1);
34
+ return true;
35
+ } catch (e) {
36
+ return false;
37
+ }
38
+ }
39
+
13
40
  function getSetting(settings, key, fallback) {
14
41
  const v = settings && Object.prototype.hasOwnProperty.call(settings, key) ? settings[key] : undefined;
15
42
  if (v == null || v === '') return fallback;
@@ -163,7 +190,7 @@ async function expirePending() {
163
190
  // Reminder to validators while still pending
164
191
  if (validatorReminderMins > 0 && createdAt && now >= (createdAt + validatorReminderMins * 60 * 1000) && now < expiresAt) {
165
192
  const reminderKey = 'calendar-onekite:email:validatorReminder:pending';
166
- const first = await db.setAdd(reminderKey, rid);
193
+ const first = await addOnce(reminderKey, rid);
167
194
  if (first && validatorUids.length) {
168
195
  const requesterUid = parseInt(resv.uid, 10) || 0;
169
196
  const requester = requesterUid ? await user.getUserFields(requesterUid, ['username']) : null;
@@ -185,7 +212,7 @@ async function expirePending() {
185
212
  if (now > expiresAt) {
186
213
  // Expire (remove from calendar) + notify requester + validators
187
214
  const expiredKey = 'calendar-onekite:email:expiredSent:pending';
188
- const firstExpired = await db.setAdd(expiredKey, rid);
215
+ const firstExpired = await addOnce(expiredKey, rid);
189
216
 
190
217
  const requesterUid = parseInt(resv.uid, 10) || 0;
191
218
  const requester = requesterUid ? await user.getUserFields(requesterUid, ['username']) : null;
@@ -293,7 +320,7 @@ async function processAwaitingPayment() {
293
320
  if (!r.reminderSent && now >= reminderAt && now < expireAt) {
294
321
  // Send reminder once (guarded across clustered NodeBB processes)
295
322
  const reminderKey = 'calendar-onekite:email:reminderSent';
296
- const first = await db.setAdd(reminderKey, rid);
323
+ const first = await addOnce(reminderKey, rid);
297
324
  if (!first) {
298
325
  // another process already sent it
299
326
  r.reminderSent = true;
@@ -327,12 +354,12 @@ async function processAwaitingPayment() {
327
354
  // Expire: remove reservation so it disappears from calendar and frees items
328
355
  // Guard email send across clustered NodeBB processes
329
356
  const expiredKey = 'calendar-onekite:email:expiredSent';
330
- const firstExpired = await db.setAdd(expiredKey, rid);
357
+ const firstExpired = await addOnce(expiredKey, rid);
331
358
  const shouldEmail = !!firstExpired;
332
359
 
333
360
  // Guard Discord notification across clustered NodeBB processes
334
361
  const discordKey = 'calendar-onekite:discord:cancelledSent';
335
- const firstDiscord = await db.setAdd(discordKey, rid);
362
+ const firstDiscord = await addOnce(discordKey, rid);
336
363
  const shouldDiscord = !!firstDiscord;
337
364
 
338
365
  const toUid = parseInt(r.uid, 10);
@@ -394,8 +421,14 @@ async function processAwaitingPayment() {
394
421
  function start() {
395
422
  if (timer) return;
396
423
  timer = setInterval(() => {
397
- expirePending().catch(() => {});
398
- processAwaitingPayment().catch(() => {});
424
+ expirePending().catch((err) => {
425
+ // eslint-disable-next-line no-console
426
+ console.warn('[calendar-onekite] Scheduler error in expirePending', err && err.message ? err.message : err);
427
+ });
428
+ processAwaitingPayment().catch((err) => {
429
+ // eslint-disable-next-line no-console
430
+ console.warn('[calendar-onekite] Scheduler error in processAwaitingPayment', err && err.message ? err.message : err);
431
+ });
399
432
  }, 60 * 1000);
400
433
  }
401
434
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-onekite-calendar",
3
- "version": "2.0.26",
3
+ "version": "2.0.28",
4
4
  "description": "FullCalendar-based equipment reservation workflow with admin approval & HelloAsso payment for NodeBB",
5
5
  "main": "library.js",
6
6
  "license": "MIT",
package/plugin.json CHANGED
@@ -39,5 +39,5 @@
39
39
  "acpScripts": [
40
40
  "public/admin.js"
41
41
  ],
42
- "version": "2.0.26"
42
+ "version": "2.0.28"
43
43
  }