@glissandoo/lib 1.116.0 → 1.118.0

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.
Files changed (58) hide show
  1. package/functions/event.d.ts +22 -0
  2. package/functions/eventPlayer.d.ts +2 -0
  3. package/functions/eventoPayout.d.ts +70 -0
  4. package/functions/eventoPayout.js +2 -0
  5. package/functions/groupModule.d.ts +13 -0
  6. package/functions/groupModule.js +2 -0
  7. package/functions/groupPayment.d.ts +62 -0
  8. package/functions/groupPayment.js +2 -0
  9. package/functions/groupPayoutRule.d.ts +18 -0
  10. package/functions/groupPayoutRule.js +2 -0
  11. package/functions/index.d.ts +12 -0
  12. package/functions/index.js +12 -0
  13. package/functions/regions.js +12 -0
  14. package/helpers/appScenes.d.ts +2 -0
  15. package/helpers/appScenes.js +2 -0
  16. package/helpers/currency.d.ts +4 -0
  17. package/helpers/currency.js +277 -0
  18. package/helpers/errors.d.ts +7 -1
  19. package/helpers/errors.js +6 -0
  20. package/helpers/paymentForecast.d.ts +37 -0
  21. package/helpers/paymentForecast.js +58 -0
  22. package/helpers/payoutRules.d.ts +45 -0
  23. package/helpers/payoutRules.js +166 -0
  24. package/lang/ca.json +6 -0
  25. package/lang/de.json +6 -0
  26. package/lang/en.json +6 -0
  27. package/lang/es.json +6 -0
  28. package/lang/eu.json +6 -0
  29. package/lang/fr.json +6 -0
  30. package/lang/gl.json +6 -0
  31. package/lang/it.json +6 -0
  32. package/lang/nl.json +6 -0
  33. package/lang/pt.json +6 -0
  34. package/models/Evento/Player/basic.d.ts +1 -0
  35. package/models/Evento/Player/basic.js +3 -0
  36. package/models/Evento/Player/index.d.ts +1 -0
  37. package/models/Evento/Player/index.js +3 -0
  38. package/models/Evento/Player/types.d.ts +1 -0
  39. package/models/Evento/index.d.ts +2 -0
  40. package/models/Evento/index.js +6 -0
  41. package/models/Evento/types.d.ts +14 -1
  42. package/models/Evento/types.js +3 -0
  43. package/models/Group/Payment/index.d.ts +45 -0
  44. package/models/Group/Payment/index.js +110 -0
  45. package/models/Group/Payment/supabase.d.ts +16 -0
  46. package/models/Group/Payment/supabase.js +46 -0
  47. package/models/Group/Payment/types.d.ts +96 -0
  48. package/models/Group/Payment/types.js +26 -0
  49. package/models/Group/index.d.ts +8 -1
  50. package/models/Group/index.js +19 -0
  51. package/models/Group/types.d.ts +30 -0
  52. package/models/Group/types.js +14 -1
  53. package/models/Notification/types.d.ts +4 -1
  54. package/models/Notification/types.js +3 -0
  55. package/package.json +1 -1
  56. package/types/payoutRule.d.ts +126 -0
  57. package/types/payoutRule.js +34 -0
  58. package/types/payoutRule.ts +132 -0
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildEventPaymentForecast = void 0;
4
+ const types_1 = require("../models/Evento/Player/types");
5
+ const types_2 = require("../models/Evento/types");
6
+ const payoutRules_1 = require("./payoutRules");
7
+ /**
8
+ * Computes the simulated ("forecast") payment rows shown in the event payments
9
+ * tab for players that don't yet have a real payment.
10
+ *
11
+ * Exclusion rules per player:
12
+ * - There is already a payment for the player on this event.
13
+ * - `status === Declined`.
14
+ * - When `selectionMode === Closed`, require `selected === true` (rejects
15
+ * `false` and `null`).
16
+ * - The payout rules engine returns `excluded` (PlayerExclude rule).
17
+ *
18
+ * Returns an empty array when no `payout` is configured for the event or when
19
+ * the event has already been roll-called (`isRollCalled`).
20
+ */
21
+ function buildEventPaymentForecast({ players, payout, playerIdsWithPayment, selectionMode, isRollCalled, }) {
22
+ if (!payout)
23
+ return [];
24
+ if (isRollCalled)
25
+ return [];
26
+ const requireSelected = selectionMode === types_2.EventSelectionMode.Closed;
27
+ const result = [];
28
+ for (const player of players) {
29
+ if (playerIdsWithPayment.has(player.id))
30
+ continue;
31
+ if (player.status === types_1.EventPlayerStatus.Declined)
32
+ continue;
33
+ if (requireSelected && player.selected !== true)
34
+ continue;
35
+ const input = {
36
+ id: player.id,
37
+ mainInstrument: player.mainInstrument ?? '',
38
+ isGuest: player.isGuest,
39
+ customFields: {},
40
+ };
41
+ const evaluation = (0, payoutRules_1.evaluateRulesForPlayer)(input, payout.rules ?? [], payout.importByMember);
42
+ if (evaluation.excluded)
43
+ continue;
44
+ result.push({
45
+ playerId: player.id,
46
+ displayName: player.displayName,
47
+ mainInstrument: player.mainInstrument ?? '',
48
+ photoURL: player.photoURL ?? '',
49
+ isGuest: player.isGuest,
50
+ currency: payout.currency,
51
+ baseAmount: evaluation.baseAmount,
52
+ totalAmount: evaluation.finalAmount,
53
+ appliedRules: evaluation.appliedRules,
54
+ });
55
+ }
56
+ return result;
57
+ }
58
+ exports.buildEventPaymentForecast = buildEventPaymentForecast;
@@ -0,0 +1,45 @@
1
+ import { EventoPayoutRuleEntry, PayoutRuleCondition, PayoutRuleEffect, PayoutRulePlayerInput } from '../types/payoutRule';
2
+ /**
3
+ * Per-player payout calculation used at rollcall time.
4
+ *
5
+ * Stored in each `GroupPayment` so the UI can show the breakdown
6
+ * (base struck-through + tooltip with rules) and to keep historical
7
+ * traceability when rules change later.
8
+ */
9
+ export interface AppliedRuleEntry {
10
+ ruleId: string;
11
+ name: string;
12
+ effect: PayoutRuleEffect;
13
+ /** Signed change introduced by this rule. `null` if the base was null and the rule depends on it (multiplier/fixed). */
14
+ delta: number | null;
15
+ /** Running amount after applying this rule. `null` if not yet resolvable. */
16
+ runningAmount: number | null;
17
+ }
18
+ export interface EvaluateRulesResult {
19
+ excluded: boolean;
20
+ excludedByRuleId: string | null;
21
+ baseAmount: number | null;
22
+ finalAmount: number | null;
23
+ appliedRules: AppliedRuleEntry[];
24
+ }
25
+ export declare function evaluateCondition(player: PayoutRulePlayerInput, condition: PayoutRuleCondition): boolean;
26
+ export declare function ruleMatchesPlayer(player: PayoutRulePlayerInput, rule: Pick<EventoPayoutRuleEntry, 'conditions'>): boolean;
27
+ /**
28
+ * Pure function that evaluates the event payout rules against a single player.
29
+ *
30
+ * Apply order (after sorting rules by `order` asc):
31
+ * 1. `PlayerExclude` — short-circuits with `excluded: true`.
32
+ * 2. `PlayerFixed` — replaces the running amount.
33
+ * 3. `PlayerMultiplier` — multiplies the running amount.
34
+ * 4. `PlayerBonus` — adds a fixed amount.
35
+ *
36
+ * When `baseAmount === null` (importByMember "to be determined"):
37
+ * - Rules that depend on the base (Fixed, Multiplier) keep `runningAmount: null`
38
+ * in their `AppliedRuleEntry` and the result `finalAmount` stays `null`.
39
+ * - `PlayerBonus` is recorded with its `delta` but `runningAmount` stays `null`
40
+ * until the base is set.
41
+ *
42
+ * Non-player rules (`EntityShare`, `DefaultExpense`) are ignored here — they
43
+ * affect the global budget, not the per-player amount.
44
+ */
45
+ export declare function evaluateRulesForPlayer(player: PayoutRulePlayerInput, rules: EventoPayoutRuleEntry[], baseAmount: number | null): EvaluateRulesResult;
@@ -0,0 +1,166 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.evaluateRulesForPlayer = exports.ruleMatchesPlayer = exports.evaluateCondition = void 0;
4
+ const payoutRule_1 = require("../types/payoutRule");
5
+ function resolveFieldValue(player, field) {
6
+ if (field === 'mainInstrument')
7
+ return player.mainInstrument;
8
+ if (field === 'isGuest')
9
+ return player.isGuest;
10
+ if (field.startsWith('custom.')) {
11
+ const key = field.slice('custom.'.length);
12
+ const v = player.customFields[key];
13
+ return v === undefined ? null : v;
14
+ }
15
+ return null;
16
+ }
17
+ function evaluateCondition(player, condition) {
18
+ const fieldValue = resolveFieldValue(player, condition.field);
19
+ const target = condition.value;
20
+ switch (condition.operator) {
21
+ case payoutRule_1.PayoutRuleConditionOperator.Eq:
22
+ return fieldValue === target;
23
+ case payoutRule_1.PayoutRuleConditionOperator.Neq:
24
+ return fieldValue !== target;
25
+ case payoutRule_1.PayoutRuleConditionOperator.Gt:
26
+ return (typeof fieldValue === 'number' && typeof target === 'number' && fieldValue > target);
27
+ case payoutRule_1.PayoutRuleConditionOperator.Gte:
28
+ return (typeof fieldValue === 'number' && typeof target === 'number' && fieldValue >= target);
29
+ case payoutRule_1.PayoutRuleConditionOperator.Lt:
30
+ return (typeof fieldValue === 'number' && typeof target === 'number' && fieldValue < target);
31
+ case payoutRule_1.PayoutRuleConditionOperator.Lte:
32
+ return (typeof fieldValue === 'number' && typeof target === 'number' && fieldValue <= target);
33
+ case payoutRule_1.PayoutRuleConditionOperator.In:
34
+ return Array.isArray(target) && target.includes(fieldValue);
35
+ case payoutRule_1.PayoutRuleConditionOperator.Nin:
36
+ return Array.isArray(target) && !target.includes(fieldValue);
37
+ default:
38
+ return false;
39
+ }
40
+ }
41
+ exports.evaluateCondition = evaluateCondition;
42
+ function ruleMatchesPlayer(player, rule) {
43
+ if (!rule.conditions || rule.conditions.length === 0)
44
+ return true;
45
+ return rule.conditions.every((c) => evaluateCondition(player, c));
46
+ }
47
+ exports.ruleMatchesPlayer = ruleMatchesPlayer;
48
+ const PLAYER_EFFECT_TYPES = new Set([
49
+ payoutRule_1.PayoutRuleType.PlayerExclude,
50
+ payoutRule_1.PayoutRuleType.PlayerFixed,
51
+ payoutRule_1.PayoutRuleType.PlayerMultiplier,
52
+ payoutRule_1.PayoutRuleType.PlayerBonus,
53
+ ]);
54
+ function round2(n) {
55
+ return Math.round(n * 100) / 100;
56
+ }
57
+ /**
58
+ * Pure function that evaluates the event payout rules against a single player.
59
+ *
60
+ * Apply order (after sorting rules by `order` asc):
61
+ * 1. `PlayerExclude` — short-circuits with `excluded: true`.
62
+ * 2. `PlayerFixed` — replaces the running amount.
63
+ * 3. `PlayerMultiplier` — multiplies the running amount.
64
+ * 4. `PlayerBonus` — adds a fixed amount.
65
+ *
66
+ * When `baseAmount === null` (importByMember "to be determined"):
67
+ * - Rules that depend on the base (Fixed, Multiplier) keep `runningAmount: null`
68
+ * in their `AppliedRuleEntry` and the result `finalAmount` stays `null`.
69
+ * - `PlayerBonus` is recorded with its `delta` but `runningAmount` stays `null`
70
+ * until the base is set.
71
+ *
72
+ * Non-player rules (`EntityShare`, `DefaultExpense`) are ignored here — they
73
+ * affect the global budget, not the per-player amount.
74
+ */
75
+ function evaluateRulesForPlayer(player, rules, baseAmount) {
76
+ const playerRules = rules
77
+ .filter((r) => PLAYER_EFFECT_TYPES.has(r.effect.type))
78
+ .slice()
79
+ .sort((a, b) => a.order - b.order);
80
+ const appliedRules = [];
81
+ let running = baseAmount;
82
+ let excluded = false;
83
+ let excludedByRuleId = null;
84
+ for (const rule of playerRules) {
85
+ if (!ruleMatchesPlayer(player, rule))
86
+ continue;
87
+ if (rule.effect.type === payoutRule_1.PayoutRuleType.PlayerExclude) {
88
+ excluded = true;
89
+ excludedByRuleId = rule.id;
90
+ appliedRules.push({
91
+ ruleId: rule.id,
92
+ name: rule.name,
93
+ effect: rule.effect,
94
+ delta: null,
95
+ runningAmount: null,
96
+ });
97
+ break;
98
+ }
99
+ if (rule.effect.type === payoutRule_1.PayoutRuleType.PlayerFixed) {
100
+ const next = round2(rule.effect.data.amount);
101
+ const delta = running === null ? null : round2(next - running);
102
+ appliedRules.push({
103
+ ruleId: rule.id,
104
+ name: rule.name,
105
+ effect: rule.effect,
106
+ delta,
107
+ runningAmount: next,
108
+ });
109
+ running = next;
110
+ continue;
111
+ }
112
+ if (rule.effect.type === payoutRule_1.PayoutRuleType.PlayerMultiplier) {
113
+ if (running === null) {
114
+ appliedRules.push({
115
+ ruleId: rule.id,
116
+ name: rule.name,
117
+ effect: rule.effect,
118
+ delta: null,
119
+ runningAmount: null,
120
+ });
121
+ continue;
122
+ }
123
+ const next = round2(running * rule.effect.data.multiplier);
124
+ appliedRules.push({
125
+ ruleId: rule.id,
126
+ name: rule.name,
127
+ effect: rule.effect,
128
+ delta: round2(next - running),
129
+ runningAmount: next,
130
+ });
131
+ running = next;
132
+ continue;
133
+ }
134
+ if (rule.effect.type === payoutRule_1.PayoutRuleType.PlayerBonus) {
135
+ const delta = round2(rule.effect.data.amount);
136
+ if (running === null) {
137
+ appliedRules.push({
138
+ ruleId: rule.id,
139
+ name: rule.name,
140
+ effect: rule.effect,
141
+ delta,
142
+ runningAmount: null,
143
+ });
144
+ continue;
145
+ }
146
+ const next = round2(running + delta);
147
+ appliedRules.push({
148
+ ruleId: rule.id,
149
+ name: rule.name,
150
+ effect: rule.effect,
151
+ delta,
152
+ runningAmount: next,
153
+ });
154
+ running = next;
155
+ continue;
156
+ }
157
+ }
158
+ return {
159
+ excluded,
160
+ excludedByRuleId,
161
+ baseAmount,
162
+ finalAmount: excluded ? null : running,
163
+ appliedRules,
164
+ };
165
+ }
166
+ exports.evaluateRulesForPlayer = evaluateRulesForPlayer;
package/lang/ca.json CHANGED
@@ -50,6 +50,12 @@
50
50
  "group.players.remove.title": "🚫 Grup suprimit",
