mirror of
https://github.com/ForgeFlow/stock-rma.git
synced 2025-01-21 12:57:49 +02:00
[FIX] rma_purchase: write-off differences in price between rma line and vendor refund
This commit is contained in:
committed by
AaronHForgeFlow
parent
f5df36d3b8
commit
933b24b15e
@@ -5,3 +5,4 @@ from . import purchase_order_line
|
|||||||
from . import rma_operation
|
from . import rma_operation
|
||||||
from . import procurement
|
from . import procurement
|
||||||
from . import account_move
|
from . import account_move
|
||||||
|
from . import account_move_line
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
# Copyright 2017-22 ForgeFlow S.L.
|
# Copyright 2017-22 ForgeFlow S.L.
|
||||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||||
|
|
||||||
from odoo import models
|
from odoo import fields, models
|
||||||
|
from odoo.tools.float_utils import float_compare
|
||||||
|
|
||||||
|
|
||||||
class AccountMove(models.Model):
|
class AccountMove(models.Model):
|
||||||
@@ -40,3 +41,173 @@ class AccountMove(models.Model):
|
|||||||
)
|
)
|
||||||
amls.reconcile()
|
amls.reconcile()
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
def _stock_account_prepare_anglo_saxon_in_lines_vals(self):
|
||||||
|
lines_vals_list_rma = []
|
||||||
|
rma_refunds = self.env["account.move"]
|
||||||
|
price_unit_prec = self.env["decimal.precision"].precision_get("Product Price")
|
||||||
|
for move in self:
|
||||||
|
if (
|
||||||
|
move.move_type != "in_refund"
|
||||||
|
or not move.company_id.anglo_saxon_accounting
|
||||||
|
):
|
||||||
|
continue
|
||||||
|
move = move.with_company(move.company_id)
|
||||||
|
for line in move.invoice_line_ids.filtered(lambda l: l.rma_line_id):
|
||||||
|
# Filter out lines being not eligible for price difference.
|
||||||
|
# Moreover, this function is used for standard cost method only.
|
||||||
|
if (
|
||||||
|
line.product_id.type != "product"
|
||||||
|
or line.product_id.valuation != "real_time"
|
||||||
|
):
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Retrieve accounts needed to generate the price difference.
|
||||||
|
debit_expense_account = line._get_price_diff_account()
|
||||||
|
if not debit_expense_account:
|
||||||
|
continue
|
||||||
|
# Retrieve stock valuation moves.
|
||||||
|
valuation_stock_moves = (
|
||||||
|
self.env["stock.move"].search(
|
||||||
|
[
|
||||||
|
("rma_line_id", "=", line.rma_line_id.id),
|
||||||
|
("state", "=", "done"),
|
||||||
|
("product_qty", "!=", 0.0),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
if line.rma_line_id
|
||||||
|
else self.env["stock.move"]
|
||||||
|
)
|
||||||
|
|
||||||
|
if line.product_id.cost_method != "standard" and line.rma_line_id:
|
||||||
|
if move.move_type == "in_refund":
|
||||||
|
valuation_stock_moves = valuation_stock_moves.filtered(
|
||||||
|
lambda stock_move: stock_move._is_out()
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
valuation_stock_moves = valuation_stock_moves.filtered(
|
||||||
|
lambda stock_move: stock_move._is_in()
|
||||||
|
)
|
||||||
|
|
||||||
|
if not valuation_stock_moves:
|
||||||
|
continue
|
||||||
|
|
||||||
|
(
|
||||||
|
valuation_price_unit_total,
|
||||||
|
valuation_total_qty,
|
||||||
|
) = valuation_stock_moves._get_valuation_price_and_qty(
|
||||||
|
line, move.currency_id
|
||||||
|
)
|
||||||
|
valuation_price_unit = (
|
||||||
|
valuation_price_unit_total / valuation_total_qty
|
||||||
|
)
|
||||||
|
valuation_price_unit = line.product_id.uom_id._compute_price(
|
||||||
|
valuation_price_unit, line.product_uom_id
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# Valuation_price unit is always expressed in invoice currency,
|
||||||
|
# so that it can always be computed with the good rate
|
||||||
|
price_unit = line.product_id.uom_id._compute_price(
|
||||||
|
line.product_id.standard_price, line.product_uom_id
|
||||||
|
)
|
||||||
|
price_unit = (
|
||||||
|
-price_unit
|
||||||
|
if line.move_id.move_type == "in_refund"
|
||||||
|
else price_unit
|
||||||
|
)
|
||||||
|
valuation_date = (
|
||||||
|
valuation_stock_moves
|
||||||
|
and max(valuation_stock_moves.mapped("date"))
|
||||||
|
or move.date
|
||||||
|
)
|
||||||
|
valuation_price_unit = line.company_currency_id._convert(
|
||||||
|
price_unit,
|
||||||
|
move.currency_id,
|
||||||
|
move.company_id,
|
||||||
|
valuation_date,
|
||||||
|
round=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
price_unit = line._get_gross_unit_price()
|
||||||
|
|
||||||
|
price_unit_val_dif = abs(price_unit) - valuation_price_unit
|
||||||
|
relevant_qty = line.quantity
|
||||||
|
price_subtotal = relevant_qty * price_unit_val_dif
|
||||||
|
# We consider there is a price difference if the subtotal is not zero. In case a
|
||||||
|
# discount has been applied, we can't round the price unit anymore, and hence we
|
||||||
|
# can't compare them.
|
||||||
|
if (
|
||||||
|
not move.currency_id.is_zero(price_subtotal)
|
||||||
|
and float_compare(
|
||||||
|
line["price_unit"],
|
||||||
|
line.price_unit,
|
||||||
|
precision_digits=price_unit_prec,
|
||||||
|
)
|
||||||
|
== 0
|
||||||
|
):
|
||||||
|
# Add price difference account line.
|
||||||
|
vals = {
|
||||||
|
"name": line.name[:64],
|
||||||
|
"move_id": move.id,
|
||||||
|
"partner_id": line.partner_id.id
|
||||||
|
or move.commercial_partner_id.id,
|
||||||
|
"currency_id": line.currency_id.id,
|
||||||
|
"product_id": line.product_id.id,
|
||||||
|
"product_uom_id": line.product_uom_id.id,
|
||||||
|
"quantity": relevant_qty,
|
||||||
|
"price_unit": price_unit_val_dif,
|
||||||
|
"price_subtotal": relevant_qty * price_unit_val_dif,
|
||||||
|
"amount_currency": relevant_qty
|
||||||
|
* price_unit_val_dif
|
||||||
|
* line.move_id.direction_sign,
|
||||||
|
"balance": line.currency_id._convert(
|
||||||
|
relevant_qty
|
||||||
|
* price_unit_val_dif
|
||||||
|
* line.move_id.direction_sign,
|
||||||
|
line.company_currency_id,
|
||||||
|
line.company_id,
|
||||||
|
fields.Date.today(),
|
||||||
|
),
|
||||||
|
"account_id": debit_expense_account.id,
|
||||||
|
"analytic_distribution": line.analytic_distribution,
|
||||||
|
"display_type": "cogs",
|
||||||
|
"rma_line_id": line.rma_line_id.id,
|
||||||
|
}
|
||||||
|
|
||||||
|
lines_vals_list_rma.append(vals)
|
||||||
|
|
||||||
|
# Correct the amount of the current line.
|
||||||
|
vals = {
|
||||||
|
"name": line.name[:64],
|
||||||
|
"move_id": move.id,
|
||||||
|
"partner_id": line.partner_id.id
|
||||||
|
or move.commercial_partner_id.id,
|
||||||
|
"currency_id": line.currency_id.id,
|
||||||
|
"product_id": line.product_id.id,
|
||||||
|
"product_uom_id": line.product_uom_id.id,
|
||||||
|
"quantity": relevant_qty,
|
||||||
|
"price_unit": -price_unit_val_dif,
|
||||||
|
"price_subtotal": relevant_qty * -price_unit_val_dif,
|
||||||
|
"amount_currency": relevant_qty
|
||||||
|
* -price_unit_val_dif
|
||||||
|
* line.move_id.direction_sign,
|
||||||
|
"balance": line.currency_id._convert(
|
||||||
|
relevant_qty
|
||||||
|
* -price_unit_val_dif
|
||||||
|
* line.move_id.direction_sign,
|
||||||
|
line.company_currency_id,
|
||||||
|
line.company_id,
|
||||||
|
fields.Date.today(),
|
||||||
|
),
|
||||||
|
"account_id": line.account_id.id,
|
||||||
|
"analytic_distribution": line.analytic_distribution,
|
||||||
|
"display_type": "cogs",
|
||||||
|
"rma_line_id": line.rma_line_id.id,
|
||||||
|
}
|
||||||
|
lines_vals_list_rma.append(vals)
|
||||||
|
rma_refunds |= move
|
||||||
|
lines_vals_list = super(
|
||||||
|
AccountMove, self - rma_refunds
|
||||||
|
)._stock_account_prepare_anglo_saxon_in_lines_vals()
|
||||||
|
lines_vals_list += lines_vals_list_rma
|
||||||
|
return lines_vals_list
|
||||||
|
|||||||
20
rma_purchase/models/account_move_line.py
Normal file
20
rma_purchase/models/account_move_line.py
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
from odoo import models
|
||||||
|
|
||||||
|
|
||||||
|
class AccountMoveLine(models.Model):
|
||||||
|
_inherit = "account.move.line"
|
||||||
|
|
||||||
|
def _get_price_diff_account(self):
|
||||||
|
# force the price difference account to be taken from the price
|
||||||
|
# different properties as they was in the previous Odoo versions
|
||||||
|
self.ensure_one()
|
||||||
|
if self.product_id.cost_method != "standard":
|
||||||
|
debit_pdiff_account = (
|
||||||
|
self.product_id.property_account_creditor_price_difference
|
||||||
|
or self.product_id.categ_id.property_account_creditor_price_difference_categ
|
||||||
|
)
|
||||||
|
debit_pdiff_account = self.move_id.fiscal_position_id.map_account(
|
||||||
|
debit_pdiff_account
|
||||||
|
)
|
||||||
|
return debit_pdiff_account
|
||||||
|
return super()._get_price_diff_account()
|
||||||
@@ -17,7 +17,7 @@ class TestRmaStockAccountPurchase(TestRmaStockAccount):
|
|||||||
cls.rma_operation_supplier_refund = cls.env.ref(
|
cls.rma_operation_supplier_refund = cls.env.ref(
|
||||||
"rma_account.rma_operation_supplier_refund"
|
"rma_account.rma_operation_supplier_refund"
|
||||||
)
|
)
|
||||||
acc_type = cls._create_account_type("expense", "other")
|
acc_type = "expense"
|
||||||
cls.account_price_diff = cls._create_account(
|
cls.account_price_diff = cls._create_account(
|
||||||
acc_type, "Refund Price Difference Expense", "rpde", cls.company, False
|
acc_type, "Refund Price Difference Expense", "rpde", cls.company, False
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user