From 3e8fda2270e08a2388101528a8750107bd8fd2d7 Mon Sep 17 00:00:00 2001 From: Victor Champonnois Date: Thu, 24 Oct 2024 19:30:19 +0200 Subject: [PATCH 1/6] [ADD] contract_timesheet_monitoring --- contract_timesheet_monitoring/README.rst | 67 +++ contract_timesheet_monitoring/__init__.py | 1 + contract_timesheet_monitoring/__manifest__.py | 21 + .../models/__init__.py | 4 + .../models/account_analytic_account.py | 19 + .../models/account_invoice_line.py | 26 ++ .../models/contract_line.py | 30 ++ .../models/product_template.py | 14 + .../readme/DESCRIPTION.md | 6 + contract_timesheet_monitoring/readme/USAGE.md | 2 + .../static/description/index.html | 420 ++++++++++++++++++ .../views/account_invoice.xml | 13 + .../views/account_invoice_report.xml | 27 ++ .../views/contract.xml | 15 + .../views/contract_portal_templates.xml | 47 ++ .../views/product_template_view.xml | 21 + 16 files changed, 733 insertions(+) create mode 100644 contract_timesheet_monitoring/README.rst create mode 100644 contract_timesheet_monitoring/__init__.py create mode 100644 contract_timesheet_monitoring/__manifest__.py create mode 100644 contract_timesheet_monitoring/models/__init__.py create mode 100644 contract_timesheet_monitoring/models/account_analytic_account.py create mode 100644 contract_timesheet_monitoring/models/account_invoice_line.py create mode 100644 contract_timesheet_monitoring/models/contract_line.py create mode 100644 contract_timesheet_monitoring/models/product_template.py create mode 100644 contract_timesheet_monitoring/readme/DESCRIPTION.md create mode 100644 contract_timesheet_monitoring/readme/USAGE.md create mode 100644 contract_timesheet_monitoring/static/description/index.html create mode 100644 contract_timesheet_monitoring/views/account_invoice.xml create mode 100644 contract_timesheet_monitoring/views/account_invoice_report.xml create mode 100644 contract_timesheet_monitoring/views/contract.xml create mode 100644 contract_timesheet_monitoring/views/contract_portal_templates.xml create mode 100644 contract_timesheet_monitoring/views/product_template_view.xml diff --git a/contract_timesheet_monitoring/README.rst b/contract_timesheet_monitoring/README.rst new file mode 100644 index 000000000..32f52fcbb --- /dev/null +++ b/contract_timesheet_monitoring/README.rst @@ -0,0 +1,67 @@ +============================= +Contract timesheet monitoring +============================= + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:00fb3cdc565442ffcd3351e97d0516ce6f4ceb55402981b183f7e717a1e23173 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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-coopiteasy%2Faddons-lightgray.png?logo=github + :target: https://github.com/coopiteasy/addons/tree/16.0/contract_timesheet_monitoring + :alt: coopiteasy/addons + +|badge1| |badge2| |badge3| + +This module was developped for clients paying a subscription fee for +functional support. We wanted to invoice a fixed amount per period, but +invoice excess time. This module provide a way for the clients and the +service provider to monitor the time spent to compare it with the +quantity bought. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +The time spent for the current period is indicated in the contract line. +Time spent for past periods is indicated in the previous invoices. Note +: this might be confusing if the contract is configured to create +invoices at the begining of the period. + +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 `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* Coop IT Easy SC + +Maintainers +----------- + +This module is part of the `coopiteasy/addons `_ project on GitHub. + +You are welcome to contribute. diff --git a/contract_timesheet_monitoring/__init__.py b/contract_timesheet_monitoring/__init__.py new file mode 100644 index 000000000..0650744f6 --- /dev/null +++ b/contract_timesheet_monitoring/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/contract_timesheet_monitoring/__manifest__.py b/contract_timesheet_monitoring/__manifest__.py new file mode 100644 index 000000000..7ca46c598 --- /dev/null +++ b/contract_timesheet_monitoring/__manifest__.py @@ -0,0 +1,21 @@ +# Copyright 2017 Tecnativa - Luis M. Ontalba +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +{ + "name": "Contract timesheet monitoring", + "summary": "Compute time spent on service contracts", + "version": "16.0.1.0.0", + "category": "Sales", + "author": "Coop IT Easy SC, Odoo Community Association (OCA)", + "website": "https://github.com/coopiteasy/addons", + "depends": ["contract", "hr_timesheet", "contract_invoice_start_end_dates"], + "data": [ + "views/contract.xml", + "views/account_invoice.xml", + "views/account_invoice_report.xml", + "views/product_template_view.xml", + "views/contract_portal_templates.xml", + ], + "license": "AGPL-3", + "installable": True, +} diff --git a/contract_timesheet_monitoring/models/__init__.py b/contract_timesheet_monitoring/models/__init__.py new file mode 100644 index 000000000..b616c44a9 --- /dev/null +++ b/contract_timesheet_monitoring/models/__init__.py @@ -0,0 +1,4 @@ +from . import contract_line +from . import account_invoice_line +from . import account_analytic_account +from . import product_template diff --git a/contract_timesheet_monitoring/models/account_analytic_account.py b/contract_timesheet_monitoring/models/account_analytic_account.py new file mode 100644 index 000000000..b456b3f3a --- /dev/null +++ b/contract_timesheet_monitoring/models/account_analytic_account.py @@ -0,0 +1,19 @@ +from odoo import models + + +class AccountAnalyticAccount(models.Model): + _inherit = "account.analytic.account" + + def get_time_spent_for_period(self, start_date, end_date=None): + analytic_account_lines = self.line_ids + timesheets = analytic_account_lines.filtered( + # keep only timesheets + # ensure the uom is the same as the one configure for the project + # timesheets (hours or day) + lambda x: (x.product_uom_id.measure_type == "time") + ) + if timesheets: + time_spent_on_account = timesheets.filtered( + lambda x: (x.date >= start_date) + ).mapped("unit_amount") + return sum(time_spent_on_account) diff --git a/contract_timesheet_monitoring/models/account_invoice_line.py b/contract_timesheet_monitoring/models/account_invoice_line.py new file mode 100644 index 000000000..29ec2d725 --- /dev/null +++ b/contract_timesheet_monitoring/models/account_invoice_line.py @@ -0,0 +1,26 @@ +# Copyright 2016 Tecnativa - Carlos Dauden +# Copyright 2018 ACSONE SA/NV. +# Copyright 2020 Tecnativa - Pedro M. Baeza +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class AccountInvoiceLine(models.Model): + _inherit = "account.invoice.line" + + time_spent = fields.Float( + string="Time Spent", compute="_compute_time_spent" + ) + time_available = fields.Integer(related="product_id.hours_available") + + + + def _compute_time_spent(self): + for line in self: + if line.analytic_account and line.start_date: + line.time_spent = line.analytic_account_id.get_time_spent_for_period( + line.start_date, line.end_date + ) + else: + line.time_spent = False diff --git a/contract_timesheet_monitoring/models/contract_line.py b/contract_timesheet_monitoring/models/contract_line.py new file mode 100644 index 000000000..f79bc7518 --- /dev/null +++ b/contract_timesheet_monitoring/models/contract_line.py @@ -0,0 +1,30 @@ +from odoo import api, fields, models + + +class ContractLine(models.Model): + _inherit = "contract.line" + + time_spent = fields.Float( + string="Time Spent", compute="_compute_time_spent" + ) + time_available = fields.Integer(related="product_id.hours_available") + + time_remaining = fields.Float( + string="Time Remaining", compute="_compute_time_remaining" + ) + + @api.depends("analytic_account_id.line_ids") + def _compute_time_spent(self): + for line in self: + if line.analytic_account_id: + period_start_date = line.last_date_invoiced or line.date_start + line.time_spent = line.analytic_account_id.get_time_spent_for_period( + period_start_date + ) + else: + line.time_spent = False + + @api.depends("time_available", "time_spent") + def _compute_time_remaining(self): + for line in self: + line.time_remaining = line.time_available - line.time_spent diff --git a/contract_timesheet_monitoring/models/product_template.py b/contract_timesheet_monitoring/models/product_template.py new file mode 100644 index 000000000..497b2ff65 --- /dev/null +++ b/contract_timesheet_monitoring/models/product_template.py @@ -0,0 +1,14 @@ +# Copyright 2023 Coop IT Easy SC +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from odoo import api, fields, models + + +class ProductTemplate(models.Model): + _inherit = "product.template" + + is_support_product = fields.Boolean() + hours_available = fields.Integer( + string="Hours available", + default=0, + ) diff --git a/contract_timesheet_monitoring/readme/DESCRIPTION.md b/contract_timesheet_monitoring/readme/DESCRIPTION.md new file mode 100644 index 000000000..7c07c3e31 --- /dev/null +++ b/contract_timesheet_monitoring/readme/DESCRIPTION.md @@ -0,0 +1,6 @@ + +This module was developped for clients paying a subscription fee for functional support. We wanted to invoice a fixed amount per period, but invoice excess time. +This module provide a way for the clients and the service provider to monitor the time spent to compare it with the quantity bought. + + + diff --git a/contract_timesheet_monitoring/readme/USAGE.md b/contract_timesheet_monitoring/readme/USAGE.md new file mode 100644 index 000000000..42dd081ad --- /dev/null +++ b/contract_timesheet_monitoring/readme/USAGE.md @@ -0,0 +1,2 @@ +The time spent for the current period is indicated in the contract line. Time spent for past periods is indicated in the previous invoices. +Note : this might be confusing if the contract is configured to create invoices at the begining of the period. diff --git a/contract_timesheet_monitoring/static/description/index.html b/contract_timesheet_monitoring/static/description/index.html new file mode 100644 index 000000000..821f15548 --- /dev/null +++ b/contract_timesheet_monitoring/static/description/index.html @@ -0,0 +1,420 @@ + + + + + +Contract timesheet monitoring + + + +
+

