Association blueprint

(albert) #21

I think it should be noted that many associations have some kind of “honour” members who do not pay for their membership.

(Cédric Krier) #22

I think this can work with a request of amount 0 which will be considered as paid.

(Sergi Almacellas Abellana) #23

IIUC the period should be configurable as some associations manage their membership on a yearly period and others on monthly, trimester, etc.

How should this period be defined?

(Cédric Krier) #24

Why not let the user choose the dates?

Indeed there could be a model that store each period (from-to) and on it for each membership type, there will be the price. So instead of a wizard, it will be a button on this model that create the request.

(Luca Cristaldi) #25

I think this will fit most user cases (or at lest it fits mine)

Ok, what state a membercan be? i propose:

  • draft
  • pending (for approval)
  • unpaid
  • payed
  • expelled (this should be manual i think)

I like this solution, yes i think we don’t need to have a history of all the membership fee amount. Should we use the product category for this (maybe add a new type)

I’m prone to reuse the rrule of the subscription module (or create something similar specific to this module). The problem of the rrule is that will not trigger for the first instance, but i think the module can create a move, and then use the rrule.

I feel confident enough this will be the final solution, so I’ll try to draft (very roughly) something this weekend

(Cédric Krier) #26

I do not see the point of having two states. A draft membership is the same as pending.

I think the payment status should be different from the state. So I would have a running state and another field which provides paid Boolean for the current date.

I would named it stopped.

(albert) #27

I would agree with distinguishing between draft and pending for approval. The cases I know, candidates must provide certain information before they’re considered for approval. So having a draft state seems convenient waiting for all the information to be provided.

(Cédric Krier) #28

No it is not necessary and create extra burden. If there are some requirements to met to be running, then it should be managed with a condition on the transition (and there could be a domain to find those).

(Luca Cristaldi) #29

The only motivation i can think of to have an intermediate state is:
If someone goes from stopped/expelled to edit(or pending) they should maintain the same code(and same record)

user case

A member have some unpaid membership fee, and you want to force him to pay all the past dept before being accepted.
I think the norm(and please correct me if i’m wrong) is overwrite the past code of the record when you go to the next state.

This i think can be the only reason (if assumption above is correct) to have a separate state from edit.

(Cédric Krier) #30

I think the stopped state should be finale. Re-introduce back a member should be done using a new membership.

He can not have dunning if he is not yet running.

I do not understand.

(Luca Cristaldi) #31

I’m fine with this. So i think we can reduce all the state to:

  • draft
  • running
  • stopped

Now lets discuss how to organize the membership part:
I’m proposing to re-use the product model, and adding a “membership” type.
This is the structure i have in mind:

  • association.membership.line:
    • member (many2one of association.member)
    • description
    • membership (a product of type membership)
    • uom
    • quantity
    • unit_price
    • from_date (default to_date from the last membership line)
    • to_date
    • payment_lines (all the payments line associated to this one)
    • membership_move (the move to pay)
    • state (function field: Boolean for paid/unpaid)
  • association.member
    • membership (many2many of association.membership.line)

What do you think?

(Cédric Krier) #32

I would name it association.membership.fee.

I do not think it is needed.

I do not think it needs to be a product because we do not need any of the accounting stuffs (account, taxes etc.)
I think we need to have a membership fee type which can be used to define the price per period and for how much members.

I think a fee could be linked to multiple members. E.g. there is often family pack.

I think we should consider that the periods are common to all members (or at least some part). So we would need a association.membership.period.
But maybe there could be different kind of period (e.g. per month and per year). So a member should be subscribe to one kind. But this may be too complex for simple association and so I think the multiple period should be managed by a second module (but initial module should take care to leave room for that).

It should be account.move.line and it will be used only for technical usage. A relate should open them for the accountant (like paybale/receivable on party).

There should be no move to pay. Because it is not a debt, it is just a request to renew the membership.

(Luca Cristaldi) #33

Fair enough.

In my user case this is frowned upon, but I think this should be fine to implement (and I like the idea)

well, I still need to define an account receivable and an account for revenue (see last paragraph TL;DR: fees due are debt). The product model gives me that. If i can reuse it, i will.

I don’t understand, you mean crate a model for membership type, or add a type to the product model (i think is the former… but I’m not sure)

Mmmm, the module main goal (or it was initially) is to keep track of membership fee they are due (so they are a debt in my view). I need to register it as such, in Italy the fee is mandatory.
How the dunning module will work without a receivable move? (maybe this is not the correct phrasing, but i hope the message is clear) Is not a rhetorical question because i didn’t use this module much.

(Cédric Krier) #34

On a second though, I think it is better to keep a Many2One.
So the family case could be solved by having a single member link to a main party but with extra parties for the family members.

The receivable is given on the party.

Well in my initial thoughts, it would have been filled on the statement.

But now, I think it may be useful that the membership.fee creates a draft move that will be posed when the statement tries to reconcile it (a little bit like account_payment_clearing).

