Commit Graph

20 Commits

Author SHA1 Message Date
Bastian Wagner
812061fc6c feat: emit notification event on player creation 2026-08-04 19:27:45 +02:00
Bastian Wagner
017e6445fa feat: log and emit notification events on public-access enable/rotate 2026-08-04 19:21:01 +02:00
Bastian Wagner
d6733eff0d feat: emit notification events on player active/role changes 2026-08-04 19:13:42 +02:00
Bastian Wagner
6531f2553f fix: wrap team creation in a transaction, add more-menu entry point, fix lint
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-03 17:27:23 +02:00
Bastian Wagner
c1478f07f1 feat: make team creator a captain of the new team 2026-08-03 15:44:12 +02:00
Bastian Wagner
92eacbc5bb feat: allow any logged-in user to create a team 2026-08-03 15:38:43 +02:00
Bastian Wagner
84bab04523 fix export type 2026-08-03 15:01:49 +02:00
Bastian Wagner
b21641f37a ag grid 2026-08-03 14:49:35 +02:00
Bastian Wagner
3cb8cd9a4a fix: strengthen deactivation-exclusion test and align sign rule with canonical logic
- teams.service.spec.ts: pick a checkpoint older than the adjustment's own
  month so the exclusion test actually fails without the exclusion filter
- teams.service.ts: only negate fine/levy/fee amounts when positive,
  matching TeamMembersService.recomputeBalance and Transaction.setBalance()
  exactly, instead of negating unconditionally
- teams.service.ts: outstanding-history helper now returns a positive
  value when players owe money, matching the house convention already
  established by getOverview()'s team.outstanding
- overview.spec.ts: assert the balance chart's legend becomes visible
- teams.service.spec.ts: add coverage for inactive-player exclusion and
  a positive-balance (prepaid credit) case

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-03 11:24:34 +02:00
Bastian Wagner
d8f13d674d refactor: extract shared backward-reconstruction logic
Extract the month-by-month backward-walk algorithm (used for both
team-level cash balance and player-level debt history) into a single
shared private helper `reconstructBackward()`. This eliminates code
duplication while preserving behavior:

- Team-level balanceHistory: maps movements through signedFlowAmount(),
  rounds each point, calls the shared helper
- Player-level balance history: maps transactions using type.id rule,
  skips rounding (only rounds at final merge to avoid compounding
  errors), calls the shared helper

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-03 10:58:48 +02:00
Bastian Wagner
1b6ce57fbf feat: add theoretical balance history to team overview stats
Reconstructs each active player's balance per month (same backward
technique as the existing cash-balance history) so the overview stats
endpoint can report what the team balance would be if all currently
open dues had already been paid.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-03 10:44:22 +02:00
Bastian Wagner
27ab505aba berechtigungen 2026-08-03 10:16:42 +02:00
Bastian Wagner
a94caed85f Merge branch 'worktree-kasse-kpi-charts' 2026-08-01 21:49:07 +02:00
Bastian Wagner
e2f271fd35 fix(teams): gate empty-state and add membership check to overview stats
Whole-branch review findings:

1. balanceHistory/monthlyFlow always returned 12 entries, even for a
   brand-new team with zero transactions, so the frontend's empty-state
   (gated on .length === 0) could never fire for a real "no movements yet"
   team. Now returns empty arrays when there are no relevant movements at
   all (not just none in the last 12 months, so a team with older-but-real
   history still gets a flat chart). Also added the same defensive
   `?? []` guard on players/transactions that getOverview already has, so a
   team with no players/relations loaded doesn't throw.

2. GET :id/overview/stats had no team-membership check -- any logged-in
   user (RoleEnum.user is the default role) could read any other team's
   financial stats by iterating ids. Injected TeamAccessService into
   TeamsService (already a sibling provider in TeamsModule, no module
   wiring needed) and call assertMember(actorUserId, teamId) as the first
   line of getOverviewStats, threaded from the controller via @Req(). Read
   access only (assertMember, not assertManager), matching who can already
   view the overview page. Sibling routes with the same pre-existing gap
   were left untouched, per review scope.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-01 21:41:54 +02:00
Bastian Wagner
1058d641e7 fix(teams): anchor balanceHistory to team.balance instead of forward-summing
Manual verification against real data (Task 3) found balanceHistory drifted
from team.balance for real teams, since team.balance carries historical
adjustments (e.g. from the removed legacy backend) that don't trace back to
the current payment/credit/expense rows. Forward-summing those rows from
zero could never be trusted to tie out.

Rewrite balanceHistory to anchor on team.balance (the authoritative current
value) and walk the movements backward, newest to oldest, undoing each one
to reconstruct earlier month-end balances. This guarantees the most recent
point equals team.balance by construction, and is mathematically identical
to the old forward sum for teams whose movements fully explain their
balance. monthlyFlow/topOutstanding are unaffected and left as-is.

Updated teams.service.spec.ts to use a fixture where team.balance
intentionally does not equal the sum of its own movements, so the tests
actually exercise the drift-handling behavior instead of a case where
forward-sum and backward-anchor happen to coincide.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-01 21:02:32 +02:00
Bastian Wagner
ecb6fd4394 feat(teams): add overview stats endpoint for KPI charts
Adds GET :id/overview/stats + TeamsService#getOverviewStats, aggregating
team-wallet and player payment transactions into a 12-month balanceHistory
(cumulative, carry-forward), monthlyFlow (income/expense), and topOutstanding
(top 10 active debtors) for the upcoming overview KPI charts. fine/levy/fee
and player-level credit are excluded, matching the "Ist-Kasse" cash-flow rule.

Replaces the unmodified NestJS-boilerplate placeholder specs for
TeamsService/TeamsController (which already failed at baseline) with real
tests using the team-access.service.spec.ts direct-construction convention.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-01 19:44:49 +02:00
Bastian Wagner
6eab6251d5 fehlerhafte tests entfernt 2026-08-01 19:44:07 +02:00
Bastian Wagner
3551641a85 feat(teams): manage player active status and team-role with treasurer safeguard
Team managers (captain and above) can now deactivate/reactivate a player and
change their team-role from the player detail page. Deactivation zeroes the
open balance via an auditable adjustment transaction instead of overwriting
the balance field, and both actions are blocked if they would leave a team
without an active treasurer. Also hardens the existing PUT teams/:id/players
endpoint down to profile-only fields, fixing a typo bug and closing a gap
where any authenticated user could mutate a player's active/role/balance in
any team.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-01 15:42:09 +02:00
Bastian Wagner
17228a52db feat: secure penalty catalog management 2026-08-01 13:17:44 +02:00
Bastian Wagner
6bea4f766a first commit 2026-07-31 21:02:47 +02:00