51
51
  "group.players.removePermissions.text": "S'han eliminat tots els permisos a {string:user.0.displayName}",
52
52
  "group.players.removePermissions.title": "🔐 Permisos actualitzats",
53
+ "groupPayment.paid.title": "✅ Pagament marcat com a pagat",
54
+ "groupPayment.paid.text": "El pagament «{string:extra.concept}» s'ha marcat com a pagat",
55
+ "groupPayment.cancelled.title": "❌ Pagament cancel·lat",
56
+ "groupPayment.cancelled.text": "El pagament «{string:extra.concept}» s'ha cancel·lat",
57
+ "groupPayment.amountChanged.title": "💶 Import actualitzat",
58
+ "groupPayment.amountChanged.text": "L'import de «{string:extra.concept}» s'ha actualitzat a {string:extra.amount}",
53
59
  "group.questions.default.confirmed.answer1": "🚌 Bus",
54
60
  "group.questions.default.confirmed.answer2": "🚗 Cotxe",
55
61
  "group.questions.default.confirmed.title": "Quin transport utilitzaràs?",
package/lang/de.json CHANGED
@@ -50,6 +50,12 @@
50
50
  "group.players.remove.title": "🚫 Gruppe verlassen",
51
51
  "group.players.removePermissions.text": "Alle Berechtigungen von {string:user.0.displayName} wurden entfernt",
