WIP: Payment Concept closes #210 #221

Draft
moritz wants to merge 2 commits from docs/210_payment-concept into main
Owner
No description provided.
moritz self-assigned this 2025-11-27 21:31:50 +01:00
moritz added 1 commit 2025-11-27 21:31:52 +01:00
docs: payment concept
All checks were successful
continuous-integration/drone/push Build is passing
7d38a76e78
moritz added this to the Sprint 9: 20.11 - 11.12 project 2025-11-27 21:31:52 +01:00
requested reviews from simon, carla, rafael 2025-11-27 21:35:40 +01:00
carla approved these changes 2025-12-01 08:47:32 +01:00
carla left a comment
Owner

Great work!! 💯
very detailed and you already thought of all the small things :)
I just have some minor comments!

Great work!! 💯 very detailed and you already thought of all the small things :) I just have some minor comments!
@ -0,0 +145,4 @@
- `contribution_start_date` (Date, nullable)
**Existing Fields Used:**
- `joined_at` - For calculating contribution start
Owner

We should keep that in mind for member_fields, that joined_at and left_at should be member_fields.

We should keep that in mind for member_fields, that joined_at and left_at should be member_fields.
moritz marked this conversation as resolved
@ -0,0 +234,4 @@
- `mark_as_suspended` - Set status to :suspended
- `mark_as_unpaid` - Set status to :unpaid (error correction)
**Bulk Operations:**
Owner

Maybe we give bulk operation a lower prio for now

Maybe we give bulk operation a lower prio for now
moritz marked this conversation as resolved
@ -0,0 +80,4 @@
- id (UUID)
- name (String) - e.g., "Regular", "Reduced", "Student"
- amount (Decimal) - Contribution amount in Euro
- interval (Enum) - :monthly, :quarterly, :half_yearly, :yearly
Owner

I am a bit confused about the interval being connected to the type here on a global level. Isn't it more a member level decision if the member wants to pay monthly or yearly? If I allow the members to pay monthly OR quarterly would it mean I need to add two seperate contribution types?
I get that this makes calculations easier, right? And also the amount is clearly defined per interval. We just need to communicate that in a good way to the user.

I am a bit confused about the interval being connected to the type here on a global level. Isn't it more a member level decision if the member wants to pay monthly or yearly? If I allow the members to pay monthly OR quarterly would it mean I need to add two seperate contribution types? I get that this makes calculations easier, right? And also the amount is clearly defined per interval. We just need to communicate that in a good way to the user.
Author
Owner

I think it's a decision what is allowed on a global level. Should there be monthly payments, or only yearly.
Also the amount should be connected to the interval.
For example:

  • Default yearly Membership: 150€
  • Default monthly Membership: 10€
  • Special yearly Membership: 300€
I think it's a decision what is allowed on a global level. Should there be monthly payments, or only yearly. Also the amount should be connected to the interval. For example: - Default yearly Membership: 150€ - Default monthly Membership: 10€ - Special yearly Membership: 300€
Owner

I stumpled upon this, too and I think it's a question how we handle this in the UI.

e.g. if I want to allow monthly, quarterly, half-yearly and yearly subscriptions and have 3 types of subscriptions, I have to model them by myself and find a naming scheme that supports me in the way these fee types are sorted:
Regular - monthly
Regular - quarterly
Regular - half yearly
Regular - yearly
Reduced - ...
Reduced - ...
Reduced - ...
Reduced - ...
Student - ...
...

Might be just an edge-case, but the task to create some kind of similar structure remains nevertheless.

I wonder whether we actually need to differentiate which fee type can be yearly, monthly etc. yet.
And if so, i'd argue that we should specify an enum set for the fee types and name it "allowed intervals" to then be able and set the actual interval member-specific.
Feels cleaner to me

Actually I wonder whether an additional resource would fit the domain better:

  • We have a member
  • member can have multiple contributions, which have at least a contribution type, interval and validity period
  • based off those contributions, we generate contribution periods that reflect the payment intervals. or maybe even call it payment period

because i think the periods in which payments have to be made and checked are a different concept to those periods that a specific payment type is active for a user - and handling those via the same resource feels a bit complicated

