Merge pull request #360 from ForgeFlow/14.0-fix-rma_account-gdni-when-replace

[14.0][FIX] rma_account: reconcile GDNI when receiving but refund is not expected
This commit is contained in:
Jordi Ballester Alomar
2023-01-06 11:50:55 +01:00
committed by GitHub
7 changed files with 84 additions and 4 deletions

View File

@@ -28,6 +28,16 @@ class RmaOperation(models.Model):
comodel_name="account.journal",
compute="_compute_domain_valid_journal",
)
automated_refund = fields.Boolean(
help="In the scenario where a company uses anglo-saxon accounting, if "
"you receive products from a customer and don't expect to refund the customer "
"but send a replacement unit, mark this flag to be accounting consistent"
)
refund_free_of_charge = fields.Boolean(
help="In case of automated refund you should mark this option as long automated"
"refunds mean to compensate Stock Interim accounts only without hitting"
"Accounts receivable"
)
@api.onchange("type")
def _compute_domain_valid_journal(self):
@@ -40,3 +50,9 @@ class RmaOperation(models.Model):
rec.valid_refund_journal_ids = self.env["account.journal"].search(
[("type", "=", "purchase")]
)
@api.onchange("automated_refund")
def _onchange_automated_refund(self):
for rec in self:
if rec.automated_refund:
rec.refund_free_of_charge = True

View File

@@ -360,3 +360,39 @@ class RmaOrderLine(models.Model):
# We get the cost from the original invoice line
price_unit = self.account_move_line_id.price_unit
return price_unit
def _refund_at_zero_cost(self):
make_refund = (
self.env["rma.refund"]
.with_context(
{
"customer": True,
"active_ids": self.ids,
"active_model": "rma.order.line",
}
)
.create({"description": "RMA Anglosaxon Regularisation"})
)
for item in make_refund.item_ids:
item.qty_to_refund = item.line_id.qty_received - item.line_id.qty_refunded
action_refund = make_refund.invoice_refund()
refund_id = action_refund.get("res_id", False)
if refund_id:
refund = self.env["account.move"].browse(refund_id)
refund._post()
def _check_refund_zero_cost(self):
"""
In the scenario where a company uses anglo-saxon accounting, if you receive
products from a customer and don't expect to refund the customer but send a
replacement unit you still need to create a debit entry on the
Stock Interim (Delivered) account. In order to do this the best approach is
to create a customer refund from the RMA, but set as free of charge
(price unit = 0). The refund will be 0, but the Stock Interim (Delivered)
account will be posted anyways.
"""
# For some reason api.depends on qty_received is not working. Using the
# _account_entry_move method in stock move as trigger then
for rec in self.filtered(lambda l: l.operation_id.automated_refund):
if rec.qty_received > rec.qty_refunded:
rec._refund_at_zero_cost()

View File

@@ -13,4 +13,5 @@ class StockMove(models.Model):
# Eventually reconcile together the invoice and valuation accounting
# entries on the stock interim accounts
self.rma_line_id._stock_account_anglo_saxon_reconcile_valuation()
self.rma_line_id._check_refund_zero_cost()
return res

View File

@@ -324,3 +324,26 @@ class TestRmaStockAccount(TestRma):
self.assertEqual(gdni_balance, 0.0)
# The GDNI entries should be now reconciled
self.assertEqual(all(gdni_amls.mapped("reconciled")), True)
def test_05_reconcile_grni_when_no_refund(self):
"""
Test that receive and send a replacement order leaves GDNI reconciled
"""
self.product_fifo_1.standard_price = 15
rma_line = Form(self.rma_line)
rma_line.partner_id = self.partner_id
rma_line.product_id = self.product_fifo_1
rma_line.operation_id.automated_refund = True
rma_line = rma_line.save()
rma_line.action_rma_to_approve()
# receiving should trigger the refund at zero cost
self._receive_rma(rma_line)
gdni_amls = self.env["account.move.line"].search(
[
("rma_line_id", "in", rma_line.ids),
("account_id", "=", self.account_gdni.id),
]
) + rma_line.refund_line_ids.filtered(
lambda l: l.account_id == self.account_gdni
)
self.assertEqual(all(gdni_amls.mapped("reconciled")), True)

View File

@@ -21,6 +21,10 @@
<field name="valid_refund_journal_ids" invisible="1" />
<field name="refund_journal_id" />
</field>
<field name="customer_to_supplier" position="before">
<field name="automated_refund" />
<field name="refund_free_of_charge" />
</field>
</field>
</record>
</odoo>

View File

@@ -92,10 +92,6 @@ class RmaRefund(models.TransientModel):
def invoice_refund(self):
rma_line_ids = self.env["rma.order.line"].browse(self.env.context["active_ids"])
for line in rma_line_ids:
if line.refund_policy == "no":
raise ValidationError(
_("The operation is not refund for at least one line")
)
if line.state != "approved":
raise ValidationError(_("RMA %s is not approved") % line.name)
new_invoice = self.compute_refund()
@@ -111,6 +107,8 @@ class RmaRefund(models.TransientModel):
return result
def _get_refund_price_unit(self, rma):
if rma.operation_id.refund_free_of_charge:
return 0.0
price_unit = rma.price_unit
# If this references a previous invoice/bill, use the same unit price
if rma.account_move_line_id:

View File

@@ -14,6 +14,8 @@ class RmaRefund(models.TransientModel):
def _get_refund_price_unit(self, rma):
price_unit = super(RmaRefund, self)._get_refund_price_unit(rma)
if rma.operation_id.refund_free_of_charge:
return price_unit
if rma.type == "customer":
if rma.account_move_line_id:
price_unit = rma.account_move_line_id.price_unit