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 +8 -0
- package/lib/admin.js +3 -1
- package/lib/scheduler.js +40 -7
- package/package.json +1 -1
- package/plugin.json +1 -1
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
package/plugin.json
CHANGED