52
52
  "group.players.removePermissions.title": "🔐 Berechtigungen aktualisiert",
53
+ "groupPayment.paid.title": "✅ Zahlung als bezahlt markiert",
54
+ "groupPayment.paid.text": "Die Zahlung „{string:extra.concept}“ wurde als bezahlt markiert",
55
+ "groupPayment.cancelled.title": "❌ Zahlung storniert",
56
+ "groupPayment.cancelled.text": "Die Zahlung „{string:extra.concept}“ wurde storniert",
57
+ "groupPayment.amountChanged.title": "💶 Zahlungsbetrag aktualisiert",
58
+ "groupPayment.amountChanged.text": "Der Betrag für „{string:extra.concept}“ wurde auf {string:extra.amount} aktualisiert",
53
59
  "group.questions.default.confirmed.answer1": "🚌 Bus",
54
60
  "group.questions.default.confirmed.answer2": "🚗 Auto",
55
61
  "group.questions.default.confirmed.title": "Welches Transportmittel wirst du nutzen?",
package/lang/en.json CHANGED
@@ -50,6 +50,12 @@
50
50
  "group.players.remove.title": "🚫 Group removed",
51
51
  "group.players.removePermissions.text": "All permissions have been removed from {string:user.0.displayName}",
52
52
  "group.players.removePermissions.title": "🔐 Permissions updated",
