From 91cf8c52ce24b2c6049a175eb36078ffae791858 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Mart=C3=ADnez?= Date: Mon, 27 Jun 2022 10:07:02 +0200 Subject: [PATCH 01/15] [ADD] sale_timesheet_budget: New addon --- sale_timesheet_budget/README.rst | 98 ++++ sale_timesheet_budget/__init__.py | 1 + sale_timesheet_budget/__manifest__.py | 17 + sale_timesheet_budget/i18n/es.po | 124 +++++ .../i18n/sale_timesheet_budget.pot | 119 +++++ sale_timesheet_budget/models/__init__.py | 3 + .../models/project_project.py | 72 +++ sale_timesheet_budget/readme/CONTRIBUTORS.rst | 4 + sale_timesheet_budget/readme/DESCRIPTION.rst | 1 + sale_timesheet_budget/readme/ROADMAP.rst | 1 + sale_timesheet_budget/readme/USAGE.rst | 5 + .../security/ir.model.access.csv | 3 + .../static/description/icon.png | Bin 0 -> 9455 bytes .../static/description/index.html | 443 ++++++++++++++++++ sale_timesheet_budget/tests/__init__.py | 3 + .../tests/test_sale_timesheet_budget.py | 45 ++ .../views/project_project_view.xml | 46 ++ 17 files changed, 985 insertions(+) create mode 100644 sale_timesheet_budget/README.rst create mode 100644 sale_timesheet_budget/__init__.py create mode 100644 sale_timesheet_budget/__manifest__.py create mode 100644 sale_timesheet_budget/i18n/es.po create mode 100644 sale_timesheet_budget/i18n/sale_timesheet_budget.pot create mode 100644 sale_timesheet_budget/models/__init__.py create mode 100644 sale_timesheet_budget/models/project_project.py create mode 100644 sale_timesheet_budget/readme/CONTRIBUTORS.rst create mode 100644 sale_timesheet_budget/readme/DESCRIPTION.rst create mode 100644 sale_timesheet_budget/readme/ROADMAP.rst create mode 100644 sale_timesheet_budget/readme/USAGE.rst create mode 100644 sale_timesheet_budget/security/ir.model.access.csv create mode 100644 sale_timesheet_budget/static/description/icon.png create mode 100644 sale_timesheet_budget/static/description/index.html create mode 100644 sale_timesheet_budget/tests/__init__.py create mode 100644 sale_timesheet_budget/tests/test_sale_timesheet_budget.py create mode 100644 sale_timesheet_budget/views/project_project_view.xml diff --git a/sale_timesheet_budget/README.rst b/sale_timesheet_budget/README.rst new file mode 100644 index 0000000000..0a719c8e38 --- /dev/null +++ b/sale_timesheet_budget/README.rst @@ -0,0 +1,98 @@ +===================== +Sale timesheet budget +===================== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Ftimesheet-lightgray.png?logo=github + :target: https://github.com/OCA/timesheet/tree/14.0/sale_timesheet_budget + :alt: OCA/timesheet +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/timesheet-14-0/timesheet-14-0-sale_timesheet_budget + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/117/14.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This addon adds the "Budget" tab to the projects to be able to set some prices (benefits/expenses) linked to sales orders. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +#. Go to *Projects* and create and create a new one and set Customer and analytic account. +#. Go to *Sales -> Orders -> Quotations* and create a new one according to Customer and Analytic account previously created. +#. Go to *Projects* and edit project previously created. +#. Add some records (positive or negative) in "Budget" tab. +#. Go to *Project Overview* smart-button and a new line related to *Profitability* block have been created. + +Known issues / Roadmap +====================== + +* Consider the planned hours of the tasks based on price/hour profiles. + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Tecnativa + +Contributors +~~~~~~~~~~~~ + +* `Tecnativa `_: + + * Víctor Martínez + * Pedro M. Baeza + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +.. |maintainer-victoralmau| image:: https://github.com/victoralmau.png?size=40px + :target: https://github.com/victoralmau + :alt: victoralmau + +Current `maintainer `__: + +|maintainer-victoralmau| + +This module is part of the `OCA/timesheet `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/sale_timesheet_budget/__init__.py b/sale_timesheet_budget/__init__.py new file mode 100644 index 0000000000..0650744f6b --- /dev/null +++ b/sale_timesheet_budget/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/sale_timesheet_budget/__manifest__.py b/sale_timesheet_budget/__manifest__.py new file mode 100644 index 0000000000..6148842d52 --- /dev/null +++ b/sale_timesheet_budget/__manifest__.py @@ -0,0 +1,17 @@ +# Copyright 2022 Tecnativa - Víctor Martínez +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +{ + "name": "Sale timesheet budget", + "version": "14.0.1.0.0", + "category": "Timesheet", + "website": "https://github.com/OCA/timesheet", + "author": "Tecnativa, Odoo Community Association (OCA)", + "license": "AGPL-3", + "depends": ["sale_timesheet"], + "installable": True, + "data": [ + "security/ir.model.access.csv", + "views/project_project_view.xml", + ], + "maintainers": ["victoralmau"], +} diff --git a/sale_timesheet_budget/i18n/es.po b/sale_timesheet_budget/i18n/es.po new file mode 100644 index 0000000000..5803370b9d --- /dev/null +++ b/sale_timesheet_budget/i18n/es.po @@ -0,0 +1,124 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * sale_timesheet_budget +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-06-27 11:03+0000\n" +"PO-Revision-Date: 2022-06-27 13:04+0200\n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: \n" +"X-Generator: Poedit 2.3\n" + +#. module: sale_timesheet_budget +#: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget__allowed_sale_order_ids +msgid "Allowed Sale Order" +msgstr "" + +#. module: sale_timesheet_budget +#: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget__amount +#: model_terms:ir.ui.view,arch_db:sale_timesheet_budget.edit_project +msgid "Amount" +msgstr "Importe" + +#. module: sale_timesheet_budget +#: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget__analytic_account_id +msgid "Analytic Account" +msgstr "Cuenta analítica" + +#. module: sale_timesheet_budget +#: model:ir.model.fields,help:sale_timesheet_budget.field_project_project_budget__analytic_account_id +msgid "" +"Analytic account to which this project is linked for financial management. " +"Use an analytic account to record cost and revenue on your project." +msgstr "" +"Cuenta analítica a la que se vincula este proyecto para la gestión " +"financiera. Utilice una cuenta analítica para registrar los costes y los " +"ingresos de su proyecto." + +#. module: sale_timesheet_budget +#: model_terms:ir.ui.view,arch_db:sale_timesheet_budget.timesheet_plan +msgid "Budget" +msgstr "Presupuesto" + +#. module: sale_timesheet_budget +#: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project__budget_amount +msgid "Budget Amount" +msgstr "Importe de presupuesto" + +#. module: sale_timesheet_budget +#: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project__budget_ids +#: model_terms:ir.ui.view,arch_db:sale_timesheet_budget.edit_project +msgid "Budgets" +msgstr "Presupuestos" + +#. module: sale_timesheet_budget +#: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget__create_uid +msgid "Created by" +msgstr "Creado por" + +#. module: sale_timesheet_budget +#: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget__create_date +msgid "Created on" +msgstr "Creado el" + +#. module: sale_timesheet_budget +#: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project__display_name +#: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget__display_name +msgid "Display Name" +msgstr "Nombre mostrado" + +#. module: sale_timesheet_budget +#: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project__id +#: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget__id +msgid "ID" +msgstr "ID" + +#. module: sale_timesheet_budget +#: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project____last_update +#: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget____last_update +msgid "Last Modified on" +msgstr "Última modificación el" + +#. module: sale_timesheet_budget +#: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget__write_uid +msgid "Last Updated by" +msgstr "Última Actualización por" + +#. module: sale_timesheet_budget +#: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget__write_date +msgid "Last Updated on" +msgstr "Actualizado el" + +#. module: sale_timesheet_budget +#: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget__price_unit +msgid "Product Price" +msgstr "Precio de producto" + +#. module: sale_timesheet_budget +#: model:ir.model,name:sale_timesheet_budget.model_project_project +#: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget__project_id +msgid "Project" +msgstr "Proyecto" + +#. module: sale_timesheet_budget +#: model:ir.model,name:sale_timesheet_budget.model_project_project_budget +msgid "Project Project Budget" +msgstr "" + +#. module: sale_timesheet_budget +#: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget__quantity +msgid "Quantity" +msgstr "Cantidad" + +#. module: sale_timesheet_budget +#: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget__sale_order_id +msgid "Sale Order" +msgstr "Pedido de venta" diff --git a/sale_timesheet_budget/i18n/sale_timesheet_budget.pot b/sale_timesheet_budget/i18n/sale_timesheet_budget.pot new file mode 100644 index 0000000000..442c33fd76 --- /dev/null +++ b/sale_timesheet_budget/i18n/sale_timesheet_budget.pot @@ -0,0 +1,119 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * sale_timesheet_budget +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-06-27 11:03+0000\n" +"PO-Revision-Date: 2022-06-27 11:03+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: sale_timesheet_budget +#: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget__allowed_sale_order_ids +msgid "Allowed Sale Order" +msgstr "" + +#. module: sale_timesheet_budget +#: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget__amount +#: model_terms:ir.ui.view,arch_db:sale_timesheet_budget.edit_project +msgid "Amount" +msgstr "" + +#. module: sale_timesheet_budget +#: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget__analytic_account_id +msgid "Analytic Account" +msgstr "" + +#. module: sale_timesheet_budget +#: model:ir.model.fields,help:sale_timesheet_budget.field_project_project_budget__analytic_account_id +msgid "" +"Analytic account to which this project is linked for financial management. " +"Use an analytic account to record cost and revenue on your project." +msgstr "" + +#. module: sale_timesheet_budget +#: model_terms:ir.ui.view,arch_db:sale_timesheet_budget.timesheet_plan +msgid "Budget" +msgstr "" + +#. module: sale_timesheet_budget +#: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project__budget_amount +msgid "Budget Amount" +msgstr "" + +#. module: sale_timesheet_budget +#: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project__budget_ids +#: model_terms:ir.ui.view,arch_db:sale_timesheet_budget.edit_project +msgid "Budgets" +msgstr "" + +#. module: sale_timesheet_budget +#: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget__create_uid +msgid "Created by" +msgstr "" + +#. module: sale_timesheet_budget +#: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget__create_date +msgid "Created on" +msgstr "" + +#. module: sale_timesheet_budget +#: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project__display_name +#: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget__display_name +msgid "Display Name" +msgstr "" + +#. module: sale_timesheet_budget +#: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project__id +#: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget__id +msgid "ID" +msgstr "" + +#. module: sale_timesheet_budget +#: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project____last_update +#: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget____last_update +msgid "Last Modified on" +msgstr "" + +#. module: sale_timesheet_budget +#: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: sale_timesheet_budget +#: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget__write_date +msgid "Last Updated on" +msgstr "" + +#. module: sale_timesheet_budget +#: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget__price_unit +msgid "Product Price" +msgstr "" + +#. module: sale_timesheet_budget +#: model:ir.model,name:sale_timesheet_budget.model_project_project +#: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget__project_id +msgid "Project" +msgstr "" + +#. module: sale_timesheet_budget +#: model:ir.model,name:sale_timesheet_budget.model_project_project_budget +msgid "Project Project Budget" +msgstr "" + +#. module: sale_timesheet_budget +#: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget__quantity +msgid "Quantity" +msgstr "" + +#. module: sale_timesheet_budget +#: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget__sale_order_id +msgid "Sale Order" +msgstr "" diff --git a/sale_timesheet_budget/models/__init__.py b/sale_timesheet_budget/models/__init__.py new file mode 100644 index 0000000000..c183898c17 --- /dev/null +++ b/sale_timesheet_budget/models/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import project_project diff --git a/sale_timesheet_budget/models/project_project.py b/sale_timesheet_budget/models/project_project.py new file mode 100644 index 0000000000..c8fd41748f --- /dev/null +++ b/sale_timesheet_budget/models/project_project.py @@ -0,0 +1,72 @@ +# Copyright 2022 Tecnativa - Víctor Martínez +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models + + +class ProjectProject(models.Model): + _inherit = "project.project" + + budget_ids = fields.One2many( + comodel_name="project.project.budget", + inverse_name="project_id", + string="Budgets", + copy=False, + ) + budget_amount = fields.Float( + compute="_compute_budget_amount", string="Budget Amount" + ) + + @api.depends("budget_ids") + def _compute_budget_amount(self): + for item in self: + item.budget_amount = sum(item.mapped("budget_ids.amount")) + + def _plan_prepare_values(self): + res = super()._plan_prepare_values() + res["dashboard"]["profit"]["budget_amount"] = sum(self.mapped("budget_amount")) + res["dashboard"]["profit"]["total"] += sum(self.mapped("budget_amount")) + return res + + +class ProjectProjectBudget(models.Model): + _name = "project.project.budget" + _description = "Project Project Budget" + + project_id = fields.Many2one( + comodel_name="project.project", string="Project", required=True + ) + allowed_sale_order_ids = fields.Many2many( + comodel_name="sale.order", compute="_compute_allowed_sale_order_ids" + ) + sale_order_id = fields.Many2one( + comodel_name="sale.order", + string="Sale Order", + domain="[('id', 'in', allowed_sale_order_ids)]", + ) + analytic_account_id = fields.Many2one(related="project_id.analytic_account_id") + quantity = fields.Float( + string="Quantity", digits="Account", default=1, required=True + ) + price_unit = fields.Float(string="Product Price", digits="Account", required=True) + amount = fields.Float(compute="_compute_amount", string="Amount", store=True) + + @api.depends("project_id") + def _compute_allowed_sale_order_ids(self): + sale_order_model = self.env["sale.order"].sudo() + for item in self: + item.allowed_sale_order_ids = sale_order_model.search( + [ + ("partner_id", "=", item.project_id.partner_id.id), + ( + "analytic_account_id", + "=", + item.project_id.analytic_account_id.id, + ), + ] + ) + + @api.depends("quantity", "price_unit") + def _compute_amount(self): + for item in self: + item.amount = item.quantity * item.price_unit diff --git a/sale_timesheet_budget/readme/CONTRIBUTORS.rst b/sale_timesheet_budget/readme/CONTRIBUTORS.rst new file mode 100644 index 0000000000..5fb7130530 --- /dev/null +++ b/sale_timesheet_budget/readme/CONTRIBUTORS.rst @@ -0,0 +1,4 @@ +* `Tecnativa `_: + + * Víctor Martínez + * Pedro M. Baeza diff --git a/sale_timesheet_budget/readme/DESCRIPTION.rst b/sale_timesheet_budget/readme/DESCRIPTION.rst new file mode 100644 index 0000000000..e527ae62d9 --- /dev/null +++ b/sale_timesheet_budget/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +This addon adds the "Budget" tab to the projects to be able to set some prices (benefits/expenses) linked to sales orders. diff --git a/sale_timesheet_budget/readme/ROADMAP.rst b/sale_timesheet_budget/readme/ROADMAP.rst new file mode 100644 index 0000000000..9347a7c403 --- /dev/null +++ b/sale_timesheet_budget/readme/ROADMAP.rst @@ -0,0 +1 @@ +* Consider the planned hours of the tasks based on price/hour profiles. diff --git a/sale_timesheet_budget/readme/USAGE.rst b/sale_timesheet_budget/readme/USAGE.rst new file mode 100644 index 0000000000..966fd19ebb --- /dev/null +++ b/sale_timesheet_budget/readme/USAGE.rst @@ -0,0 +1,5 @@ +#. Go to *Projects* and create and create a new one and set Customer and analytic account. +#. Go to *Sales -> Orders -> Quotations* and create a new one according to Customer and Analytic account previously created. +#. Go to *Projects* and edit project previously created. +#. Add some records (positive or negative) in "Budget" tab. +#. Go to *Project Overview* smart-button and a new line related to *Profitability* block have been created. diff --git a/sale_timesheet_budget/security/ir.model.access.csv b/sale_timesheet_budget/security/ir.model.access.csv new file mode 100644 index 0000000000..a047a568e8 --- /dev/null +++ b/sale_timesheet_budget/security/ir.model.access.csv @@ -0,0 +1,3 @@ +id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink +access_project_project_budget_admin,project_project_budget_portal,model_project_project_budget,project.group_project_manager,1,1,1,1 +access_project_project_budget_user,project_project_budget_user,model_project_project_budget,project.group_project_user,1,0,0,0 diff --git a/sale_timesheet_budget/static/description/icon.png b/sale_timesheet_budget/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d GIT binary patch literal 9455 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 z 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 Xviia!U7SGha1wx#SCgwmn*{w2TRX*I literal 0 HcmV?d00001 diff --git a/sale_timesheet_budget/static/description/index.html b/sale_timesheet_budget/static/description/index.html new file mode 100644 index 0000000000..7d49620830 --- /dev/null +++ b/sale_timesheet_budget/static/description/index.html @@ -0,0 +1,443 @@ + + + + + + +Sale timesheet budget + + + +
+

