OCA / contract

GNU Affero General Public License v3.0
171 stars 524 forks source link

Implementation of a 'Contract group' notion #200

Closed gva-acsone closed 5 years ago

gva-acsone commented 6 years ago

Hello,

Problem with periodical contract changes

I find it currently really difficult to deal with periodical upsells / downsells / suspensions / contract product changes, i.e when a contract is modified, but only for a fixed duration of time. Currently, if I want to apply a periodical upsell for instance, I need to add a new contract line and once the 'periodical upsell period' is reached, a manual action is required by a user to put the quantity on this contract line back to 0. The same is true when I want to apply a periodical contract product modification (example: a customer concludes a contract for a year for product A. But after four months, he asks to try out product B during two months, before switching back to product A for the last six months of the contract. To deal with this situation in the current module, the quantity for product A has to be set to 0 and a new contract line has to be added for product B once the modification period starts. Again, once the modification period ends, a manual intervention is necessary to change the quantity for product A back to its original value and set the quantity for product B back to zero.

This mechanism leads to three problems: 1) Manual actions are required by users at certain moments during the contract life cycle, which will possibly lead to mistakes (product B invoiced for one more month etc...). 2) I find it difficult to understand the history of the contract, i.e what happened with the contract (upsells, downsells, product changes... between the start date and now. The user has to open all the invoices to understand the history of the contract, which is annoying for multi-year contracts. 3) While opening a contract form, users ignore for instance at what time the periodical upsell will end. So, they lack a view on the future of the contract.

I know planned activities and the tracking of certain fields (ex: product, quantity...) on contract lines could be used to avoid a part of these three problems, but we believe an easier way to deal with this use case would be to work with contract groups.

Contract groups

Our plan would be to change the way 'upsells / suspensions / contract modifications' are recorded in the OCA module, without touching / changing the invoicing mechanism, which is crucial.

Our idea is that every 'important' change to a contract leads to the creation of a new contract, linked to the original contract by this new notion of 'Contract group' (explained below) . New buttons on a contract will enable users to trigger three different actions: Suspension, Upsell, Product modification. One contract would correspond to one contract product only.

1° In case of an upsell, the user has to complete four fields in the wizard: Upsell start date ; New contract product related to the upsell; Quantity; Upsell end date (optional). --> The original contract is not modified. However, a new contract is created by Odoo with a start and (eventual) end date and a contract product that correspond to the informations mentioned by the user in the wizard. The contract group mentioned on the original contract will be copied to the new contract, to indicate that those two contracts are related to each other.

2° In case of a suspension, the user has to complete two fields in the wizard: Suspension start date and suspension end date. The suspension end date is not mandatory. --> The suspension start date will be set as the end date on the original contract. If a suspension end date was mentioned, a new contract (copy of the previous one) will be generated by Odoo with a start date that corresponds to the 'suspension end date'. Again, the contract group mentioned on the original contract will be copied to the new contract, to indicate that those two contracts are related to each other.

3° In case of a product change (ex: we change from basic pack to premium pack), the user has to complete 4 fields in the wizard: modification start date; new contract product; quantity ; modification end date (optional). --> The end date of the original contract is filled in with the 'modification start date'. A new contract is created by Odoo with the new contract product (and quantity), a start date that corresponds to the 'modification start date' and an end date that corresponds to the 'modification end date' (in case of a periodic product modification). Again, the contract group mentioned on the original contract will be copied to the new contract, to indicate that those two contracts are related to each other.

Advantages of contract groups

The advantages of this solution are fourfold: 1) The invoicing mechanism is not modified at all. Invoices are still generated in the same way as before. However, a grouping mechanism should maybe be implemented to avoid generating 2 different invoices for a same customer (other issue that will be created soon). 2) The contract upsell/modification/suspension are completed by the user once the information has been received from the customer, even though this action will take place in the future. Afterwards, no manual intervention is required by the user as everything will be computed by Odoo. This avoids a whole serie of possible mistakes. 3) The history of the contract can be easily understood by opening a contract group (new menu in the contract module). All contracts are related to each other by a contract group. So the user just has to open this contract group to find a list view of all related contracts (with their contract product, start date, end date...)... Understanding all the modifications that were brought to a contract (suspensions, modifications, upsells...) will be much clearer now. Moreover, a timeline view could be implemented on the contract groups to present all the modifications brought to a contract visually on a timeline. 4) As the modifications are recorded in Odoo in advance, the user has a clear view on the future of the contract.

What do you think about this new feature? Should it be included in a separate module or in the core module?

Thanks for your feedback / input