53
+ "groupPayment.paid.title": "✅ Payment marked as paid",
54
+ "groupPayment.paid.text": "The payment «{string:extra.concept}» has been marked as paid",
55
+ "groupPayment.cancelled.title": "❌ Payment cancelled",
56
+ "groupPayment.cancelled.text": "The payment «{string:extra.concept}» has been cancelled",
57
+ "groupPayment.amountChanged.title": "💶 Payment amount updated",
58
+ "groupPayment.amountChanged.text": "The amount for «{string:extra.concept}» has been updated to {string:extra.amount}",
53
59
  "group.questions.default.confirmed.answer1": "🚌 Bus",
54
60
  "group.questions.default.confirmed.answer2": "🚗 Car",
55
61
  "group.questions.default.confirmed.title": "What transport will you use?",
package/lang/es.json CHANGED
@@ -50,6 +50,12 @@
50
50
  "group.players.remove.title": "🚫 Grupo suprimido",
51
51
  "group.players.removePermissions.text": "Se han eliminado todos los permisos a {string:user.0.displayName}",
52
52
  "group.players.removePermissions.title": "🔐 Permisos actualizados",
53
+ "groupPayment.paid.title": "✅ Pago marcado como pagado",
54
+ "groupPayment.paid.text": "El pago «{string:extra.concept}» se ha marcado como pagado",
55
+ "groupPayment.cancelled.title": "❌ Pago cancelado",
56
+ "groupPayment.cancelled.text": "El pago «{string:extra.concept}» se ha cancelado",
57
+ "groupPayment.amountChanged.title": "💶 Importe actualizado",
58
+ "groupPayment.amountChanged.text": "El importe de «{string:extra.concept}» se ha actualizado a {string:extra.amount}",
53
59
  "group.questions.default.confirmed.answer1": "🚌 Bus",
