docs(membership): condense membership, onboarding and import docs and align with the code
This commit is contained in:
parent
8d783276d0
commit
5d8f173529
4 changed files with 436 additions and 1904 deletions
|
|
@ -1,50 +1,20 @@
|
|||
# Membership Fees - Overview
|
||||
|
||||
**Project:** Mila - Membership Management System
|
||||
**Feature:** Membership Fee Management
|
||||
**Version:** 1.0
|
||||
**Last Updated:** 2026-01-13
|
||||
**Status:** ✅ Implemented
|
||||
**Feature:** Membership Fee Management — **Status:** Implemented
|
||||
|
||||
---
|
||||
|
||||
## Purpose
|
||||
|
||||
This document provides a comprehensive overview of the Membership Fees system. It covers business logic, data model, UI/UX design, and technical architecture in a concise, bullet-point format.
|
||||
|
||||
**For detailed implementation:** See [membership-fee-implementation-plan.md](./membership-fee-implementation-plan.md) (created after concept iterations)
|
||||
|
||||
---
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Core Principle](#core-principle)
|
||||
2. [Terminology](#terminology)
|
||||
3. [Data Model](#data-model)
|
||||
4. [Business Logic](#business-logic)
|
||||
5. [UI/UX Design](#uiux-design)
|
||||
6. [Edge Cases](#edge-cases)
|
||||
7. [Technical Integration](#technical-integration)
|
||||
8. [Implementation Scope](#implementation-scope)
|
||||
Coarse, business-oriented entry point for the Membership Fees system: terminology, worked examples, and UI/UX. For architecture (data model, FK behaviors, module map, generation algorithm, policies) see [membership-fee-architecture.md](./membership-fee-architecture.md).
|
||||
|
||||
---
|
||||
|
||||
## Core Principle
|
||||
|
||||
**Maximum Simplicity:**
|
||||
|
||||
- Minimal complexity
|
||||
- Clear data model without redundancies
|
||||
- Intuitive operation
|
||||
- Calendar cycle-based (Month/Quarter/Half-Year/Year)
|
||||
Maximum simplicity: minimal complexity, clear data model without redundancies, intuitive operation, calendar-cycle-based (Month / Quarter / Half-Year / Year).
|
||||
|
||||
---
|
||||
|
||||
## Terminology
|
||||
## Terminology (German ↔ English)
|
||||
|
||||
### German ↔ English
|
||||
|
||||
**Core Entities:**
|
||||
**Core entities:**
|
||||
|
||||
- Beitragsart ↔ Membership Fee Type
|
||||
- Beitragszyklus ↔ Membership Fee Cycle
|
||||
|
|
@ -56,14 +26,14 @@ This document provides a comprehensive overview of the Membership Fees system. I
|
|||
- unbezahlt ↔ unpaid
|
||||
- ausgesetzt ↔ suspended / waived
|
||||
|
||||
**Intervals (Frequenz / Payment Frequency):**
|
||||
**Intervals (Frequenz / payment frequency):**
|
||||
|
||||
- monatlich ↔ monthly
|
||||
- quartalsweise ↔ quarterly
|
||||
- halbjährlich ↔ half-yearly / semi-annually
|
||||
- jährlich ↔ yearly / annually
|
||||
|
||||
**UI Elements:**
|
||||
**UI elements:**
|
||||
|
||||
- "Letzter Zyklus" ↔ "Last Cycle" (e.g., 2023 when in 2024)
|
||||
- "Aktueller Zyklus" ↔ "Current Cycle" (e.g., 2024)
|
||||
|
|
@ -72,112 +42,39 @@ This document provides a comprehensive overview of the Membership Fees system. I
|
|||
|
||||
---
|
||||
|
||||
## Data Model
|
||||
## Data Model (summary)
|
||||
|
||||
### Membership Fee Type (MembershipFeeType)
|
||||
Three entities — full schema, FK on-delete behaviors, and design rationale are in [membership-fee-architecture.md](./membership-fee-architecture.md).
|
||||
|
||||
```
|
||||
- id (UUID)
|
||||
- name (String) - e.g., "Regular", "Reduced", "Student"
|
||||
- amount (Decimal) - Membership fee amount in Euro
|
||||
- interval (Enum) - :monthly, :quarterly, :half_yearly, :yearly
|
||||
- description (Text, optional)
|
||||
```
|
||||
- **MembershipFeeType:** name, amount (€), `interval` (:monthly/:quarterly/:half_yearly/:yearly), optional description. `interval` is **IMMUTABLE** after creation; admin can change only name/amount/description; on amount change, future unpaid cycles regenerate with the new amount.
|
||||
- **MembershipFeeCycle:** member_id, membership_fee_type_id, `cycle_start` (calendar start: 01.01., 01.04., 01.07., 01.10., …), status (:unpaid default / :paid / :suspended), `amount` (captured at generation time → history when type changes), optional notes. NO `cycle_end` (derived from `cycle_start` + interval), NO `interval_type` (read from the fee type).
|
||||
- **Member extensions:** `membership_fee_type_id` (FK, nullable — default applied from settings at the app level), `membership_fee_start_date` (Date, nullable), plus the existing `exit_date`.
|
||||
|
||||
**Important:**
|
||||
**Calendar cycle logic:** Monthly 01.01.–31.01., etc. · Quarterly 01.01.–31.03., 01.04.–30.06., 01.07.–30.09., 01.10.–31.12. · Half-yearly 01.01.–30.06., 01.07.–31.12. · Yearly 01.01.–31.12.
|
||||
|
||||
- `interval` is **IMMUTABLE** after creation!
|
||||
- Admin can only change `name`, `amount`, `description`
|
||||
- On change: Future unpaid cycles regenerated with new amount
|
||||
### `membership_fee_start_date` derivation
|
||||
|
||||
### Membership Fee Cycle (MembershipFeeCycle)
|
||||
Auto-set from global setting `include_joining_cycle`:
|
||||
|
||||
```
|
||||
- id (UUID)
|
||||
- member_id (FK → members.id)
|
||||
- membership_fee_type_id (FK → membership_fee_types.id)
|
||||
- cycle_start (Date) - Calendar cycle start (01.01., 01.04., 01.07., 01.10., etc.)
|
||||
- status (Enum) - :unpaid (default), :paid, :suspended
|
||||
- amount (Decimal) - Membership fee amount at generation time (history when type changes)
|
||||
- notes (Text, optional) - Admin notes
|
||||
```
|
||||
- `include_joining_cycle = true` → first day of the joining month/quarter/year (member pays from the joining cycle).
|
||||
- `include_joining_cycle = false` → first day of the NEXT cycle after joining.
|
||||
|
||||
**Important:**
|
||||
Can be manually overridden by admin. There is intentionally **no** `include_joining_cycle` field on Member — `membership_fee_start_date` makes it unnecessary.
|
||||
|
||||
- **NO** `cycle_end` - calculated from `cycle_start` + `interval`
|
||||
- **NO** `interval_type` - read from `membership_fee_type.interval`
|
||||
- Avoids redundancy and inconsistencies!
|
||||
### Global settings
|
||||
|
||||
**Calendar Cycle Logic:**
|
||||
|
||||
- Monthly: 01.01. - 31.01., 01.02. - 28./29.02., etc.
|
||||
- Quarterly: 01.01. - 31.03., 01.04. - 30.06., 01.07. - 30.09., 01.10. - 31.12.
|
||||
- Half-yearly: 01.01. - 30.06., 01.07. - 31.12.
|
||||
- Yearly: 01.01. - 31.12.
|
||||
|
||||
### Member (Extensions)
|
||||
|
||||
```
|
||||
- membership_fee_type_id (FK → membership_fee_types.id, NOT NULL, default from settings)
|
||||
- membership_fee_start_date (Date, nullable) - When to start generating membership fees
|
||||
- exit_date (Date, nullable) - Exit date (existing)
|
||||
```
|
||||
|
||||
**Logic for membership_fee_start_date:**
|
||||
|
||||
- Auto-set based on global setting `include_joining_cycle`
|
||||
- If `include_joining_cycle = true`: First day of joining month/quarter/year
|
||||
- If `include_joining_cycle = false`: First day of NEXT cycle after joining
|
||||
- Can be manually overridden by admin
|
||||
|
||||
**NO** `include_joining_cycle` field on Member - unnecessary due to `membership_fee_start_date`!
|
||||
|
||||
### Global Settings
|
||||
|
||||
```
|
||||
key: "membership_fees.include_joining_cycle"
|
||||
value: Boolean (Default: true)
|
||||
|
||||
key: "membership_fees.default_membership_fee_type_id"
|
||||
value: UUID (Required) - Default membership fee type for new members
|
||||
```
|
||||
|
||||
**Meaning include_joining_cycle:**
|
||||
|
||||
- `true`: Joining cycle is included (member pays from joining cycle)
|
||||
- `false`: Only from next full cycle after joining
|
||||
|
||||
**Meaning of default membership fee type setting:**
|
||||
|
||||
- Every new member automatically gets this membership fee type
|
||||
- Must be configured in admin settings
|
||||
- Prevents: Members without membership fee type
|
||||
- `membership_fees.include_joining_cycle` — Boolean (default `true`): whether the joining cycle is billed.
|
||||
- `membership_fees.default_membership_fee_type_id` — UUID (required): fee type auto-assigned to every new member; must be configured in admin settings (prevents members without a fee type).
|
||||
|
||||
---
|
||||
|
||||
## Business Logic
|
||||
|
||||
### Cycle Generation
|
||||
### Cycle generation
|
||||
|
||||
**Triggers:**
|
||||
**Triggers:** fee type assigned (incl. at member creation), new cycle begins (cron daily/weekly), admin manual regeneration. Uses PostgreSQL advisory locks per member.
|
||||
|
||||
- Member gets membership fee type assigned (also during member creation)
|
||||
- New cycle begins (Cron job daily/weekly)
|
||||
- Admin requests manual regeneration
|
||||
|
||||
**Algorithm:**
|
||||
|
||||
Use PostgreSQL advisory locks per member to prevent race conditions
|
||||
|
||||
1. Get `member.membership_fee_start_date` and member's membership fee type
|
||||
2. Determine generation start point:
|
||||
- If NO cycles exist: Start from `membership_fee_start_date`
|
||||
- If cycles exist: Start from the cycle AFTER the last existing one
|
||||
3. Generate cycles until today (or `exit_date` if present):
|
||||
- Use the interval to generate the cycles
|
||||
- **Note:** If cycles were explicitly deleted (gaps exist), they are NOT recreated.
|
||||
The generator always continues from the cycle AFTER the last existing cycle.
|
||||
4. Set `amount` to current membership fee type's amount
|
||||
**Algorithm:** start from `membership_fee_start_date` if no cycles exist, else from the cycle AFTER the last existing one; generate to today (or `exit_date`); set each cycle's `amount` from the current fee type. **Deleted cycles (gaps) are NOT recreated** — generation always continues after the last existing cycle. (Full algorithm in architecture doc.)
|
||||
|
||||
**Example (Yearly):**
|
||||
|
||||
|
|
@ -207,93 +104,31 @@ Generated cycles:
|
|||
- ...
|
||||
```
|
||||
|
||||
### Status Transitions
|
||||
### Status transitions
|
||||
|
||||
```
|
||||
unpaid → paid
|
||||
unpaid → suspended
|
||||
paid → unpaid
|
||||
suspended → paid
|
||||
suspended → unpaid
|
||||
```
|
||||
unpaid → paid · unpaid → suspended · paid → unpaid · suspended → paid · suspended → unpaid. Admin + Treasurer (Kassenwart) can change status, via the existing permission system.
|
||||
|
||||
**Permissions:**
|
||||
### Membership fee type change
|
||||
|
||||
- Admin + Treasurer (Kassenwart) can change status
|
||||
- Uses existing permission system
|
||||
MVP allows changing only to a fee type with the **same interval** (e.g. "Regular (yearly)" → "Reduced (yearly)" ✓; → "Reduced (monthly)" ✗). On change: set `member.membership_fee_type_id`; future **unpaid** cycles deleted and regenerated with the new amount; paid/suspended cycles unchanged (historical amount). Future: enable interval switching (overlap handling, extra validation).
|
||||
|
||||
### Membership Fee Type Change
|
||||
### Member exit
|
||||
|
||||
**MVP - Same Cycle Only:**
|
||||
|
||||
- Member can only choose membership fee type with **same cycle**
|
||||
- Example: From "Regular (yearly)" to "Reduced (yearly)" ✓
|
||||
- Example: From "Regular (yearly)" to "Reduced (monthly)" ✗
|
||||
|
||||
**Logic on Change:**
|
||||
|
||||
1. Check: New membership fee type has same interval
|
||||
2. If yes: Set `member.membership_fee_type_id`
|
||||
3. Future **unpaid** cycles: Delete and regenerate with new amount
|
||||
4. Paid/suspended cycles: Remain unchanged (historical amount)
|
||||
|
||||
**Future - Different Intervals:**
|
||||
|
||||
- Enable interval switching (e.g., yearly → monthly)
|
||||
- More complex logic for cycle overlaps
|
||||
- Needs additional validation
|
||||
|
||||
### Member Exit
|
||||
|
||||
**Logic:**
|
||||
|
||||
- Cycles only generated until `member.exit_date`
|
||||
- Existing cycles remain visible
|
||||
- Unpaid exit cycle can be marked as "suspended"
|
||||
|
||||
**Example:**
|
||||
|
||||
```
|
||||
Exit: 15.08.2024
|
||||
Yearly cycle: 01.01.2024 - 31.12.2024
|
||||
|
||||
→ Cycle 2024 is shown (Status: unpaid)
|
||||
→ Admin can set to "suspended"
|
||||
→ No cycles for 2025+ generated
|
||||
```
|
||||
Cycles generated only up to `member.exit_date`; existing cycles remain visible; an unpaid exit cycle can be marked "suspended". E.g. exit 15.08.2024 with a yearly cycle 01.01.–31.12.2024 → 2024 cycle shown (unpaid, admin may suspend); no 2025+ cycles generated.
|
||||
|
||||
---
|
||||
|
||||
## UI/UX Design
|
||||
|
||||
### Member List View
|
||||
### Member List View — column "Membership Fee Status"
|
||||
|
||||
**New Column: "Membership Fee Status"**
|
||||
- **Default (last completed cycle):** in 2024, shows the 2023 status. Color: green = paid ✓, red = unpaid ✗, gray = suspended ⊘.
|
||||
- **Optional toggle:** "Show current cycle" (2024).
|
||||
- **Filters:** "Unpaid membership fees in last cycle", "Unpaid membership fees in current cycle".
|
||||
|
||||
**Default Display (Last Cycle):**
|
||||
### Member Detail View — section "Membership Fees"
|
||||
|
||||
- Shows status of **last completed** cycle
|
||||
- Example in 2024: Shows membership fee for 2023
|
||||
- Color coding:
|
||||
- Green: paid ✓
|
||||
- Red: unpaid ✗
|
||||
- Gray: suspended ⊘
|
||||
|
||||
**Optional: Show Current Cycle**
|
||||
|
||||
- Toggle: "Show current cycle" (2024)
|
||||
- Admin decides what to display
|
||||
|
||||
**Filters:**
|
||||
|
||||
- "Unpaid membership fees in last cycle"
|
||||
- "Unpaid membership fees in current cycle"
|
||||
|
||||
### Member Detail View
|
||||
|
||||
**Section: "Membership Fees"**
|
||||
|
||||
**Membership Fee Type Assignment:**
|
||||
**Fee type assignment:**
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
|
|
@ -303,7 +138,7 @@ Yearly cycle: 01.01.2024 - 31.12.2024
|
|||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Cycle Table:**
|
||||
**Cycle table:**
|
||||
|
||||
```
|
||||
┌───────────────┬──────────┬────────┬──────────┬─────────┐
|
||||
|
|
@ -322,11 +157,7 @@ Yearly cycle: 01.01.2024 - 31.12.2024
|
|||
Legend: ☑ = paid | ☐ = unpaid | ⊘ = suspended
|
||||
```
|
||||
|
||||
**Quick Marking:**
|
||||
|
||||
- Checkbox in each row for fast marking
|
||||
- Button: "Mark selected as paid/unpaid/suspended"
|
||||
- Bulk action for multiple cycles
|
||||
**Quick marking:** checkbox per row; "Mark selected as paid/unpaid/suspended" button; bulk action for multiple cycles.
|
||||
|
||||
### Admin: Membership Fee Types Management
|
||||
|
||||
|
|
@ -342,18 +173,13 @@ Legend: ☑ = paid | ☐ = unpaid | ⊘ = suspended
|
|||
└────────────┴──────────┴──────────┴────────────┴─────────┘
|
||||
```
|
||||
|
||||
**Edit:**
|
||||
**Edit:** Name ✓, Amount ✓, Description ✓ editable; Interval ✗ **NOT** editable (grayed out).
|
||||
|
||||
- Name: ✓ editable
|
||||
- Amount: ✓ editable
|
||||
- Description: ✓ editable
|
||||
- Interval: ✗ **NOT** editable (grayed out)
|
||||
|
||||
**Warning on Amount Change:**
|
||||
**Warning on amount change:**
|
||||
|
||||
```
|
||||
⚠ Change amount to 65 €?
|
||||
|
||||
|
||||
Impact:
|
||||
- 45 members affected
|
||||
- Future unpaid cycles will be generated with 65 €
|
||||
|
|
@ -362,9 +188,7 @@ Impact:
|
|||
[Cancel] [Confirm]
|
||||
```
|
||||
|
||||
### Admin: Settings
|
||||
|
||||
**Membership Fee Configuration:**
|
||||
### Admin: Settings — Membership Fee Configuration
|
||||
|
||||
```
|
||||
Default Membership Fee Type: [Dropdown: Membership Fee Types]
|
||||
|
|
@ -397,135 +221,58 @@ Joining: 15.03.2023
|
|||
|
||||
## Edge Cases
|
||||
|
||||
### 1. Membership Fee Type Change with Different Interval
|
||||
1. **Type change with different interval:** MVP blocks it. UI message:
|
||||
|
||||
**MVP:** Blocked (only same interval allowed)
|
||||
```
|
||||
Error: Interval change not possible
|
||||
|
||||
**UI:**
|
||||
Current membership fee type: "Regular (Yearly)"
|
||||
Selected membership fee type: "Student (Monthly)"
|
||||
|
||||
```
|
||||
Error: Interval change not possible
|
||||
Changing the interval is currently not possible.
|
||||
Please select a membership fee type with interval "Yearly".
|
||||
|
||||
Current membership fee type: "Regular (Yearly)"
|
||||
Selected membership fee type: "Student (Monthly)"
|
||||
[OK]
|
||||
```
|
||||
|
||||
Changing the interval is currently not possible.
|
||||
Please select a membership fee type with interval "Yearly".
|
||||
Future: allow interval switching with overlap calculation and no duplicate cycles.
|
||||
|
||||
[OK]
|
||||
```
|
||||
2. **Exit with unpaid fees (low prio):** on exit, offer to mark unpaid cycles "suspended".
|
||||
|
||||
**Future:**
|
||||
```
|
||||
⚠ Unpaid membership fees present
|
||||
|
||||
- Allow interval switching
|
||||
- Calculate overlaps
|
||||
- Generate new cycles without duplicates
|
||||
This member has 1 unpaid cycle(s):
|
||||
- 2024: 60 € (unpaid)
|
||||
|
||||
### 2. Exit with Unpaid Membership Fees
|
||||
Do you want to continue?
|
||||
|
||||
**Scenario:**
|
||||
[ ] Mark membership fee as "suspended"
|
||||
[Cancel] [Confirm Exit]
|
||||
```
|
||||
|
||||
```
|
||||
Member exits: 15.08.2024
|
||||
Yearly cycle 2024: unpaid
|
||||
```
|
||||
3. **Multiple unpaid cycles:** all shown; select several and bulk-mark.
|
||||
|
||||
**UI Notice on Exit: (Low Prio)**
|
||||
```
|
||||
┌───────────────┬──────────┬────────┬──────────┬─────────┐
|
||||
│ 2023 │ Yearly │ 50 € │ ☐ Open │ [✓] │
|
||||
│ 2024 │ Yearly │ 60 € │ ☐ Open │ [✓] │
|
||||
│ 2025 │ Yearly │ 60 € │ ☐ Open │ [ ] │
|
||||
└───────────────┴──────────┴────────┴──────────┴─────────┘
|
||||
|
||||
```
|
||||
⚠ Unpaid membership fees present
|
||||
[Mark selected as paid/unpaid/suspended] (2 selected)
|
||||
```
|
||||
|
||||
This member has 1 unpaid cycle(s):
|
||||
- 2024: 60 € (unpaid)
|
||||
4. **Amount changes:** 2023 Regular = 50 €, 2024 = 60 € → 2023 cycle keeps 50 € (history), 2024 generated with 60 €; each cycle shows its historical amount.
|
||||
|
||||
Do you want to continue?
|
||||
|
||||
[ ] Mark membership fee as "suspended"
|
||||
[Cancel] [Confirm Exit]
|
||||
```
|
||||
|
||||
### 3. Multiple Unpaid Cycles
|
||||
|
||||
**Scenario:** Member hasn't paid for 2 years
|
||||
|
||||
**Display:**
|
||||
|
||||
```
|
||||
┌───────────────┬──────────┬────────┬──────────┬─────────┐
|
||||
│ 2023 │ Yearly │ 50 € │ ☐ Open │ [✓] │
|
||||
│ 2024 │ Yearly │ 60 € │ ☐ Open │ [✓] │
|
||||
│ 2025 │ Yearly │ 60 € │ ☐ Open │ [ ] │
|
||||
└───────────────┴──────────┴────────┴──────────┴─────────┘
|
||||
|
||||
[Mark selected as paid/unpaid/suspended] (2 selected)
|
||||
```
|
||||
|
||||
### 4. Amount Changes
|
||||
|
||||
**Scenario:**
|
||||
|
||||
```
|
||||
2023: Regular = 50 €
|
||||
2024: Regular = 60 € (increase)
|
||||
```
|
||||
|
||||
**Result:**
|
||||
|
||||
- Cycle 2023: Saved with 50 € (history)
|
||||
- Cycle 2024: Generated with 60 € (current)
|
||||
- Both cycles show correct historical amount
|
||||
|
||||
### 5. Date Boundaries
|
||||
|
||||
**Problem:** What if today = 01.01.2025?
|
||||
|
||||
**Solution:**
|
||||
|
||||
- Current cycle (2025) is generated
|
||||
- Status: unpaid (open)
|
||||
- Shown in overview
|
||||
5. **Date boundaries:** today = 01.01.2025 → current 2025 cycle generated, status unpaid, shown in overview.
|
||||
|
||||
---
|
||||
|
||||
## Implementation Scope
|
||||
|
||||
### MVP (Phase 1)
|
||||
**MVP (Phase 1) — included:** fee types CRUD; automatic cycle generation; status management (paid/unpaid/suspended); member overview with status; per-member cycle view; quick checkbox marking; bulk actions; amount history; same-interval type change; default fee type; joining-cycle configuration.
|
||||
|
||||
**Included:**
|
||||
**NOT included:** interval change; payment details (date, method); automatic vereinfacht.digital integration; prorata; reports/statistics; reminders/dunning (manual via filters).
|
||||
|
||||
- ✓ Membership fee types (CRUD)
|
||||
- ✓ Automatic cycle generation
|
||||
- ✓ Status management (paid/unpaid/suspended)
|
||||
- ✓ Member overview with membership fee status
|
||||
- ✓ Cycle view per member
|
||||
- ✓ Quick checkbox marking
|
||||
- ✓ Bulk actions
|
||||
- ✓ Amount history
|
||||
- ✓ Same-interval type change
|
||||
- ✓ Default membership fee type
|
||||
- ✓ Joining cycle configuration
|
||||
|
||||
**NOT Included:**
|
||||
|
||||
- ✗ Interval change (only same interval)
|
||||
- ✗ Payment details (date, method)
|
||||
- ✗ Automatic integration (vereinfacht.digital)
|
||||
- ✗ Prorata calculation
|
||||
- ✗ Reports/statistics
|
||||
- ✗ Reminders/dunning (manual via filters)
|
||||
|
||||
### Future Enhancements
|
||||
|
||||
**Phase 2:**
|
||||
|
||||
- Payment details (date, amount, method)
|
||||
- Interval change for future unpaid cycles
|
||||
- Manual vereinfacht.digital links per member
|
||||
- Extended filter options
|
||||
|
||||
**Phase 3:**
|
||||
|
||||
- Automated vereinfacht.digital integration
|
||||
- Automatic payment matching
|
||||
- SEPA integration
|
||||
- Advanced reports
|
||||
**Future:** Phase 2 — payment details, interval change for future unpaid cycles, manual vereinfacht.digital links per member, extended filters. Phase 3 — automated vereinfacht.digital integration, automatic payment matching, SEPA, advanced reports.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue