@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.
- package/functions/event.d.ts +22 -0
- package/functions/eventPlayer.d.ts +2 -0
- package/functions/eventoPayout.d.ts +70 -0
- package/functions/eventoPayout.js +2 -0
- package/functions/groupModule.d.ts +13 -0
- package/functions/groupModule.js +2 -0
- package/functions/groupPayment.d.ts +62 -0
- package/functions/groupPayment.js +2 -0
- package/functions/groupPayoutRule.d.ts +18 -0
- package/functions/groupPayoutRule.js +2 -0
- package/functions/index.d.ts +12 -0
- package/functions/index.js +12 -0
- package/functions/regions.js +12 -0
- package/helpers/appScenes.d.ts +2 -0
- package/helpers/appScenes.js +2 -0
- package/helpers/currency.d.ts +4 -0
- package/helpers/currency.js +277 -0
- package/helpers/errors.d.ts +7 -1
- package/helpers/errors.js +6 -0
- package/helpers/paymentForecast.d.ts +37 -0
- package/helpers/paymentForecast.js +58 -0
- package/helpers/payoutRules.d.ts +45 -0
- package/helpers/payoutRules.js +166 -0
- package/lang/ca.json +6 -0
- package/lang/de.json +6 -0
- package/lang/en.json +6 -0
- package/lang/es.json +6 -0
- package/lang/eu.json +6 -0
- package/lang/fr.json +6 -0
- package/lang/gl.json +6 -0
- package/lang/it.json +6 -0
- package/lang/nl.json +6 -0
- package/lang/pt.json +6 -0
- package/models/Evento/Player/basic.d.ts +1 -0
- package/models/Evento/Player/basic.js +3 -0
- package/models/Evento/Player/index.d.ts +1 -0
- package/models/Evento/Player/index.js +3 -0
- package/models/Evento/Player/types.d.ts +1 -0
- package/models/Evento/index.d.ts +2 -0
- package/models/Evento/index.js +6 -0
- package/models/Evento/types.d.ts +14 -1
- package/models/Evento/types.js +3 -0
- package/models/Group/Payment/index.d.ts +45 -0
- package/models/Group/Payment/index.js +110 -0
- package/models/Group/Payment/supabase.d.ts +16 -0
- package/models/Group/Payment/supabase.js +46 -0
- package/models/Group/Payment/types.d.ts +96 -0
- package/models/Group/Payment/types.js +26 -0
- package/models/Group/index.d.ts +8 -1
- package/models/Group/index.js +19 -0
- package/models/Group/types.d.ts +30 -0
- package/models/Group/types.js +14 -1
- package/models/Notification/types.d.ts +4 -1
- package/models/Notification/types.js +3 -0
- package/package.json +1 -1
- package/types/payoutRule.d.ts +126 -0
- package/types/payoutRule.js +34 -0
- 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 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
|
}
|
|
@@ -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;
|
package/models/Evento/index.d.ts
CHANGED
|
@@ -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 {};
|
package/models/Evento/index.js
CHANGED
|
@@ -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;
|
package/models/Evento/types.d.ts
CHANGED
|
@@ -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
|
+
}
|
package/models/Evento/types.js
CHANGED
|
@@ -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
|
+
}
|