54
60
  "group.questions.default.confirmed.answer2": "🚗 Coche",
55
61
  "group.questions.default.confirmed.title": "¿Qué transporte utilizarás?",
package/lang/eu.json CHANGED
@@ -50,6 +50,12 @@
50
50
  "group.players.remove.title": "🚫 Taldea kenduta",
51
51
  "group.players.removePermissions.text": "{string:user.0.displayName} erabiltzaileari baimen guztiak kendu zaizkio",
52
52
  "group.players.removePermissions.title": "🔐 Baimenak eguneratu dira",
53
+ "groupPayment.paid.title": "✅ Ordainketa ordaindutzat markatu da",
54
+ "groupPayment.paid.text": "«{string:extra.concept}» ordainketa ordaindutzat markatu da",
55
+ "groupPayment.cancelled.title": "❌ Ordainketa bertan behera",
56
+ "groupPayment.cancelled.text": "«{string:extra.concept}» ordainketa bertan behera utzi da",
57
+ "groupPayment.amountChanged.title": "💶 Zenbatekoa eguneratuta",
58
+ "groupPayment.amountChanged.text": "«{string:extra.concept}» ordainketaren zenbatekoa {string:extra.amount} izatera eguneratu da",
53
59
  "group.questions.default.confirmed.answer1": "🚌 Autobusa",
54
60
  "group.questions.default.confirmed.answer2": "🚗 Kotxea",
55
61
  "group.questions.default.confirmed.title": "Zein garraiobide erabiliko duzu?",
package/lang/fr.json CHANGED
@@ -50,6 +50,12 @@
50
50
  "group.players.remove.title": "🚫 Groupe quitté",
51
51
  "group.players.removePermissions.text": "Toutes les permissions de {string:user.0.displayName} ont été supprimées",
52
52
  "group.players.removePermissions.title": "🔐 Permissions mises à jour",
