feat(sprint8): Phase 5+6 — Integration, schedulers, tier enforcement, testing

Phase 5 — Integration:
- PaymentReminderScheduler: monthly cron at 9am, sends PAYMENT_REMINDER
  and PAYMENT_OVERDUE (30+ days) notifications, audit logged
- BoardTermScheduler: daily cron at 8am, sends BOARD_TERM_EXPIRING
  notification 30 days before term end (1-day window for single delivery)
- Assembly protocol auto-archive: completeAssembly() generates PDF via
  AssemblyProtocolService and stores it in DocumentService.archiveProtocol()
- PlanTierService: Sprint 8 limits added (Kassenbuch 3mo starter, 1 MV/year
  starter, 100MB/1GB/unlimited document storage)
- Notification wiring: PAYMENT_RECEIVED sent to member on recordPayment(),
  sendToAllMembers() added to NotificationService for assembly invitations
- Seed data: 2 fee schedules (Regular €30, Reduced €15), 4 fee assignments,
  3 sample payments, 2 board positions, 2 board members

Phase 6 — Testing infrastructure:
- V22 migration: protocol_document_id on assemblies table
- Schedulers disabled in test profile (cannamanage.schedulers.enabled=false)
- Scheduler property configurable via SCHEDULERS_ENABLED env var

Additional fixes (pre-existing Phase 4 issues):
- AssemblyProtocolService: fixed Document import ambiguity (OpenPDF vs entity)
- AuditService: added convenience overloads for UUID actorId/clubId
- ReceiptPdfService: fixed getReceiptNumber/getMemberNumber/getPaymentDate
- StaffPermissionChecker: added getUserId/getClubId/getTenantId helpers
- FinanceService: added getPaymentById, exportLedgerCsv methods
This commit is contained in:
Patrick Plate
2026-06-15 09:22:49 +02:00
parent e4698827ee
commit 61b0cd92be
17 changed files with 639 additions and 13 deletions
+75
View File
@@ -122,3 +122,78 @@ VALUES
('h1000000-0000-0000-0000-000000000004', 'a1000000-0000-0000-0000-000000000001',
'e1000000-0000-0000-0000-000000000001', 'DISTRIBUTION', -8.00, 'Distributed to members')
ON CONFLICT DO NOTHING;
-- ============================================================================
-- Sprint 8: Fee Schedules (2 tiers)
-- ============================================================================
INSERT INTO fee_schedules (id, tenant_id, club_id, name, amount_cents, interval, is_default, is_active)
VALUES
('f8000000-0000-0000-0000-000000000001', 'a1000000-0000-0000-0000-000000000001',
'a1000000-0000-0000-0000-000000000001', 'Regulär', 3000, 'MONTHLY', true, true),
('f8000000-0000-0000-0000-000000000002', 'a1000000-0000-0000-0000-000000000001',
'a1000000-0000-0000-0000-000000000001', 'Ermäßigt', 1500, 'MONTHLY', false, true)
ON CONFLICT DO NOTHING;
-- ============================================================================
-- Sprint 8: Fee Assignments (members assigned to fee schedules)
-- ============================================================================
INSERT INTO member_fee_assignments (id, tenant_id, member_id, club_id, fee_schedule_id, valid_from)
VALUES
('f8100000-0000-0000-0000-000000000001', 'a1000000-0000-0000-0000-000000000001',
'c1000000-0000-0000-0000-000000000001', 'a1000000-0000-0000-0000-000000000001',
'f8000000-0000-0000-0000-000000000001', '2024-01-15'),
('f8100000-0000-0000-0000-000000000002', 'a1000000-0000-0000-0000-000000000001',
'c1000000-0000-0000-0000-000000000002', 'a1000000-0000-0000-0000-000000000001',
'f8000000-0000-0000-0000-000000000001', '2024-01-20'),
('f8100000-0000-0000-0000-000000000003', 'a1000000-0000-0000-0000-000000000001',
'c1000000-0000-0000-0000-000000000003', 'a1000000-0000-0000-0000-000000000001',
'f8000000-0000-0000-0000-000000000002', '2024-02-01'),
('f8100000-0000-0000-0000-000000000004', 'a1000000-0000-0000-0000-000000000001',
'c1000000-0000-0000-0000-000000000004', 'a1000000-0000-0000-0000-000000000001',
'f8000000-0000-0000-0000-000000000001', '2024-02-15')
ON CONFLICT DO NOTHING;
-- ============================================================================
-- Sprint 8: Sample Payments
-- ============================================================================
INSERT INTO payments (id, tenant_id, club_id, member_id, amount_cents, payment_method, status, period_from, period_to, paid_at, recorded_by)
VALUES
('f8200000-0000-0000-0000-000000000001', 'a1000000-0000-0000-0000-000000000001',
'a1000000-0000-0000-0000-000000000001', 'c1000000-0000-0000-0000-000000000001',
3000, 'BANK_TRANSFER', 'PAID', '2024-12-01', '2024-12-31',
'2024-12-03 09:00:00+01', 'b1000000-0000-0000-0000-000000000001'),
('f8200000-0000-0000-0000-000000000002', 'a1000000-0000-0000-0000-000000000001',
'a1000000-0000-0000-0000-000000000001', 'c1000000-0000-0000-0000-000000000002',
3000, 'CASH', 'PAID', '2024-12-01', '2024-12-31',
'2024-12-05 14:30:00+01', 'b1000000-0000-0000-0000-000000000001'),
('f8200000-0000-0000-0000-000000000003', 'a1000000-0000-0000-0000-000000000001',
'a1000000-0000-0000-0000-000000000001', 'c1000000-0000-0000-0000-000000000001',
3000, 'BANK_TRANSFER', 'PAID', '2025-01-01', '2025-01-31',
'2025-01-02 10:00:00+01', 'b1000000-0000-0000-0000-000000000001')
ON CONFLICT DO NOTHING;
-- ============================================================================
-- Sprint 8: Board Positions (Vorstandspositionen)
-- ============================================================================
INSERT INTO board_positions (id, tenant_id, club_id, title, description, is_active, sort_order)
VALUES
('f8300000-0000-0000-0000-000000000001', 'a1000000-0000-0000-0000-000000000001',
'a1000000-0000-0000-0000-000000000001', '1. Vorsitzender',
'Gesetzlicher Vertreter nach §26 BGB', true, 1),
('f8300000-0000-0000-0000-000000000002', 'a1000000-0000-0000-0000-000000000001',
'a1000000-0000-0000-0000-000000000001', 'Kassenwart',
'Verantwortlich für Finanzen und Kassenbuch', true, 2)
ON CONFLICT DO NOTHING;
-- ============================================================================
-- Sprint 8: Board Members (assigned to positions)
-- ============================================================================
INSERT INTO board_members (id, tenant_id, club_id, position_id, member_id, elected_at, term_start, term_end, is_current)
VALUES
('f8400000-0000-0000-0000-000000000001', 'a1000000-0000-0000-0000-000000000001',
'a1000000-0000-0000-0000-000000000001', 'f8300000-0000-0000-0000-000000000001',
'c1000000-0000-0000-0000-000000000001', '2024-01-15', '2024-01-15', '2026-01-15', true),
('f8400000-0000-0000-0000-000000000002', 'a1000000-0000-0000-0000-000000000001',
'a1000000-0000-0000-0000-000000000001', 'f8300000-0000-0000-0000-000000000002',
'c1000000-0000-0000-0000-000000000004', '2024-01-15', '2024-01-15', '2026-01-15', true)
ON CONFLICT DO NOTHING;