Sale timesheet budget

+ + +

Beta License: AGPL-3 OCA/timesheet Translate me on Weblate Try me on Runbot

+

This addon adds the “Budget” tab to the projects to be able to set some prices (benefits/expenses) linked to sales orders.

+

Table of contents

+ +
+

Usage

+
    +
  1. Go to Projects and create and create a new one and set Customer and analytic account.
  2. +
  3. Go to Sales -> Orders -> Quotations and create a new one according to Customer and Analytic account previously created.
  4. +
  5. Go to Projects and edit project previously created.
  6. +
  7. Add some records (positive or negative) in “Budget” tab.
  8. +
  9. Go to Project Overview smart-button and a new line related to Profitability block have been created.
  10. +
+
+
+

Known issues / Roadmap

+
    +
  • Consider the planned hours of the tasks based on price/hour profiles.
  • +
+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Tecnativa
  • +
+
+
+

Contributors

+
    +
  • Tecnativa:
      +
    • Víctor Martínez
    • +
    • Pedro M. Baeza
    • +
    +
  • +
+
+
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

Current maintainer:

+

victoralmau

+

This module is part of the OCA/timesheet project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/sale_timesheet_budget/tests/__init__.py b/sale_timesheet_budget/tests/__init__.py new file mode 100644 index 0000000000..34e6d3d843 --- /dev/null +++ b/sale_timesheet_budget/tests/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import test_sale_timesheet_budget diff --git a/sale_timesheet_budget/tests/test_sale_timesheet_budget.py b/sale_timesheet_budget/tests/test_sale_timesheet_budget.py new file mode 100644 index 0000000000..e9b2e04505 --- /dev/null +++ b/sale_timesheet_budget/tests/test_sale_timesheet_budget.py @@ -0,0 +1,45 @@ +# Copyright 2022 Tecnativa - Víctor Martínez +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo.tests import Form, common + + +class TestSaleTimesheetBudget(common.SavepointCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.customer = cls.env["res.partner"].create({"name": "Mr Odoo"}) + cls.analytic_account = cls.env["account.analytic.account"].create( + { + "name": "Test account", + "partner_id": cls.customer.id, + } + ) + cls.sale_order = cls.env["sale.order"].create( + { + "partner_id": cls.customer.id, + "analytic_account_id": cls.analytic_account.id, + } + ) + cls.project = cls.env["project.project"].create( + { + "name": "Test project", + "partner_id": cls.customer.id, + "analytic_account_id": cls.analytic_account.id, + } + ) + + def test_project_budget(self): + project_form = Form(self.project) + with project_form.budget_ids.new() as budget_form: + budget_form.sale_order_id = self.sale_order + budget_form.quantity = 2 + budget_form.price_unit = 10 + with project_form.budget_ids.new() as budget_form: + budget_form.sale_order_id = self.sale_order + budget_form.quantity = -1 + budget_form.price_unit = 10 + project_form.save() + self.assertEqual(self.project.budget_amount, 10) + vals = self.project._plan_prepare_values() + self.assertEqual(vals["dashboard"]["profit"]["budget_amount"], 10) diff --git a/sale_timesheet_budget/views/project_project_view.xml b/sale_timesheet_budget/views/project_project_view.xml new file mode 100644 index 0000000000..277b34e3f5 --- /dev/null +++ b/sale_timesheet_budget/views/project_project_view.xml @@ -0,0 +1,46 @@ + + + project.project.form + project.project + + + + + + + + + + + + + + + + + + + project.project.timesheet_plan + project.project + + + + + + + + Budget + + + + + From e1ff2f69a82c8f3a984db2d00cc38062d76adbae Mon Sep 17 00:00:00 2001 From: "Pedro M. Baeza" Date: Sun, 3 Jul 2022 18:02:54 +0200 Subject: [PATCH 02/15] [IMP] sale_timesheet_budget: Some improvements - Better view with optional fields and column invisible - Better README [UPD] Update sale_timesheet_budget.pot [UPD] README.rst --- sale_timesheet_budget/README.rst | 16 ++++++++----- .../i18n/sale_timesheet_budget.pot | 16 +++++++++---- .../models/project_project.py | 9 ++++++-- sale_timesheet_budget/readme/DESCRIPTION.rst | 3 ++- sale_timesheet_budget/readme/USAGE.rst | 13 +++++++---- .../static/description/index.html | 18 +++++++++------ .../views/project_project_view.xml | 23 +++++++++++++------ 7 files changed, 66 insertions(+), 32 deletions(-) diff --git a/sale_timesheet_budget/README.rst b/sale_timesheet_budget/README.rst index 0a719c8e38..e341cb3898 100644 --- a/sale_timesheet_budget/README.rst +++ b/sale_timesheet_budget/README.rst @@ -25,7 +25,8 @@ Sale timesheet budget |badge1| |badge2| |badge3| |badge4| |badge5| -This addon adds the "Budget" tab to the projects to be able to set some prices (benefits/expenses) linked to sales orders. +This module adds the "Budget" tab to the projects/sales orders to be able to set +some additional lines (incomes/expenses) linked to a planned budget. **Table of contents** @@ -35,11 +36,14 @@ This addon adds the "Budget" tab to the projects to be able to set some prices ( Usage ===== -#. Go to *Projects* and create and create a new one and set Customer and analytic account. -#. Go to *Sales -> Orders -> Quotations* and create a new one according to Customer and Analytic account previously created. -#. Go to *Projects* and edit project previously created. -#. Add some records (positive or negative) in "Budget" tab. -#. Go to *Project Overview* smart-button and a new line related to *Profitability* block have been created. +#. Go to *Projects* and create a new one, setting Customer and analytic account. +#. Go to *Sales -> Orders -> Quotations* and create a new one setting the same + customer and project previously created. +#. Alternatively, you can create a sales order with lines that creates a project. +#. Go to the project, and edit it. +#. Add some records (positive or negative) in the "Budget" tab. +#. Go to *Project Overview* smart-button and a new line called "Budget" in the + *Profitability* section will appear with the total amount of the lines. Known issues / Roadmap ====================== diff --git a/sale_timesheet_budget/i18n/sale_timesheet_budget.pot b/sale_timesheet_budget/i18n/sale_timesheet_budget.pot index 442c33fd76..bbfc8a18e4 100644 --- a/sale_timesheet_budget/i18n/sale_timesheet_budget.pot +++ b/sale_timesheet_budget/i18n/sale_timesheet_budget.pot @@ -6,8 +6,6 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 14.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-06-27 11:03+0000\n" -"PO-Revision-Date: 2022-06-27 11:03+0000\n" "Last-Translator: \n" "Language-Team: \n" "MIME-Version: 1.0\n" @@ -22,7 +20,7 @@ msgstr "" #. module: sale_timesheet_budget #: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget__amount -#: model_terms:ir.ui.view,arch_db:sale_timesheet_budget.edit_project +#: model_terms:ir.ui.view,arch_db:sale_timesheet_budget.project_project_view_form msgid "Amount" msgstr "" @@ -50,10 +48,15 @@ msgstr "" #. module: sale_timesheet_budget #: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project__budget_ids -#: model_terms:ir.ui.view,arch_db:sale_timesheet_budget.edit_project +#: model_terms:ir.ui.view,arch_db:sale_timesheet_budget.project_project_view_form msgid "Budgets" msgstr "" +#. module: sale_timesheet_budget +#: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget__name +msgid "Concept" +msgstr "" + #. module: sale_timesheet_budget #: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget__create_uid msgid "Created by" @@ -64,6 +67,11 @@ msgstr "" msgid "Created on" msgstr "" +#. module: sale_timesheet_budget +#: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget__date +msgid "Date" +msgstr "" + #. module: sale_timesheet_budget #: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project__display_name #: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget__display_name diff --git a/sale_timesheet_budget/models/project_project.py b/sale_timesheet_budget/models/project_project.py index c8fd41748f..61b592a24a 100644 --- a/sale_timesheet_budget/models/project_project.py +++ b/sale_timesheet_budget/models/project_project.py @@ -23,16 +23,21 @@ def _compute_budget_amount(self): item.budget_amount = sum(item.mapped("budget_ids.amount")) def _plan_prepare_values(self): + """Inject the budget amounts in the project overview.""" res = super()._plan_prepare_values() - res["dashboard"]["profit"]["budget_amount"] = sum(self.mapped("budget_amount")) - res["dashboard"]["profit"]["total"] += sum(self.mapped("budget_amount")) + budget_amount = sum(self.mapped("budget_amount")) + res["dashboard"]["profit"]["budget_amount"] = budget_amount + res["dashboard"]["profit"]["total"] += budget_amount return res class ProjectProjectBudget(models.Model): _name = "project.project.budget" _description = "Project Project Budget" + _order = "date, id" + date = fields.Date() + name = fields.Char(string="Concept") project_id = fields.Many2one( comodel_name="project.project", string="Project", required=True ) diff --git a/sale_timesheet_budget/readme/DESCRIPTION.rst b/sale_timesheet_budget/readme/DESCRIPTION.rst index e527ae62d9..a2ef1abc85 100644 --- a/sale_timesheet_budget/readme/DESCRIPTION.rst +++ b/sale_timesheet_budget/readme/DESCRIPTION.rst @@ -1 +1,2 @@ -This addon adds the "Budget" tab to the projects to be able to set some prices (benefits/expenses) linked to sales orders. +This module adds the "Budget" tab to the projects/sales orders to be able to set +some additional lines (incomes/expenses) linked to a planned budget. diff --git a/sale_timesheet_budget/readme/USAGE.rst b/sale_timesheet_budget/readme/USAGE.rst index 966fd19ebb..f0e97cf2ac 100644 --- a/sale_timesheet_budget/readme/USAGE.rst +++ b/sale_timesheet_budget/readme/USAGE.rst @@ -1,5 +1,8 @@ -#. Go to *Projects* and create and create a new one and set Customer and analytic account. -#. Go to *Sales -> Orders -> Quotations* and create a new one according to Customer and Analytic account previously created. -#. Go to *Projects* and edit project previously created. -#. Add some records (positive or negative) in "Budget" tab. -#. Go to *Project Overview* smart-button and a new line related to *Profitability* block have been created. +#. Go to *Projects* and create a new one, setting Customer and analytic account. +#. Go to *Sales -> Orders -> Quotations* and create a new one setting the same + customer and project previously created. +#. Alternatively, you can create a sales order with lines that creates a project. +#. Go to the project, and edit it. +#. Add some records (positive or negative) in the "Budget" tab. +#. Go to *Project Overview* smart-button and a new line called "Budget" in the + *Profitability* section will appear with the total amount of the lines. diff --git a/sale_timesheet_budget/static/description/index.html b/sale_timesheet_budget/static/description/index.html index 7d49620830..e601d0efbf 100644 --- a/sale_timesheet_budget/static/description/index.html +++ b/sale_timesheet_budget/static/description/index.html @@ -3,7 +3,7 @@ - + Sale timesheet budget -
-