53
+ "groupPayment.paid.title": "✅ Paiement marqué comme payé",
54
+ "groupPayment.paid.text": "Le paiement « {string:extra.concept} » a été marqué comme payé",
55
+ "groupPayment.cancelled.title": "❌ Paiement annulé",
56
+ "groupPayment.cancelled.text": "Le paiement « {string:extra.concept} » a été annulé",
57
+ "groupPayment.amountChanged.title": "💶 Montant du paiement mis à jour",
58
+ "groupPayment.amountChanged.text": "Le montant de « {string:extra.concept} » a été mis à jour à {string:extra.amount}",
53
59
  "group.questions.default.confirmed.answer1": "🚌 Bus",
54
60
  "group.questions.default.confirmed.answer2": "🚗 Voiture",
55
61
  "group.questions.default.confirmed.title": "Quel moyen de transport vas-tu utiliser ?",
package/lang/gl.json CHANGED
@@ -50,6 +50,12 @@
50
50
  "group.players.remove.title": "🚫 Grupo suprimido",
51
51
  "group.players.removePermissions.text": "Elimináronse todos os permisos a {string:user.0.displayName}",
52
52
  "group.players.removePermissions.title": "🔐 Permisos actualizados",
53
+ "groupPayment.paid.title": "✅ Pago marcado como pagado",
54
+ "groupPayment.paid.text": "O pago «{string:extra.concept}» foi marcado como pagado",
55
+ "groupPayment.cancelled.title": "❌ Pago cancelado",
56
+ "groupPayment.cancelled.text": "O pago «{string:extra.concept}» foi cancelado",
57
+ "groupPayment.amountChanged.title": "💶 Importe actualizado",
58
+ "groupPayment.amountChanged.text": "O importe de «{string:extra.concept}» actualizouse a {string:extra.amount}",
53
59
  "group.questions.default.confirmed.answer1": "🚌 Autobús",
54
60
  "group.questions.default.confirmed.answer2": "🚗 Coche",
55
61
  "group.questions.default.confirmed.title": "Que transporte vas usar?",
package/lang/it.json CHANGED
@@ -50,6 +50,12 @@
50
50
  "group.players.remove.title": "🚫 Gruppo rimosso",
51
51
  "group.players.removePermissions.text": "Tutti i permessi di {string:user.0.displayName} sono stati rimossi",
52
52
  "group.players.removePermissions.title": "🔐 Permessi aggiornati",
53
+ "groupPayment.paid.title": "✅ Pagamento contrassegnato come pagato",
54
+ "groupPayment.paid.text": "Il pagamento «{string:extra.concept}» è stato contrassegnato come pagato",
55
+ "groupPayment.cancelled.title": "❌ Pagamento annullato",
56
+ "groupPayment.cancelled.text": "Il pagamento «{string:extra.concept}» è stato annullato",
57
+ "groupPayment.amountChanged.title": "💶 Importo del pagamento aggiornato",
58
+ "groupPayment.amountChanged.text": "L'importo di «{string:extra.concept}» è stato aggiornato a {string:extra.amount}",
53
59
  "group.questions.default.confirmed.answer1": "🚌 Autobus",
54
60
  "group.questions.default.confirmed.answer2": "🚗 Auto",
55
61
  "group.questions.default.confirmed.title": "Quale mezzo di trasporto userai?",
package/lang/nl.json CHANGED
@@ -50,6 +50,12 @@
50
50
  "group.players.remove.title": "🚫 Groep verwijderd",
51
51
  "group.players.removePermissions.text": "Alle rechten van {string:user.0.displayName} zijn verwijderd",
52
52
  "group.players.removePermissions.title": "🔐 Rechten bijgewerkt",
53
+ "groupPayment.paid.title": "✅ Betaling als betaald gemarkeerd",
54
+ "groupPayment.paid.text": "De betaling «{string:extra.concept}» is als betaald gemarkeerd",
55
+ "groupPayment.cancelled.title": "❌ Betaling geannuleerd",
56
+ "groupPayment.cancelled.text": "De betaling «{string:extra.concept}» is geannuleerd",
57
+ "groupPayment.amountChanged.title": "💶 Betalingsbedrag bijgewerkt",
58
+ "groupPayment.amountChanged.text": "Het bedrag voor «{string:extra.concept}» is bijgewerkt naar {string:extra.amount}",
53
59
  "group.questions.default.confirmed.answer1": "🚌 Bus",
54
60
  "group.questions.default.confirmed.answer2": "🚗 Auto",
55
61
  "group.questions.default.confirmed.title": "Welk vervoermiddel gebruik je?",
package/lang/pt.json CHANGED
@@ -50,6 +50,12 @@
50
50
  "group.players.remove.title": "🚫 Grupo removido",