I mean create a new model association.membership.type which will hold:

  • prices per period (multivalue)
  • revenue account (multivalue)
  • number of linked member allowed etc.

(Jean-Christophe Michel) #35

In many associations I know, there can be two kinds of members with different amounts paid. Having a product would be a simple way to store these amounts.

(Luca Cristaldi) #36

mmm, I don’t think this is necessary… or at least i think it should be a separate module.

I modified the top post with all the feedback gathered so far (I hope is correct, if not please edit or discuss it here).

I drafted the structure the association.membership.type as so:

  • association.membership.type
    • name
    • period
    • fee_amount
    • revenue (the revenue account, if not specified use the one indicated int he parent type)
    • receivable (default to the party receivable if not specified, or use the parent account)
    • parent
    • children

My only doubt is the receivable account: should i use the party default one alone, or have the ability to define it in the type?

now i want to discuss how to create the association.membership.period:
The easiest way is to have this (or at least i think is the simplest way):

  • name
  • from_date
  • to_date

and the have a wizard that generate new periods based on user input (like +1Year, +1Month, a end date ecc…).
The wizard will take the record with the latest to_date and copy it with the from/to date changed accordingly. For this to wort the should not be any overlap, so this will limit to only one period per association.
We can have a period type and have multiple period that can overlap (like @ced suggested), I’m not thinking to implement it in this module unless there is a strong reason/user case that will benefit from such feature.

(Cédric Krier) #37

I think the fee amount should be defined by a list with a from date. So to compute it will take the last amount with a from date before the period date. (Similar to the cost price of employee).

I do not see the point to make a tree structure.

Receivable should always be taken from party.

Yes it should be similar to the fiscal year.
But I think we should allow different kind of period (e.g. monthly, quaterly, yearly etc.). But it should just be a name. It does not require to have any frequency defined.
I do not know how we can call that. But it will be set on period and on membership.type

If it is not implemented in base, it will not be possible to extend the module to add it.

(Luca Cristaldi) #38

If I structure it more like the Fiscal year periods the “type”(like a product type) is not necessary: so we have something like:

  • membership.TBD

    • name
    • periods (a many2many field with period lines)
  • memership.period.line (TBD name)

    • name
    • to_date
    • from_date (so we can have non contiguous periods, dunno… summer vacation?)
    • fee (the fee amount)

and like the fiscal year, two wizard:

  • For generating contiguous periods (like Monty, weekly ecc…)
  • For creating a new “membership.TBD”(the one that collect all the period line) based from the one you select, but will add a year to all the period date.

then a wizard can generate all the fee lines (association.membership.fee) based on the “membership.TBD” the join_date and the leave_date (association.member ). (need to add “membership.TBD” filed to the “association.member” for this to work")

Sorry, but i think i misunderstood you. Can you elaborate more on this?

Thank you for all the feedback (specially @ced)

(Luca Cristaldi) #39

Ok, I’m proposing this structure:

  • association.membership
    • name
    • periods
    • account_revenue
    • company (from CompanyMultiValueMixin)
  • association.membership.period
    • name
    • start_date
    • end_date
    • fee_amount
    • membership (many2One)
    • company (function)
  • association.membership.fee
    • sequence (from sequence_ordered)
    • member (many2one of association.member)
    • fee_amount (multivalue)
    • period (the association.membership.period associated to this line)
    • payment_lines (a function field, like the one in the invoice model)
    • membership_move (the account.move.line associate with this fee line)
    • state (a function field with selector field, so you can check if the line is payed or not)
    • company (from CompanyMultiValueMixin)

and for the member:

  • association.member
    • state
    • code (read-only, set by member_sequence)
    • company (taken from context)
    • request_date (maybe this is not necessary)
    • join_date
    • leave_date
    • memberships (Many2Many to association.membership)
    • membership_fees (many2one field with all the association.membership.fee lines)

The new idea is that a member can have multiple “membership”(association.membership). with association.membership model is now possible to do so.

the association.membership in short:

  • there is no state to a membership (not like a fiscal year, and there is no need)
  • the association.membership defines the account revenue.
  • you need to add a ‘association.membership.period’, and the the wizard/cron job will generate all the association.membership.fee for each member based on a given date.

the association.membership.fee in short:

  • defined by a start-end date
  • the price can vary between periods

If there are no other comment/necessary feature to implement, I’ll start to program the module with this structure/feature

(Cédric Krier) #40

I do not see the point. For me, the order should be based on start_date of the linked period.

I would name it simply amount.
I do not think it should be a multivalue, it should be the value for the linked company.

Just name it move.

I think it is better to name it paid and store the reconciliation date (behave like the reconciled of invoice).

I think the create_date could be enough (or it could be delegated to customization)

I think it should be a One2Many with a Many2One to association.membership. The relation model should have a start and end date (so the join_date and leave_date move to this relation model).
It could still have a join_date and leave_date but they will be Function field computed out of the memberships.