Skip to content

Commit

Permalink
[FIX] project_account, project_hr_expense: prevent double counting in…
Browse files Browse the repository at this point in the history
… project upgrade report

Issue Description:
There is an issue in the project upgrade report where an expense with a related analytic account appears twice. This occurs once as "Expenses" and again as "Vendor Bills". This problem does not manifest on runbot with all apps installed, indicating a specific configuration issue.

The installation of the 'project_purchase' module resolves the issue, as the method "_get_already_included_profitability_invoice_line_ids" within both the "project_purchase" and "project_hr_expense" modules performs a check for an 'expense_sheet_id' in account moves. This check helps to exclude these entries from the profitability items, thereby preventing duplication. However, while this solution is effective, it leads to an undesirable addition of the Purchase app to the client's database, which is not acceptable for the client.
Relevant code sections: [project_hr_expense](https://github.com/odoo/odoo/blob/1fbcfdf69b503e77e1a931d23dd47df0daf8b2fe/addons/project_hr_expense/models/project_project.py#L70), [project_purchase](https://github.com/odoo/odoo/blob/1fbcfdf69b503e77e1a931d23dd47df0daf8b2fe/addons/project_purchase/models/project_project.py#L138C15-L138C15).

Steps to Reproduce:
1. Install Expense, Accounting, Project, Sales, Employees, Contacts apps on base runbot.
2. Create a service product with 'Prepaid/Fixed Price' and ensure 'Create an Order: Project & Task' is selected.
3. Create and confirm a sales order for the service product created in step 2.
4. In the Expenses app, create an employee-paid expense linked to the sales order's analytic account (e.g., Analytic Distribution: Departments > S00074).
5. Follow the process in the Expenses app by clicking on 'Create Report' > 'Submit to Manager' > 'Approve' > 'Post Journal Entries'.
6. Access Project Updates in the Projects app.
7. Observe that in the project profitability cost section, the same expense is listed twice under different labels: once as "Expenses" and once as "Vendor Bills".

Proposed Solution:
The proposed solution involves modifying the domain of the `_add_purchase_items` function within the `project_account` module, specifically at [this code section](https://github.com/odoo/odoo/blob/763f88e2d45cb7ba107db135eecd0365ba2b8c8b/addons/project_account/models/project_project.py#L14). The enhancement would entail adding a condition to the function's domain to exclude any IDs that are already present in the profitability report. This approach will efficiently prevent the double counting of expenses, ensuring that each expense is represented only once in the project profitability report, thereby maintaining accuracy and consistency in financial tracking. This solution focuses on enhancing the existing functionality with a targeted and efficient modification, ensuring minimal impact on other system components while effectively addressing the issue.

opw-3522293

closes odoo#149623

X-original-commit: 0902d57
Signed-off-by: Xavier Bol (xbo) <xbo@odoo.com>
Signed-off-by: Ilya Rudy (ilru) <ilru@odoo.com>
  • Loading branch information
ilru-odoo committed Jan 17, 2024
1 parent 5065f52 commit 86accec
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 1 deletion.
4 changes: 3 additions & 1 deletion addons/project_account/models/project_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@ def _add_purchase_items(self, profitability_items, with_action=True):
self._get_costs_items_from_purchase(domain, profitability_items, with_action=with_action)

def _get_add_purchase_items_domain(self):
purchase_order_line_invoice_line_ids = self._get_already_included_profitability_invoice_line_ids()
return [
('move_type', 'in', ['in_invoice', 'in_refund']),
('parent_state', 'in', ['draft', 'posted']),
('price_subtotal', '>', 0)
('price_subtotal', '>', 0),
('id', 'not in', purchase_order_line_invoice_line_ids),
]

def _get_costs_items_from_purchase(self, domain, profitability_items, with_action=True):
Expand Down
38 changes: 38 additions & 0 deletions addons/project_hr_expense/tests/test_project_profitability.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,41 @@ def test_project_profitability(self):
self.project_profitability_items_empty,
'No data should be found since the sheets are not approved yet.',
)

def test_project_profitability_after_expense_sheet_actions(self):
expense = self.env["hr.expense"].create(
{
"name": "Car Travel Expenses",
"employee_id": self.expense_employee.id,
"product_id": self.product_c.id,
"total_amount": 50.00,
"company_id": self.project.company_id.id,
"analytic_distribution": {self.project.analytic_account_id.id: 100},
}
)
expense_sheet = self.env["hr.expense.sheet"].create(
{
"name": "Expense for Jannette",
"employee_id": self.expense_employee.id,
"expense_line_ids": expense,
}
)

sequence_per_invoice_type = self.project._get_profitability_sequence_per_invoice_type()
self.assertIn('expenses', sequence_per_invoice_type)
expense_sequence = sequence_per_invoice_type['expenses']

expense_sheet.action_submit_sheet()
expense_sheet.action_approve_expense_sheets()
expense_sheet.action_sheet_move_create()

self.assertDictEqual(
self.project._get_profitability_items(False),
{
'costs': {
'data': [{'id': 'expenses', 'sequence': expense_sequence, 'to_bill': 0.0, 'billed': -expense.untaxed_amount_currency}],
'total': {'to_bill': 0.0, 'billed': -expense.untaxed_amount_currency},
},
'revenues': {'data': [], 'total': {'to_invoice': 0.0, 'invoiced': 0.0}},
},
)

0 comments on commit 86accec

Please sign in to comment.