Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FR: Register expenses for non-users #4

Open
max-tet opened this issue Oct 4, 2022 · 17 comments
Open

FR: Register expenses for non-users #4

max-tet opened this issue Oct 4, 2022 · 17 comments
Labels
enhancement New feature or request non-trivial

Comments

@max-tet
Copy link

max-tet commented Oct 4, 2022

It seems like right now, everyone participating in a group must have an account and register their own expenses. But often, there is a single user in a group whom everyone tells what they paid and who keeps track of everything. It would be great if money-balancer would support that.

It would mean adding participants not as users but only as names. And when registering an expense, select one of those names.

@dorianim
Copy link
Owner

dorianim commented Oct 4, 2022

Hmm not so sure about that. What if someone is created as a "name only" member and later registers and wants to join as a regular member, ther'd have to be a way to merge them.

A solution to taht would be to create personalized invite links, wich are used as "name only" for as long as nobody used them to join. But I feel like this is too complex right now. I'd like to focus on the core features first, since I don't have so much time.

But I'd be happy to consider a different approach or even a PR.

@max-tet
Copy link
Author

max-tet commented Oct 4, 2022

Ok, good points. Maybe you could proceed iteratively. Step 1) Introduce name-only members, which should be simple. Step 2) Allow an admin to transfer name-only transactions to a registered user which might be a little more complex. You know, avoid premature optimization, implement quick wins that are needed now and improve on it later.

Step 1) would be very benefitial, even without step 2) I believe. At least in my groups of friends, we trust each other enough that a single person can track expenses but not all want to create yet another account with yet another service.

Unfortunately I have no clue about Rust, so I cannot contribute myself, sorry.

@dorianim
Copy link
Owner

dorianim commented Oct 4, 2022

Creating name-only members is not that simple. The database has a table for users and the id of a user is the foreign key for the creditor / debtor of a transaction. Not sure how to handle name-only users right now...
Maybe I need to give the member of a group an id and use that id, and then I can have a name-only member which can be converted into a member. But this will be a major change.

This has to be thought out well, so it doesn't lead to a ton of technical debt and problems in the future.

@dorianim dorianim added enhancement New feature or request non-trivial labels Oct 4, 2022
@max-tet
Copy link
Author

max-tet commented Oct 4, 2022

In OOP-speak, you have a superclass: User and two subclasses: real user and name-only user. There are proven ways to design a DB schema for that, see e.g. here: https://stackoverflow.com/questions/3579079/how-can-you-represent-inheritance-in-a-database

In your case, Single Table Inheritance should probably suffice. This should also be the easiest one to add.

@dorianim
Copy link
Owner

dorianim commented Oct 4, 2022

Yea, but I'll still have to change everything to use a member id instead of a user id. Since It's not a User with two subclasses, but a GroupMember with to subclasses (DummyMember and UserMember or something like that).

@dorianim
Copy link
Owner

dorianim commented Oct 4, 2022

But I like this approach, it gives even more flexibility:

  • Should a user decide to leave the group, the usermember could just be turned into a dummymember
  • Should there be any other types of members, e.g. from a remote server via federation in the future, thsi would also work

@max-tet
Copy link
Author

max-tet commented Oct 4, 2022

Ok, I'm not sure where the difference is between member and user. But yeah, this would be the general idea.

@dorianim
Copy link
Owner

dorianim commented Oct 4, 2022

There is a m:n relation between user and group (many users have many groups). So you need an additional table to make this possible. This table contains memberships of users in groups.
So one user can have multiple groups, and therefore be a Member of multiple groups. A Member can only have one group. As a Dummy can only be used in one group, the dummy has to be on the layer of the Member and not the user.

@max-tet
Copy link
Author

max-tet commented Oct 4, 2022

Ah, so Member is actually the relationship. Probably a table with two columns: 1) foreign keys of users, 2) foreign keys of groups.

A Dummy can only be used in one group

Why? Would it not even be better if a name-only user can be used across groups? The actual person could also be in multiple groups so the name-only user should, too. And it would be much simpler to implement. Also if you want to convert them to "real" users at some point, this would be much easier.

