diff --git a/project_task_stock/models/stock_move.py b/project_task_stock/models/stock_move.py index 3ae2e6f13a..5d7e836bdc 100644 --- a/project_task_stock/models/stock_move.py +++ b/project_task_stock/models/stock_move.py @@ -1,5 +1,6 @@ # Copyright 2022-2025 Tecnativa - Víctor Martínez # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) + from odoo import api, fields, models from odoo.tools import float_is_zero @@ -90,32 +91,39 @@ def _prepare_analytic_line_from_task(self): product = self.product_id company_id = self.env.company task = self.task_id or self.raw_material_task_id - analytic_account = task.stock_analytic_account_id or task.project_id.account_id + project_id = task.project_id + analytic_account = task.stock_analytic_account_id or project_id.account_id if not analytic_account: return False # Apply sudo() in case there is any rule that does not allow access to # the analytic account, for example with analytic_hr_department_restriction analytic_account = analytic_account.sudo() + is_return = bool( + self.origin_returned_move_id + and self.location_id == project_id.location_dest_id + and self.location_dest_id == project_id.location_id + ) + quantity_done = self.quantity * (-1 if is_return else 1) res = { "date": ( task.stock_analytic_date - or task.project_id.stock_analytic_date + or project_id.stock_analytic_date or fields.date.today() ), "name": task.name + ": " + product.name, - "unit_amount": self.quantity, + "unit_amount": quantity_done, "account_id": analytic_account.id, "user_id": self.env.user.id, "product_uom_id": self.product_uom.id, "company_id": analytic_account.company_id.id or self.env.company.id, - "partner_id": task.partner_id.id or task.project_id.partner_id.id or False, + "partner_id": task.partner_id.id or project_id.partner_id.id or False, "stock_move_id": self.id, "stock_task_id": task.id, } amount_unit = product.with_context(uom=self.product_uom.id)._price_compute( "standard_price" )[product.id] - amount = amount_unit * self.quantity or 0.0 + amount = amount_unit * quantity_done or 0.0 result = round(amount, company_id.currency_id.decimal_places) * -1 vals = {"amount": result} analytic_line_fields = self.env["account.analytic.line"]._fields diff --git a/project_task_stock/tests/test_project_task_stock.py b/project_task_stock/tests/test_project_task_stock.py index ca02ece974..ecdc4c3d0e 100644 --- a/project_task_stock/tests/test_project_task_stock.py +++ b/project_task_stock/tests/test_project_task_stock.py @@ -147,6 +147,45 @@ def test_project_task_analytic_lines_with_tag_2(self): fields.first(self.task.stock_analytic_line_ids).date, fields.date.today() ) + def test_project_task_analytic_lines_with_returned_picking(self): + # Create initial moves + self.task = self.env["project.task"].browse(self.task.id) + self.task.action_assign() + picking = self.task.move_ids.picking_id + for move in picking.move_ids: + move.quantity = move.product_uom_qty + picking.button_validate() + self.assertEqual(picking.state, "done") + # Return the initial moves + stock_return_picking_form = Form( + self.env["stock.return.picking"].with_context( + active_ids=picking.ids, + active_id=picking.id, + active_model="stock.picking", + ) + ) + stock_return_picking = stock_return_picking_form.save() + for return_line in stock_return_picking.product_return_moves: + return_line.quantity = return_line.move_id.product_uom_qty + stock_return_picking_action = stock_return_picking.action_create_returns() + return_pick = self.env["stock.picking"].browse( + stock_return_picking_action["res_id"] + ) + return_pick.action_assign() + for return_line in return_pick.move_ids: + return_line.quantity = return_line.origin_returned_move_id.quantity + return_pick.button_validate() + self.assertEqual(return_pick.state, "done") + # Check that the resulting analytic lines sum is 0 + stock_analytic_lines = self.task.sudo().stock_analytic_line_ids + self.assertEqual(len(stock_analytic_lines), 4) + self.assertEqual(sum(stock_analytic_lines.mapped("unit_amount")), 0) + self.assertEqual(sum(stock_analytic_lines.mapped("amount")), 0) + self.assertIn( + self.analytic_account, + stock_analytic_lines.mapped("account_id"), + ) + @users("manager-user") def test_project_task_analytic_lines_with_tag_2_manager_user(self): self.task.stock_analytic_distribution = {