[FIX] sale{,_expense}: bad conversion distr. keys

**Current behavior:**
Trying to post journal entries for an expense report sheet
contianing an expense that has:
  A) an associated analytic distribution with
     both a Project and Department, and
  B) a customer to be re-invoiced (requires the expense
     to be for a product which permits this operation),
attempting to post the journal entries for the approved expense
sheet will raise a ValueError.

---

**Expected behavior:**
The entries get posted to their respective accounting journals.

---

Steps to reproduce:
0. Install the Project, Accounting, Sales, Expense apps
   and enable analytic accounting in the db settings

1. Create a new expense with:
   A) an analytic distribution which has
      both available fields filled out, and
   B) a category that permits a customer to be re-invoiced
      (then enter a customer)

2. Create the report, submit it to the manager, approve it,
   then attempt to post the journal entries

3. This should cause the traceback, if the process was blocked
   try again after deleting any tax rules in the expense

---

Cause of the issue:
The analytic_distribution field in the hr.expense module is
stored as a dictionary. During the process of recording the
journal entries, the keys are converted from a string to
integers. However, when multiple keys are in the dict, the
conversion is set up improperly and fails.

---

Fix:
Modify the conversion sequence so that multiple dict keys are
accounted for.

---

opw-3663082

closes odoo/odoo#147985

Signed-off-by: John Laterre (jol) <jol@odoo.com>
This commit is contained in:
Ethan Vincent
2024-01-31 01:31:53 +00:00
parent b0f0fd2ee3
commit 4b2286bd5b
2 changed files with 58 additions and 3 deletions
+5 -2
View File
@@ -155,12 +155,15 @@ class AccountMoveLine(models.Model):
for move_line in self:
if move_line.analytic_distribution:
distribution_json = move_line.analytic_distribution
sale_order = self.env['sale.order'].search([('analytic_account_id', 'in', list(int(account_id) for account_id in distribution_json.keys())),
account_ids = [int(account_id) for key in distribution_json.keys() for account_id in key.split(',')]
sale_order = self.env['sale.order'].search([('analytic_account_id', 'in', account_ids),
('state', '=', 'sale')], order='create_date ASC', limit=1)
if sale_order:
mapping[move_line.id] = sale_order
else:
sale_order = self.env['sale.order'].search([('analytic_account_id', 'in', list(int(account_id) for account_id in distribution_json.keys()))], order='create_date ASC', limit=1)
sale_order = self.env['sale.order'].search([('analytic_account_id', 'in', account_ids)],
order='create_date ASC', limit=1)
mapping[move_line.id] = sale_order
# map of AAL index with the SO on which it needs to be reinvoiced. Maybe be None if no SO found
+53 -1
View File
@@ -1,5 +1,5 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import Command
from odoo import Command, fields
from odoo.addons.hr_expense.tests.common import TestExpenseCommon
from odoo.addons.sale.tests.common import TestSaleCommon
from odoo.tests import tagged
@@ -97,3 +97,55 @@ class TestSaleExpense(TestExpenseCommon, TestSaleCommon):
# both expenses should be invoiced
inv = so._create_invoices()
self.assertEqual(inv.amount_untaxed, 621.5 + (prod_exp_2.list_price * 100.0), 'Sale Expense: invoicing of expense is wrong')
def test_expense_multi_id_analytic_distribution(self):
"""
Test conversion of analytic_distribution dict into account numbers when a hr.expense.sheet containing
a hr.expense with an analytic_distribution having 2+ account ids
"""
expensed_product = self.env['product.product'].create({
'name': 'test product',
'can_be_expensed': True,
'detailed_type': 'service',
'invoice_policy': 'order',
'standard_price': 100,
'expense_policy': 'cost',
})
sale_order = self.env['sale.order'].create({
'partner_id': self.partner_a.id,
'partner_invoice_id': self.partner_a.id,
'partner_shipping_id': self.partner_a.id,
'order_line': [Command.create({'product_id': self.product_b.id})],
})
sale_order.action_confirm()
sale_order._create_invoices()
analytic_account_3 = self.env['account.analytic.account'].create({
'name': 'analytic_account_3',
'plan_id': self.analytic_plan.id,
})
expense_sheet = self.env['hr.expense.sheet'].create({
'name': 'Test Expense Report',
'employee_id': self.expense_employee.id,
'company_id': self.company_data['company'].id,
'expense_line_ids': [Command.create({
'employee_id': self.expense_employee.id,
'product_id': expensed_product.id,
'quantity': 1000.00,
'date': fields.Date.today(),
'company_id': self.company_data['company'].id,
'currency_id': self.company_data['currency'].id,
'analytic_distribution': {
f'{self.analytic_account_1.id},{self.analytic_account_2.id}': 60,
f'{analytic_account_3.id}': 40,
},
'sale_order_id': sale_order.id,
})],
})
expense_sheet.action_submit_sheet()
expense_sheet.action_approve_expense_sheets()
expense_sheet.action_sheet_move_create()
self.assertTrue(self.env['account.move'].search([('expense_sheet_id', '=', expense_sheet.id)], limit=1))