51
51
  "group.players.removePermissions.text": "Todas as permissões de {string:user.0.displayName} foram removidas",
52
52
  "group.players.removePermissions.title": "🔐 Permissões atualizadas",
53
+ "groupPayment.paid.title": "✅ Pagamento marcado como pago",
54
+ "groupPayment.paid.text": "O pagamento «{string:extra.concept}» foi marcado como pago",
55
+ "groupPayment.cancelled.title": "❌ Pagamento cancelado",
56
+ "groupPayment.cancelled.text": "O pagamento «{string:extra.concept}» foi cancelado",
57
+ "groupPayment.amountChanged.title": "💶 Valor do pagamento atualizado",
58
+ "groupPayment.amountChanged.text": "O valor de «{string:extra.concept}» foi atualizado para {string:extra.amount}",
53
59
  "group.questions.default.confirmed.answer1": "🚌 Autocarro",
54
60
  "group.questions.default.confirmed.answer2": "🚗 Carro",
55
61
  "group.questions.default.confirmed.title": "Que meio de transporte vais usar?",
@@ -34,4 +34,5 @@ export default class EventoPlayerBasic {
34
34
  get isRollCallConfirmed(): boolean;
35
35
  get isRollCallDeclined(): boolean;
36
36
  get questions(): import("./types").EventPlayerAnswers[];
37
+ get paymentId(): string | null;
37
38
  }
@@ -91,5 +91,8 @@ class EventoPlayerBasic {
91
91
  get questions() {
92
92
  return this.data.questions || [];
93
93
  }
94
+ get paymentId() {
95
+ return this.data.paymentId || null;
96
+ }
94
97
  }
95
98
  exports.default = EventoPlayerBasic;
@@ -34,4 +34,5 @@ export default class EventoPlayer extends PlayerBasic<EventPlayerData> {
34
34
  get remarks(): string | null;
35
35
  get questions(): import("./types").EventPlayerAnswers[];
36
36
  get rollCalledVia(): import("./types").EventPlayerRollCallVia | null;
37
+ get paymentId(): string | null;
37
38
  }
@@ -96,5 +96,8 @@ class EventoPlayer extends basic_1.default {
96
96
  get rollCalledVia() {
97
97
  return this.data.rollCalledVia || null;
98
98
  }
99
+ get paymentId() {
100
+ return this.data.paymentId || null;
101
+ }
99
102
  }
100
103
  exports.default = EventoPlayer;
@@ -73,6 +73,7 @@ export interface EventPlayerData extends EventPlayerBasicData {
73
73
  questions: EventPlayerAnswers[];
74
74
  history: EventPlayerHistory[];
75
75
  remarks: string | null;
76
+ paymentId: string | null;
76
77
  }
77
78
  export interface AEventPlayerData extends EventPlayerData {
78
79
  id: string;
@@ -87,5 +87,7 @@ export default class Evento extends EventoPromoter<EventData> {
87
87
  };
88
88
  getQuestionsByStatus(status: EventPlayerStatus): import("./types").EventQuestions[];
89
89
  get reminders(): import("./types").EventReminderOptions[];
90
+ get payout(): import("./types").EventPayoutConfig | null;
91
+ get payoutRules(): import("../../types/payoutRule").EventoPayoutRuleEntry[];
90
92
  }
91
93
  export {};
@@ -245,5 +245,11 @@ class Evento extends promoter_1.default {
245
245
  get reminders() {
246
246
  return this.data.reminders || [];
247
247
  }
248
+ get payout() {
249
+ return this.data.payout || null;
250
+ }
251
+ get payoutRules() {
252
+ return this.data.payout?.rules || [];
253
+ }
248
254
  }
249
255
  exports.default = Evento;
@@ -1,6 +1,7 @@
1
1
  import { DocumentReference, GeoPoint, Timestamp } from '@google-cloud/firestore';
2
2
  import { Descendant } from '../../helpers/slate';
3
3
  import { CreatedOn } from '../../helpers/types';
4
+ import { EventoPayoutRuleEntry } from '../../types/payoutRule';
4
5
  import { StageTemplate } from '../Group/StageTemplate/types';
5
6
  import { GroupBasicData } from '../Group/types';
6
7
  import { PlayerBasicData } from '../Player/types';