Contract timesheet monitoring

+ + +

Beta License: AGPL-3 coopiteasy/addons

+

This module was developped for clients paying a subscription fee for +functional support. We wanted to invoice a fixed amount per period, but +invoice excess time. This module provide a way for the clients and the +service provider to monitor the time spent to compare it with the +quantity bought.

+

Table of contents

+ +
+

Usage

+

The time spent for the current period is indicated in the contract line. +Time spent for past periods is indicated in the previous invoices. Note +: this might be confusing if the contract is configured to create +invoices at the begining of the period.

+
+
+

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.

+

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

+
+
+

Credits

+
+

Authors

+
    +
  • Coop IT Easy SC
  • +
+
+
+

Maintainers

+

This module is part of the coopiteasy/addons project on GitHub.

+

You are welcome to contribute.

+
+
+
+ + diff --git a/contract_timesheet_monitoring/views/account_invoice.xml b/contract_timesheet_monitoring/views/account_invoice.xml new file mode 100644 index 000000000..261e1b772 --- /dev/null +++ b/contract_timesheet_monitoring/views/account_invoice.xml @@ -0,0 +1,13 @@ + + + + account.invoice.form.view + account.invoice + + + + + + + + diff --git a/contract_timesheet_monitoring/views/account_invoice_report.xml b/contract_timesheet_monitoring/views/account_invoice_report.xml new file mode 100644 index 000000000..93597cacc --- /dev/null +++ b/contract_timesheet_monitoring/views/account_invoice_report.xml @@ -0,0 +1,27 @@ + + + + + diff --git a/contract_timesheet_monitoring/views/contract.xml b/contract_timesheet_monitoring/views/contract.xml new file mode 100644 index 000000000..799787b02 --- /dev/null +++ b/contract_timesheet_monitoring/views/contract.xml @@ -0,0 +1,15 @@ + + + + contract.contract.form.view + contract.contract + + + + + + + + + + diff --git a/contract_timesheet_monitoring/views/contract_portal_templates.xml b/contract_timesheet_monitoring/views/contract_portal_templates.xml new file mode 100644 index 000000000..cb61fd22d --- /dev/null +++ b/contract_timesheet_monitoring/views/contract_portal_templates.xml @@ -0,0 +1,47 @@ + + + + + diff --git a/contract_timesheet_monitoring/views/product_template_view.xml b/contract_timesheet_monitoring/views/product_template_view.xml new file mode 100644 index 000000000..e4901ce01 --- /dev/null +++ b/contract_timesheet_monitoring/views/product_template_view.xml @@ -0,0 +1,21 @@ + + + + + + product.template.form.view + product.template + + + + + + + + + + + + + + From 55a466d296c59a0fc45bc9af202bc04cb285ae4a Mon Sep 17 00:00:00 2001 From: Victor Champonnois Date: Fri, 25 Oct 2024 09:47:13 +0200 Subject: [PATCH 2/6] fixup --- contract_timesheet_monitoring/models/account_invoice_line.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contract_timesheet_monitoring/models/account_invoice_line.py b/contract_timesheet_monitoring/models/account_invoice_line.py index 29ec2d725..13654d982 100644 --- a/contract_timesheet_monitoring/models/account_invoice_line.py +++ b/contract_timesheet_monitoring/models/account_invoice_line.py @@ -18,7 +18,7 @@ class AccountInvoiceLine(models.Model): def _compute_time_spent(self): for line in self: - if line.analytic_account and line.start_date: + if line.analytic_account_id and line.start_date: line.time_spent = line.analytic_account_id.get_time_spent_for_period( line.start_date, line.end_date ) From 18ed1b2bb85b1a6ea28506a1b3c9aab00ea4b153 Mon Sep 17 00:00:00 2001 From: Victor Champonnois Date: Fri, 25 Oct 2024 10:37:02 +0200 Subject: [PATCH 3/6] [FIX] compute time spent based on last invoice date --- .../models/account_analytic_account.py | 9 +++++---- .../models/account_invoice_line.py | 18 +++++++++++++----- .../models/contract_line.py | 10 +++++++++- .../views/account_invoice.xml | 4 +++- 4 files changed, 30 insertions(+), 11 deletions(-) diff --git a/contract_timesheet_monitoring/models/account_analytic_account.py b/contract_timesheet_monitoring/models/account_analytic_account.py index b456b3f3a..85fb0abe6 100644 --- a/contract_timesheet_monitoring/models/account_analytic_account.py +++ b/contract_timesheet_monitoring/models/account_analytic_account.py @@ -13,7 +13,8 @@ def get_time_spent_for_period(self, start_date, end_date=None): lambda x: (x.product_uom_id.measure_type == "time") ) if timesheets: - time_spent_on_account = timesheets.filtered( - lambda x: (x.date >= start_date) - ).mapped("unit_amount") - return sum(time_spent_on_account) + if start_date: + timesheets = timesheets.filtered( + lambda x: (x.date >= start_date) + ) + return sum(timesheets.mapped("unit_amount")) diff --git a/contract_timesheet_monitoring/models/account_invoice_line.py b/contract_timesheet_monitoring/models/account_invoice_line.py index 13654d982..d71665a85 100644 --- a/contract_timesheet_monitoring/models/account_invoice_line.py +++ b/contract_timesheet_monitoring/models/account_invoice_line.py @@ -3,7 +3,7 @@ # Copyright 2020 Tecnativa - Pedro M. Baeza # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo import fields, models +from odoo import api, fields, models class AccountInvoiceLine(models.Model): @@ -13,14 +13,22 @@ class AccountInvoiceLine(models.Model): string="Time Spent", compute="_compute_time_spent" ) time_available = fields.Integer(related="product_id.hours_available") + + time_remaining = fields.Float( + string="Time Remaining", compute="_compute_time_remaining" + ) - - + @api.depends("account_analytic_id.line_ids") def _compute_time_spent(self): for line in self: - if line.analytic_account_id and line.start_date: - line.time_spent = line.analytic_account_id.get_time_spent_for_period( + if line.account_analytic_id and line.start_date: + line.time_spent = line.account_analytic_id.get_time_spent_for_period( line.start_date, line.end_date ) else: line.time_spent = False + + @api.depends("time_available", "time_spent") + def _compute_time_remaining(self): + for line in self: + line.time_remaining = line.time_available - line.time_spent diff --git a/contract_timesheet_monitoring/models/contract_line.py b/contract_timesheet_monitoring/models/contract_line.py index f79bc7518..5ff3179c1 100644 --- a/contract_timesheet_monitoring/models/contract_line.py +++ b/contract_timesheet_monitoring/models/contract_line.py @@ -12,12 +12,20 @@ class ContractLine(models.Model): time_remaining = fields.Float( string="Time Remaining", compute="_compute_time_remaining" ) + date_of_last_invoice = fields.Date(compute="_get_date_of_last_invoice") + + def _get_date_of_last_invoice(self): + invoices = self.contract_id._get_related_invoices().filtered(lambda x: (x.state != "draft")) + if any(invoices.mapped("date_invoice")): + return max(invoices.mapped("date_invoice")) + else: + return False @api.depends("analytic_account_id.line_ids") def _compute_time_spent(self): for line in self: if line.analytic_account_id: - period_start_date = line.last_date_invoiced or line.date_start + period_start_date = line._get_date_of_last_invoice() line.time_spent = line.analytic_account_id.get_time_spent_for_period( period_start_date ) diff --git a/contract_timesheet_monitoring/views/account_invoice.xml b/contract_timesheet_monitoring/views/account_invoice.xml index 261e1b772..f19453b9f 100644 --- a/contract_timesheet_monitoring/views/account_invoice.xml +++ b/contract_timesheet_monitoring/views/account_invoice.xml @@ -6,7 +6,9 @@ - + + + From fc67bbdda2cd853e18be273359a99063a6b84a7f Mon Sep 17 00:00:00 2001 From: Victor Champonnois Date: Fri, 25 Oct 2024 11:05:24 +0200 Subject: [PATCH 4/6] [FIX] hours_available>time_available and hide if empty --- .../models/account_invoice_line.py | 2 +- contract_timesheet_monitoring/models/contract_line.py | 2 +- contract_timesheet_monitoring/models/product_template.py | 4 ++-- contract_timesheet_monitoring/views/contract.xml | 6 +++--- .../views/product_template_view.xml | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/contract_timesheet_monitoring/models/account_invoice_line.py b/contract_timesheet_monitoring/models/account_invoice_line.py index d71665a85..478d98adf 100644 --- a/contract_timesheet_monitoring/models/account_invoice_line.py +++ b/contract_timesheet_monitoring/models/account_invoice_line.py @@ -12,7 +12,7 @@ class AccountInvoiceLine(models.Model): time_spent = fields.Float( string="Time Spent", compute="_compute_time_spent" ) - time_available = fields.Integer(related="product_id.hours_available") + time_available = fields.Integer(related="product_id.time_available") time_remaining = fields.Float( string="Time Remaining", compute="_compute_time_remaining" diff --git a/contract_timesheet_monitoring/models/contract_line.py b/contract_timesheet_monitoring/models/contract_line.py index 5ff3179c1..aa2c8be01 100644 --- a/contract_timesheet_monitoring/models/contract_line.py +++ b/contract_timesheet_monitoring/models/contract_line.py @@ -7,7 +7,7 @@ class ContractLine(models.Model): time_spent = fields.Float( string="Time Spent", compute="_compute_time_spent" ) - time_available = fields.Integer(related="product_id.hours_available") + time_available = fields.Integer(related="product_id.time_available") time_remaining = fields.Float( string="Time Remaining", compute="_compute_time_remaining" diff --git a/contract_timesheet_monitoring/models/product_template.py b/contract_timesheet_monitoring/models/product_template.py index 497b2ff65..6372ba9ab 100644 --- a/contract_timesheet_monitoring/models/product_template.py +++ b/contract_timesheet_monitoring/models/product_template.py @@ -8,7 +8,7 @@ class ProductTemplate(models.Model): _inherit = "product.template" is_support_product = fields.Boolean() - hours_available = fields.Integer( - string="Hours available", + time_available = fields.Integer( + string="Time available", default=0, ) diff --git a/contract_timesheet_monitoring/views/contract.xml b/contract_timesheet_monitoring/views/contract.xml index 799787b02..e5e74d7e0 100644 --- a/contract_timesheet_monitoring/views/contract.xml +++ b/contract_timesheet_monitoring/views/contract.xml @@ -6,9 +6,9 @@ - - - + + + diff --git a/contract_timesheet_monitoring/views/product_template_view.xml b/contract_timesheet_monitoring/views/product_template_view.xml index e4901ce01..7efea9c2a 100644 --- a/contract_timesheet_monitoring/views/product_template_view.xml +++ b/contract_timesheet_monitoring/views/product_template_view.xml @@ -10,7 +10,7 @@ - + From 3be5b9159d99474c024c7757d2d069f6b4d57cff Mon Sep 17 00:00:00 2001 From: Victor Champonnois Date: Fri, 25 Oct 2024 11:19:08 +0200 Subject: [PATCH 5/6] [REM] display on invoices --- contract_timesheet_monitoring/__manifest__.py | 2 -- .../models/__init__.py | 1 - .../models/account_invoice_line.py | 34 ------------------- .../views/account_invoice.xml | 15 -------- .../views/account_invoice_report.xml | 27 --------------- .../views/product_template_view.xml | 2 -- 6 files changed, 81 deletions(-) delete mode 100644 contract_timesheet_monitoring/models/account_invoice_line.py delete mode 100644 contract_timesheet_monitoring/views/account_invoice.xml delete mode 100644 contract_timesheet_monitoring/views/account_invoice_report.xml diff --git a/contract_timesheet_monitoring/__manifest__.py b/contract_timesheet_monitoring/__manifest__.py index 7ca46c598..e55bbb672 100644 --- a/contract_timesheet_monitoring/__manifest__.py +++ b/contract_timesheet_monitoring/__manifest__.py @@ -11,8 +11,6 @@ "depends": ["contract", "hr_timesheet", "contract_invoice_start_end_dates"], "data": [ "views/contract.xml", - "views/account_invoice.xml", - "views/account_invoice_report.xml", "views/product_template_view.xml", "views/contract_portal_templates.xml", ], diff --git a/contract_timesheet_monitoring/models/__init__.py b/contract_timesheet_monitoring/models/__init__.py index b616c44a9..48294c074 100644 --- a/contract_timesheet_monitoring/models/__init__.py +++ b/contract_timesheet_monitoring/models/__init__.py @@ -1,4 +1,3 @@ from . import contract_line -from . import account_invoice_line from . import account_analytic_account from . import product_template diff --git a/contract_timesheet_monitoring/models/account_invoice_line.py b/contract_timesheet_monitoring/models/account_invoice_line.py deleted file mode 100644 index 478d98adf..000000000 --- a/contract_timesheet_monitoring/models/account_invoice_line.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright 2016 Tecnativa - Carlos Dauden -# Copyright 2018 ACSONE SA/NV. -# Copyright 2020 Tecnativa - Pedro M. Baeza -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). - -from odoo import api, fields, models - - -class AccountInvoiceLine(models.Model): - _inherit = "account.invoice.line" - - time_spent = fields.Float( - string="Time Spent", compute="_compute_time_spent" - ) - time_available = fields.Integer(related="product_id.time_available") - - time_remaining = fields.Float( - string="Time Remaining", compute="_compute_time_remaining" - ) - - @api.depends("account_analytic_id.line_ids") - def _compute_time_spent(self): - for line in self: - if line.account_analytic_id and line.start_date: - line.time_spent = line.account_analytic_id.get_time_spent_for_period( - line.start_date, line.end_date - ) - else: - line.time_spent = False - - @api.depends("time_available", "time_spent") - def _compute_time_remaining(self): - for line in self: - line.time_remaining = line.time_available - line.time_spent diff --git a/contract_timesheet_monitoring/views/account_invoice.xml b/contract_timesheet_monitoring/views/account_invoice.xml deleted file mode 100644 index f19453b9f..000000000 --- a/contract_timesheet_monitoring/views/account_invoice.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - account.invoice.form.view - account.invoice - - - - - - - - - - diff --git a/contract_timesheet_monitoring/views/account_invoice_report.xml b/contract_timesheet_monitoring/views/account_invoice_report.xml deleted file mode 100644 index 93597cacc..000000000 --- a/contract_timesheet_monitoring/views/account_invoice_report.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - diff --git a/contract_timesheet_monitoring/views/product_template_view.xml b/contract_timesheet_monitoring/views/product_template_view.xml index 7efea9c2a..ab46423b3 100644 --- a/contract_timesheet_monitoring/views/product_template_view.xml +++ b/contract_timesheet_monitoring/views/product_template_view.xml @@ -15,7 +15,5 @@ - - From 60a6d744a1e00c1c12a2af61777dbc8657cc3cf3 Mon Sep 17 00:00:00 2001 From: Victor Champonnois Date: Fri, 25 Oct 2024 14:49:02 +0200 Subject: [PATCH 6/6] [FIX] use contract date rather than invoice date Invoice date might not the date of the invoiced period, because invoice are not validated and sent on the first day of the period. --- .../models/account_analytic_account.py | 2 -- .../models/contract_line.py | 17 ++++++++++------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/contract_timesheet_monitoring/models/account_analytic_account.py b/contract_timesheet_monitoring/models/account_analytic_account.py index 85fb0abe6..dfcd16434 100644 --- a/contract_timesheet_monitoring/models/account_analytic_account.py +++ b/contract_timesheet_monitoring/models/account_analytic_account.py @@ -8,8 +8,6 @@ def get_time_spent_for_period(self, start_date, end_date=None): analytic_account_lines = self.line_ids timesheets = analytic_account_lines.filtered( # keep only timesheets - # ensure the uom is the same as the one configure for the project - # timesheets (hours or day) lambda x: (x.product_uom_id.measure_type == "time") ) if timesheets: diff --git a/contract_timesheet_monitoring/models/contract_line.py b/contract_timesheet_monitoring/models/contract_line.py index aa2c8be01..90d6d83ad 100644 --- a/contract_timesheet_monitoring/models/contract_line.py +++ b/contract_timesheet_monitoring/models/contract_line.py @@ -1,4 +1,5 @@ from odoo import api, fields, models +from odoo.exceptions import UserError class ContractLine(models.Model): @@ -14,18 +15,20 @@ class ContractLine(models.Model): ) date_of_last_invoice = fields.Date(compute="_get_date_of_last_invoice") - def _get_date_of_last_invoice(self): - invoices = self.contract_id._get_related_invoices().filtered(lambda x: (x.state != "draft")) - if any(invoices.mapped("date_invoice")): - return max(invoices.mapped("date_invoice")) - else: - return False + def _get_period_start_date(self): + if self.recurring_invoicing_type == 'post-paid': + start_date = self.recurring_next_dat + else: + start_date = self.recurring_next_date - self.get_relative_delta( + self.recurring_rule_type, self.recurring_interval + ) + return start_date @api.depends("analytic_account_id.line_ids") def _compute_time_spent(self): for line in self: if line.analytic_account_id: - period_start_date = line._get_date_of_last_invoice() + period_start_date = line._get_period_start_date() line.time_spent = line.analytic_account_id.get_time_spent_for_period( period_start_date )