refactor: improve cycle generation code quality and documentation
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
- Remove Process.sleep calls from integration tests (tests run synchronously in SQL sandbox) - Improve error handling: membership_fee_type_not_found now returns changeset error instead of just logging - Clarify partial_failure documentation: successful_cycles are not persisted on rollback - Update documentation: joined_at → join_date, left_at → exit_date - Document PostgreSQL advisory locks per member (not whole table lock) - Document gap handling: explicitly deleted cycles are not recreated
This commit is contained in:
parent
e6ac5d1ab1
commit
82897d5cd3
5 changed files with 53 additions and 51 deletions
|
|
@ -120,7 +120,7 @@ This document provides a comprehensive overview of the Membership Fees system. I
|
|||
```
|
||||
- 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
|
||||
- left_at (Date, nullable) - Exit date (existing)
|
||||
- exit_date (Date, nullable) - Exit date (existing)
|
||||
```
|
||||
|
||||
**Logic for membership_fee_start_date:**
|
||||
|
|
@ -167,16 +167,17 @@ value: UUID (Required) - Default membership fee type for new members
|
|||
|
||||
**Algorithm:**
|
||||
|
||||
Lock the whole cycle table for the duration of the 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. Generate cycles until today (or `left_at` if present):
|
||||
- If no cycle exists:
|
||||
- Generate all cycles from `membership_fee_start_date`
|
||||
- else:
|
||||
- Generate all cycles from last existing cycle
|
||||
- use the interval to generate the cycles
|
||||
3. Set `amount` to current membership fee type's amount
|
||||
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
|
||||
|
||||
**Example (Yearly):**
|
||||
|
||||
|
|
@ -246,7 +247,7 @@ suspended → unpaid
|
|||
|
||||
**Logic:**
|
||||
|
||||
- Cycles only generated until `member.left_at`
|
||||
- Cycles only generated until `member.exit_date`
|
||||
- Existing cycles remain visible
|
||||
- Unpaid exit cycle can be marked as "suspended"
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue