- Reject dates that are not strict YYYY-MM-DD (was accepting full ISO
datetimes, which silently produced empty exports instead of a 400)
and reject from > to with a 400 before touching the team/DB.
- Emit the cashbox_export_download and cashbox_export_subscription_update
audit log events that were declared but never fired, matching the
audit trail every sibling feature already has.
- Restore full type checking on the pdfkit import via `import = require()`
instead of an untyped require() with an eslint-disable.
- Tighten a cashbox.spec.ts assertion to check the exact dialog class
instead of expect.anything(), so it can't pass with the wrong dialog
wired to the Export button.
- Style and announce the export dialogs' error messages using this
codebase's established error-message/role=alert pattern.
openExportDialog()/openExportSubscriptionDialog() only guarded on teamId
truthiness, relying solely on the template @if for permission gating.
Every other permission-gated method in Cashbox (submitPlayerBooking,
reverseBooking) re-checks the permission internally too. Add the same
guard here, plus a test asserting direct invocation without booking
rights does not call dialog.open.
Adds an Export button (opens CashboxExportDialog directly) plus a
secondary menu (opens CashboxExportSubscriptionDialog) to the journal
toolbar, gated by the existing canBook permission signal.
Lets treasurers/captains/coaches define recurring fee/levy dues that
are automatically booked for all active players on a monthly,
quarterly, or yearly schedule via a daily cron job, instead of having
to book them manually every cycle.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- 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>
Adds a second, dashed line to the existing balance-history chart that
includes currently open player dues, so managers can see at a glance
how far the actual cash balance lags behind what has been pledged.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The vi.mock('chart.js', ...) MockChart class was copy-pasted verbatim
between chart-canvas.spec.ts and overview.spec.ts. Extract it to
shared/chart-canvas/testing/mock-chart.ts and import it via
vi.hoisted(async () => import(...)) in each spec, since vi.mock's
factory is hoisted above regular imports and can't reference a
plain top-level import.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds three chart.js-backed KPI cards (Kassenstand-Verlauf, Einnahmen &
Ausgaben, Top-10 offene Beitraege) to the existing Uebersicht page,
consuming the new GET teams/:id/overview/stats endpoint via a new
TeamStatsApi service. Introduces a small reusable ChartCanvas shared
component that wraps the Chart.js instance lifecycle via @Input()/
ngOnChanges, following this codebase's existing input-decorator
convention rather than effect().
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds a catalog picker to the member-booking form in the cashbox (prefills
amount/note/type, stays editable) and a "Buchen" button on each penalty
catalog entry that jumps to the cashbox with that entry preselected via a
penaltyId query param. No backend changes — reuses the existing POST
/transactions flow, the catalog only supplies starting values.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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>