Cycle Generation System closes #277 #290

Merged
moritz merged 11 commits from feature/277_cycle_generation into main 2025-12-18 11:53:12 +01:00
Owner

Description of the implemented changes

The changes were:

  • Bugfixing
  • New Feature
  • Breaking Change
  • Refactoring

Definition of Done

Code Quality

  • No new technical depths
  • Linting passed
  • Documentation is added were needed

Accessibility

  • New elements are properly defined with html-tags
  • Colour contrast follows WCAG criteria
  • Aria labels are added when needed
  • Everything is accessible by keyboard
  • Tab-Order is comprehensible
  • All interactive elements have a visible focus

Testing

  • Tests for new code are written
  • All tests pass
  • axe-core dev tools show no critical or major issues
## Description of the implemented changes The changes were: - [ ] Bugfixing - [x] New Feature - [ ] Breaking Change - [ ] Refactoring ## Definition of Done ### Code Quality - [ ] No new technical depths - [x] Linting passed - [x] Documentation is added were needed ### Accessibility - [ ] New elements are properly defined with html-tags - [ ] Colour contrast follows WCAG criteria - [ ] Aria labels are added when needed - [ ] Everything is accessible by keyboard - [ ] Tab-Order is comprehensible - [ ] All interactive elements have a visible focus ### Testing - [x] Tests for new code are written - [x] All tests pass - [ ] axe-core dev tools show no critical or major issues
moritz added this to the Membership Fees milestone 2025-12-12 16:56:35 +01:00
moritz self-assigned this 2025-12-12 16:56:36 +01:00
moritz added 15 commits 2025-12-12 16:56:37 +01:00
fix(membership-fees): add DB constraints for enum and decimal precision
All checks were successful
continuous-integration/drone/push Build is passing
ebbf347e42
feat: implement calendar-based cycle calculation functions
All checks were successful
continuous-integration/drone/push Build is passing
822d06ed54
Add CalendarCycles module with functions for all interval types.
Includes comprehensive tests for edge cases.
refactor: improve CalendarCycles API and tests based on code review
All checks were successful
continuous-integration/drone/push Build is passing
b257c9897f
docs: fix CalendarCycles documentation to match actual implementation
All checks were successful
continuous-integration/drone/push Build is passing
ecddf55331
feat: implement automatic cycle generation for members
All checks were successful
continuous-integration/drone/push Build is passing
162d06da21
- Add CycleGenerator module with advisory lock mechanism
- Add SetMembershipFeeStartDate change for auto-calculation
- Extend Settings with include_joining_cycle and default_membership_fee_type_id
- Add scheduled job skeleton for future Oban integration
- Replace Application.get_env(:mv, :env) with :sql_sandbox config
- Remove redundant :env config from test.exs
- More explicit and less error-prone for test environment detection
- Log warnings when cycle generation fails in Member create/update
- Extract generate_fn to reduce code duplication
- Improves debuggability of silent failures
- Add warning logging for unexpected errors (not missing prerequisites)
- Use CalendarCycles.interval() type instead of generic atom()
- Update moduledoc to reflect actual usage (no where clause needed)
- Remove exit_date filter from generate_cycles_for_all_members query
- Inactive members now get cycles generated up to their exit_date
- Add tests for inactive member processing and exit_date boundary
- Document exit_date == cycle_start behavior (cycle still generated)
- Handle Task crashes in async_stream with {:exit, reason}
- Return {:error, {:partial_failure, successes, errors}} when some cycles fail
- Previously returned {:ok, successful} even on partial failures
- Improves debuggability and allows callers to handle partial failures
- Replace weak assertions (>= 0, if length > 0) with concrete expectations
- Remove unnecessary Process.sleep calls (tests run synchronously)
- Add get_member_cycles helper for direct cycle verification
- Tests now validate actual generated cycles instead of relying on async behavior
- Change algorithm to start from last existing cycle instead of start_date
- Deleted cycles (gaps) are no longer automatically filled
- Add test to verify gaps remain unfilled
- Update documentation to clarify gap handling behavior
- Add create_member_with_cycles helper that uses fixed 'today' date
- Update tests to use explicit 'today:' option instead of Date.utc_today()
- Prevents test failures when current date changes (e.g., in 2026+)
- Tests now explicitly delete and regenerate cycles with fixed dates
- Ensures consistent test behavior regardless of execution date
fix: handle Ash notifications in CycleGenerator transactions
All checks were successful
continuous-integration/drone/push Build is passing
e6ac5d1ab1
- Use return_notifications?: true when creating cycles within transaction
- Collect notifications and send them after transaction commits
- Prevents 'Missed notifications' warnings in test output
- Notifications are now properly sent via Ash.Notifier.notify/1
moritz added 1 commit 2025-12-12 17:41:42 +01:00
refactor: improve cycle generation code quality and documentation
All checks were successful
continuous-integration/drone/push Build is passing
82897d5cd3
- 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
moritz added a new dependency 2025-12-15 21:38:28 +01:00
moritz added a new dependency 2025-12-15 21:38:52 +01:00
moritz force-pushed feature/277_cycle_generation from 82897d5cd3 to 5acf4364fa 2025-12-16 15:07:11 +01:00 Compare
moritz force-pushed feature/277_cycle_generation from 5acf4364fa to ed083830b9 2025-12-16 16:40:20 +01:00 Compare
requested review from carla 2025-12-17 07:59:45 +01:00
carla approved these changes 2025-12-17 10:55:15 +01:00
carla left a comment
Owner

Nice work :)
Just the small thing with the docs.
And I asked myself if it might be performance wise an issue if a lot of members are imported the first time...

Nice work :) Just the small thing with the docs. And I asked myself if it might be performance wise an issue if a lot of members are imported the first time...
@ -80,7 +80,7 @@ defmodule Mv.Membership.Member do
argument :user, :map, allow_nil?: true
# Accept member fields plus membership_fee_type_id (belongs_to FK)
Owner
  • membership fee start date
+ membership fee start date
@ -12,2 +12,4 @@
- `member_field_visibility` - JSONB map storing visibility configuration for member fields
(e.g., `%{"street" => false, "house_number" => false}`). Fields not in the map default to `true`.
- `include_joining_cycle` - Whether to include the joining cycle in membership fee generation (default: true)
- `default_membership_fee_type_id` - Default membership fee type for new members (optional)
Owner

Good idea!

Good idea!
moritz marked this conversation as resolved
@ -0,0 +128,4 @@
- Has a membership_fee_type assigned
- Has a join_date set
- Is active (no exit_date or exit_date >= today)
Owner

We thought about payment status "suspended", should we keep that in mind somehow?

We thought about payment status "suspended", should we keep that in mind somehow?
Author
Owner

The suspended status is implemented in another issue

The suspended status is implemented in another issue
moritz marked this conversation as resolved
moritz merged commit ff39448fd6 into main 2025-12-18 11:53:12 +01:00
moritz deleted branch feature/277_cycle_generation 2025-12-18 11:53:12 +01:00
Sign in to join this conversation.
No description provided.