nodebb-plugin-onekite-calendar 2.0.75 → 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/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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-onekite-calendar",
3
- "version": "2.0.75",
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/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.');