gva-acsone commented 6 years ago

cc @sbidoul @sbejaoui

rafaelbn commented 6 years ago

Hello @gva-acsone ,

A contract in fact is an Analytic Account (account.analytic.account) so you are looking for:

Plus (+) some king of nice UX for creating them.

I really recommend to think in https://github.com/OCA/contract/tree/11.0/contract_variable_quantity because you can Define any formula based on Python code that stores at some moment a float/integer value of the quantity to invoice in the variable 'result'.

What do you think @carlosdauden ?

pedrobaeza commented 6 years ago

I would go for this with a more simply approach: adding starting/ending date at contract line level, and being evaluated when generating invoices.

sbidoul commented 6 years ago

Our idea with the contract groups was to leave the contract module mostly unchanged.

@pedrobaeza do you mean adding optional start/end date on contract lines, and using the contract dates if they are not set? So that means moving all fields of the recurrence algorithm down to the line (eg recurring_next_date)? We would probably also need to move the recurrence rule to the line too, using the contract-level rule by default if not set on the line.

That sounds feasible, and at first glance looks better from a UX point of view. It's a major refactoring of the module with a significant migration though.

One thing that worries me is that the invoice line is currently linked to the contract via the analytic account. Hence we can deduce the recurring rules that led to an invoice line. If we move the recurring rule down to the contract line, we would lose that link. Unless we add a link to the contract line on the invoice line?

pedrobaeza commented 6 years ago

Well, I was talking more about validity dates at contract line. Something similar to pricelist validity dates.

We have here several concepts:

  1. Different prices/lines through time for the same contract. For example, first 3 months of a contract, there's a discount of the fee, and after that, you have full price.

    This is the concept I was talking about, and I think it can be easily covered through this validity lines. At the end, you will have a contract with for example 4 lines, where 2 lines applied in the past (and serve as historic data), and 2 lines are valid for now on. Implementing this is very simple, as you only need to filter contract lines that you are going to invoice according start date of the period being invoiced.

    The only problem with this is the "noise" inside the same contract, but I even prefer to have everything together. Other approach for this can be a contract versioning system, similar to https://github.com/OCA/sale-workflow/tree/11.0/sale_order_revision.

  2. Several recurrence periods for services that are provided at the same time. Example: you have an annual fee for a service and also another monthly fee. This is what you are talking about now. As you say, one possible solution is to move recurrence definition at contract line level. There's already a work on this at #109. It's a major refactoring of the code indeed, but not too costly at migration level: you only have to copy recurrence fields from header to lines.

    As a curious note, the first implementing a recurring invoicing system was me (actually, it was my first module ever in OpenERP) in 6.0:

    https://github.com/serviciosbaeza/serviciosbaeza-odoo-addons/tree/6.0/account_periodical_invoicing

    and I introduced the recurrence interval by line as my preferred choice. When community switches in v8 to account_analytic_analysis module from Odoo, and then derive current contract module from that one, we lose this feature.

    Other option that we used for a customer in v9 (that is no longer active, and thus, we don't migrate it to newer versions), was to have independent contracts (following the example, one for the yearly fee, and another for the monthly one), and being merged at invoicing time through the module https://github.com/OCA/contract/tree/9.0/contract_invoice_merge_by_partner. Currently on v11, we already have a hook for being able to merge several invoices if required at invoice generation level:

    https://github.com/OCA/contract/blob/75d973b38ad15cd5e77c6989b7f6e113843205b9/contract/models/account_analytic_account.py#L264

    and it's used in the module contract_sale_invoicing for adding the invoice lines of the sales orders.

  3. Finally, about the link contract line <-> invoice line, this is definitively a good improvement, that can be added right now to v12 contract migration, independently from the rest of the approaches.

    But I suppose you mention this because you want to specify a different analytic account for lines for "profiling" activity types or similar. The module https://github.com/OCA/contract/tree/10.0/contract_recurring_analytic_distribution allows this, although through an analytic distribution. The same can be done directly with an analytic account field. Others like @alexis-via mentioned in the past about decoupling analytic accounts from contracts, and they started a parallel set of modules for that (agreement_account and agreement_sale in v10). I don't know what do you think about that. Now @max3903 has started another agreement series in v11 for specifying terms, sales condition and so on, independently from the recurring invoicing part.

sbejaoui commented 6 years ago

I will propose a PR that:

  1. Add recurrence mechanism to contract lines

  2. Adapt the invoice generation and next invoice date calculation with the new changes

pedrobaeza commented 5 years ago

Can this be closed and followed on PRs?