@@ -34,7 +35,10 @@ export declare enum EventHistoryAction {
34
35
  PlayerSetNote = "player_set_note",
35
36
  PlayerSetQuestions = "player_set_questions",
36
37
  PlayerRollCallQR = "player_roll_call_qr",
37
- PlayerRollCallGeoLoc = "player_roll_call_geo_loc"
38
+ PlayerRollCallGeoLoc = "player_roll_call_geo_loc",
39
+ PayoutInitialize = "payout_initialize",
40
+ PayoutEditConfig = "payout_edit_config",
41
+ PayoutEditRules = "payout_edit_rules"
38
42
  }
39
43
  export declare enum EventReminderOptions {
40
44
  OneHours = "1-hours",
@@ -114,6 +118,7 @@ export interface EventPlayerBasicData extends PlayerBasicData {
114
118
  reason?: EventPlayerReason | null;
115
119
  /** @deprecated use status */
116
120
  interested: true | null;
121
+ paymentId?: string | null;
117
122
  }
118
123
  export interface AEventPlayerBasicData extends EventPlayerBasicData {
119
124
  id: string;
@@ -177,7 +182,15 @@ export interface EventData extends EventPromoterData {
177
182
  attachmentsPath: string[];
178
183
  questions: Record<EventPlayerStatus, EventQuestions[]>;
179
184
  reminders: EventReminderOptions[];
185
+ payout: EventPayoutConfig | null;
180
186
  readonly owner: DocumentReference;
181
187
  readonly createdAt: Timestamp;
182
188
  readonly createdOn: CreatedOn;
183
189
  }
190
+ export interface EventPayoutConfig {
191
+ grossAmount: number;
192
+ currency: string;
193
+ importByMember: number | null;
194
+ rules: EventoPayoutRuleEntry[];
195
+ expenses: string[];
196
+ }
@@ -31,6 +31,9 @@ var EventHistoryAction;
31
31
  EventHistoryAction["PlayerSetQuestions"] = "player_set_questions";
32
32
  EventHistoryAction["PlayerRollCallQR"] = "player_roll_call_qr";
33
33
  EventHistoryAction["PlayerRollCallGeoLoc"] = "player_roll_call_geo_loc";
34
+ EventHistoryAction["PayoutInitialize"] = "payout_initialize";
35
+ EventHistoryAction["PayoutEditConfig"] = "payout_edit_config";
36
+ EventHistoryAction["PayoutEditRules"] = "payout_edit_rules";
34
37
  })(EventHistoryAction = exports.EventHistoryAction || (exports.EventHistoryAction = {}));
35
38
  var EventReminderOptions;
36
39
  (function (EventReminderOptions) {
@@ -0,0 +1,45 @@
1
+ import { GroupPaymentData, GroupPaymentHistoryItem, GroupPaymentMethod, GroupPaymentStatus, GroupPaymentType } from './types';
2
+ /**
3
+ * Plain-object model for a `group_payment` row. Mirrors the previous
4
+ * Firestore-backed model API so dashboard components keep working with
5
+ * `payment.foo` getters. Build with `new GroupPayment(rowData)` where
6
+ * `rowData` is the deserialized DB record (or a snapshot built from a
7
+ * realtime callback).
8
+ *
9
+ * Timestamp getters return native `Date` objects so consumers can call
10
+ * `.getTime()` / format them with `date-fns`/`dayjs` directly.
11
+ */
12
+ export default class GroupPayment {
13
+ id: string;
14
+ exists: boolean;
15
+ private _data;
16
+ constructor(data: GroupPaymentData);
17
+ get data(): GroupPaymentData;
18
+ get groupId(): string;
19
+ get type(): GroupPaymentType;
20
+ get isIncome(): boolean;
21
+ get isExpense(): boolean;
22
+ get eventId(): string | null;
23
+ get playerId(): string | null;
24
+ get concept(): string;
25
+ get assignedTo(): string;
26
+ get totalAmount(): number | null;
27
+ get baseAmount(): number | null;
28
+ get appliedRules(): import("../../../helpers/payoutRules").AppliedRuleEntry[];
29
+ get currency(): string;
30
+ get displayTotal(): string;
31
+ get status(): GroupPaymentStatus;
32
+ get isPending(): boolean;
33
+ get isPaid(): boolean;
34
+ get isCancelled(): boolean;
35
+ get paymentMethod(): GroupPaymentMethod | null;
36
+ get history(): GroupPaymentHistoryItem[];
37
+ get historyOrdered(): GroupPaymentHistoryItem[];
38
+ get paidAt(): Date | null;
39
+ get paidBy(): string | null;
40
+ get note(): string | null;
41
+ get createdAt(): Date;
42
+ get createdBy(): string;
43
+ get editedAt(): Date | null;
44
+ get editedBy(): string | null;
45
+ }