[FIX] stock_account: base reversed anglo-saxon AML on original one
When reversing an invoice that contains some anglo-saxo AML, the new
anglo-saxo AML should have the same unit price than the original one
To reproduce the issue:
(Need account_accountant,purchase)
1. Create a product category PC:
- Costing Method: AVCO
- Inventory Valuation: Automated
2. Create a product P:
- Type: Storable
- Product Category: PC
3. Create a purchase order PO01 with 2 x P for $10
4. Confirm PO01 and process the receipt
5. Create and Post an invoice INV01 with 2 x P
- As listed in the journal items, the anglo-saxo lines have been
generated with a value of $20
6. Create a purchase order PO02 with 2 x P for $20
- The cost of P becomes $15
7. Confirm PO02 and process the receipt
8. Add a credit note to INV01:
- Credit Method: Partial Refund
9. Set the quantity of P to 1
10. Post the new invoice INV02
Error: The anglo-saxo lines are listed in the journal items, which is
correct, but their value is $15 (the new cost of P) while it should be
$10
When reversing an invoice with the "partial refund" method, the
anglo-saxo lines are generated via the regular flow (as if it were a
"standard" invoice). Therefore, when getting the unit price of the line,
it uses the product's standard price. In such situation, it should use
the unit price of the original line.
OPW-2646926
OPW-2628215
X-original-commit: 87f7e78340dfe553923b2b65f61de06d5778cfbd
Part-of: odoo/odoo#82978
This commit is contained in:
@@ -240,4 +240,8 @@ class AccountMoveLine(models.Model):
|
||||
self.ensure_one()
|
||||
if not self.product_id:
|
||||
return self.price_unit
|
||||
return self.product_id.with_company(self.company_id)._stock_account_get_anglo_saxon_price_unit(uom=self.product_uom_id)
|
||||
original_line = self.move_id.reversed_entry_id.line_ids.filtered(lambda l: l.is_anglo_saxon_line
|
||||
and l.product_id == self.product_id and l.product_uom_id == self.product_uom_id and l.price_unit >= 0)
|
||||
original_line = original_line and original_line[0]
|
||||
return original_line.price_unit if original_line \
|
||||
else self.product_id.with_company(self.company_id)._stock_account_get_anglo_saxon_price_unit(uom=self.product_uom_id)
|
||||
|
||||
@@ -901,3 +901,62 @@ class TestStockValuationChangeValuation(TestStockValuationCommon):
|
||||
# An accounting entry should only be created for the emptying now that the category is manual.
|
||||
self.assertEqual(len(self.product1.stock_valuation_layer_ids.mapped('account_move_id')), 2)
|
||||
self.assertEqual(len(self.product1.stock_valuation_layer_ids), 3)
|
||||
|
||||
@tagged('post_install', '-at_install')
|
||||
class TestAngloSaxonAccounting(TestStockValuationCommon):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestAngloSaxonAccounting, cls).setUpClass()
|
||||
cls.env.company.anglo_saxon_accounting = True
|
||||
cls.stock_input_account, cls.stock_output_account, cls.stock_valuation_account, cls.expense_account, cls.stock_journal = _create_accounting_data(cls.env)
|
||||
cls.product1.write({
|
||||
'property_account_expense_id': cls.expense_account.id,
|
||||
})
|
||||
cls.product1.categ_id.write({
|
||||
'property_valuation': 'real_time',
|
||||
'property_stock_account_input_categ_id': cls.stock_input_account.id,
|
||||
'property_stock_account_output_categ_id': cls.stock_output_account.id,
|
||||
'property_stock_valuation_account_id': cls.stock_valuation_account.id,
|
||||
'property_stock_journal': cls.stock_journal.id,
|
||||
})
|
||||
cls.default_journal_purchase = cls.env['account.journal'].search([
|
||||
('company_id', '=', cls.env.company.id),
|
||||
('type', '=', 'purchase')
|
||||
], limit=1)
|
||||
|
||||
def test_avco_and_credit_note(self):
|
||||
"""
|
||||
When reversing an invoice that contains some anglo-saxo AML, the new anglo-saxo AML should have the same value
|
||||
"""
|
||||
self.product1.categ_id.property_cost_method = 'average'
|
||||
|
||||
self._make_in_move(self.product1, 2, unit_cost=10)
|
||||
|
||||
invoice_form = Form(self.env['account.move'].with_context(default_move_type='out_invoice'))
|
||||
invoice_form.partner_id = self.env['res.partner'].create({'name': 'Super Client'})
|
||||
with invoice_form.invoice_line_ids.new() as invoice_line_form:
|
||||
invoice_line_form.product_id = self.product1
|
||||
invoice_line_form.quantity = 2
|
||||
invoice_line_form.price_unit = 25
|
||||
invoice_line_form.account_id = self.default_journal_purchase.default_account_id
|
||||
invoice = invoice_form.save()
|
||||
invoice.action_post()
|
||||
|
||||
self._make_in_move(self.product1, 2, unit_cost=20)
|
||||
self.assertEqual(self.product1.standard_price, 15)
|
||||
|
||||
refund_wizard = self.env['account.move.reversal'].with_context(active_model="account.move", active_ids=invoice.ids).create({
|
||||
'refund_method': 'refund',
|
||||
'journal_id': invoice.journal_id.id,
|
||||
})
|
||||
action = refund_wizard.reverse_moves()
|
||||
reverse_invoice = self.env['account.move'].browse(action['res_id'])
|
||||
with Form(reverse_invoice) as reverse_invoice_form:
|
||||
with reverse_invoice_form.invoice_line_ids.edit(0) as line:
|
||||
line.quantity = 1
|
||||
reverse_invoice.action_post()
|
||||
|
||||
anglo_lines = reverse_invoice.line_ids.filtered(lambda l: l.is_anglo_saxon_line)
|
||||
self.assertEqual(len(anglo_lines), 2)
|
||||
self.assertEqual(abs(anglo_lines[0].balance), 10)
|
||||
self.assertEqual(abs(anglo_lines[1].balance), 10)
|
||||
|
||||
Reference in New Issue
Block a user