Sale timesheet budget

+
+ + +Odoo Community Association + +
+

Sale timesheet budget

-

Beta License: AGPL-3 OCA/timesheet Translate me on Weblate Try me on Runboat

+

Beta License: AGPL-3 OCA/timesheet Translate me on Weblate Try me on Runboat

This module adds the “Budget” tab to the projects/sales orders to be able to set some additional lines (incomes/expenses) linked to a planned budget.

@@ -388,7 +393,7 @@

Sale timesheet budget

-

Usage

+

Usage

  1. Go to Projects and create a new one, setting Customer, analytic account and Billable.
  2. @@ -404,13 +409,13 @@

    Usage

-

Known issues / Roadmap

+

Known issues / Roadmap

  • Consider the planned hours of the tasks based on price/hour profiles.
-

Bug Tracker

+

Bug Tracker

Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed @@ -418,15 +423,15 @@

Bug Tracker

Do not contact contributors directly about support or help with technical issues.

-

Credits

+

Credits

-

Authors

+

Authors

  • Tecnativa
-

Contributors

+

Contributors

-

Maintainers

+

Maintainers

This module is maintained by the OCA.

Odoo Community Association @@ -451,5 +456,6 @@

Maintainers

+
From c7b9f28f62eb9e991638ebb48fb978aeb0bdfc0c Mon Sep 17 00:00:00 2001 From: Ed-Spain Date: Thu, 16 Apr 2026 18:56:41 +0000 Subject: [PATCH 13/15] Translated using Weblate (Spanish) Currently translated at 95.2% (20 of 21 strings) Translation: timesheet-18.0/timesheet-18.0-sale_timesheet_budget Translate-URL: https://translation.odoo-community.org/projects/timesheet-18-0/timesheet-18-0-sale_timesheet_budget/es/ --- sale_timesheet_budget/i18n/es.po | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/sale_timesheet_budget/i18n/es.po b/sale_timesheet_budget/i18n/es.po index 3beaa01cdd..a674a4996a 100644 --- a/sale_timesheet_budget/i18n/es.po +++ b/sale_timesheet_budget/i18n/es.po @@ -7,15 +7,15 @@ msgstr "" "Project-Id-Version: Odoo Server 14.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-06-27 11:03+0000\n" -"PO-Revision-Date: 2022-06-27 13:04+0200\n" -"Last-Translator: \n" +"PO-Revision-Date: 2026-04-16 21:45+0000\n" +"Last-Translator: Ed-Spain \n" "Language-Team: \n" "Language: es\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: \n" -"X-Generator: Poedit 2.3\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 5.15.2\n" #. module: sale_timesheet_budget #: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget__amount @@ -40,6 +40,15 @@ msgid "" "necessary.\n" "An analytic account is required in order to use timesheets." msgstr "" +"Cuenta analítica vinculada a este proyecto, sus tareas y sus hojas de " +"horas.. \n" +"Realice un seguimiento de los costos e ingresos de su proyecto configurando " +"esta cuenta analítica en los documentos relacionados (por ejemplo, pedidos " +"de venta, facturas, órdenes de compra, facturas de proveedores, gastos, etc.)" +".\n" +"Esta cuenta analítica se puede modificar individualmente para cada tarea si " +"es necesario.\n" +"Se requiere una cuenta analítica para utilizar las hojas de horas." #. module: sale_timesheet_budget #: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project__budget_amount @@ -58,7 +67,7 @@ msgstr "Presupuestos" #. module: sale_timesheet_budget #: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget__name msgid "Concept" -msgstr "" +msgstr "Concepto" #. module: sale_timesheet_budget #: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget__create_uid @@ -73,7 +82,7 @@ msgstr "Creado el" #. module: sale_timesheet_budget #: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget__date msgid "Date" -msgstr "" +msgstr "Fecha" #. module: sale_timesheet_budget #: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget__display_name @@ -114,12 +123,12 @@ msgstr "Proyecto" #. module: sale_timesheet_budget #: model:ir.actions.act_window,name:sale_timesheet_budget.action_project_project_budget msgid "Project Budgets" -msgstr "" +msgstr "Presupuestos Proyectos" #. module: sale_timesheet_budget #: model:ir.model,name:sale_timesheet_budget.model_project_project_budget msgid "Project Project Budget" -msgstr "" +msgstr "Proyecto Presupuesto del Proyecto" #. module: sale_timesheet_budget #: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget__quantity @@ -135,4 +144,3 @@ msgstr "Pedido de venta" #: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget__sale_order_id_domain msgid "Sale Order Id Domain" msgstr "" - From c24f61b5fbc1cc0ce8869b379050739d3fb124e4 Mon Sep 17 00:00:00 2001 From: Ed-Spain Date: Sun, 10 May 2026 09:26:46 +0000 Subject: [PATCH 14/15] Translated using Weblate (Spanish) Currently translated at 100.0% (21 of 21 strings) Translation: timesheet-18.0/timesheet-18.0-sale_timesheet_budget Translate-URL: https://translation.odoo-community.org/projects/timesheet-18-0/timesheet-18-0-sale_timesheet_budget/es/ --- sale_timesheet_budget/i18n/es.po | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sale_timesheet_budget/i18n/es.po b/sale_timesheet_budget/i18n/es.po index a674a4996a..baa862697e 100644 --- a/sale_timesheet_budget/i18n/es.po +++ b/sale_timesheet_budget/i18n/es.po @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: Odoo Server 14.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-06-27 11:03+0000\n" -"PO-Revision-Date: 2026-04-16 21:45+0000\n" +"PO-Revision-Date: 2026-05-10 09:27+0000\n" "Last-Translator: Ed-Spain \n" "Language-Team: \n" "Language: es\n" @@ -143,4 +143,4 @@ msgstr "Pedido de venta" #. module: sale_timesheet_budget #: model:ir.model.fields,field_description:sale_timesheet_budget.field_project_project_budget__sale_order_id_domain msgid "Sale Order Id Domain" -msgstr "" +msgstr "Dominio del ID del pedido de venta" From 3bdd82f58cec8bc3d5fb678ac77badf4a00eb2da Mon Sep 17 00:00:00 2001 From: uncannycs Date: Mon, 18 May 2026 13:20:18 +0530 Subject: [PATCH 15/15] [MIG] sale_timesheet_budget : Migration to 19.0. --- sale_timesheet_budget/README.rst | 10 ++++---- sale_timesheet_budget/__manifest__.py | 2 +- sale_timesheet_budget/i18n/es.po | 2 +- .../models/project_project.py | 20 +++++++++------ .../static/description/index.html | 6 ++--- .../tests/test_sale_timesheet_budget.py | 25 ++++++++++++++----- 6 files changed, 42 insertions(+), 23 deletions(-) diff --git a/sale_timesheet_budget/README.rst b/sale_timesheet_budget/README.rst index ed9d923ee5..d5104915d5 100644 --- a/sale_timesheet_budget/README.rst +++ b/sale_timesheet_budget/README.rst @@ -21,13 +21,13 @@ Sale timesheet budget :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Ftimesheet-lightgray.png?logo=github - :target: https://github.com/OCA/timesheet/tree/18.0/sale_timesheet_budget + :target: https://github.com/OCA/timesheet/tree/19.0/sale_timesheet_budget :alt: OCA/timesheet .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/timesheet-18-0/timesheet-18-0-sale_timesheet_budget + :target: https://translation.odoo-community.org/projects/timesheet-19-0/timesheet-19-0-sale_timesheet_budget :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png - :target: https://runboat.odoo-community.org/builds?repo=OCA/timesheet&target_branch=18.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/timesheet&target_branch=19.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| @@ -67,7 +67,7 @@ Bug Tracker Bugs are tracked on `GitHub Issues `_. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -108,6 +108,6 @@ Current `maintainer `__: |maintainer-victoralmau| -This module is part of the `OCA/timesheet `_ project on GitHub. +This module is part of the `OCA/timesheet `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/sale_timesheet_budget/__manifest__.py b/sale_timesheet_budget/__manifest__.py index 3768171cc2..53dd6694af 100644 --- a/sale_timesheet_budget/__manifest__.py +++ b/sale_timesheet_budget/__manifest__.py @@ -2,7 +2,7 @@ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). { "name": "Sale timesheet budget", - "version": "18.0.1.0.0", + "version": "19.0.1.0.0", "category": "Timesheet", "website": "https://github.com/OCA/timesheet", "author": "Tecnativa, Odoo Community Association (OCA)", diff --git a/sale_timesheet_budget/i18n/es.po b/sale_timesheet_budget/i18n/es.po index baa862697e..45207e7138 100644 --- a/sale_timesheet_budget/i18n/es.po +++ b/sale_timesheet_budget/i18n/es.po @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: Odoo Server 14.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-06-27 11:03+0000\n" -"PO-Revision-Date: 2026-05-10 09:27+0000\n" +"PO-Revision-Date: 2026-04-16 21:45+0000\n" "Last-Translator: Ed-Spain \n" "Language-Team: \n" "Language: es\n" diff --git a/sale_timesheet_budget/models/project_project.py b/sale_timesheet_budget/models/project_project.py index 284dbcdf36..e83237ab6a 100644 --- a/sale_timesheet_budget/models/project_project.py +++ b/sale_timesheet_budget/models/project_project.py @@ -1,7 +1,7 @@ # Copyright 2022-2024 Tecnativa - Víctor Martínez # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo import _lt, api, fields, models +from odoo import api, fields, models class ProjectProject(models.Model): @@ -17,12 +17,12 @@ class ProjectProject(models.Model): @api.depends("budget_ids") def _compute_budget_amount(self): - data = self.env["project.project.budget"].read_group( + data = self.env["project.project.budget"]._read_group( domain=[("project_id", "in", self.ids)], - fields=["project_id", "amount:sum"], groupby=["project_id"], + aggregates=["amount:sum"], ) - mapped_data = {x["project_id"][0]: x["amount"] for x in data} + mapped_data = {project.id: amount_sum for project, amount_sum in data} for item in self: item.budget_amount = mapped_data.get(item.id, 0) @@ -35,18 +35,24 @@ def action_profitability_budget_item(self): def _get_profitability_labels(self): res = super()._get_profitability_labels() - res["budgets"] = _lt("Budgets") + res["budgets"] = self.env._("Budgets") + return res + + def _get_profitability_sequence_per_invoice_type(self): + res = super()._get_profitability_sequence_per_invoice_type() + res["budgets"] = 8 return res def _get_profitability_items(self, with_action=True): items = super()._get_profitability_items(with_action) if not self.budget_ids: return items - last_sequence = len(items["revenues"]["data"]) items["revenues"]["data"].append( { "id": "budgets", - "sequence": last_sequence + 1, + "sequence": self._get_profitability_sequence_per_invoice_type()[ + "budgets" + ], "invoiced": 0, "to_invoice": self.budget_amount, "action": { diff --git a/sale_timesheet_budget/static/description/index.html b/sale_timesheet_budget/static/description/index.html index 2017008179..5a52e8e616 100644 --- a/sale_timesheet_budget/static/description/index.html +++ b/sale_timesheet_budget/static/description/index.html @@ -374,7 +374,7 @@