@dorianim
Copy link
Owner

dorianim commented Oct 4, 2022

This would make things super complicated. And also has another problem:
If dummys are users and an existing user wants to take ownership of a dummy, all occurrences of the dummys ID would have to be changed to the users ID. A Member, on the other hand, could just be changed to be a dummy or a user by altering a single column in the database of that member.
Also, what if the user wants to actively participate only in some of the groups where a dummy for them exists? This can only be properly implemented when the dummy is member-dependent.
And even more problematic: How would permissions be handled for that dummy? Can everybody use it, or only the user who crated it? In the latter case, there will be multiple dummys in case the user needs a dummy in groups of different people.
It'd be a huge mess and cause lots of cunfusion.

@max-tet
Copy link
Author

max-tet commented Oct 5, 2022

Ok, maybe you caught a case of analysis paralysis there? 😉

If I were you, I'd forget the corner cases right now. You have to decide on one way the feature works and it is ok to be opinionated about it.

I would have a user with two types: normal and dummy. Both are in the same table and there is an enum column containing the type. When converting a dummy to a normal user, you just have to change the type and fill some other columns but there is no need to change any other table.

Also, what if the user wants to actively participate only in some of the groups where a dummy for them exists?

I would forget that. If it turns out, someone wants that, it can be implemented later. Avoid premature optimization.

How would permissions be handled for that dummy?

The admin of the app is the only one who can convert dummys to normal users. Keep it simple.

@dorianim
Copy link
Owner

dorianim commented Oct 5, 2022

The admin of the app

There is no admin...

Avoid premature optimization.

This is an unfortunate approach in my opinion, as it always leads to a ton of technical debt and problems later on.

@max-tet
Copy link
Author

max-tet commented Oct 5, 2022

There is no admin...

Oh. Don't you have users who have more permissions than others? Some who can create/delete groups and some who can only participate?

This is an unfortunate approach in my opinion, as it always leads to a ton of technical debt and problems later on.

Yes, that can happen and then the debt must be repaid by refactoring your code. But that is normal. Technical debt is not to be avoided at all cost, it must merely be managed and not allowed to accumulate too much. At least that is how it works best in my experience.

Consider what happens if you try to anticipate every requirement beforehand and make lots of effort to fulfill them. And then it turns out, noone needs them in the end but some other things are needed you did not even think about. Then you will have to refactor anyway but you now had twice the effort.

Anyway those are just some things I learned along the way, your mileage may vary.

@dorianim
Copy link
Owner

dorianim commented Oct 5, 2022

Oh. Don't you have users who have more permissions than others?

Nope, I'd like to keep it simple.

And then it turns out, noone needs them in the end but some other things are needed you did not even think about. Then you will have to refactor anyway but you now had twice the effort.

That's a fair point.

I still want to implement this on the Member-level, tough, because I think, I'll be less work in the long run. Let's agree to disagree here :)

@max-tet
Copy link
Author

max-tet commented Oct 6, 2022

Sure, absolutely! Didn't wanna push my view, sorry if it came across that way.

Also, without a kind of admin user, your approach makes a lot more sense.

@dorianim dorianim changed the title Feature Request: Register expenses for someone else FR: Register expenses for someone else Oct 11, 2022
@Szeraax
Copy link

Szeraax commented Oct 13, 2022

Another option would be to still require them to have real account, but make it possible to designate who is paying for something. E.g. I can add a transaction on behalf of another user. It would show "purchased by" with the name of the person you select. And you would add another line for something like an "entered by" that would show my name.

Something like this:
image

You could then add a single-select box called "Payer" or "provider" or something down below Consumers to select which user is actually paying the money. A la:
image

@dorianim
Copy link
Owner

You are right, that should be in a different issue, though.

@dorianim dorianim changed the title FR: Register expenses for someone else FR: Register expenses for non-users Oct 13, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request non-trivial
Projects
None yet
Development

No branches or pull requests

3 participants