nodebb-plugin-onekite-calendar 2.0.76 → 2.0.77

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/lib/admin.js CHANGED
@@ -89,7 +89,6 @@ admin.approveReservation = async function (req, res) {
89
89
  r.pickupLat = String((req.body && req.body.pickupLat) || '').trim();
90
90
  r.pickupLon = String((req.body && req.body.pickupLon) || '').trim();
91
91
  r.approvedAt = Date.now();
92
- r.paymentDeferred = !!(req.body && req.body.paymentDeferred);
93
92
 
94
93
  try {
95
94
  const approver = await user.getUserFields(req.uid, ['username']);
package/lib/api.js CHANGED
@@ -1321,6 +1321,9 @@ api.createReservation = async function (req, res) {
1321
1321
 
1322
1322
  const isForSelf = (targetUid === uid);
1323
1323
 
1324
+ // Explicit regularization flag: admin records a payment directly (any date, any target)
1325
+ const isRegularization = !!isValidator && !!(req.body && req.body.isRegularization);
1326
+
1324
1327
  // Free only when validator creates for themselves with a future date (within configured maxDays)
1325
1328
  const validatorFreeMaxDays = (() => {
1326
1329
  try {
@@ -1328,10 +1331,17 @@ api.createReservation = async function (req, res) {
1328
1331
  return Number.isFinite(v) ? v : 0;
1329
1332
  } catch (e) { return 0; }
1330
1333
  })();
1331
- const isValidatorFree = !!isValidator && isForSelf && !isPastDate && (validatorFreeMaxDays <= 0 || nbDays <= validatorFreeMaxDays);
1334
+ const isValidatorFree = !!isValidator && !isRegularization && isForSelf && !isPastDate && (validatorFreeMaxDays <= 0 || nbDays <= validatorFreeMaxDays);
1335
+
1336
+ // Past-dated reservation for self → paid immediately (no checkbox needed)
1337
+ const isRegularizationSelf = !!isValidator && !isRegularization && isForSelf && isPastDate;
1338
+ // Past-dated reservation for a third party without explicit regularization → awaiting_payment
1339
+ const isRegularizationOther = !!isValidator && !isRegularization && !isForSelf && isPastDate;
1332
1340
 
1333
- // Regularization: past-dated reservation created by a validator → paid immediately with amount
1334
- const isRegularization = !!isValidator && isPastDate;
1341
+ const isAutoPaid = isValidatorFree || isRegularizationSelf || isRegularization;
1342
+ const resolvedStatus = isAutoPaid ? 'paid'
1343
+ : isRegularizationOther ? 'awaiting_payment'
1344
+ : 'pending';
1335
1345
 
1336
1346
  const resv = {
1337
1347
  rid,
@@ -1348,14 +1358,15 @@ api.createReservation = async function (req, res) {
1348
1358
  end,
1349
1359
  startDate,
1350
1360
  endDate,
1351
- status: (isValidatorFree || isRegularization) ? 'paid' : 'pending',
1361
+ status: resolvedStatus,
1352
1362
  createdAt: now,
1353
- paidAt: (isValidatorFree || isRegularization) ? now : 0,
1354
- approvedBy: (isValidatorFree || isRegularization) ? uid : 0,
1355
- approvedByUsername: (isValidatorFree || isRegularization) ? (creatorUsername || '') : '',
1363
+ paidAt: isAutoPaid ? now : 0,
1364
+ approvedAt: (isAutoPaid || isRegularizationOther) ? now : 0,
1365
+ approvedBy: (isAutoPaid || isRegularizationOther) ? uid : 0,
1366
+ approvedByUsername: (isAutoPaid || isRegularizationOther) ? (creatorUsername || '') : '',
1356
1367
  isFree: !!isValidatorFree,
1357
1368
  total: isValidatorFree ? 0 : (isNaN(total) ? 0 : total),
1358
- manuallyPaid: isRegularization ? true : undefined,
1369
+ manuallyPaid: (isRegularizationSelf || isRegularization) ? true : undefined,
1359
1370
  };
1360
1371
 
1361
1372
  // Validator self-reservations are FREE (no payment required) and tracked separately in accounting.
@@ -1368,7 +1379,8 @@ api.createReservation = async function (req, res) {
1368
1379
 
1369
1380
  // Audit
1370
1381
  const auditAction = isValidatorFree ? 'reservation_self_checked'
1371
- : isRegularization ? 'reservation_manually_paid'
1382
+ : (isRegularizationSelf || isRegularization) ? 'reservation_manually_paid'
1383
+ : isRegularizationOther ? 'reservation_regularization_other'
1372
1384
  : 'reservation_requested';
1373
1385
  await auditLog(auditAction, uid, {
1374
1386
  targetType: 'reservation',
@@ -1385,7 +1397,7 @@ api.createReservation = async function (req, res) {
1385
1397
  status: resv.status,
1386
1398
  });
1387
1399
 
1388
- if (!isValidatorFree && !isRegularization) {
1400
+ if (!isValidatorFree && !isRegularizationSelf && !isRegularization) {
1389
1401
 
1390
1402
 
1391
1403
  // Notify groups by email (NodeBB emailer config)
@@ -1459,7 +1471,7 @@ api.createReservation = async function (req, res) {
1459
1471
 
1460
1472
  }
1461
1473
 
1462
- res.json({ ok: true, rid, status: resv.status, autoPaid: !!(isValidatorFree || isRegularization) });
1474
+ res.json({ ok: true, rid, status: resv.status, autoPaid: isAutoPaid });
1463
1475
  };
1464
1476
 
1465
1477
  api.searchUsers = async function (req, res) {
package/lib/scheduler.js CHANGED
@@ -224,7 +224,6 @@ async function processAwaitingPayment(preIds, preReservations) {
224
224
  const rid = ids[i];
225
225
  const r = reservations[i];
226
226
  if (!r || r.status !== 'awaiting_payment') continue;
227
- if (r.paymentDeferred) continue;
228
227
 
229
228
  const approvedAt = parseInt(r.approvedAt || r.validatedAt || 0, 10) || 0;
230
229
  if (!approvedAt) continue;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-onekite-calendar",
3
- "version": "2.0.76",
3
+ "version": "2.0.77",
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/public/admin.js CHANGED
@@ -838,10 +838,6 @@ define('admin/plugins/calendar-onekite', ['alerts', 'bootbox'], function (alerts
838
838
  <label class="form-label">Heure de récupération</label>
839
839
  <select class="form-select" id="onekite-pickup-time">${opts}</select>
840
840
  </div>
841
- <div class="form-check mb-2">
842
- <input class="form-check-input" type="checkbox" id="onekite-payment-deferred" />
843
- <label class="form-check-label" for="onekite-payment-deferred">Paiement différé <span class="text-muted" style="font-size:12px;">(pas d'annulation automatique)</span></label>
844
- </div>
845
841
  <div class="text-muted" style="font-size:12px;">Ces infos seront appliquées aux ${rids.length} demandes sélectionnées.</div>
846
842
  `;
847
843
  const dlg = bootbox.dialog({
@@ -860,9 +856,8 @@ define('admin/plugins/calendar-onekite', ['alerts', 'bootbox'], function (alerts
860
856
  const pickupTime = (document.getElementById('onekite-pickup-time')?.value || '').trim();
861
857
  const pickupLat = (document.getElementById('onekite-pickup-lat')?.value || '').trim();
862
858
  const pickupLon = (document.getElementById('onekite-pickup-lon')?.value || '').trim();
863
- const paymentDeferred = !!(document.getElementById('onekite-payment-deferred')?.checked);
864
859
  for (const rr of rids) {
865
- await approve(rr, { pickupAddress, notes, pickupTime, pickupLat, pickupLon, paymentDeferred });
860
+ await approve(rr, { pickupAddress, notes, pickupTime, pickupLat, pickupLon });
866
861
  }
867
862
  showAlert('success', `${rids.length} demande(s) validée(s).`);
868
863
  await refreshPending();
@@ -1015,10 +1010,6 @@ define('admin/plugins/calendar-onekite', ['alerts', 'bootbox'], function (alerts
1015
1010
  <label class="form-label">Heure de récupération</label>
1016
1011
  <select class="form-select" id="onekite-pickup-time">${opts}</select>
1017
1012
  </div>
1018
- <div class="form-check mb-2">
1019
- <input class="form-check-input" type="checkbox" id="onekite-payment-deferred" />
1020
- <label class="form-check-label" for="onekite-payment-deferred">Paiement différé <span class="text-muted" style="font-size:12px;">(pas d'annulation automatique)</span></label>
1021
- </div>
1022
1013
  `;
1023
1014
 
1024
1015
  const dlg = bootbox.dialog({
@@ -1037,8 +1028,7 @@ define('admin/plugins/calendar-onekite', ['alerts', 'bootbox'], function (alerts
1037
1028
  const pickupTime = (document.getElementById('onekite-pickup-time')?.value || '').trim();
1038
1029
  const pickupLat = (document.getElementById('onekite-pickup-lat')?.value || '').trim();
1039
1030
  const pickupLon = (document.getElementById('onekite-pickup-lon')?.value || '').trim();
1040
- const paymentDeferred = !!(document.getElementById('onekite-payment-deferred')?.checked);
1041
- await approve(rid, { pickupAddress, notes, pickupTime, pickupLat, pickupLon, paymentDeferred });
1031
+ await approve(rid, { pickupAddress, notes, pickupTime, pickupLat, pickupLon });
1042
1032
  if (rowEl && rowEl.parentNode) rowEl.parentNode.removeChild(rowEl);
1043
1033
  showAlert('success', 'Demande validée.');
1044
1034
  await refreshPending();
package/public/client.js CHANGED
@@ -1229,6 +1229,12 @@ function toDatetimeLocalValue(date) {
1229
1229
  <label style="font-size:13px; font-weight:600; margin-bottom:3px; display:block;">Pour (pseudo, vide = moi-même)</label>
1230
1230
  <input type="text" class="form-control form-control-sm" id="onekite-target-username" placeholder="Pseudo de l'adhérent" autocomplete="off">
1231
1231
  </div>
1232
+ <div class="mb-2">
1233
+ <div class="form-check">
1234
+ <input class="form-check-input" type="checkbox" id="onekite-regularization">
1235
+ <label class="form-check-label" for="onekite-regularization" style="font-size:13px;">Régularisation <span class="text-muted" style="font-size:12px;">(passe directement en payé)</span></label>
1236
+ </div>
1237
+ </div>
1232
1238
  ` : '';
1233
1239
 
1234
1240
  const messageHtml = `
@@ -1280,7 +1286,8 @@ function toDatetimeLocalValue(date) {
1280
1286
  // Return the effective end date (exclusive) because duration shortcuts can
1281
1287
  // change the range without updating the original FullCalendar selection.
1282
1288
  const targetUsername = isValidatorMode ? ((document.getElementById('onekite-target-username') || {}).value || '').trim() : '';
1283
- resolve({ itemIds, itemNames, total, days, endDate: toLocalYmd(end), targetUsername });
1289
+ const isRegularization = isValidatorMode ? !!((document.getElementById('onekite-regularization') || {}).checked) : false;
1290
+ resolve({ itemIds, itemNames, total, days, endDate: toLocalYmd(end), targetUsername, isRegularization });
1284
1291
  },
1285
1292
  },
1286
1293
  },
@@ -1568,6 +1575,7 @@ function toDatetimeLocalValue(date) {
1568
1575
  total: chosen.total,
1569
1576
  };
1570
1577
  if (chosen.targetUsername) reqPayload.targetUsername = chosen.targetUsername;
1578
+ if (chosen.isRegularization) reqPayload.isRegularization = true;
1571
1579
  const resp = await requestReservation(reqPayload);
1572
1580
  if (resp && (resp.autoPaid || String(resp.status) === 'paid')) {
1573
1581
  showAlert('success', chosen.targetUsername ? `Réservation confirmée pour ${chosen.targetUsername}.` : 'Réservation confirmée.');
@@ -1659,6 +1667,7 @@ function toDatetimeLocalValue(date) {
1659
1667
  total: chosen.total,
1660
1668
  };
1661
1669
  if (chosen.targetUsername) reqPayload.targetUsername = chosen.targetUsername;
1670
+ if (chosen.isRegularization) reqPayload.isRegularization = true;
1662
1671
  const resp = await requestReservation(reqPayload);
1663
1672
  if (resp && (resp.autoPaid || String(resp.status) === 'paid')) {
1664
1673
  showAlert('success', chosen.targetUsername ? `Réservation confirmée pour ${chosen.targetUsername}.` : 'Réservation confirmée.');