Sale timesheet budget

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! source digest: sha256:f87109f6f4372bd1ff932d9dd90bd4c19896fda92a1e729aacd3678eea72c1e1 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

Beta License: AGPL-3 OCA/timesheet Translate me on Weblate Try me on Runboat

+

Beta License: AGPL-3 OCA/timesheet Translate me on Weblate Try me on Runboat

This module adds the “Budget” tab to the projects/sales orders to be able to set some additional lines (incomes/expenses) linked to a planned budget.

@@ -419,7 +419,7 @@

Bug Tracker

Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed -feedback.

+feedback.

Do not contact contributors directly about support or help with technical issues.

@@ -451,7 +451,7 @@

Maintainers

promote its widespread use.

Current maintainer:

victoralmau

-

This module is part of the OCA/timesheet project on GitHub.

+

This module is part of the OCA/timesheet project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

diff --git a/sale_timesheet_budget/tests/test_sale_timesheet_budget.py b/sale_timesheet_budget/tests/test_sale_timesheet_budget.py index 8427b45bfe..6b3004e870 100644 --- a/sale_timesheet_budget/tests/test_sale_timesheet_budget.py +++ b/sale_timesheet_budget/tests/test_sale_timesheet_budget.py @@ -19,12 +19,6 @@ def setUpClass(cls): "plan_id": cls.plan.id, } ) - cls.sale_order = cls.env["sale.order"].create( - { - "partner_id": cls.customer.id, - "project_account_id": cls.analytic_account.id, - } - ) cls.project = cls.env["project.project"].create( { "name": "Test project", @@ -33,8 +27,27 @@ def setUpClass(cls): "allow_billable": True, } ) + cls.sale_order = cls.env["sale.order"].create( + { + "partner_id": cls.customer.id, + "project_id": cls.project.id, + } + ) def test_project_budget(self): + # Test project without budgets to cover early return in _get_profitability_items + data_no_budget = self.project.get_panel_data() + if "profitability_items" in data_no_budget: + self.assertNotIn( + "budgets", + [ + item["id"] + for item in data_no_budget["profitability_items"]["revenues"][ + "data" + ] + ], + ) + project_form = Form(self.project) with project_form.budget_ids.new() as budget_form: budget_form.sale_order_id = self.sale_order