Recursive Circles
This proposal proposes a slight rework of the Circle concept, adding mainly recursion and changing some small things.
Current situation
To the right you can see the current connections between Circles
New situation
Changing Global Circles to recursion
Looking at actual use-cases the current proposal using Global rules definitely makes sense: this would probably suffice in most cases. Looking at it implementation wise however it does not really make a lot of sense. Implementing it this way made it clear to me that the two classes have a very high amount of overlap and causes the API to be a bit wonky.
As both GlobalCircles and BodyCircles are nearly identical, the difference being a relation to a body and parent Circle I propose to remove the concept of a GlobalCircle and letting instead have a single Circle be able to store a parent Circle on top of a contextual body it is related to.
Aside from cleaning up the code and API, this would remove the unnecessary limit that is currently set on having a tree depth of 1 and adds additional future flexibility, even now allowing a root Circle (prev. GlobalCircle) to be linked to a body, which can be used for example to link commission assistants to the commission Body itself. Mostly, it has nearly no downsides, in practice it will likely mostly be used for a 2-level tree, but why restrict it on a DB level? If we want to restrict this it would be better done through logic.
The new proposal can be seen on the right.
Wonky API example:
Having a different endpoint for selecting a single circle dependent on the Circle type:
api/circles/bodies/{circle_id} api/circles/global/{circle_id}
Linking circles to Users as opposed to BodyMemberships
Before circles were linked to BodyMemberships, which in turn could be linked to User, a construction which I think can be improved upon while having the same semantic properties.
The way BodyMemberships are set up is that a User can have multiple, and each of those memberships belongs to a single Body (lets say Local). With the addition of Circles it no longer makes sense to have multiple memberships to the same Body, instead Circles take care of having multiple roles within that Body, the membership could be seen as memberships fee that are being paid, which in turn gives me the only logical case I can think of in what way one could have multiple memberships: by paying multiple fees. From this argumentation I will assume that in virtually all cases a User will have 1 BodyMembership between him and the Body.
What this means is that when linking a User to Circles within that Body, there will always be one BodyMembership to which the Circles will be linked, the fact that DB-wise a User could have multiple BodyMemberships between the same Body is unused. Additionally, very common use cases will be to get all the Users from a Circle, this will be far more frequent than using any of the other fields of BodyMemberships. The new linking optimizes for that: the linking makes it easier and quicker to access all the Users belonging to a Circle. Getting all the Circles within a Body that a User is member of is slightly more complicated, but again this will most likely be less used compared to getting all the Users in a Circle.
Finally, optimizations aside, the new linking actually allows some useful new relations: A User can be a member of a Circle without being in a Body. This can be a very useful use case for Users who need to be in a GlobalCircle (now root Circle), for example Having IT oldies still present in the IT root Circle, without being related to a Body. Additionally, by removing the DB-level constraint of having to belong to the Body the Circle is related to, it is now also possible to have a User join a circle of a Body he is not a member of. While this will probably not be an often used use case, again it provides additional flexibility that might become useful in the future. (One use case could be helping another Body with some kind of committee (maybe twin locals?))
Concluding, I believe that linking Circles to Users directly is more efficient and offers greater flexibility without having significant disadvantages.
Adding positions within a Circle
While Circles are intended to be used to differentiate between groups within a Body, differentiating between positions in a Circle (let's say a Local's board) is not possible. (Actually with recursive Circles it is possible, yet this could be considered overkill).
What would be useful is to have a single String that specifies the position (for example: 'Treasurer'). In stead of having this simply be a String inside the membership of a circle, it is better to have these globally defined, in order to have it consistent across bodies and be able to filter on these positions better. For this reason I propose having a separate table for keeping track of positions, and being able to choose from them when assigning a User to a Circle. In most (default) cases this position would just be 'member', in this case I propose to leave the reference empty, as in my opinion member mostly means undefined position.
An alternative to a new table would be to have an enum field inside the DB, yet I think it is better not to restrict this on a DB-level and instead do this with logic.
Summing up
While I have made the diagrams in an incremental way, all these 3 improvements could really be implemented separately.
However, While implementing the first version of the Circle concept I realized these issues and thought of these improvements, I personally believe all of them are good additions and I would love to hear any other comments / feedback / improvements on them.