odoo/odoo#126536

Created by fw-bot
Merged at 08613dc3ae15d53702716288354a28f52f80de94

Statuses:

label
odoo-dev:master-16.0-OPW-3217215-stock_account_reverse_impact_pdiff-awt-jJi9-fw
head
621fd0bade4198e260316be3b6a40e342a6a0a07
merged
3 years ago by Bugfix, Adrien Widart (awt)
odoo/odoo
16.0 #122231
saas-16.1 #124844
saas-16.2 #124860
saas-16.3 #125016
17.0
18.0
saas-18.2
saas-18.3
saas-18.4
19.0
saas-19.1
saas-19.2
master #126536

[FW][FIX] purchase_stock,stock_account: refund price difference

If a bill has a price difference with the PO, and if the user
refunds it, it will create some errors in the inventory valuation and
the accounting entries

To reproduce the issue:
(Need account_accountant)
1. Create a product category PC
- Costing method: FIFO
- Inventory valuation: Automated
2. Create a product P
- Type: Storable
- Category: PC
3. Confirm a PO with 1 x P at $10
4. Receive P
5. Bill it at $15
- It should create a price diff SVL, see inventory valuation
6. Refund

Errors: The inventory valuation is not impacted, it is still valued
at $15. Because of the refund, it should be $10 (i.e., the price
difference should be cancelled). Then, suppose the user creates a
new bill at $20, it won't do anything (the stock valuation will not
be impacted).

Long story short: the price difference feature, which is supposed to
impact inventory valuation/account entries, does not work if there
is a (partial/full) refund in the flow.

Now, let's think about a more complicated use case:
- Receive 12 products in several times
- Bill in several times (with different quantities than the receipts)

It could give something like (where x are products):

       SVL01        SVL02           SVL03
/---------------\/---------\/------------------\
  x   x   x   x   x   x   x   x   x   x   x   x
\-----------/\-----/\--/\---------------/\------/
     B01       B02   B03       B04          B05
('B' means Bill)

We observe that
- a bill could impact several layers
- a layers could be impacted by several bills

And here is the issue: currently in the code, we don't have a relevant
link between layers, account move lines and the quantity that links
both. The only thing we have is a link between the price difference SVL
and the account move line that has generated that SVL (see field
account_move_line_id on stock.valuation.layer). But this is
clearly not enough and is really problematic: if I refund BILL04, how
should it impact SVL02 ? Then, what if I return a part of the third
delivery before refunding BILL04 ? What if I deliver a part of the
received products before refunding several bills ? What if I refund
B02, B05, then I bill 4 products ?

-> You get the idea: we definitly need a clear link between account
move lines and stock valuation layers and that link has to give a
quantity.

Moreover, it is difficult to create an order between bills. We have
their name, their ID, but the posted time is actually a date. So, if
we mix reset & repost, a draft bill and a draft partial refund, and
so on, and if this mix happens the same day, it is very difficult to
define a clear order. But, considering the above schema, we see that
the order does matter (switch BILL02 and BILL03, the remaining
values of SVL01 and SVL02 will not be the same)

-> So, we also need a way to order the links between account move lines
and stock valuation layers.

Now, about the solution.

First, a disclaimer: We are in stable, we are limited by the stable
policy, and we can't let the above use cases unresolved. So, we took
some decisions to fix them and to repesct all the constraints we had.
This is clearly a (big) patch, it should be considered as such and
will be replaced by a cleaner/better solution on master as soon as
possible
.

About the link between SVL and AML, we had the possibility to create
a new model in a new module. But this would have decreased the
impact of the fix deployment, would have created some
complications for support (different behaviours depending on whether
the module is installed or not) and would have make testing more
complicated (again, different behaviours depending on whether the
module is installed or not).

This is the reason why we decided to "replay the receipts and the
bills". That way, we know which layer is impacted by which invoices,
and vice versa. And, to set the order between all of them:
- For the layers, we use their create_date
- For the bills, we use a hack: each time an account move is posted,
because its state is tracked, a tracking value is posted on the
chatter, and this tracking value has a create_date (remind the
constraints explained above and the disclaimer...)

opw-3217215

Forward-Port-Of: #125016
Forward-Port-Of: #122231