I stumpled upon this, too and I think it's a question how we handle this in the UI. e.g. if I want to allow monthly, quarterly, half-yearly and yearly subscriptions and have 3 types of subscriptions, I have to model them by myself and find a naming scheme that supports me in the way these fee types are sorted: Regular - monthly Regular - quarterly Regular - half yearly Regular - yearly Reduced - ... Reduced - ... Reduced - ... Reduced - ... Student - ... ... Might be just an edge-case, but the task to create some kind of similar structure remains nevertheless. I wonder whether we actually need to differentiate which fee type can be yearly, monthly etc. yet. And if so, i'd argue that we should specify an `enum set` for the fee types and name it "allowed intervals" to then be able and set the actual interval member-specific. Feels cleaner to me Actually I wonder whether an additional resource would fit the domain better: - We have a `member` - member can have multiple `contributions`, which have at least a `contribution type`, `interval` and `validity period` - based off those contributions, we generate `contribution periods` that reflect the payment intervals. or maybe even call it `payment period` because i think the periods in which payments have to be made and checked are a different concept to those periods that a specific payment type is active for a user - and handling those via the same resource feels a bit complicated
@ -0,0 +137,4 @@
### Global Settings
```
key: "contributions.include_joining_period"
Owner

I like that you thought about this setting!

I like that you thought about this setting!
moritz marked this conversation as resolved
@ -0,0 +321,4 @@
**Quick Marking:**
- Checkbox in each row for fast marking
- Button: "Mark selected as paid"
Owner

Just a minor thing: [Mark as unpaid / suspended] as addition.

Just a minor thing: [Mark as unpaid / suspended] as addition.
moritz marked this conversation as resolved
@ -0,0 +429,4 @@
**UI Notice on Exit:**
```
⚠ Unpaid contributions present
Owner

If we decide for this warning, maybe we add that also to settings that people can omit that? Or we add the warning + setting as low priority new issue, because I don't think it is that important to have that for now.

If we decide for this warning, maybe we add that also to settings that people can omit that? Or we add the warning + setting as low priority new issue, because I don't think it is that important to have that for now.
moritz marked this conversation as resolved
@ -0,0 +453,4 @@
│ 2025 │ Yearly │ 60 € │ ☐ Open │ [ ] │
└───────────────┴──────────┴────────┴──────────┴─────────┘
[Mark selected as paid] (2 selected)
Owner

User could also mark two as suspended here, right? So we would need "mark as paid/unpaid/suspended" depending on the current state right?

User could also mark two as suspended here, right? So we would need "mark as paid/unpaid/suspended" depending on the current state right?
moritz marked this conversation as resolved
moritz added 1 commit 2025-12-01 15:43:11 +01:00
resolve review issues
All checks were successful
continuous-integration/drone/push Build is passing
d79205e75d
simon requested changes 2025-12-02 12:40:06 +01:00
simon left a comment
Owner

Looks very solid!
I'd argue for adding an intermediate resource between member and contribution_period as you can see from my comments

Looks very solid! I'd argue for adding an intermediate resource between member and contribution_period as you can see from my comments
@ -0,0 +1,651 @@
# Membership Contributions - Technical Architecture
Owner

Could we call it "Membership Fee"?
Think that translation fits the context better

Could we call it "Membership Fee"? Think that translation fits the context better
@ -0,0 +82,4 @@
- amount (Decimal) - Contribution amount in Euro
- interval (Enum) - :monthly, :quarterly, :half_yearly, :yearly
- description (Text, optional)
- timestamps
Owner

I don't get what the timestamps are supposed for

