Files
stock-rma/rma_purchase/models/account_move.py

214 lines
9.6 KiB
Python

# Copyright 2017-22 ForgeFlow S.L.
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
from odoo import fields, models
from odoo.tools.float_utils import float_compare
class AccountMove(models.Model):
_inherit = "account.move"
def _prepare_invoice_line_from_rma_line(self, line):
data = super(AccountMove, self)._prepare_invoice_line_from_rma_line(line)
if line.purchase_order_line_id:
data["purchase_line_id"]: line.purchase_order_line_id.id
return data
def action_post(self):
res = super(AccountMove, self).action_post()
for move in self:
rma_mls = move.line_ids.filtered(lambda l: l.rma_line_id)
if rma_mls:
# Try to reconcile the interim accounts for RMA lines
rmas = rma_mls.mapped("rma_line_id")
for rma in rmas:
product_accounts = (
rma.product_id.product_tmpl_id._get_product_accounts()
)
if rma.type == "customer":
product_interim_account = product_accounts["stock_output"]
else:
product_interim_account = product_accounts["stock_input"]
if product_interim_account.reconcile:
# Get the in and out moves
amls = self.env["account.move.line"].search(
[
("rma_line_id", "=", rma.id),
("account_id", "=", product_interim_account.id),
("parent_state", "=", "posted"),
("reconciled", "=", False),
]
)
amls.reconcile()
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