I don't get what the timestamps are supposed for
@ -0,0 +123,4 @@
- contribution_type_id (FK → contribution_types.id, NOT NULL, default from settings)
- contribution_start_date (Date, nullable) - When to start generating contributions
- left_at (Date, nullable) - Exit date (existing)
```
Owner

feels like another argument for a dedicated resource, as the contribution relevant information is spread across multiple resources where it all has a clear context and could be handled in one place

feels like another argument for a dedicated resource, as the contribution relevant information is spread across multiple resources where it all has a clear context and could be handled in one place
@ -0,0 +285,4 @@
- "Unpaid contributions in last period"
- "Unpaid contributions in current period"
### Member Detail View
Owner

I'd like if we continue the concept that all values from the member detail view can (optionally) also be shown in the membership overview.

And if thats too much information at once, i'd perspectively be able to define custom views (just with preset filters and sorting), that show up as sub-menu, like

  • Membership overview
  • Contributions overview

and thus can be customized to the users likings and needs just as our default overview

I'd like if we continue the concept that all values from the member detail view can (optionally) also be shown in the membership overview. And if thats too much information at once, i'd perspectively be able to define custom views (just with preset filters and sorting), that show up as sub-menu, like - Membership overview - Contributions overview and thus can be customized to the users likings and needs just as our default overview
@ -0,0 +353,4 @@
Impact:
- 45 members affected
- Future unpaid periods will be generated with 65 €
- Already paid periods remain with old amount
Owner

how do we handle this?
if we change the entry in database and rely on it for calculations of old periods - that won't work I guess?

how do we handle this? if we change the entry in database and rely on it for calculations of old periods - that won't work I guess?
Owner

ah, got it, from the amount in the contribution period

ah, got it, from the amount in the contribution period
@ -0,0 +368,4 @@
Selected: "Regular (60 €, Yearly)"
This contribution type is automatically assigned to all new members.
Can be changed individually per member.
Owner

I read it as, its just pre-selected when I create a new member, but if I select something else from the drop-down I don't have to change it individually later, right?

Description is a little misleading

I read it as, its just pre-selected when I create a new member, but if I select something else from the drop-down I don't have to change it individually later, right? Description is a little misleading
@ -0,0 +372,4 @@
---
☐ Include joining period
Owner

important to handle this - but we should check-in with the pilot organizations on how they actually handle it. As it affects the money members pay and organizations receive, this is rather important.

e.g. is there a need to include "partly" payment periods? Maybe not daily, but if we only have a yearly regular fee, should ppl still be able to be "billed" only the remaining 2-3 months or so?

important to handle this - but we should check-in with the pilot organizations on how they `actually` handle it. As it affects the money members pay and organizations receive, this is rather important. e.g. is there a need to include "partly" payment periods? Maybe not daily, but if we only have a yearly regular fee, should ppl still be able to be "billed" only the remaining 2-3 months or so?
rafael requested changes 2025-12-02 14:15:13 +01:00
rafael left a comment
Collaborator

Questions for organizations:

  • What are the different payment intervals you offer?
  • Do you have different amounts / "payment plans"?
  • What are common support requests regarding fees?
  • Do payments start at the entry date of the member, or when a new year begins?
  • Do you change bills retroactively? E.g. the amount, due date
  • Are there partial payment intervals?
  • What happens when members can't or won't pay? Are they suspended?
Questions for organizations: - What are the different payment intervals you offer? - Do you have different amounts / "payment plans"? - What are common support requests regarding fees? - Do payments start at the entry date of the member, or when a new year begins? - Do you change bills retroactively? E.g. the amount, due date - Are there partial payment intervals? - What happens when members can't or won't pay? Are they suspended?
@ -0,0 +169,4 @@
**Algorithm:**
1. Get `member.contribution_start_date` and `member.contribution_type`
Collaborator

this should probably lock the whole contribution period table for the duration of the algorithm.

this should probably lock the whole contribution period table for the duration of the algorithm.
rafael changed title from Payment Concept closes #210 to WIP: Payment Concept closes #210 2025-12-02 15:53:31 +01:00
rafael removed this from the Sprint 9: 20.11 - 11.12 project 2025-12-02 16:13:17 +01:00
All checks were successful
continuous-integration/drone/push Build is passing
This pull request is marked as a work in progress.
This branch is out-of-date with the base branch
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin docs/210_payment-concept:docs/210_payment-concept
git checkout docs/210_payment-concept

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git checkout main
git merge --no-ff docs/210_payment-concept
git checkout docs/210_payment-concept
git rebase main
git checkout main
git merge --ff-only docs/210_payment-concept
git checkout docs/210_payment-concept
git rebase main
git checkout main
git merge --no-ff docs/210_payment-concept
git checkout main
git merge --squash docs/210_payment-concept
git checkout main
git merge --ff-only docs/210_payment-concept
git checkout main
git merge docs/210_payment-concept
git push origin main
Sign in to join this conversation.
No description provided.